diff --git a/.gitignore b/.gitignore index decfc82..85b1f20 100644 --- a/.gitignore +++ b/.gitignore @@ -43,4 +43,5 @@ replay_*.log todo.txt cambios.md -remappedSrc/ \ No newline at end of file +remappedSrc/ +.claude/ \ No newline at end of file diff --git a/cambios.md b/cambios.md index 75bdcf6..4e3241c 100644 --- a/cambios.md +++ b/cambios.md @@ -1,18 +1,33 @@ -# v5.2 +# v5.3 ## novedades +- actualizado a 26.2 + ### 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: ### arreglos / mejoras -- `andamios` ya funciona correctamente -- autoguardado cada cierto intervalo de tiempo en vez de guardar inmediatamente tras cada cambio en los ajustes, por optimización -- el guardado se realiza desde otro hilo ahora, para evitar que el I/O bloque el hilo principal +- los módulos con tilde en el nombre (`cámara libre`, `críticos`, `partículas`...) ya recuperan +la posición de su marco de ajustes al arrancar; eran 12 y ninguno la guardaba +- 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 - lo de siempre. -- el ítem del tótem no se renderiza en el editor del HUD si es abierto en la pantalla de inicio \ No newline at end of file +- 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 diff --git a/gradle.properties b/gradle.properties index 4224110..257c107 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,15 +1,15 @@ org.gradle.jvmargs=-Xmx2G org.gradle.parallel=true -minecraft_version=26.1.2 -loader_version=0.19.2 -loom_version=1.16-SNAPSHOT +minecraft_version=26.2 +loader_version=0.19.3 +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 neutrino_version=1.1.0 jdk_version=25 -mod_version=5.2 +mod_version=5.3 maven_group=me.retucio archives_base_name=sputnik \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 1a70468..a351597 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME 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 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/src/main/java/me/retucio/sputnik/Sputnik.java b/src/main/java/me/retucio/sputnik/Sputnik.java index 9d43cc2..e4144aa 100644 --- a/src/main/java/me/retucio/sputnik/Sputnik.java +++ b/src/main/java/me/retucio/sputnik/Sputnik.java @@ -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.AbstractSignEditScreen; 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.Logger; @@ -183,7 +184,7 @@ public class Sputnik implements ClientModInitializer { // se ocupa de la lógica de encendido y apagado de los módulos 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()) { // evitar interrumpir combinaciones de teclas del F3 @@ -211,12 +212,12 @@ public class Sputnik implements ClientModInitializer { if (key != ClientSettingsPanel.clientSettings.getKey() || anyFocused || isOnTypingScreen()) return; - if (mc.screen != ClickGui.INSTANCE) { - prevScreen = mc.screen; - mc.setScreen(ClickGui.INSTANCE); + if (mc.gui.screen() != ClickGui.INSTANCE) { + prevScreen = mc.gui.screen(); + mc.gui.setScreen(ClickGui.INSTANCE); } else { 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); if (key != hud.editorKey.getValue() || anyFocused || isOnTypingScreen()) return; - if (mc.screen != HudEditorScreen.INSTANCE) { + if (mc.gui.screen() != HudEditorScreen.INSTANCE) { if (!hud.isEnabled()) { - ChatUtil.warn("HUD está desactivado, lumbreras"); + ChatUtil.warn(Component.translatable("sputnik.hud.disabled")); return; } - prevScreen = mc.screen; - mc.setScreen(HudEditorScreen.INSTANCE); + prevScreen = mc.gui.screen(); + mc.gui.setScreen(HudEditorScreen.INSTANCE); } else { 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 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()) if (module.shouldToggleOnBindRelease() && key == module.getKey()) @@ -248,19 +249,29 @@ public class Sputnik implements ClientModInitializer { } private boolean isOnTypingScreen() { - return mc.screen instanceof ChatScreen - || mc.screen instanceof AnvilScreen - || mc.screen instanceof AbstractSignEditScreen - || mc.screen instanceof AbstractCommandBlockEditScreen; + return mc.gui.screen() instanceof ChatScreen + || mc.gui.screen() instanceof AnvilScreen + || mc.gui.screen() instanceof AbstractSignEditScreen + || mc.gui.screen() instanceof AbstractCommandBlockEditScreen; } + private boolean keysVerified = false; + @EventListener // notificar al usuario de que hay una actualización disponible, si la hay public void onSetScreen(OpenScreenEvent event) { - if (VersionChecker.INSTANCE.shouldShowScreen && event.getScreen() instanceof TitleScreen) { - event.cancel(); - VersionChecker.INSTANCE.shouldShowScreen = false; - mc.execute(() -> mc.screen = new UpdateScreen()); + if (event.getScreen() instanceof TitleScreen) { + // aquí el idioma ya está cargado, que en onInitializeClient todavía no + if (!keysVerified) { + keysVerified = true; + I18nUtil.verifyKeys(); + } + + if (VersionChecker.INSTANCE.shouldShowScreen) { + event.cancel(); + VersionChecker.INSTANCE.shouldShowScreen = false; + mc.execute(() -> mc.gui.setScreen(new UpdateScreen())); + } } } diff --git a/src/main/java/me/retucio/sputnik/command/args/EntityArgumentType.java b/src/main/java/me/retucio/sputnik/command/args/EntityArgumentType.java index ac762a3..6c0b6dc 100644 --- a/src/main/java/me/retucio/sputnik/command/args/EntityArgumentType.java +++ b/src/main/java/me/retucio/sputnik/command/args/EntityArgumentType.java @@ -25,7 +25,7 @@ public class EntityArgumentType implements ArgumentType { public static final EntityArgumentType INSTANCE = new EntityArgumentType(); 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 EXAMPLES = List.of( "AdlerHitdolf", diff --git a/src/main/java/me/retucio/sputnik/command/args/EnumArgumentType.java b/src/main/java/me/retucio/sputnik/command/args/EnumArgumentType.java index a822d67..c5f8388 100644 --- a/src/main/java/me/retucio/sputnik/command/args/EnumArgumentType.java +++ b/src/main/java/me/retucio/sputnik/command/args/EnumArgumentType.java @@ -15,7 +15,8 @@ import java.util.concurrent.CompletableFuture; public class EnumArgumentType> implements ArgumentType { - 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; @@ -33,8 +34,10 @@ public class EnumArgumentType> implements ArgumentType { public T parse(StringReader reader) throws CommandSyntaxException { 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) - .filter((value) -> value.toString().equals(argument)) + .filter((value) -> value.toString().equalsIgnoreCase(argument)) .findFirst() .orElseThrow(() -> NO_SUCH_TYPE.create(argument) ); diff --git a/src/main/java/me/retucio/sputnik/command/args/ModuleArgumentType.java b/src/main/java/me/retucio/sputnik/command/args/ModuleArgumentType.java index b8c7e75..0ac4516 100644 --- a/src/main/java/me/retucio/sputnik/command/args/ModuleArgumentType.java +++ b/src/main/java/me/retucio/sputnik/command/args/ModuleArgumentType.java @@ -22,15 +22,15 @@ public class ModuleArgumentType implements ArgumentType { public static final ModuleArgumentType INSTANCE = new ModuleArgumentType(); 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 examples = ModuleManager.INSTANCE.getModules() - .stream().limit(3).map(module -> module.getName().replace(" ", "_")).toList(); + .stream().limit(3).map(module -> module.getDisplayName().replace(" ", "_")).toList(); @Override public Module parse(StringReader reader) throws CommandSyntaxException { 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); return module; } @@ -38,7 +38,7 @@ public class ModuleArgumentType implements ArgumentType { @Override public CompletableFuture listSuggestions(CommandContext context, SuggestionsBuilder builder) { 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 diff --git a/src/main/java/me/retucio/sputnik/command/args/PlayerArgumentType.java b/src/main/java/me/retucio/sputnik/command/args/PlayerArgumentType.java index 216be95..60e2b98 100644 --- a/src/main/java/me/retucio/sputnik/command/args/PlayerArgumentType.java +++ b/src/main/java/me/retucio/sputnik/command/args/PlayerArgumentType.java @@ -21,7 +21,8 @@ import static me.retucio.sputnik.Sputnik.mc; public class PlayerArgumentType implements ArgumentType { 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 EXAMPLES = List.of("retucio", "prepucio", "postpucio", "pucio", "adler hitdolf"); diff --git a/src/main/java/me/retucio/sputnik/command/commands/BindCommand.java b/src/main/java/me/retucio/sputnik/command/commands/BindCommand.java index 6376a11..ac6cac1 100644 --- a/src/main/java/me/retucio/sputnik/command/commands/BindCommand.java +++ b/src/main/java/me/retucio/sputnik/command/commands/BindCommand.java @@ -24,7 +24,7 @@ public class BindCommand extends Command { private static Module listeningModule = null; 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 @@ -34,14 +34,16 @@ public class BindCommand extends Command { .executes(ctx -> { Module module = ctx.getArgument("módulo", Module.class); 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; }) .then(literal("reset").executes(ctx -> { Module module = ctx.getArgument("módulo", Module.class); module.getBind().reset(); - ChatUtil.info("tecla para el módulo " + ChatFormatting.GREEN + module.getName() - + " restablecida a " + ChatFormatting.AQUA + KeyUtil.getKeyName(module.getKey())); + ChatUtil.info(Component.translatable("sputnik.commands.bind.keyreset", + ChatFormatting.GREEN + module.getDisplayName(), + ChatFormatting.AQUA + KeyUtil.getKeyName(module.getKey()) + )); return SUCCESS; })) ); @@ -51,17 +53,18 @@ public class BindCommand extends Command { if (listeningModule == null) return false; 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 keys = new ArrayList<>(List.of(mc.options.keyMappings)); keys.removeAll(List.of(mc.options.debugKeys)); for (KeyMapping kb : keys) { - boolean keyAlreadyBound = kb.matches(new KeyEvent(key, 0, 0)); - boolean allowMultiple = ClientSettingsPanel.clientSettings.multipleKeybinds.getValue(); - - if (keyAlreadyBound && !allowMultiple) { - ChatUtil.warn("esa tecla ya está cogida por " - + ChatFormatting.GREEN + "\"" + I18n.get(kb.getName() + "\"")); + if (kb.matches(new KeyEvent(key, 0, 0))) { + // la comilla iba dentro del I18n.get, así que buscaba una clave inexistente + ChatUtil.warn(Component.translatable("sputnik.commands.bind.keytaken", + ChatFormatting.GREEN + "\"" + I18n.get(kb.getName()) + "\"")); listeningModule = null; return true; } @@ -70,10 +73,10 @@ public class BindCommand extends Command { if (bind != null) bind.setValue(key); - ChatUtil.info( - Component.nullToEmpty("la tecla " + ChatFormatting.AQUA + KeyUtil.getKeyName(key) + ChatFormatting.RESET + - " ha sido asignada al módulo " + ChatFormatting.GREEN + listeningModule.getName()) - ); + ChatUtil.info(Component.translatable("sputnik.commands.bind.keybound", + ChatFormatting.AQUA + KeyUtil.getKeyName(key) + ChatFormatting.RESET, + ChatFormatting.GREEN + listeningModule.getDisplayName() + )); listeningModule = null; return true; diff --git a/src/main/java/me/retucio/sputnik/command/commands/ClickSlotCommand.java b/src/main/java/me/retucio/sputnik/command/commands/ClickSlotCommand.java index a6aef02..fafd8e0 100644 --- a/src/main/java/me/retucio/sputnik/command/commands/ClickSlotCommand.java +++ b/src/main/java/me/retucio/sputnik/command/commands/ClickSlotCommand.java @@ -7,13 +7,14 @@ import me.retucio.sputnik.command.args.EnumArgumentType; import net.minecraft.client.gui.screens.Screen; import net.minecraft.client.gui.screens.inventory.ContainerScreen; import net.minecraft.commands.SharedSuggestionProvider; +import net.minecraft.network.chat.Component; 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& public class ClickSlotCommand extends Command { public ClickSlotCommand() { - super("clickslot", "simula un clic a un slot"); + super("clickslot", Component.translatable("sputnik.commands.clickslot.desc").getString(), "cs"); } public void build(LiteralArgumentBuilder builder) { @@ -23,7 +24,7 @@ public class ClickSlotCommand extends Command { .executes(context -> { int slot = context.getArgument("slot", Integer.class), button = context.getArgument("botón", Integer.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; if (mc.gameMode == null) return 0; mc.gameMode.handleContainerInput(syncId, slot, button, action, mc.player); diff --git a/src/main/java/me/retucio/sputnik/command/commands/ConfigCommand.java b/src/main/java/me/retucio/sputnik/command/commands/ConfigCommand.java index e42a244..e75b12f 100644 --- a/src/main/java/me/retucio/sputnik/command/commands/ConfigCommand.java +++ b/src/main/java/me/retucio/sputnik/command/commands/ConfigCommand.java @@ -9,11 +9,12 @@ import me.retucio.sputnik.ui.screen.ClickGui; import me.retucio.sputnik.ui.widgets.panels.SettingsPanel; import net.minecraft.commands.SharedSuggestionProvider; import me.retucio.sputnik.module.Module; +import net.minecraft.network.chat.Component; public class ConfigCommand extends Command { 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 @@ -40,7 +41,7 @@ public class ConfigCommand extends Command { private void openSf(CommandContext ctx) { Module module = ctx.getArgument("módulo", Module.class); - mc.setScreen(ClickGui.INSTANCE); + mc.gui.setScreen(ClickGui.INSTANCE); if (ClickGui.INSTANCE.isSettingsPanelOpen(module)) return; @@ -53,7 +54,7 @@ public class ConfigCommand extends Command { private void openSfWithPos(CommandContext ctx, int x, int y) { Module module = ctx.getArgument("módulo", Module.class); - mc.setScreen(ClickGui.INSTANCE); + mc.gui.setScreen(ClickGui.INSTANCE); if (ClickGui.INSTANCE.isSettingsPanelOpen(module)) { SettingsPanel sf = ClickGui.INSTANCE.getSettingsPanelOfModule(module); diff --git a/src/main/java/me/retucio/sputnik/command/commands/CopyScreenshotCommand.java b/src/main/java/me/retucio/sputnik/command/commands/CopyScreenshotCommand.java index 53c2fc1..2494fdd 100644 --- a/src/main/java/me/retucio/sputnik/command/commands/CopyScreenshotCommand.java +++ b/src/main/java/me/retucio/sputnik/command/commands/CopyScreenshotCommand.java @@ -5,12 +5,13 @@ import me.retucio.sputnik.command.Command; import me.retucio.sputnik.module.ModuleManager; import me.retucio.sputnik.module.modules.misc.ScreenshotPlus; 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 public class CopyScreenshotCommand extends Command { public CopyScreenshotCommand() { - super("copiarcaptura", "copia la captura más reciente al portapapeles"); + super("copiarcaptura", Component.translatable("sputnik.commands.copyscreenshot.desc").getString(), "copyscreenshot"); } @Override diff --git a/src/main/java/me/retucio/sputnik/command/commands/EnderChestCommand.java b/src/main/java/me/retucio/sputnik/command/commands/EnderChestCommand.java index 2a74122..1049699 100644 --- a/src/main/java/me/retucio/sputnik/command/commands/EnderChestCommand.java +++ b/src/main/java/me/retucio/sputnik/command/commands/EnderChestCommand.java @@ -8,6 +8,7 @@ import me.retucio.sputnik.ui.screen.PreviewScreen; import me.retucio.sputnik.util.ChatUtil; import me.retucio.sputnik.util.InventoryUtil; import net.minecraft.commands.SharedSuggestionProvider; +import net.minecraft.network.chat.Component; // accede a los contenidos de tu enderchest public class EnderChestCommand extends Command { @@ -15,7 +16,7 @@ public class EnderChestCommand extends Command { private boolean shouldOpenEchest = false; 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 @@ -24,7 +25,7 @@ public class EnderChestCommand extends Command { mc.execute(() -> { if (mc.player == null) return; if (InventoryUtil.getEchestInv() == null) { - ChatUtil.warn("necesitas abrir un enderchest una vez primero"); + ChatUtil.warn(Component.translatable( "sputnik.commands.echest.openfirst")); return; } @@ -40,7 +41,7 @@ public class EnderChestCommand extends Command { if (shouldOpenEchest) { shouldOpenEchest = false; if (InventoryUtil.getEchestInv() != null) - mc.setScreen(new PreviewScreen(InventoryUtil.getEchestInv(), null)); + mc.gui.setScreen(new PreviewScreen(InventoryUtil.getEchestInv(), null)); } } } \ No newline at end of file diff --git a/src/main/java/me/retucio/sputnik/command/commands/FriendCommand.java b/src/main/java/me/retucio/sputnik/command/commands/FriendCommand.java index 0e0a241..d7cc0aa 100644 --- a/src/main/java/me/retucio/sputnik/command/commands/FriendCommand.java +++ b/src/main/java/me/retucio/sputnik/command/commands/FriendCommand.java @@ -8,12 +8,14 @@ import me.retucio.sputnik.friend.FriendManager; import me.retucio.sputnik.util.ChatUtil; import net.minecraft.ChatFormatting; import net.minecraft.commands.SharedSuggestionProvider; +import net.minecraft.network.chat.Component; import net.minecraft.world.entity.player.Player; + public class FriendCommand extends Command { public FriendCommand() { - super("friend", "gestión de amigos", "amigo", "f"); + super("friend", Component.translatable("sputnik.commands.friend.desc").getString(), "amigo", "f"); } @Override @@ -24,7 +26,10 @@ public class FriendCommand extends Command { .executes(ctx -> { Player friend = ctx.getArgument("amigo", Player.class); 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; }) ) @@ -34,14 +39,17 @@ public class FriendCommand extends Command { .executes(ctx -> { Player friend = ctx.getArgument("amigo", Player.class); 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; }) ) ) .then(literal("list") .executes(ctx -> { - ChatUtil.info(ChatFormatting.GOLD + "amigos:"); + ChatUtil.info(ChatFormatting.GOLD + Component.translatable("sputnik.commands.friend.list").getString()); for (Friend friend : FriendManager.INSTANCE.getFriends()) { ChatUtil.info("- " + friend.getName()); } diff --git a/src/main/java/me/retucio/sputnik/command/commands/GarbageCleanerCommand.java b/src/main/java/me/retucio/sputnik/command/commands/GarbageCleanerCommand.java index d168ddd..ea1bc3b 100644 --- a/src/main/java/me/retucio/sputnik/command/commands/GarbageCleanerCommand.java +++ b/src/main/java/me/retucio/sputnik/command/commands/GarbageCleanerCommand.java @@ -9,14 +9,14 @@ import net.minecraft.network.chat.Component; public class GarbageCleanerCommand extends Command { 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 public void build(LiteralArgumentBuilder builder) { builder.executes(context -> { System.gc(); - ChatUtil.info(Component.nullToEmpty("basura recolectada")); + ChatUtil.info(Component.translatable("sputnik.commands.gc.collected")); return SUCCESS; }); } diff --git a/src/main/java/me/retucio/sputnik/command/commands/PeekCommand.java b/src/main/java/me/retucio/sputnik/command/commands/PeekCommand.java index fb2827b..1e878c3 100644 --- a/src/main/java/me/retucio/sputnik/command/commands/PeekCommand.java +++ b/src/main/java/me/retucio/sputnik/command/commands/PeekCommand.java @@ -6,12 +6,15 @@ import me.retucio.sputnik.command.args.PlayerArgumentType; import me.retucio.sputnik.util.MiscUtil; import net.minecraft.client.gui.screens.inventory.InventoryScreen; 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 public class PeekCommand extends Command { 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 diff --git a/src/main/java/me/retucio/sputnik/command/commands/PluginsCommand.java b/src/main/java/me/retucio/sputnik/command/commands/PluginsCommand.java index cbaf3f5..9e5213e 100644 --- a/src/main/java/me/retucio/sputnik/command/commands/PluginsCommand.java +++ b/src/main/java/me/retucio/sputnik/command/commands/PluginsCommand.java @@ -12,6 +12,7 @@ import me.retucio.sputnik.util.ChatUtil; import net.minecraft.client.multiplayer.ClientPacketListener; import net.minecraft.client.multiplayer.ClientSuggestionProvider; import net.minecraft.commands.SharedSuggestionProvider; +import net.minecraft.network.chat.Component; import net.minecraft.network.protocol.game.ClientboundCommandsPacket; import java.util.HashSet; @@ -23,7 +24,7 @@ public class PluginsCommand extends Command { private boolean scanning = false; 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); } @@ -31,12 +32,12 @@ public class PluginsCommand extends Command { public void build(LiteralArgumentBuilder builder) { builder.executes(context -> { if (mc.hasSingleplayerServer()) { - ChatUtil.error("estás en un solo jugador"); + ChatUtil.error(Component.translatable("sputnik.commands.plugins.singleplayer")); return SUCCESS; } if (scanning) { - ChatUtil.error("calmaaa"); + ChatUtil.error(Component.translatable("sputnik.commands.plugins.calmdown")); return SUCCESS; } @@ -60,7 +61,7 @@ public class PluginsCommand extends Command { root.getChildren().forEach(this::checkNodeForPlugins); 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() .sorted() .forEach(plugin -> ChatUtil.info(" - " + plugin)); @@ -69,7 +70,7 @@ public class PluginsCommand extends Command { displayResults(); } 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() { if (!plugins.isEmpty()) { - ChatUtil.info(plugins.size() + " plugin(s) encontrado(s)"); + ChatUtil.info(Component.translatable("sputnik.commands.plugins.pluginsfound", plugins.size())); plugins.stream().sorted() .forEach(plugin -> ChatUtil.info(" - " + plugin)); } else { - ChatUtil.warn("sin plugins (probablemente)"); + ChatUtil.warn(Component.translatable("sputnik.commands.plugins.noplugins")); } scanning = false; diff --git a/src/main/java/me/retucio/sputnik/command/commands/PrefixCommand.java b/src/main/java/me/retucio/sputnik/command/commands/PrefixCommand.java index bde4659..4ac3abe 100644 --- a/src/main/java/me/retucio/sputnik/command/commands/PrefixCommand.java +++ b/src/main/java/me/retucio/sputnik/command/commands/PrefixCommand.java @@ -13,17 +13,17 @@ import net.minecraft.network.chat.Component; public class PrefixCommand extends Command { public PrefixCommand() { - super("prefijo", "cambia el prefijo de los comandos", "prefix"); + super("prefijo", Component.translatable("sputnik.commands.prefix.desc").getString(), "prefix"); } @Override public void build(LiteralArgumentBuilder builder) { builder - .then(argument("prefijo", StringArgumentType.word()).executes(ctx -> { - String prefix = ctx.getArgument("prefijo", String.class); - ClientSettingsPanel.clientSettings.commandPrefix.setValue(prefix); - ChatUtil.info(Component.literal("prefijo cambiado a " + ChatFormatting.AQUA + prefix)); - return SUCCESS; - })); + .then(argument("prefijo", StringArgumentType.word()).executes(ctx -> { + String prefix = ctx.getArgument("prefijo", String.class); + ClientSettingsPanel.clientSettings.commandPrefix.setValue(prefix); + ChatUtil.info(Component.translatable("sputnik.commands.prefix.changed", ChatFormatting.AQUA + prefix)); + return SUCCESS; + })); } } diff --git a/src/main/java/me/retucio/sputnik/command/commands/PurgeCommand.java b/src/main/java/me/retucio/sputnik/command/commands/PurgeCommand.java index 17e171f..3a0261e 100644 --- a/src/main/java/me/retucio/sputnik/command/commands/PurgeCommand.java +++ b/src/main/java/me/retucio/sputnik/command/commands/PurgeCommand.java @@ -7,13 +7,15 @@ import me.retucio.sputnik.util.interfaces.IChatComponent; import net.minecraft.client.gui.components.ChatComponent; import net.minecraft.client.multiplayer.chat.GuiMessage; import net.minecraft.commands.SharedSuggestionProvider; +import net.minecraft.network.chat.Component; +import java.awt.*; import java.util.List; public class PurgeCommand extends Command { public PurgeCommand() { - super("purgar", "elimina mensajes del chat", "purge"); + super("purgar", Component.translatable("sputnik.commands.purge.desc").getString(), "purge"); } @Override @@ -28,7 +30,7 @@ public class PurgeCommand extends Command { } private void purgeMessages(int amount) { - ChatComponent chatHud = mc.gui.getChat(); + ChatComponent chatHud = mc.gui.hud.getChat(); synchronized (chatHud) { List visibleMessages = ((IChatComponent) chatHud).sputnik$getVisibleMessages(); diff --git a/src/main/java/me/retucio/sputnik/command/commands/RepeatCommand.java b/src/main/java/me/retucio/sputnik/command/commands/RepeatCommand.java index f23e041..9c17f9d 100644 --- a/src/main/java/me/retucio/sputnik/command/commands/RepeatCommand.java +++ b/src/main/java/me/retucio/sputnik/command/commands/RepeatCommand.java @@ -6,11 +6,12 @@ import com.mojang.brigadier.builder.LiteralArgumentBuilder; import me.retucio.sputnik.command.Command; import me.retucio.sputnik.util.ChatUtil; import net.minecraft.commands.SharedSuggestionProvider; +import net.minecraft.network.chat.Component; public class RepeatCommand extends Command { public RepeatCommand() { - super("repetir", "repite un comando x veces", "repeat"); + super("repetir", Component.translatable("sputnik.commands.repeat.desc").getString(), "repeat"); } @Override diff --git a/src/main/java/me/retucio/sputnik/command/commands/RepeatWaitCommand.java b/src/main/java/me/retucio/sputnik/command/commands/RepeatWaitCommand.java index 9ca63b3..0dfa221 100644 --- a/src/main/java/me/retucio/sputnik/command/commands/RepeatWaitCommand.java +++ b/src/main/java/me/retucio/sputnik/command/commands/RepeatWaitCommand.java @@ -6,6 +6,7 @@ import com.mojang.brigadier.builder.LiteralArgumentBuilder; import me.retucio.sputnik.command.Command; import me.retucio.sputnik.util.ChatUtil; import net.minecraft.commands.SharedSuggestionProvider; +import net.minecraft.network.chat.Component; import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.TimeUnit; @@ -13,7 +14,7 @@ import java.util.concurrent.TimeUnit; public class RepeatWaitCommand extends Command { public RepeatWaitCommand() { - super("repesperar", "combinación de $repetir y $esperar"); + super("repesperar", Component.translatable("sputnik.commands.repeatwait.desc").getString(), "repeatwait"); } @Override diff --git a/src/main/java/me/retucio/sputnik/command/commands/SaveScreenshotCommand.java b/src/main/java/me/retucio/sputnik/command/commands/SaveScreenshotCommand.java index c46651f..80290f9 100644 --- a/src/main/java/me/retucio/sputnik/command/commands/SaveScreenshotCommand.java +++ b/src/main/java/me/retucio/sputnik/command/commands/SaveScreenshotCommand.java @@ -6,6 +6,7 @@ import me.retucio.sputnik.module.ModuleManager; import me.retucio.sputnik.module.modules.misc.ScreenshotPlus; import me.retucio.sputnik.util.ChatUtil; import net.minecraft.commands.SharedSuggestionProvider; +import net.minecraft.network.chat.Component; import java.io.IOException; @@ -13,7 +14,7 @@ import java.io.IOException; public class SaveScreenshotCommand extends Command { public SaveScreenshotCommand() { - super("guardarcaptura", "guarda localmente la captura más reciente"); + super("guardarcaptura", Component.translatable("sputnik.commands.savescreenshot.desc").getString(), "savescreenshot"); } @Override @@ -26,7 +27,7 @@ public class SaveScreenshotCommand extends Command { try { screenshotPlus.saveScreenshot(); } catch (IOException e) { - ChatUtil.error("no se pudo guardar la captura"); + ChatUtil.error(Component.translatable("sputnik.commands.savescreenshot.error")); } } }); diff --git a/src/main/java/me/retucio/sputnik/command/commands/SendCommand.java b/src/main/java/me/retucio/sputnik/command/commands/SendCommand.java index 2cd8ff8..884c3e6 100644 --- a/src/main/java/me/retucio/sputnik/command/commands/SendCommand.java +++ b/src/main/java/me/retucio/sputnik/command/commands/SendCommand.java @@ -6,6 +6,7 @@ import me.retucio.sputnik.command.Command; import me.retucio.sputnik.mixin.accessors.ClientPacketListenerAccessor; import net.minecraft.client.multiplayer.ClientPacketListener; import net.minecraft.commands.SharedSuggestionProvider; +import net.minecraft.network.chat.Component; import net.minecraft.network.chat.LastSeenMessagesTracker; import net.minecraft.network.chat.MessageSignature; import net.minecraft.network.chat.SignedMessageBody; @@ -18,7 +19,7 @@ import java.time.Instant; public class SendCommand extends Command { public SendCommand() { - super("enviar", "manda un mensaje en el chat", "send"); + super("enviar", Component.translatable("sputnik.commands.send.desc").getString(), "send"); } @Override @@ -37,7 +38,7 @@ public class SendCommand extends Command { LastSeenMessagesTracker tracker = ((ClientPacketListenerAccessor) handler).getLastSeenMessagesTracker(); LastSeenMessagesTracker.Update lastSeenMessages = tracker.generateAndApplyUpdate(); - // empacar firma para un chat seguro + // empacar firma MessageSignature messageSignature = ((ClientPacketListenerAccessor) handler) .getSignedMessageEncoder() .pack(new SignedMessageBody( diff --git a/src/main/java/me/retucio/sputnik/command/commands/SpectateCommand.java b/src/main/java/me/retucio/sputnik/command/commands/SpectateCommand.java index ca76e31..b5834cb 100644 --- a/src/main/java/me/retucio/sputnik/command/commands/SpectateCommand.java +++ b/src/main/java/me/retucio/sputnik/command/commands/SpectateCommand.java @@ -7,19 +7,22 @@ import me.retucio.sputnik.command.args.EntityArgumentType; import me.retucio.sputnik.event.input.KeyEvent; import me.retucio.sputnik.util.EntityUtil; import net.minecraft.commands.SharedSuggestionProvider; +import net.minecraft.network.chat.Component; import net.minecraft.world.entity.Entity; import org.lwjgl.glfw.GLFW; +import java.awt.*; + public class SpectateCommand extends Command { 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 public void build(LiteralArgumentBuilder builder) { builder - .executes(ctx -> { // If no argument, use the entity player is looking at + .executes(ctx -> { mc.execute(() -> { Entity target = EntityUtil.getEntityPlayerIsLookingAt(); if (target != null) @@ -40,7 +43,7 @@ public class SpectateCommand extends Command { @EventListener 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.cancel(); mc.setCameraEntity(mc.player); diff --git a/src/main/java/me/retucio/sputnik/command/commands/ToggleCommand.java b/src/main/java/me/retucio/sputnik/command/commands/ToggleCommand.java index 4758a6f..59b96fc 100644 --- a/src/main/java/me/retucio/sputnik/command/commands/ToggleCommand.java +++ b/src/main/java/me/retucio/sputnik/command/commands/ToggleCommand.java @@ -6,12 +6,15 @@ import me.retucio.sputnik.command.args.ModuleArgumentType; import me.retucio.sputnik.module.Module; import me.retucio.sputnik.module.ModuleManager; 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 public class ToggleCommand extends Command { public ToggleCommand() { - super("alternar", "enciende / apaga módulos", "toggle"); + super("alternar", Component.translatable("sputnik.commands.toggle.desc").getString(), "toggle"); } @Override diff --git a/src/main/java/me/retucio/sputnik/command/commands/WaitCommand.java b/src/main/java/me/retucio/sputnik/command/commands/WaitCommand.java index 888eadb..ed4561e 100644 --- a/src/main/java/me/retucio/sputnik/command/commands/WaitCommand.java +++ b/src/main/java/me/retucio/sputnik/command/commands/WaitCommand.java @@ -6,6 +6,7 @@ import com.mojang.brigadier.builder.LiteralArgumentBuilder; import me.retucio.sputnik.command.Command; import me.retucio.sputnik.util.ChatUtil; import net.minecraft.commands.SharedSuggestionProvider; +import net.minecraft.network.chat.Component; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledThreadPoolExecutor; @@ -16,7 +17,7 @@ public class WaitCommand extends Command { private static final ScheduledExecutorService DELAYED_EXECUTOR = new ScheduledThreadPoolExecutor(2); 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 diff --git a/src/main/java/me/retucio/sputnik/config/BinarySerializer.java b/src/main/java/me/retucio/sputnik/config/BinarySerializer.java index 1d7bbdb..d3ace7c 100644 --- a/src/main/java/me/retucio/sputnik/config/BinarySerializer.java +++ b/src/main/java/me/retucio/sputnik/config/BinarySerializer.java @@ -1,5 +1,7 @@ package me.retucio.sputnik.config; +import net.minecraft.network.chat.Component; + import java.io.*; import java.nio.charset.StandardCharsets; import java.nio.file.Files; @@ -83,25 +85,26 @@ public class BinarySerializer { public static ClientConfig readConfig(File file) throws IOException { 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( new BufferedInputStream(new FileInputStream(file)))) { 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 int magic = in.readInt(); 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(); 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(); diff --git a/src/main/java/me/retucio/sputnik/config/ClientConfig.java b/src/main/java/me/retucio/sputnik/config/ClientConfig.java index c022c32..8aafca1 100644 --- a/src/main/java/me/retucio/sputnik/config/ClientConfig.java +++ b/src/main/java/me/retucio/sputnik/config/ClientConfig.java @@ -17,7 +17,7 @@ import java.util.Map; import static me.retucio.sputnik.Sputnik.EVENT_BUS; 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 { // nombre del módulo -> estado del módulo @@ -104,9 +104,11 @@ public class ClientConfig { 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 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().getY(), event.getPanel().isExtended())); @@ -124,7 +126,7 @@ public class ClientConfig { @EventListener public void onMoveClientSettingsPanel(ClientSettingsPanelEvent.Move event) { - extendablePanels.replace("ajustes", new PanelData( + extendablePanels.put("ajustes", new PanelData( ClickGui.INSTANCE.getClientSettingsPanel().getX(), ClickGui.INSTANCE.getClientSettingsPanel().getY(), ClickGui.INSTANCE.getClientSettingsPanel().isExtended())); @@ -142,7 +144,7 @@ public class ClientConfig { @EventListener public void onMoveFriendsPanel(FriendPanelEvent.Move event) { - extendablePanels.replace("amigos", new PanelData( + extendablePanels.put("amigos", new PanelData( ClickGui.INSTANCE.getFriendsPanel().getX(), ClickGui.INSTANCE.getFriendsPanel().getY(), ClickGui.INSTANCE.getFriendsPanel().isExtended())); diff --git a/src/main/java/me/retucio/sputnik/config/ConfigManager.java b/src/main/java/me/retucio/sputnik/config/ConfigManager.java index 9bdb494..0a817c3 100644 --- a/src/main/java/me/retucio/sputnik/config/ConfigManager.java +++ b/src/main/java/me/retucio/sputnik/config/ConfigManager.java @@ -12,12 +12,14 @@ import me.retucio.sputnik.module.setting.*; import me.retucio.sputnik.module.setting.settings.*; import me.retucio.sputnik.ui.hud.HudRenderer; 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.ModulePanel; import me.retucio.sputnik.ui.screen.ClickGui; import me.retucio.sputnik.ui.widgets.panels.settings.ClientSettingsPanel; import me.retucio.sputnik.ui.widgets.panels.SettingsPanel; import me.retucio.sputnik.util.ChatUtil; +import net.minecraft.network.chat.Component; import java.io.File; import java.io.FileReader; @@ -65,7 +67,7 @@ public class ConfigManager { try { snapshot = BinarySerializer.toBytes(config); } catch (IOException e) { - Sputnik.LOGGER.error("error al serializar ajustes", e); + Sputnik.LOGGER.error(Component.translatable("sputnik.config.error.serialization").getString(), e); return; } @@ -75,9 +77,9 @@ public class ConfigManager { saveExecutor.execute(() -> { try { BinarySerializer.writeBytes(snapshot, CONFIG_FILE); - Sputnik.LOGGER.info("ajustes guardados"); + Sputnik.LOGGER.info(Component.translatable("sputnik.config.info.saved").getString()); } catch (IOException e) { - Sputnik.LOGGER.error("error al guardar ajustes", e); + Sputnik.LOGGER.error(Component.translatable("sputnik.config.error.saving").getString(), e); } finally { saveQueued.set(false); } @@ -90,7 +92,7 @@ public class ConfigManager { try { // dar hasta 5 segundos para que termine el guardado en curso 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) { Thread.currentThread().interrupt(); @@ -101,15 +103,15 @@ public class ConfigManager { } public void load() { - Sputnik.LOGGER.info("cargando ajustes..."); + Sputnik.LOGGER.info(Component.translatable("sputnik.config.info.loading").getString()); if (CONFIG_FILE.exists()) { try { config = BinarySerializer.readConfig(CONFIG_FILE); - Sputnik.LOGGER.info("ajustes cargados"); + Sputnik.LOGGER.info(Component.translatable("sputnik.config.info.loaded").getString()); return; } 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)) { Gson gson = new GsonBuilder().setPrettyPrinting().create(); 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(); return; } 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(); loaded = true; - Sputnik.LOGGER.info("ajustes aplicados"); + Sputnik.LOGGER.info(Component.translatable("sputnik.config.info.applied").getString()); } // obtener configuración actual @@ -211,7 +213,7 @@ public class ConfigManager { friend.setName(name); FriendManager.INSTANCE.add(friend); }); - Sputnik.LOGGER.info("amigos aplicados"); + Sputnik.LOGGER.info(Component.translatable("sputnik.config.info.friends").getString()); } @SuppressWarnings({"rawtypes", "unchecked"}) @@ -231,7 +233,8 @@ public class ConfigManager { case ListSetting listSetting -> applyListSetting(listSetting, value); case ColorSetting colorSetting -> applyColorSetting(colorSetting, 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())); } }); - Sputnik.LOGGER.info("estados de módulos aplicados"); + Sputnik.LOGGER.info(Component.translatable("sputnik.config.info.modulestates").getString()); } private void applyModuleSettings() { ModuleManager.INSTANCE.getModules().forEach(module -> { 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() { @@ -256,14 +259,14 @@ public class ConfigManager { Module module = ModuleManager.INSTANCE.getModuleByName(moduleName); if (module == null) { - Sputnik.LOGGER.warn("\"null\" como módulo (\"{}\")", moduleName); + Sputnik.LOGGER.warn(Component.translatable("sputnik.config.warn.nullmodule", moduleName).getString()); return; } 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() { @@ -271,13 +274,13 @@ public class ConfigManager { ClickGui.INSTANCE.getSearchBar().setX(config.searchBarPosition[0]); 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() { ClientSettingsPanel.clientSettings.setEnabled(true); 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() { @@ -287,7 +290,7 @@ public class ConfigManager { applyExtendablePanel(ClickGui.INSTANCE.getClientSettingsPanel()); 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(); } @@ -308,14 +311,8 @@ public class ConfigManager { panel.setX(panelData.x()); panel.setY(panelData.y()); - if (panel instanceof ModulePanel mPanel) { - mPanel.setExtended(panelData.extended()); - } - if (panel instanceof ClientSettingsPanel sPanel) { - sPanel.setExtended(panelData.extended()); - } - if (panel instanceof FriendsPanel fPanel) { - fPanel.setExtended(panelData.extended()); + if (panel instanceof ExtendablePanel ePanel) { + ePanel.setExtended(panelData.extended()); } } } @@ -444,7 +441,9 @@ public class ConfigManager { long intervalMs = (long) (settings.autosaveInterval.getValue() * 1000); 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(); dirty = false; } diff --git a/src/main/java/me/retucio/sputnik/mixin/mixins/entity/LivingEntityMixin.java b/src/main/java/me/retucio/sputnik/mixin/mixins/entity/LivingEntityMixin.java index cf2e958..6a47667 100644 --- a/src/main/java/me/retucio/sputnik/mixin/mixins/entity/LivingEntityMixin.java +++ b/src/main/java/me/retucio/sputnik/mixin/mixins/entity/LivingEntityMixin.java @@ -8,6 +8,7 @@ import me.retucio.sputnik.module.modules.movement.Velocity; import net.minecraft.client.player.LocalPlayer; import net.minecraft.sounds.SoundEvents; import net.minecraft.sounds.SoundSource; +import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.phys.Vec3; @@ -61,8 +62,8 @@ public abstract class LivingEntityMixin { 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) - private void onTakeKb(double strength, double x, double z, CallbackInfo ci, @Local(name = "deltaMovement") Vec3 dm, @Local(name = "deltaVector") Vec3 dv) { + @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, 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); if (!velocity.isEnabled() || velocity.hits.getValue()) return; boolean onGround = ((LivingEntity) (Object) this).onGround(); diff --git a/src/main/java/me/retucio/sputnik/mixin/mixins/hud/ChatComponentMixin.java b/src/main/java/me/retucio/sputnik/mixin/mixins/hud/ChatComponentMixin.java index 5157a2e..98ce340 100644 --- a/src/main/java/me/retucio/sputnik/mixin/mixins/hud/ChatComponentMixin.java +++ b/src/main/java/me/retucio/sputnik/mixin/mixins/hud/ChatComponentMixin.java @@ -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;")) 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; 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;")) 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()); return line; } diff --git a/src/main/java/me/retucio/sputnik/mixin/mixins/hud/GuiMixin.java b/src/main/java/me/retucio/sputnik/mixin/mixins/hud/GuiMixin.java index ef31532..ccd427a 100644 --- a/src/main/java/me/retucio/sputnik/mixin/mixins/hud/GuiMixin.java +++ b/src/main/java/me/retucio/sputnik/mixin/mixins/hud/GuiMixin.java @@ -1,107 +1,21 @@ 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.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 me.retucio.sputnik.event.interact.OpenScreenEvent; import net.minecraft.client.gui.Gui; -import net.minecraft.client.gui.GuiGraphicsExtractor; -import net.minecraft.client.renderer.RenderPipelines; -import net.minecraft.resources.Identifier; +import net.minecraft.client.gui.screens.Screen; 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.ModifyArgs; -import org.spongepowered.asm.mixin.injection.Redirect; 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) public abstract class GuiMixin { - @Unique - NoRender noRender; - - @Inject(method = "", 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(); + @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(); } } diff --git a/src/main/java/me/retucio/sputnik/mixin/mixins/hud/HudMixin.java b/src/main/java/me/retucio/sputnik/mixin/mixins/hud/HudMixin.java new file mode 100644 index 0000000..f56a793 --- /dev/null +++ b/src/main/java/me/retucio/sputnik/mixin/mixins/hud/HudMixin.java @@ -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 = "", 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(); + } +} diff --git a/src/main/java/me/retucio/sputnik/mixin/mixins/item/ItemMixin.java b/src/main/java/me/retucio/sputnik/mixin/mixins/item/ItemMixin.java index 841a6fb..e4d8a61 100644 --- a/src/main/java/me/retucio/sputnik/mixin/mixins/item/ItemMixin.java +++ b/src/main/java/me/retucio/sputnik/mixin/mixins/item/ItemMixin.java @@ -27,13 +27,13 @@ public abstract class ItemMixin { if (stack.getItem() instanceof BlockItem blockItem && blockItem.getBlock() instanceof ShulkerBoxBlock) { 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 { builder.accept( - Component.literal("mantén ") - .append(Component.literal(shulkerPeek.previewKey.getKeyName()) - .withStyle(ChatFormatting.GOLD, ChatFormatting.BOLD)) - .append(" para previsualizar") + Component.translatable("sputnik.module.shulkerpeek.holdtopreview", + Component.literal(shulkerPeek.previewKey.getKeyName()) + .withStyle(ChatFormatting.GOLD, ChatFormatting.BOLD)) .withStyle(ChatFormatting.GRAY) ); } diff --git a/src/main/java/me/retucio/sputnik/mixin/mixins/misc/MinecraftMixin.java b/src/main/java/me/retucio/sputnik/mixin/mixins/misc/MinecraftMixin.java index 236f855..c9b2823 100644 --- a/src/main/java/me/retucio/sputnik/mixin/mixins/misc/MinecraftMixin.java +++ b/src/main/java/me/retucio/sputnik/mixin/mixins/misc/MinecraftMixin.java @@ -38,9 +38,6 @@ public abstract class MinecraftMixin { // eventos - @Shadow @Nullable - public Screen screen; - @Shadow public abstract @Nullable Entity getCameraEntity(); @@ -63,12 +60,6 @@ public abstract class MinecraftMixin { 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) private void onJoinWorld(ClientLevel level, CallbackInfo ci) { JoinWorldEvent event = Sputnik.EVENT_BUS.post(new JoinWorldEvent(level)); diff --git a/src/main/java/me/retucio/sputnik/mixin/mixins/network/ClientCommonPacketListenerImplMixin.java b/src/main/java/me/retucio/sputnik/mixin/mixins/network/ClientCommonPacketListenerImplMixin.java index f4718f1..cd7c748 100644 --- a/src/main/java/me/retucio/sputnik/mixin/mixins/network/ClientCommonPacketListenerImplMixin.java +++ b/src/main/java/me/retucio/sputnik/mixin/mixins/network/ClientCommonPacketListenerImplMixin.java @@ -46,7 +46,7 @@ public abstract class ClientCommonPacketListenerImplMixin { final Screen screen = cir.getReturnValue(); ((IConfirmScreen) screen).sputnik$setBypassAction(() -> { - minecraft.setScreen(((PackConfirmScreenAccessor) screen).getParentScreen()); + minecraft.gui.setScreen(((PackConfirmScreenAccessor) screen).getParentScreen()); if (serverData != null) { serverData.setResourcePackStatus(bypassPack.getStatus()); minecraft.getDownloadedPackSource().allowServerPacks(); diff --git a/src/main/java/me/retucio/sputnik/mixin/mixins/network/ClientPacketListenerMixin.java b/src/main/java/me/retucio/sputnik/mixin/mixins/network/ClientPacketListenerMixin.java index b8cd050..b22c7bd 100644 --- a/src/main/java/me/retucio/sputnik/mixin/mixins/network/ClientPacketListenerMixin.java +++ b/src/main/java/me/retucio/sputnik/mixin/mixins/network/ClientPacketListenerMixin.java @@ -48,7 +48,7 @@ public abstract class ClientPacketListenerMixin { ChatUtil.error(e.getMessage()); } - mc.gui.getChat().addRecentChat(content); + mc.gui.hud.getChat().addRecentChat(content); ci.cancel(); } diff --git a/src/main/java/me/retucio/sputnik/mixin/mixins/player/LocalPlayerMixin.java b/src/main/java/me/retucio/sputnik/mixin/mixins/player/LocalPlayerMixin.java index 6274d52..cf8b98b 100644 --- a/src/main/java/me/retucio/sputnik/mixin/mixins/player/LocalPlayerMixin.java +++ b/src/main/java/me/retucio/sputnik/mixin/mixins/player/LocalPlayerMixin.java @@ -12,7 +12,6 @@ import net.minecraft.world.entity.Entity; import net.minecraft.world.phys.EntityHitResult; import net.minecraft.world.phys.HitResult; import net.minecraft.world.phys.Vec3; -import org.objectweb.asm.Opcodes; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; @@ -28,7 +27,7 @@ public abstract class LocalPlayerMixin { 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) { if (ModuleManager.INSTANCE.getModuleByClass(PortalGUI.class).isEnabled()) return null; return original; diff --git a/src/main/java/me/retucio/sputnik/mixin/mixins/render/CameraMixin.java b/src/main/java/me/retucio/sputnik/mixin/mixins/render/CameraMixin.java index 3959538..ceedb60 100644 --- a/src/main/java/me/retucio/sputnik/mixin/mixins/render/CameraMixin.java +++ b/src/main/java/me/retucio/sputnik/mixin/mixins/render/CameraMixin.java @@ -1,5 +1,6 @@ package me.retucio.sputnik.mixin.mixins.render; +import com.llamalad7.mixinextras.injector.ModifyExpressionValue; import com.llamalad7.mixinextras.injector.ModifyReturnValue; import me.retucio.sputnik.Sputnik; import me.retucio.sputnik.event.render.GetFOVEvent; @@ -78,6 +79,13 @@ public abstract class CameraMixin { 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")) private void onUpdateSetPosArgs(Args args) { if (freecam.isEnabled()) { diff --git a/src/main/java/me/retucio/sputnik/mixin/mixins/render/GameRendererMixin.java b/src/main/java/me/retucio/sputnik/mixin/mixins/render/GameRendererMixin.java index afdf14c..57ac0c7 100644 --- a/src/main/java/me/retucio/sputnik/mixin/mixins/render/GameRendererMixin.java +++ b/src/main/java/me/retucio/sputnik/mixin/mixins/render/GameRendererMixin.java @@ -14,7 +14,6 @@ import net.minecraft.client.DeltaTracker; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.GameRenderer; import net.minecraft.client.renderer.ItemInHandRenderer; -import net.minecraft.client.renderer.RenderBuffers; import net.minecraft.client.renderer.state.level.CameraRenderState; import net.minecraft.client.resources.model.ModelManager; import org.joml.Matrix4fc; @@ -44,7 +43,7 @@ public abstract class GameRendererMixin { private Minecraft minecraft; @Inject(method = "", 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);; freecam = ModuleManager.INSTANCE.getModuleByClass(Freecam.class); noRender = ModuleManager.INSTANCE.getModuleByClass(NoRender.class); diff --git a/src/main/java/me/retucio/sputnik/mixin/mixins/render/ItemFeatureRendererMixin.java b/src/main/java/me/retucio/sputnik/mixin/mixins/render/ItemFeatureRendererMixin.java index ea2b8be..0b844b6 100644 --- a/src/main/java/me/retucio/sputnik/mixin/mixins/render/ItemFeatureRendererMixin.java +++ b/src/main/java/me/retucio/sputnik/mixin/mixins/render/ItemFeatureRendererMixin.java @@ -15,21 +15,14 @@ public abstract class ItemFeatureRendererMixin { // 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() { GlintPlus glintPlus = ModuleManager.INSTANCE.getModuleByClass(GlintPlus.class); if (glintPlus == null) return RenderTypes.glint(); return glintPlus.getGlint(); } - @Redirect(method = "getFoilRenderType", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/rendertype/RenderTypes;entityGlint()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;")) + @Redirect(method = "getFoilBuffer", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/rendertype/RenderTypes;glintTranslucent()Lnet/minecraft/client/renderer/rendertype/RenderType;")) private static RenderType redirectGlintTranslucent() { GlintPlus glintPlus = ModuleManager.INSTANCE.getModuleByClass(GlintPlus.class); if (glintPlus == null) return RenderTypes.glintTranslucent(); diff --git a/src/main/java/me/retucio/sputnik/mixin/mixins/render/ItemInHandRendererMixin.java b/src/main/java/me/retucio/sputnik/mixin/mixins/render/ItemInHandRendererMixin.java index d854985..9f461e8 100644 --- a/src/main/java/me/retucio/sputnik/mixin/mixins/render/ItemInHandRendererMixin.java +++ b/src/main/java/me/retucio/sputnik/mixin/mixins/render/ItemInHandRendererMixin.java @@ -49,12 +49,12 @@ public abstract class ItemInHandRendererMixin { 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) { 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) { EVENT_BUS.post(new RenderArmEvent(matrices, hand)); } diff --git a/src/main/java/me/retucio/sputnik/mixin/mixins/render/LevelRendererMixin.java b/src/main/java/me/retucio/sputnik/mixin/mixins/render/LevelRendererMixin.java index ab8d694..baa526b 100644 --- a/src/main/java/me/retucio/sputnik/mixin/mixins/render/LevelRendererMixin.java +++ b/src/main/java/me/retucio/sputnik/mixin/mixins/render/LevelRendererMixin.java @@ -12,8 +12,7 @@ import me.retucio.sputnik.module.ModuleManager; import me.retucio.sputnik.module.modules.camera.Freecam; import net.minecraft.client.DeltaTracker; import net.minecraft.client.renderer.LevelRenderer; -import net.minecraft.client.renderer.MultiBufferSource; -import net.minecraft.client.renderer.chunk.ChunkSectionsToRender; +import net.minecraft.client.renderer.SubmitNodeCollector; import net.minecraft.client.renderer.state.level.CameraRenderState; import net.minecraft.client.renderer.state.level.LevelRenderState; import net.minecraft.util.profiling.ProfilerFiller; @@ -31,14 +30,8 @@ import static me.retucio.sputnik.Sputnik.mc; @Mixin(LevelRenderer.class) public abstract class LevelRendererMixin { - // renderLevel()?? - @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 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) { + @Inject(method = "render", at = @At("RETURN")) + 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) { if (mc == null || mc.level == null) return; PoseStack matrices = new PoseStack(); @@ -54,8 +47,8 @@ public abstract class LevelRendererMixin { matrices.popPose(); } - @Inject(method = "renderBlockOutline", at = @At("HEAD"), cancellable = true) - private void noRenderBlockOutlinesFreecam(MultiBufferSource.BufferSource bufferSource, PoseStack poseStack, boolean onlyTranslucentBlocks, LevelRenderState levelRenderState, CallbackInfo ci) { + @Inject(method = "submitBlockOutline", at = @At("HEAD"), cancellable = true) + private void noRenderBlockOutlinesFreecam(PoseStack poseStack, SubmitNodeCollector collector, LevelRenderState levelRenderState, CallbackInfo ci) { Freecam freecam = ModuleManager.INSTANCE.getModuleByClass(Freecam.class); if (freecam.isEnabled() && !freecam.blockOutlines.getValue()) ci.cancel(); } @@ -68,13 +61,13 @@ public abstract class LevelRendererMixin { // } // 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) { - // SIX SEVEN!!! (me pegan en casa) - RenderBlockOutlineEvent event = EVENT_BUS.post(new RenderBlockOutlineEvent(args.get(6), args.get(7))); - if (event.getColor() != (int) args.get(6)) - args.set(6, event.getColor()); - if (event.getLineWidth() != (float) args.get(7)) - args.set(7, event.getLineWidth()); + // ahora cuatro cinco... (rip 67) + RenderBlockOutlineEvent event = EVENT_BUS.post(new RenderBlockOutlineEvent(args.get(4), args.get(5))); + if (event.getColor() != (int) args.get(4)) + args.set(4, event.getColor()); + if (event.getLineWidth() != (float) args.get(5)) + args.set(5, event.getLineWidth()); } } \ No newline at end of file diff --git a/src/main/java/me/retucio/sputnik/mixin/mixins/render/LightmapMixin.java b/src/main/java/me/retucio/sputnik/mixin/mixins/render/LightmapMixin.java index 859e4b7..2ba8cc9 100644 --- a/src/main/java/me/retucio/sputnik/mixin/mixins/render/LightmapMixin.java +++ b/src/main/java/me/retucio/sputnik/mixin/mixins/render/LightmapMixin.java @@ -31,7 +31,7 @@ public abstract class LightmapMixin { profiler.push("lightmap"); RenderSystem.getDevice().createCommandEncoder() - .clearColorTexture(texture, ARGB.color(255, 255, 255, 255)); + .clearColorTexture(texture, ARGB.vector4fFromARGB32(ARGB.color(255, 255, 255, 255))); profiler.pop(); ci.cancel(); diff --git a/src/main/java/me/retucio/sputnik/mixin/mixins/render/LivingEntityRendererMixin.java b/src/main/java/me/retucio/sputnik/mixin/mixins/render/LivingEntityRendererMixin.java index 7cd4653..a5971ef 100644 --- a/src/main/java/me/retucio/sputnik/mixin/mixins/render/LivingEntityRendererMixin.java +++ b/src/main/java/me/retucio/sputnik/mixin/mixins/render/LivingEntityRendererMixin.java @@ -9,6 +9,7 @@ import me.retucio.sputnik.module.modules.render.Nametags; import net.minecraft.client.renderer.entity.LivingEntityRenderer; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.EntityTypes; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.player.Player; import org.spongepowered.asm.mixin.Mixin; @@ -50,7 +51,7 @@ public abstract class LivingEntityRendererMixin { @ModifyReturnValue(method = "shouldShowName(Lnet/minecraft/world/entity/LivingEntity;D)Z", at = @At("RETURN")) private boolean shouldRenderPlayerNametag(boolean original, @Local(argsOnly = true) T livingEntity) { if (nametags.isEnabled() && livingEntity instanceof Player) - return nametags.entities.isEnabled(EntityType.PLAYER) && original; + return nametags.entities.isEnabled(EntityTypes.PLAYER) && original; return original; } diff --git a/src/main/java/me/retucio/sputnik/mixin/mixins/render/RenderBuffersMixin.java b/src/main/java/me/retucio/sputnik/mixin/mixins/render/RenderBuffersMixin.java index 24ab881..42a6b3e 100644 --- a/src/main/java/me/retucio/sputnik/mixin/mixins/render/RenderBuffersMixin.java +++ b/src/main/java/me/retucio/sputnik/mixin/mixins/render/RenderBuffersMixin.java @@ -1,25 +1,18 @@ package me.retucio.sputnik.mixin.mixins.render; -import com.mojang.blaze3d.vertex.ByteBufferBuilder; -import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap; -import me.retucio.sputnik.util.render.GlintRenderType; -import net.minecraft.client.renderer.MultiBufferSource; +import me.retucio.sputnik.util.render.SputnikBuffers; import net.minecraft.client.renderer.RenderBuffers; -import net.minecraft.client.renderer.rendertype.RenderType; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Redirect; - -import java.util.SequencedMap; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin(RenderBuffers.class) public abstract class RenderBuffersMixin { - @Redirect(method = "", 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)) - private MultiBufferSource.BufferSource injectGlintBuffers(SequencedMap fixedBuffers, ByteBufferBuilder sharedBuffer) { - if (fixedBuffers instanceof Object2ObjectLinkedOpenHashMap map) { - GlintRenderType.addGlintTypes(map); - } - return MultiBufferSource.immediateWithBuffers(fixedBuffers, sharedBuffer); + // devolvemos nuestros buffers al pool cuando el juego hace lo propio + @Inject(method = "endFrame", at = @At("TAIL")) + private void endSputnikFrame(CallbackInfo ci) { + SputnikBuffers.endFrame(); } -} \ No newline at end of file +} diff --git a/src/main/java/me/retucio/sputnik/mixin/mixins/render/ScreenEffectRendererMixin.java b/src/main/java/me/retucio/sputnik/mixin/mixins/render/ScreenEffectRendererMixin.java index 35953c3..417509f 100644 --- a/src/main/java/me/retucio/sputnik/mixin/mixins/render/ScreenEffectRendererMixin.java +++ b/src/main/java/me/retucio/sputnik/mixin/mixins/render/ScreenEffectRendererMixin.java @@ -4,8 +4,8 @@ import com.mojang.blaze3d.vertex.PoseStack; import me.retucio.sputnik.module.ModuleManager; import me.retucio.sputnik.module.modules.render.NoRender; import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.ScreenEffectRenderer; +import net.minecraft.client.renderer.SubmitNodeCollector; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; @@ -25,13 +25,13 @@ public abstract class ScreenEffectRendererMixin { noRender = ModuleManager.INSTANCE.getModuleByClass(NoRender.class); } - @Inject(method = "renderFire", at = @At("HEAD"), cancellable = true) - private static void noRenderFireOverlay(PoseStack matrices, MultiBufferSource bufferSource, TextureAtlasSprite sprite, CallbackInfo ci) { + @Inject(method = "submitFire", at = @At("HEAD"), cancellable = true) + private static void noRenderFireOverlay(PoseStack matrices, SubmitNodeCollector collector, TextureAtlasSprite sprite, CallbackInfo ci) { if (noRender.isEnabled() && !noRender.fireOverlay.getValue()) ci.cancel(); } - @Inject(method = "renderWater", at = @At("HEAD"), cancellable = true) - private static void noRenderUnderwaterOverlay(Minecraft minecraft, PoseStack matrices, MultiBufferSource bufferSource, CallbackInfo ci) { + @Inject(method = "submitWater", at = @At("HEAD"), cancellable = true) + private static void noRenderUnderwaterOverlay(Minecraft minecraft, PoseStack matrices, SubmitNodeCollector collector, CallbackInfo ci) { if (noRender.isEnabled() && !noRender.fluidOverlay.getValue()) ci.cancel(); } } \ No newline at end of file diff --git a/src/main/java/me/retucio/sputnik/mixin/mixins/render/WeatherEffectRendererMixin.java b/src/main/java/me/retucio/sputnik/mixin/mixins/render/WeatherEffectRendererMixin.java index a710618..1752626 100644 --- a/src/main/java/me/retucio/sputnik/mixin/mixins/render/WeatherEffectRendererMixin.java +++ b/src/main/java/me/retucio/sputnik/mixin/mixins/render/WeatherEffectRendererMixin.java @@ -2,11 +2,8 @@ package me.retucio.sputnik.mixin.mixins.render; import me.retucio.sputnik.module.ModuleManager; 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.state.level.WeatherRenderState; -import net.minecraft.server.level.ParticleStatus; import net.minecraft.world.phys.Vec3; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; @@ -26,11 +23,6 @@ public abstract class WeatherEffectRendererMixin { 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")) private void noRenderRainAndSnow(Vec3 cameraPos, WeatherRenderState renderState, CallbackInfo ci) { if (noRender.isEnabled()) { diff --git a/src/main/java/me/retucio/sputnik/mixin/mixins/screen/AbstractContainerScreenMixin.java b/src/main/java/me/retucio/sputnik/mixin/mixins/screen/AbstractContainerScreenMixin.java index 53fcf44..278c716 100644 --- a/src/main/java/me/retucio/sputnik/mixin/mixins/screen/AbstractContainerScreenMixin.java +++ b/src/main/java/me/retucio/sputnik/mixin/mixins/screen/AbstractContainerScreenMixin.java @@ -33,14 +33,14 @@ public abstract class AbstractContainerScreenMixin { int by = bgTop - bh - 5; 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); }).bounds(bx, by, bw, bh).build(); screen.addRenderableWidget(stealButton); } 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); }).bounds(bx + bw + gap, by, bw, bh).build(); screen.addRenderableWidget(dumpButton); diff --git a/src/main/java/me/retucio/sputnik/mixin/mixins/screen/DisconnectedScreenMixin.java b/src/main/java/me/retucio/sputnik/mixin/mixins/screen/DisconnectedScreenMixin.java index 135cda8..c633823 100644 --- a/src/main/java/me/retucio/sputnik/mixin/mixins/screen/DisconnectedScreenMixin.java +++ b/src/main/java/me/retucio/sputnik/mixin/mixins/screen/DisconnectedScreenMixin.java @@ -27,7 +27,7 @@ public abstract class DisconnectedScreenMixin { if (reconnect == null || !reconnect.isEnabled()) return; layout.addChild(Button.builder( - Component.literal("reconectarse"), + Component.translatable("sputnik.module.reconnect.button"), button -> reconnect.reconnect() ).build()); } diff --git a/src/main/java/me/retucio/sputnik/mixin/mixins/world/ClientLevelMixin.java b/src/main/java/me/retucio/sputnik/mixin/mixins/world/ClientLevelMixin.java index 9db4000..c4cd52a 100644 --- a/src/main/java/me/retucio/sputnik/mixin/mixins/world/ClientLevelMixin.java +++ b/src/main/java/me/retucio/sputnik/mixin/mixins/world/ClientLevelMixin.java @@ -2,6 +2,8 @@ package me.retucio.sputnik.mixin.mixins.world; import me.retucio.sputnik.event.network.AddEntityEvent; 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.world.entity.Entity; import org.jetbrains.annotations.Nullable; @@ -29,4 +31,11 @@ public abstract class ClientLevelMixin { Entity entity = getEntity(entityId); 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(); + } } diff --git a/src/main/java/me/retucio/sputnik/module/Category.java b/src/main/java/me/retucio/sputnik/module/Category.java index b847f45..f03c51a 100644 --- a/src/main/java/me/retucio/sputnik/module/Category.java +++ b/src/main/java/me/retucio/sputnik/module/Category.java @@ -1,5 +1,7 @@ package me.retucio.sputnik.module; +import me.retucio.sputnik.util.I18nUtil; + public enum Category { COMBAT("combate"), @@ -19,5 +21,12 @@ public enum Category { private final String 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; } + + public String getDisplayName() { + return I18nUtil.orElse("sputnik.category." + I18nUtil.slug(name), name); + } } diff --git a/src/main/java/me/retucio/sputnik/module/Module.java b/src/main/java/me/retucio/sputnik/module/Module.java index 11b84be..5ae817e 100644 --- a/src/main/java/me/retucio/sputnik/module/Module.java +++ b/src/main/java/me/retucio/sputnik/module/Module.java @@ -11,7 +11,9 @@ import me.retucio.sputnik.module.setting.settings.KeySetting; import me.retucio.sputnik.module.setting.Setting; import me.retucio.sputnik.ui.hud.HudRenderer; import me.retucio.sputnik.util.ChatUtil; +import me.retucio.sputnik.util.I18nUtil; import net.minecraft.client.Minecraft; +import net.minecraft.network.chat.Component; import org.lwjgl.glfw.GLFW; import java.lang.reflect.Method; @@ -33,34 +35,36 @@ public class Module { // 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( "tecla", "tecla asignada al módulo, ESC para desactivar", 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 - protected EnumSetting keyMode = new EnumSetting<>( + protected EnumSetting keyMode = new EnumSetting( "modo de tecla", "cómo interpretar la tecla configurada", KeyMode.class, KeyMode.TOGGLE - ); + ).translationKey("sputnik.setting.common.keymode"); protected BooleanSetting notify = new BooleanSetting( "notificar", "notificar al activar / desactivar", true - ); + ).translationKey("sputnik.setting.common.notify"); - protected EnumSetting notifyMode = new EnumSetting<>( + protected EnumSetting notifyMode = new EnumSetting( "modo de notificación", "cómo notificar cuando se activa / desactiva", NotifyMode.class, NotifyMode.WIDGET - ); + ).translationKey("sputnik.setting.common.notifymode"); protected final List sgs = new ArrayList<>(); - protected final SettingGroup sgModule = addSg(new SettingGroup("módulo", false)); - protected final SettingGroup sgGeneral = addSg(new SettingGroup("general", true)); + protected final SettingGroup sgModule = addSg(new SettingGroup("módulo", false, "sputnik.group.common.module")); + protected final SettingGroup sgGeneral = addSg(new SettingGroup("general", true, "sputnik.group.common.general")); protected static final Minecraft mc = Minecraft.getInstance(); @@ -79,8 +83,12 @@ public class Module { this.bind.setDefaultValue(key); // 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 - .get(this.getName() + ":" + bind.getName()) == null) + .get(this.getName() + ":" + bind.getTrueName()) == null) this.bind.setValue(key); } @@ -101,9 +109,10 @@ public class Module { return sgs; } + // por nombre interno, no por el traducido (igual que SettingGroup#getSetting) public SettingGroup getSg(String name) { for (SettingGroup sg : sgs) { - if (sg.getName().equals(name)) { + if (sg.getTrueName().equals(name)) { return sg; } } @@ -134,10 +143,7 @@ public class Module { } public void onEnable() { - if (notify.getValue()) { - if (notifyMode.is(NotifyMode.CHAT)) ChatUtil.info(getName() + " fue activado"); - else HudRenderer.INSTANCE.pushNotification(getName() + " fue activado", getName() + " fue activado."); - } + notifyToggle(true); for (Method method : getClass().getDeclaredMethods()) { if (method.isAnnotationPresent(EventListener.class)) { Sputnik.EVENT_BUS.subscribe(this); @@ -147,13 +153,23 @@ public class Module { } public void onDisable() { - if (notifyMode.is(NotifyMode.CHAT)) ChatUtil.info(getName() + " fue desactivado"); - else HudRenderer.INSTANCE.pushNotification(getName() + " fue desactivado", getName() + " fue desactivado."); + notifyToggle(false); if (Sputnik.EVENT_BUS.isSubscribed(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) public void onTick() {} @@ -161,6 +177,8 @@ public class Module { // 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() { return name; } @@ -168,6 +186,19 @@ public class Module { 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() { return description; } diff --git a/src/main/java/me/retucio/sputnik/module/ModuleManager.java b/src/main/java/me/retucio/sputnik/module/ModuleManager.java index 744d5db..6d27f3f 100644 --- a/src/main/java/me/retucio/sputnik/module/ModuleManager.java +++ b/src/main/java/me/retucio/sputnik/module/ModuleManager.java @@ -48,7 +48,7 @@ public class ModuleManager { addRender(); 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 for (Module module : getEnabledModules()) { @@ -205,9 +205,20 @@ public class ModuleManager { 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) { 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 null; } diff --git a/src/main/java/me/retucio/sputnik/module/modules/camera/Freecam.java b/src/main/java/me/retucio/sputnik/module/modules/camera/Freecam.java index 9bfcea0..ea3c33c 100644 --- a/src/main/java/me/retucio/sputnik/module/modules/camera/Freecam.java +++ b/src/main/java/me/retucio/sputnik/module/modules/camera/Freecam.java @@ -25,6 +25,7 @@ import me.retucio.sputnik.util.MiscUtil; import net.minecraft.client.CameraType; import net.minecraft.client.input.MouseButtonEvent; import net.minecraft.client.input.MouseButtonInfo; +import net.minecraft.network.chat.Component; import net.minecraft.network.protocol.Packet; import net.minecraft.network.protocol.game.*; import net.minecraft.util.Mth; @@ -150,8 +151,8 @@ public class Freecam extends Module { speed = speedSetting.getValue(); - MiscUtil.copyVector(pos, mc.gameRenderer.getMainCamera().position()); - MiscUtil.copyVector(prevPos, mc.gameRenderer.getMainCamera().position()); + MiscUtil.copyVector(pos, mc.gameRenderer.mainCamera().position()); + MiscUtil.copyVector(prevPos, mc.gameRenderer.mainCamera().position()); if (mc.options.getCameraType() == CameraType.THIRD_PERSON_FRONT) { yaw += 180; @@ -171,14 +172,20 @@ public class Freecam extends Module { down = KeyUtil.isKeyDown(mc.options.keyShift); unpress(); - if (reloadChunks.getValue()) mc.levelRenderer.allChanged(); + if (reloadChunks.getValue()) invalidateChunks(); 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 public void onDisable() { - if (reloadChunks.getValue()) mc.execute(mc.levelRenderer::allChanged); + if (reloadChunks.getValue()) mc.execute(Freecam::invalidateChunks); mc.options.setCameraType(perspective); crouching = false; @@ -265,7 +272,7 @@ public class Freecam extends Module { @EventListener private void onKey(KeyEvent event) { 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); @@ -298,7 +305,7 @@ public class Freecam extends Module { @EventListener 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 (mc.screen != null) return; + if (mc.gui.screen() != null) return; MouseButtonEvent click = new MouseButtonEvent(0, 0, new MouseButtonInfo(event.getButton(), 0)); @@ -330,7 +337,7 @@ public class Freecam extends Module { @EventListener 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); if (speed < 0.1) speed = 0.1; event.cancel(); @@ -356,7 +363,7 @@ public class Freecam extends Module { toggle(); } else if (event.getPacket() instanceof ClientboundSetHealthPacket packet) { 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(); } } diff --git a/src/main/java/me/retucio/sputnik/module/modules/camera/PerspectivePlus.java b/src/main/java/me/retucio/sputnik/module/modules/camera/PerspectivePlus.java index 5198403..e2dbc94 100644 --- a/src/main/java/me/retucio/sputnik/module/modules/camera/PerspectivePlus.java +++ b/src/main/java/me/retucio/sputnik/module/modules/camera/PerspectivePlus.java @@ -60,7 +60,7 @@ public class PerspectivePlus extends Module { @EventListener private void onMouseScroll(MouseScrollEvent event) { 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()) { distance -= event.getVertical() / 4 * (scrollSens.getValue() * distance); diff --git a/src/main/java/me/retucio/sputnik/module/modules/camera/Zoom.java b/src/main/java/me/retucio/sputnik/module/modules/camera/Zoom.java index 41efda4..cdd2832 100644 --- a/src/main/java/me/retucio/sputnik/module/modules/camera/Zoom.java +++ b/src/main/java/me/retucio/sputnik/module/modules/camera/Zoom.java @@ -58,13 +58,24 @@ public class Zoom extends Module { 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 public void onEnable() { prevSmoothCam = mc.options.smoothCamera; prevMouseSens = mc.options.sensitivity().get(); prevFov = mc.options.fov().get(); - prevHUD = mc.options.hideGui; - mc.options.hideGui = !showHUD.getValue(); + prevHUD = mc.gui.hud.isHidden(); + setHudHidden(!showHUD.getValue()); value = defaultZoom.getValue(); @@ -75,9 +86,9 @@ public class Zoom extends Module { public void onDisable() { mc.options.smoothCamera = prevSmoothCam; mc.options.sensitivity().set(prevMouseSens); - mc.options.hideGui = prevHUD; + setHudHidden(prevHUD); - mc.levelRenderer.needsUpdate(); + needsUpdate(); super.onDisable(); } @@ -105,7 +116,7 @@ public class Zoom extends Module { private void onGetFov(GetFOVEvent event) { event.setFov((float) (event.getFov() / value)); - if (prevFov != event.getFov()) mc.levelRenderer.needsUpdate(); + if (prevFov != event.getFov()) needsUpdate(); prevFov = event.getFov(); } } diff --git a/src/main/java/me/retucio/sputnik/module/modules/client/DiscordRPC.java b/src/main/java/me/retucio/sputnik/module/modules/client/DiscordRPC.java index bd4976e..ff7b417 100644 --- a/src/main/java/me/retucio/sputnik/module/modules/client/DiscordRPC.java +++ b/src/main/java/me/retucio/sputnik/module/modules/client/DiscordRPC.java @@ -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.StringSetting; import me.retucio.sputnik.util.ChatUtil; +import net.minecraft.network.chat.Component; /** @@ -111,13 +112,13 @@ public class DiscordRPC extends Module { @Override public void disconnected(ErrorCode errorCode, String message) { - ChatUtil.warn("desconectado: " + errorCode + " - " + message); + ChatUtil.warn(Component.translatable("sputnik.module.discordrpc.disconnected", errorCode, message)); toggle(); } @Override public void errored(ErrorCode errorCode, String message) { - ChatUtil.error("error: " + errorCode + " - " + message); + ChatUtil.error(Component.translatable("sputnik.module.discordrpc.error", errorCode, message)); toggle(); } }; @@ -142,7 +143,7 @@ public class DiscordRPC extends Module { public void onEnable() { String token = appId.getValue(); if (token == null || token.trim().isEmpty()) { - ChatUtil.error("configura el token del bot primero"); + ChatUtil.error(Component.translatable("sputnik.module.discordrpc.notoken")); toggle(); return; } @@ -151,10 +152,10 @@ public class DiscordRPC extends Module { rpc.init(token, handler, false); initialized = true; } catch (UnsupportedOsType e) { - ChatUtil.error("sistema operativo no soportado"); + ChatUtil.error(Component.translatable("sputnik.module.discordrpc.unsupportedos")); toggle(); } catch (Exception e) { - ChatUtil.error("error al inicializar rpc: " + e.getMessage()); + ChatUtil.error(Component.translatable("sputnik.module.discordrpc.initerror", e.getMessage())); toggle(); } @@ -191,7 +192,7 @@ public class DiscordRPC extends Module { try { rpc.updatePresence(getPresence()); } 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 { timestamp = Long.parseLong(startTimestamp.getValue()); } 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(); } } diff --git a/src/main/java/me/retucio/sputnik/module/modules/client/Friends.java b/src/main/java/me/retucio/sputnik/module/modules/client/Friends.java index c96b24a..2c06064 100644 --- a/src/main/java/me/retucio/sputnik/module/modules/client/Friends.java +++ b/src/main/java/me/retucio/sputnik/module/modules/client/Friends.java @@ -9,6 +9,7 @@ import me.retucio.sputnik.module.Module; import me.retucio.sputnik.module.setting.settings.BooleanSetting; import me.retucio.sputnik.util.ChatUtil; import net.minecraft.ChatFormatting; +import net.minecraft.network.chat.Component; import net.minecraft.world.entity.Entity; import org.lwjgl.glfw.GLFW; @@ -42,12 +43,16 @@ public class Friends extends Module { if (FriendManager.INSTANCE.isFriend(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 { switch (FriendManager.INSTANCE.add(target)) { - case SUCCESS -> ChatUtil.info(ChatFormatting.GREEN + target.getName().getString() + ChatFormatting.RESET + " agregado como amigo :)"); - case ALREADY_BEFRIENDED -> ChatUtil.warn(ChatFormatting.GREEN + target.getName().getString() + ChatFormatting.RESET + " ya es tu amigo"); - case NOT_PLAYER -> ChatUtil.error("no se pudo añadir a " + ChatFormatting.GREEN + target.getName().getString() + ChatFormatting.RESET + " como amigo"); + case SUCCESS -> ChatUtil.info(Component.translatable("sputnik.commands.friend.added", + ChatFormatting.GREEN + target.getName().getString() + ChatFormatting.RESET)); + 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)); } } } diff --git a/src/main/java/me/retucio/sputnik/module/modules/combat/ChestplateSwitch.java b/src/main/java/me/retucio/sputnik/module/modules/combat/ChestplateSwitch.java index 1adb4c2..62e2ffd 100644 --- a/src/main/java/me/retucio/sputnik/module/modules/combat/ChestplateSwitch.java +++ b/src/main/java/me/retucio/sputnik/module/modules/combat/ChestplateSwitch.java @@ -7,6 +7,7 @@ import me.retucio.sputnik.module.Module; import me.retucio.sputnik.module.setting.settings.BooleanSetting; import me.retucio.sputnik.util.ChatUtil; 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.ServerboundInteractPacket; 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)) { int slot = InventoryUtil.findSlot(this::isChestplate); if (!Inventory.isHotbarSlot(slot)) { - ChatUtil.error("no se encontró una pechera en la hotbar"); + ChatUtil.error(Component.translatable("sputnik.module.chestplateswitch.nochestplate")); return; } diff --git a/src/main/java/me/retucio/sputnik/module/modules/combat/CrystalAura.java b/src/main/java/me/retucio/sputnik/module/modules/combat/CrystalAura.java index a853ec4..cb745c7 100644 --- a/src/main/java/me/retucio/sputnik/module/modules/combat/CrystalAura.java +++ b/src/main/java/me/retucio/sputnik/module/modules/combat/CrystalAura.java @@ -19,6 +19,7 @@ import net.minecraft.network.protocol.game.ServerboundUseItemOnPacket; import net.minecraft.world.InteractionHand; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.EntityTypes; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.boss.enderdragon.EndCrystal; import net.minecraft.world.entity.player.Inventory; @@ -47,7 +48,7 @@ public class CrystalAura extends Module { private final ListSetting> entities = sgGeneral.add(new ListSetting<>( "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( @@ -205,7 +206,7 @@ public class CrystalAura extends Module { } } // 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); if (dist < bestObbyPlaceDist[0]) { bestObbyPlaceDist[0] = dist; @@ -253,7 +254,7 @@ public class CrystalAura extends Module { 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)); } @@ -272,7 +273,7 @@ public class CrystalAura extends Module { BlockPos supportPos = pos.below(); 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)); } diff --git a/src/main/java/me/retucio/sputnik/module/modules/combat/MaceKill.java b/src/main/java/me/retucio/sputnik/module/modules/combat/MaceKill.java index ac1b679..a4db6dc 100644 --- a/src/main/java/me/retucio/sputnik/module/modules/combat/MaceKill.java +++ b/src/main/java/me/retucio/sputnik/module/modules/combat/MaceKill.java @@ -8,6 +8,7 @@ import me.retucio.sputnik.module.setting.settings.BooleanSetting; import me.retucio.sputnik.module.setting.settings.NumberSetting; import me.retucio.sputnik.util.ChatUtil; import net.minecraft.core.BlockPos; +import net.minecraft.network.chat.Component; import net.minecraft.network.protocol.game.ServerboundAttackPacket; import net.minecraft.network.protocol.game.ServerboundInteractPacket; import net.minecraft.network.protocol.game.ServerboundMovePlayerPacket; @@ -154,7 +155,7 @@ public class MaceKill extends Module { } } } catch (Exception e) { - ChatUtil.error("upsi: " + e.getMessage()); + ChatUtil.error(Component.translatable("sputnik.module.macekill.oops", e.getMessage())); } } } diff --git a/src/main/java/me/retucio/sputnik/module/modules/combat/ProjectileTrajectories.java b/src/main/java/me/retucio/sputnik/module/modules/combat/ProjectileTrajectories.java index 4e35620..e6854be 100644 --- a/src/main/java/me/retucio/sputnik/module/modules/combat/ProjectileTrajectories.java +++ b/src/main/java/me/retucio/sputnik/module/modules/combat/ProjectileTrajectories.java @@ -183,7 +183,7 @@ public class ProjectileTrajectories extends Module { } 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); } @@ -204,7 +204,7 @@ public class ProjectileTrajectories extends Module { private void renderTrajectory(PoseStack matrices, List trajectoryPoints, Vec3 handToEyeDelta, boolean hasHit) { if (trajectoryPoints.isEmpty()) return; - Vec3 cameraPos = mc.gameRenderer.getMainCamera().position(); + Vec3 cameraPos = mc.gameRenderer.mainCamera().position(); matrices.pushPose(); matrices.translate(-cameraPos.x, -cameraPos.y, -cameraPos.z); diff --git a/src/main/java/me/retucio/sputnik/module/modules/inventory/Burglar.java b/src/main/java/me/retucio/sputnik/module/modules/inventory/Burglar.java index 31159f4..757a7c8 100644 --- a/src/main/java/me/retucio/sputnik/module/modules/inventory/Burglar.java +++ b/src/main/java/me/retucio/sputnik/module/modules/inventory/Burglar.java @@ -68,7 +68,7 @@ public class Burglar extends Module { @EventListener private void onKey(KeyEvent event) { 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() == dumpKey.getValue()) dump(container); } diff --git a/src/main/java/me/retucio/sputnik/module/modules/inventory/InventoryPlus.java b/src/main/java/me/retucio/sputnik/module/modules/inventory/InventoryPlus.java index 981ab19..d286c03 100644 --- a/src/main/java/me/retucio/sputnik/module/modules/inventory/InventoryPlus.java +++ b/src/main/java/me/retucio/sputnik/module/modules/inventory/InventoryPlus.java @@ -44,7 +44,7 @@ public class InventoryPlus extends Module { } 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(); if (focusedSlot == null) return; diff --git a/src/main/java/me/retucio/sputnik/module/modules/inventory/ShulkerPeek.java b/src/main/java/me/retucio/sputnik/module/modules/inventory/ShulkerPeek.java index 1afb885..7013704 100644 --- a/src/main/java/me/retucio/sputnik/module/modules/inventory/ShulkerPeek.java +++ b/src/main/java/me/retucio/sputnik/module/modules/inventory/ShulkerPeek.java @@ -14,7 +14,9 @@ import me.retucio.sputnik.util.InventoryUtil; import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; import net.minecraft.core.component.DataComponents; +import net.minecraft.network.chat.Component; import net.minecraft.world.item.BlockItem; +import net.minecraft.world.item.DyeColor; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; @@ -40,22 +42,22 @@ public class ShulkerPeek extends Module { // colores y tal (https://github.com/kgriff0n/shulker-preview) SHULKER_COLORS.put(Items.SHULKER_BOX, Colors.LAVENDER); - SHULKER_COLORS.put(Items.WHITE_SHULKER_BOX, Colors.WHITE); - SHULKER_COLORS.put(Items.LIGHT_GRAY_SHULKER_BOX, Colors.SILVER); - SHULKER_COLORS.put(Items.GRAY_SHULKER_BOX, Colors.GRAY); - SHULKER_COLORS.put(Items.BLACK_SHULKER_BOX, Colors.BLACK); - SHULKER_COLORS.put(Items.BROWN_SHULKER_BOX, Colors.BROWN); - SHULKER_COLORS.put(Items.RED_SHULKER_BOX, Colors.RED); - SHULKER_COLORS.put(Items.ORANGE_SHULKER_BOX, Colors.ORANGE); - SHULKER_COLORS.put(Items.YELLOW_SHULKER_BOX, Colors.YELLOW); - SHULKER_COLORS.put(Items.LIME_SHULKER_BOX, Colors.LIME); - SHULKER_COLORS.put(Items.GREEN_SHULKER_BOX, Colors.GREEN); - SHULKER_COLORS.put(Items.CYAN_SHULKER_BOX, Colors.CYAN); - SHULKER_COLORS.put(Items.LIGHT_BLUE_SHULKER_BOX, Colors.CELESTE); - SHULKER_COLORS.put(Items.BLUE_SHULKER_BOX, Colors.BLUE); - SHULKER_COLORS.put(Items.PURPLE_SHULKER_BOX, Colors.PURPLE); - SHULKER_COLORS.put(Items.MAGENTA_SHULKER_BOX, Colors.MAGENTA); - SHULKER_COLORS.put(Items.PINK_SHULKER_BOX, Colors.PINK); + SHULKER_COLORS.put(Items.DYED_SHULKER_BOX.pick(DyeColor.WHITE), Colors.WHITE); + SHULKER_COLORS.put(Items.DYED_SHULKER_BOX.pick(DyeColor.LIGHT_GRAY), Colors.SILVER); + SHULKER_COLORS.put(Items.DYED_SHULKER_BOX.pick(DyeColor.GRAY), Colors.GRAY); + SHULKER_COLORS.put(Items.DYED_SHULKER_BOX.pick(DyeColor.BLACK), Colors.BLACK); + SHULKER_COLORS.put(Items.DYED_SHULKER_BOX.pick(DyeColor.BROWN), Colors.BROWN); + SHULKER_COLORS.put(Items.DYED_SHULKER_BOX.pick(DyeColor.RED), Colors.RED); + SHULKER_COLORS.put(Items.DYED_SHULKER_BOX.pick(DyeColor.ORANGE), Colors.ORANGE); + SHULKER_COLORS.put(Items.DYED_SHULKER_BOX.pick(DyeColor.YELLOW), Colors.YELLOW); + SHULKER_COLORS.put(Items.DYED_SHULKER_BOX.pick(DyeColor.LIME), Colors.LIME); + SHULKER_COLORS.put(Items.DYED_SHULKER_BOX.pick(DyeColor.GREEN), Colors.GREEN); + SHULKER_COLORS.put(Items.DYED_SHULKER_BOX.pick(DyeColor.CYAN), Colors.CYAN); + SHULKER_COLORS.put(Items.DYED_SHULKER_BOX.pick(DyeColor.LIGHT_BLUE), Colors.CELESTE); + SHULKER_COLORS.put(Items.DYED_SHULKER_BOX.pick(DyeColor.BLUE), Colors.BLUE); + SHULKER_COLORS.put(Items.DYED_SHULKER_BOX.pick(DyeColor.PURPLE), Colors.PURPLE); + SHULKER_COLORS.put(Items.DYED_SHULKER_BOX.pick(DyeColor.MAGENTA), Colors.MAGENTA); + SHULKER_COLORS.put(Items.DYED_SHULKER_BOX.pick(DyeColor.PINK), Colors.PINK); } @EventListener @@ -69,7 +71,7 @@ public class ShulkerPeek extends Module { } 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) openPreviewScreen(); } else openPreviewScreen(); @@ -77,7 +79,7 @@ public class ShulkerPeek extends Module { } if (event.getAction() == GLFW.GLFW_RELEASE) { - if (mc.screen instanceof PreviewScreen preview) + if (mc.gui.screen() instanceof PreviewScreen preview) preview.onClose(); } } @@ -85,25 +87,25 @@ public class ShulkerPeek extends Module { private void openPreviewScreen() { ItemStack stack; - if (mc.screen instanceof PreviewScreen previewScreen) { + if (mc.gui.screen() instanceof PreviewScreen previewScreen) { int focusedSlot = previewScreen.getFocusedSlot(); if (focusedSlot == -1) return; 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(); } else return; if (stack.getItem() == Items.ENDER_CHEST) { if (InventoryUtil.getEchestInv() == null) { - ChatUtil.warn("abre un enderchest primero"); + ChatUtil.warn(Component.translatable("sputnik.module.shulkerpeek.openechest")); return; } - mc.setScreen(new PreviewScreen(InventoryUtil.getEchestInv(), mc.screen)); + mc.gui.setScreen(new PreviewScreen(InventoryUtil.getEchestInv(), mc.gui.screen())); 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) { diff --git a/src/main/java/me/retucio/sputnik/module/modules/inventory/UIMove.java b/src/main/java/me/retucio/sputnik/module/modules/inventory/UIMove.java index 88a6a76..17d10cd 100644 --- a/src/main/java/me/retucio/sputnik/module/modules/inventory/UIMove.java +++ b/src/main/java/me/retucio/sputnik/module/modules/inventory/UIMove.java @@ -60,13 +60,13 @@ public class UIMove extends Module { @Override public void onTick() { - if (mc.player == null || mc.screen == null) return; + if (mc.player == null || mc.gui.screen() == null) return; MenuType handler = null; - if (mc.screen == ClickGui.INSTANCE) + if (mc.gui.screen() == ClickGui.INSTANCE) handler = clickGuiHandlerType; - if (mc.screen instanceof AbstractContainerScreen screen) { + if (mc.gui.screen() instanceof AbstractContainerScreen screen) { try { handler = screen.getMenu().getType(); } catch (UnsupportedOperationException e) { diff --git a/src/main/java/me/retucio/sputnik/module/modules/misc/AnvilFont.java b/src/main/java/me/retucio/sputnik/module/modules/misc/AnvilFont.java index 017df40..6671415 100644 --- a/src/main/java/me/retucio/sputnik/module/modules/misc/AnvilFont.java +++ b/src/main/java/me/retucio/sputnik/module/modules/misc/AnvilFont.java @@ -74,10 +74,10 @@ public class AnvilFont extends Module { @Override public void onTick() { - if (mc.screen == null) return; + if (mc.gui.screen() == null) return; - if (mc.screen instanceof AnvilScreen) { - EditBox nameField = ((AnvilScreenAccessor) mc.screen).getNameField(); + if (mc.gui.screen() instanceof AnvilScreen) { + EditBox nameField = ((AnvilScreenAccessor) mc.gui.screen()).getNameField(); if (fontMode.getValue() != FontMode.NORMAL) text = fonts.get(fontMode.getIndex()).replace(nameField.getValue()); @@ -87,7 +87,7 @@ public class AnvilFont extends Module { if (!text.equals(nameField.getValue())) nameField.setValue(text); - ((AnvilScreenAccessor) mc.screen).setNameField(nameField); + ((AnvilScreenAccessor) mc.gui.screen()).setNameField(nameField); } } diff --git a/src/main/java/me/retucio/sputnik/module/modules/misc/BookBot.java b/src/main/java/me/retucio/sputnik/module/modules/misc/BookBot.java index 5a44e0c..b481bef 100644 --- a/src/main/java/me/retucio/sputnik/module/modules/misc/BookBot.java +++ b/src/main/java/me/retucio/sputnik/module/modules/misc/BookBot.java @@ -107,7 +107,7 @@ public class BookBot extends Module { ItemStack book = InventoryUtil.findStack(bookPredicate); if (book == null) { - ChatUtil.warn("no se encontró ningún libro"); + ChatUtil.warn(Component.translatable("sputnik.module.bookbot.nobook")); toggle(); return; } @@ -193,7 +193,7 @@ public class BookBot extends Module { } if (bookCount > 0) { - ChatUtil.info("creado libro n. " + bookCount); + ChatUtil.info(Component.translatable("sputnik.module.bookbot.created", bookCount)); } createBook(pages, filteredPages); diff --git a/src/main/java/me/retucio/sputnik/module/modules/misc/ChatPlus.java b/src/main/java/me/retucio/sputnik/module/modules/misc/ChatPlus.java index 1a794f9..238672c 100644 --- a/src/main/java/me/retucio/sputnik/module/modules/misc/ChatPlus.java +++ b/src/main/java/me/retucio/sputnik/module/modules/misc/ChatPlus.java @@ -123,7 +123,7 @@ public class ChatPlus extends Module { private void onSendMessage(SendMessageEvent event) { // evitar mandar coordenadas por el chat 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()))); event.cancel(); @@ -200,10 +200,11 @@ public class ChatPlus extends Module { @SuppressWarnings("DataFlowIssue") private MutableComponent getSendButton(String message) { // 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 hintMsg = Component.literal("enviar de todos modos:"); + MutableComponent hintMsg = Component.translatable("sputnik.module.chatplus.sendanyway.hint"); hintMsg.setStyle(hintBaseText.getStyle().applyFormat(ChatFormatting.GRAY)); hintBaseText.append(hintMsg); diff --git a/src/main/java/me/retucio/sputnik/module/modules/misc/ScreenshotPlus.java b/src/main/java/me/retucio/sputnik/module/modules/misc/ScreenshotPlus.java index aac6d7e..62481b9 100644 --- a/src/main/java/me/retucio/sputnik/module/modules/misc/ScreenshotPlus.java +++ b/src/main/java/me/retucio/sputnik/module/modules/misc/ScreenshotPlus.java @@ -52,7 +52,8 @@ public class ScreenshotPlus extends Module { } 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 (copyButton.getValue()) baseText.append(getCopyButton().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); Toolkit.getDefaultToolkit().getSystemClipboard().setContents(trans, null); - ChatUtil.info("captura copiada al portapapeles"); + ChatUtil.info(Component.translatable("sputnik.module.screenshot.copied")); } catch (Exception e) { - ChatUtil.error("no se pudo copiar la captura al portapapeles"); + ChatUtil.error(Component.translatable("sputnik.module.screenshot.copyfailed")); e.printStackTrace(); } } @@ -85,7 +86,7 @@ public class ScreenshotPlus extends Module { public void saveScreenshot(NativeImage image) throws IOException { image.writeToFile(screenshotFile); - ChatUtil.info(Component.literal("captura guardada como: ").append( + ChatUtil.info(Component.translatable("sputnik.module.screenshot.savedas").append( Component.literal(screenshotFile.getName()) .withStyle(ChatFormatting.UNDERLINE) .withStyle(style -> style.withClickEvent(new ClickEvent.OpenFile(screenshotFile.getAbsoluteFile()))) @@ -129,7 +130,7 @@ public class ScreenshotPlus extends Module { @SuppressWarnings("DataFlowIssue") private MutableComponent getSaveButton() { - MutableComponent button = Component.literal("[GUARDAR]"); + MutableComponent button = Component.translatable("sputnik.module.screenshot.button.save"); MutableComponent hintBaseText = Component.literal(""); MutableComponent hintMsg = Component.literal(ScreenshotActions.SAVE.toString()); @@ -146,7 +147,7 @@ public class ScreenshotPlus extends Module { @SuppressWarnings("DataFlowIssue") private MutableComponent getCopyButton() { - MutableComponent button = Component.literal("[COPIAR]"); + MutableComponent button = Component.translatable("sputnik.module.screenshot.button.copy"); MutableComponent hintBaseText = Component.literal(""); MutableComponent hintMsg = Component.literal(ScreenshotActions.COPY.toString()); @@ -162,10 +163,10 @@ public class ScreenshotPlus extends Module { } private MutableComponent getOpenButton() { - MutableComponent button = Component.literal("[ABRIR]"); + MutableComponent button = Component.translatable("sputnik.module.screenshot.button.open"); 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)); hintBaseText.append(hintMsg); @@ -179,7 +180,7 @@ public class ScreenshotPlus extends Module { @SuppressWarnings("DataFlowIssue") private MutableComponent getDiscardButton() { - MutableComponent button = Component.literal("[DESCARTAR]"); + MutableComponent button = Component.translatable("sputnik.module.screenshot.button.discard"); MutableComponent hintBaseText = Component.literal(""); MutableComponent hintMsg = Component.literal(ScreenshotActions.NONE.toString()); diff --git a/src/main/java/me/retucio/sputnik/module/modules/network/BungeecordSpoofer.java b/src/main/java/me/retucio/sputnik/module/modules/network/BungeecordSpoofer.java index fec3698..7eb27f3 100644 --- a/src/main/java/me/retucio/sputnik/module/modules/network/BungeecordSpoofer.java +++ b/src/main/java/me/retucio/sputnik/module/modules/network/BungeecordSpoofer.java @@ -4,6 +4,7 @@ import me.retucio.sputnik.module.Category; import me.retucio.sputnik.module.Module; import me.retucio.sputnik.module.setting.settings.StringSetting; import me.retucio.sputnik.util.ChatUtil; +import net.minecraft.network.chat.Component; public class BungeecordSpoofer extends Module { @@ -17,7 +18,7 @@ public class BungeecordSpoofer extends Module { address.onUpdate(text -> { if (!text.matches("^[0-9a-f\\\\.:]{0,45}$")) { address.setValue(address.getDefaultValue()); - ChatUtil.error("dirección IP inválida"); + ChatUtil.error(Component.translatable("sputnik.module.bungeespoofer.invalidip")); } }); } diff --git a/src/main/java/me/retucio/sputnik/module/modules/network/PacketDelay.java b/src/main/java/me/retucio/sputnik/module/modules/network/PacketDelay.java index 6c4b7d0..fde9045 100644 --- a/src/main/java/me/retucio/sputnik/module/modules/network/PacketDelay.java +++ b/src/main/java/me/retucio/sputnik/module/modules/network/PacketDelay.java @@ -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.NumberSetting; import me.retucio.sputnik.util.ChatUtil; +import me.retucio.sputnik.util.MiscUtil; import me.retucio.sputnik.util.NetworkUtil; import net.minecraft.network.Connection; import net.minecraft.network.PacketListener; +import net.minecraft.network.chat.Component; import net.minecraft.network.protocol.Packet; import net.minecraft.network.protocol.common.ClientboundKeepAlivePacket; import net.minecraft.network.protocol.common.ServerboundKeepAlivePacket; @@ -38,8 +40,8 @@ public class PacketDelay extends Module { @Override public void onEnable() { - if (mc.isSingleplayer()) { - ChatUtil.error("delay de paquetes no funciona en un solo jugador"); + if (MiscUtil.isSingleplayer()) { + ChatUtil.error(Component.translatable("sputnik.module.packetdelay.singleplayer")); toggle(); return; } @@ -118,7 +120,11 @@ public class PacketDelay extends Module { @EventListener 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(); } diff --git a/src/main/java/me/retucio/sputnik/module/modules/network/PacketMine.java b/src/main/java/me/retucio/sputnik/module/modules/network/PacketMine.java index 42824b7..bc47e73 100644 --- a/src/main/java/me/retucio/sputnik/module/modules/network/PacketMine.java +++ b/src/main/java/me/retucio/sputnik/module/modules/network/PacketMine.java @@ -15,6 +15,7 @@ import me.retucio.sputnik.util.EntityUtil; import me.retucio.sputnik.util.render.RenderUtil; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; +import net.minecraft.network.chat.Component; import net.minecraft.network.protocol.game.ServerboundPlayerActionPacket; import net.minecraft.world.item.ItemStack; import net.minecraft.world.phys.Vec3; @@ -53,8 +54,10 @@ public class PacketMine extends Module { 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( - "delay", + "delay ", "delay entre selecciones de bloques", 5, 0, @@ -270,7 +273,7 @@ public class PacketMine extends Module { if (dontBreak.getValue() && mc.player.isHolding(ItemStack::isDamageableItem) && mc.player.getMainHandItem().getMaxDamage() - mc.player.getMainHandItem().getDamageValue() <= 1) { - ChatUtil.warn("pico por romperse"); + ChatUtil.warn(Component.translatable("sputnik.module.packetmine.pickbreaking")); toggle(); return false; } diff --git a/src/main/java/me/retucio/sputnik/module/modules/player/AutoFish.java b/src/main/java/me/retucio/sputnik/module/modules/player/AutoFish.java index 0e30c5d..b1cc959 100644 --- a/src/main/java/me/retucio/sputnik/module/modules/player/AutoFish.java +++ b/src/main/java/me/retucio/sputnik/module/modules/player/AutoFish.java @@ -10,6 +10,7 @@ import me.retucio.sputnik.module.setting.settings.BooleanSetting; import me.retucio.sputnik.module.setting.settings.NumberSetting; import me.retucio.sputnik.util.ChatUtil; import me.retucio.sputnik.util.InventoryUtil; +import net.minecraft.network.chat.Component; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; @@ -129,7 +130,7 @@ public class AutoFish extends Module { ItemStack rod = mc.player.getInventory().getItem(slot); if (rod.getDamageValue() >= rod.getMaxDamage() - 1 && dontBreak.getValue()) { if (!warned) { - ChatUtil.warn("caña a punto de romperse"); + ChatUtil.warn(Component.translatable("sputnik.module.autofish.rodbreaking")); warned = true; } return; diff --git a/src/main/java/me/retucio/sputnik/module/modules/player/KeyPearl.java b/src/main/java/me/retucio/sputnik/module/modules/player/KeyPearl.java index 9fc143b..6e8d68e 100644 --- a/src/main/java/me/retucio/sputnik/module/modules/player/KeyPearl.java +++ b/src/main/java/me/retucio/sputnik/module/modules/player/KeyPearl.java @@ -5,6 +5,7 @@ import me.retucio.sputnik.module.Module; import me.retucio.sputnik.module.setting.settings.BooleanSetting; import me.retucio.sputnik.util.ChatUtil; import me.retucio.sputnik.util.InventoryUtil; +import net.minecraft.network.chat.Component; import net.minecraft.world.entity.player.Inventory; 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)); if (slot < 0) { - ChatUtil.error("no tienes perlas"); + ChatUtil.error(Component.translatable("sputnik.module.keypearl.nopearls")); toggle(); return; } diff --git a/src/main/java/me/retucio/sputnik/module/modules/player/NoFall.java b/src/main/java/me/retucio/sputnik/module/modules/player/NoFall.java index e4cf21f..91320b0 100644 --- a/src/main/java/me/retucio/sputnik/module/modules/player/NoFall.java +++ b/src/main/java/me/retucio/sputnik/module/modules/player/NoFall.java @@ -12,6 +12,7 @@ import me.retucio.sputnik.util.ChatUtil; import me.retucio.sputnik.util.InventoryUtil; import me.retucio.sputnik.util.Lists; import net.minecraft.core.BlockPos; +import net.minecraft.network.chat.Component; import net.minecraft.network.protocol.game.ServerboundMovePlayerPacket; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; @@ -27,27 +28,23 @@ import net.minecraft.world.phys.HitResult; import net.minecraft.world.phys.Vec3; import java.util.List; +import java.util.stream.Stream; // todo: arreglar MLGs con bloques public class NoFall extends Module { private boolean placed, shouldUse; - private final List mlgItems = List.of(Items.WATER_BUCKET, Items.ENDER_PEARL, - Items.POWDER_SNOW_BUCKET, Items.TWISTING_VINES, Items.SLIME_BLOCK, - Items.HAY_BLOCK, Items.HONEY_BLOCK, Items.BLACK_BED, - Items.BLUE_BED, Items.BROWN_BED, Items.CYAN_BED, Items.GRAY_BED, - Items.GREEN_BED, Items.LIGHT_BLUE_BED, Items.LIGHT_GRAY_BED, Items.LIME_BED, - Items.MAGENTA_BED, Items.ORANGE_BED, Items.PINK_BED, Items.PURPLE_BED, - Items.RED_BED, Items.WHITE_BED, Items.YELLOW_BED); + private final List mlgItems = Stream.concat( + Stream.of(Items.WATER_BUCKET, Items.ENDER_PEARL, + Items.POWDER_SNOW_BUCKET, Items.TWISTING_VINES, Items.SLIME_BLOCK, + Items.HAY_BLOCK, Items.HONEY_BLOCK), + Items.BED.asList().stream()).toList(); - private final List safeBlocks = List.of( - Blocks.WATER, Blocks.SLIME_BLOCK, Blocks.HAY_BLOCK, Blocks.HONEY_BLOCK, - Blocks.TWISTING_VINES, Blocks.BLACK_BED, Blocks.BLUE_BED, Blocks.BROWN_BED, - Blocks.CYAN_BED, Blocks.GRAY_BED, Blocks.GREEN_BED, Blocks.LIGHT_BLUE_BED, - 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 List safeBlocks = Stream.concat( + Stream.of(Blocks.WATER, Blocks.SLIME_BLOCK, Blocks.HAY_BLOCK, + Blocks.HONEY_BLOCK, Blocks.TWISTING_VINES), + Blocks.BED.asList().stream()).toList(); private final EnumSetting mode = sgGeneral.add(new EnumSetting<>( "modo", @@ -110,7 +107,7 @@ public class NoFall extends Module { && !placed) { 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) { Vec3 impulse = new Vec3(-diff.x * 0.05, 0, -diff.z * 0.05); mc.player.push(impulse.x, impulse.y, impulse.z); @@ -129,11 +126,11 @@ public class NoFall extends Module { ItemStack mlgItem = getMlgItem(); if (mlgItem == null) { if (!placed) { - ChatUtil.warn("amortiguador (agua, etc.) no encontrado"); + ChatUtil.warn(Component.translatable("sputnik.module.nofall.nocushion")); placed = true; if (clutch.getValue()) { mode.setValue(NoFallMode.PACKET); - ChatUtil.info("cambiado a modo de paquetes"); + ChatUtil.info(Component.translatable("sputnik.module.nofall.packetmode")); } } return; diff --git a/src/main/java/me/retucio/sputnik/module/modules/render/BlockESP.java b/src/main/java/me/retucio/sputnik/module/modules/render/BlockESP.java index 967d39d..3a5c58c 100644 --- a/src/main/java/me/retucio/sputnik/module/modules/render/BlockESP.java +++ b/src/main/java/me/retucio/sputnik/module/modules/render/BlockESP.java @@ -150,7 +150,7 @@ public class BlockESP extends Module { searchBlocks(); } - Vec3 cameraPos = mc.gameRenderer.getMainCamera().position(); + Vec3 cameraPos = mc.gameRenderer.mainCamera().position(); int rendered = 0; Iterator> iterator = cachedBlocks.entrySet().iterator(); diff --git a/src/main/java/me/retucio/sputnik/module/modules/render/Nametags.java b/src/main/java/me/retucio/sputnik/module/modules/render/Nametags.java index 6fa24a1..84f3ddd 100644 --- a/src/main/java/me/retucio/sputnik/module/modules/render/Nametags.java +++ b/src/main/java/me/retucio/sputnik/module/modules/render/Nametags.java @@ -19,6 +19,7 @@ import net.minecraft.util.Mth; import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.entity.EntityReference; import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.EntityTypes; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.item.PrimedTnt; import net.minecraft.world.entity.player.Player; @@ -79,25 +80,25 @@ public class Nametags extends Module { Category.RENDER); // entidades activadas por defecto - defaultEntities.replace(EntityType.PLAYER, true); - defaultEntities.replace(EntityType.ITEM, true); - defaultEntities.replace(EntityType.ARROW, true); - defaultEntities.replace(EntityType.SPECTRAL_ARROW, true); - defaultEntities.replace(EntityType.TRIDENT, true); - defaultEntities.replace(EntityType.TNT, true); + defaultEntities.replace(EntityTypes.PLAYER, true); + defaultEntities.replace(EntityTypes.ITEM, true); + defaultEntities.replace(EntityTypes.ARROW, true); + defaultEntities.replace(EntityTypes.SPECTRAL_ARROW, true); + defaultEntities.replace(EntityTypes.TRIDENT, true); + defaultEntities.replace(EntityTypes.TNT, true); entities.setDefaultValue(defaultEntities); health.onUpdate(v -> healthMode.visibility(v)); entities.onUpdate(entities -> { - items.visibility(entities.get(EntityType.ITEM)); + items.visibility(entities.get(EntityTypes.ITEM)); - boolean anyProjectile = entities.get(EntityType.TRIDENT) - || entities.get(EntityType.ARROW) - || entities.get(EntityType.SPECTRAL_ARROW); + boolean anyProjectile = entities.get(EntityTypes.TRIDENT) + || entities.get(EntityTypes.ARROW) + || entities.get(EntityTypes.SPECTRAL_ARROW); showProjectileDamage.visibility(anyProjectile); - tntPrime.visibility(entities.get(EntityType.TNT)); + tntPrime.visibility(entities.get(EntityTypes.TNT)); }); } diff --git a/src/main/java/me/retucio/sputnik/module/modules/render/NoRender.java b/src/main/java/me/retucio/sputnik/module/modules/render/NoRender.java index 4d902b1..8e1f28f 100644 --- a/src/main/java/me/retucio/sputnik/module/modules/render/NoRender.java +++ b/src/main/java/me/retucio/sputnik/module/modules/render/NoRender.java @@ -93,6 +93,7 @@ public class NoRender extends Module { private final String name; Colors(String name) { this.name = 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()); } } } diff --git a/src/main/java/me/retucio/sputnik/module/modules/render/Tracers.java b/src/main/java/me/retucio/sputnik/module/modules/render/Tracers.java index 049555d..25a8db8 100644 --- a/src/main/java/me/retucio/sputnik/module/modules/render/Tracers.java +++ b/src/main/java/me/retucio/sputnik/module/modules/render/Tracers.java @@ -14,6 +14,7 @@ import me.retucio.sputnik.util.Lists; import me.retucio.sputnik.util.render.RenderUtil; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.EntityTypes; import net.minecraft.world.entity.player.Player; import net.minecraft.world.phys.Vec3; @@ -87,7 +88,7 @@ public class Tracers extends Module { public Tracers() { 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); } diff --git a/src/main/java/me/retucio/sputnik/module/modules/world/AutoSign.java b/src/main/java/me/retucio/sputnik/module/modules/world/AutoSign.java index 33e60dc..32ac161 100644 --- a/src/main/java/me/retucio/sputnik/module/modules/world/AutoSign.java +++ b/src/main/java/me/retucio/sputnik/module/modules/world/AutoSign.java @@ -9,6 +9,7 @@ import me.retucio.sputnik.module.Module; import me.retucio.sputnik.util.ChatUtil; import net.minecraft.client.gui.screens.inventory.AbstractSignEditScreen; import net.minecraft.core.BlockPos; +import net.minecraft.network.chat.Component; import net.minecraft.network.protocol.game.ServerboundSignUpdatePacket; import net.minecraft.world.level.block.entity.SignBlockEntity; @@ -25,7 +26,7 @@ public class AutoSign extends Module { @Override 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(); } diff --git a/src/main/java/me/retucio/sputnik/module/modules/world/BlockInfo.java b/src/main/java/me/retucio/sputnik/module/modules/world/BlockInfo.java index ada8ca9..7f43478 100644 --- a/src/main/java/me/retucio/sputnik/module/modules/world/BlockInfo.java +++ b/src/main/java/me/retucio/sputnik/module/modules/world/BlockInfo.java @@ -12,6 +12,7 @@ import me.retucio.sputnik.util.ChatUtil; import net.minecraft.core.BlockPos; import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.network.chat.Component; import net.minecraft.resources.Identifier; import net.minecraft.world.inventory.DataSlot; import net.minecraft.world.level.block.state.BlockState; @@ -64,7 +65,7 @@ public class BlockInfo extends Module { ); 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; } @@ -76,7 +77,7 @@ public class BlockInfo extends Module { } copy(blockHitResult, data); } 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()) { - ChatUtil.warn("no hay propiedades que copiar para este bloque"); + ChatUtil.warn(Component.translatable("sputnik.module.blockinfo.noproperties")); return; } diff --git a/src/main/java/me/retucio/sputnik/module/modules/world/LightOverlay.java b/src/main/java/me/retucio/sputnik/module/modules/world/LightOverlay.java index 4837eca..ee0c5da 100644 --- a/src/main/java/me/retucio/sputnik/module/modules/world/LightOverlay.java +++ b/src/main/java/me/retucio/sputnik/module/modules/world/LightOverlay.java @@ -147,7 +147,7 @@ public class LightOverlay extends Module { } // renderizado - Vec3 cameraPos = mc.gameRenderer.getMainCamera().position(); + Vec3 cameraPos = mc.gameRenderer.mainCamera().position(); int radiusValue = radius.getIntValue(); double radiusSq = radiusValue * radiusValue; diff --git a/src/main/java/me/retucio/sputnik/module/modules/world/StrongholdTriangulator.java b/src/main/java/me/retucio/sputnik/module/modules/world/StrongholdTriangulator.java index 996e6bb..845f33e 100644 --- a/src/main/java/me/retucio/sputnik/module/modules/world/StrongholdTriangulator.java +++ b/src/main/java/me/retucio/sputnik/module/modules/world/StrongholdTriangulator.java @@ -41,8 +41,8 @@ public class StrongholdTriangulator extends Module { @Override public void onEnable() { super.onEnable(); - ChatUtil.info("para empezar, lanza un ojo de ender"); - 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.throwfirst")); + ChatUtil.info(Component.translatable("sputnik.module.stronghold.standstill")); } @Override @@ -61,16 +61,15 @@ public class StrongholdTriangulator extends Module { if (result != null) { if (result.errorMessage == null) { - ChatUtil.info(Component.literal("stronghold aproximadamente en: " - + ChatFormatting.GREEN - + String.format("%.2f, %.2f", result.x, result.z) - + ChatFormatting.RESET - )); + ChatUtil.info(Component.translatable("sputnik.module.stronghold.found", + ChatFormatting.GREEN + + String.format("%.2f, %.2f", result.x, result.z) + + ChatFormatting.RESET)); } else { ChatUtil.error(result.errorMessage); } } else { - ChatUtil.error("upsi"); + ChatUtil.error(Component.translatable("sputnik.module.stronghold.oops")); } reset(); @@ -101,8 +100,8 @@ public class StrongholdTriangulator extends Module { firstEyeThrown = true; ChatUtil.info("primer ojo registrado: " + 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("cuanta más distancia te separes, más preciso será el resultado"); + ChatUtil.info(Component.translatable("sputnik.module.stronghold.movenow")); + ChatUtil.info(Component.translatable("sputnik.module.stronghold.moreaccurate")); } else if (!secondEyeThrown) { b = throwPos; beta = yaw; @@ -142,11 +141,11 @@ public class StrongholdTriangulator extends Module { // posibles casos 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)) { - 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) { - return new StrongholdResult(null, null, "los ojos apuntan a strongholds distintas"); + return new StrongholdResult(null, null, Component.translatable("sputnik.module.stronghold.error.different")); } else { return new StrongholdResult(x, z, null); } @@ -159,5 +158,5 @@ public class StrongholdTriangulator extends Module { b = null; } - public record StrongholdResult(Double x, Double z, String errorMessage) {} + public record StrongholdResult(Double x, Double z, Component errorMessage) {} } \ No newline at end of file diff --git a/src/main/java/me/retucio/sputnik/module/setting/Setting.java b/src/main/java/me/retucio/sputnik/module/setting/Setting.java index 111f5bb..6c986fc 100644 --- a/src/main/java/me/retucio/sputnik/module/setting/Setting.java +++ b/src/main/java/me/retucio/sputnik/module/setting/Setting.java @@ -3,6 +3,7 @@ package me.retucio.sputnik.module.setting; import me.retucio.sputnik.Sputnik; import me.retucio.sputnik.event.sputnik.UpdateSettingEvent; import me.retucio.sputnik.module.Module; +import me.retucio.sputnik.util.I18nUtil; import java.util.function.BooleanSupplier; import java.util.function.Consumer; @@ -10,9 +11,16 @@ import java.util.function.Consumer; // base para los tipos de ajustes public abstract class Setting { + // 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 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 defaultValue; @@ -49,6 +57,13 @@ public abstract class Setting { return (S) this; } + // fija la clave a mano en vez de derivarla, para compartir texto entre módulos + @SuppressWarnings("unchecked") + public > S translationKey(String key) { + this.translationKey = key; + return (S) this; + } + public boolean isSearchMatch() { return searchMatch; } @@ -57,14 +72,32 @@ public abstract class Setting { this.searchMatch = searchMatch; } - public String getName() { - return name.strip(); + public String getTranslationKey() { + 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 getDescription() { - return description; + return I18nUtil.orElse(getTranslationKey() + ".desc", description); } public T getValue() { diff --git a/src/main/java/me/retucio/sputnik/module/setting/SettingGroup.java b/src/main/java/me/retucio/sputnik/module/setting/SettingGroup.java index 56f3714..2419cd2 100644 --- a/src/main/java/me/retucio/sputnik/module/setting/SettingGroup.java +++ b/src/main/java/me/retucio/sputnik/module/setting/SettingGroup.java @@ -1,6 +1,7 @@ package me.retucio.sputnik.module.setting; import me.retucio.sputnik.module.Module; +import me.retucio.sputnik.util.I18nUtil; import org.jetbrains.annotations.NotNull; @@ -15,6 +16,9 @@ public class SettingGroup implements Iterable> { private String name; 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> settings = new ArrayList<>(1); public SettingGroup(String name, boolean extended) { @@ -22,6 +26,11 @@ public class SettingGroup implements Iterable> { this.extended = extended; } + public SettingGroup(String name, boolean extended, String translationKey) { + this(name, extended); + this.translationKey = translationKey; + } + @Override public @NotNull Iterator> iterator() { return settings.iterator(); @@ -40,9 +49,10 @@ public class SettingGroup implements Iterable> { } } + // busca por nombre interno, no por el traducido public Setting getSetting(String name) { for (Setting setting : this) - if (setting.getName().equals(name)) + if (setting.getTrueName().equals(name)) return setting; return null; @@ -52,10 +62,21 @@ public class SettingGroup implements Iterable> { 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() { - 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 boolean isExtended() { diff --git a/src/main/java/me/retucio/sputnik/module/setting/settings/ColorSetting.java b/src/main/java/me/retucio/sputnik/module/setting/settings/ColorSetting.java index a7052a5..300ea5f 100644 --- a/src/main/java/me/retucio/sputnik/module/setting/settings/ColorSetting.java +++ b/src/main/java/me/retucio/sputnik/module/setting/settings/ColorSetting.java @@ -228,7 +228,7 @@ public class ColorSetting extends Setting { } 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)); } diff --git a/src/main/java/me/retucio/sputnik/module/setting/settings/KeySetting.java b/src/main/java/me/retucio/sputnik/module/setting/settings/KeySetting.java index d084253..f7d6574 100644 --- a/src/main/java/me/retucio/sputnik/module/setting/settings/KeySetting.java +++ b/src/main/java/me/retucio/sputnik/module/setting/settings/KeySetting.java @@ -3,8 +3,10 @@ package me.retucio.sputnik.module.setting.settings; import me.retucio.sputnik.module.Module; import me.retucio.sputnik.module.ModuleManager; 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.KeyUtil; +import net.minecraft.network.chat.Component; import org.lwjgl.glfw.GLFW; public class KeySetting extends Setting { @@ -22,15 +24,21 @@ public class KeySetting extends Setting { if (value == GLFW.GLFW_KEY_ESCAPE) { this.value = GLFW.GLFW_KEY_UNKNOWN; // asignar la tecla ESC a deshabilitar la tecla 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; } - 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()) if (module.getKey() == value && value != -1) { module.setKey(-1); - ChatUtil.info("tecla del módulo " + module.getName() + " restablecida"); + ChatUtil.info(Component.translatable("sputnik.setting.key.reset", module.getDisplayName())); } } diff --git a/src/main/java/me/retucio/sputnik/ui/hud/HudEditorScreen.java b/src/main/java/me/retucio/sputnik/ui/hud/HudEditorScreen.java index 2de412b..ac53548 100644 --- a/src/main/java/me/retucio/sputnik/ui/hud/HudEditorScreen.java +++ b/src/main/java/me/retucio/sputnik/ui/hud/HudEditorScreen.java @@ -34,7 +34,7 @@ public class HudEditorScreen extends Screen { private int dragX, dragY; public HudEditorScreen() { - super(Component.literal("editor del HUD")); + super(Component.translatable("sputnik.hud.editor.title")); Sputnik.EVENT_BUS.subscribe(this); } @@ -50,7 +50,7 @@ public class HudEditorScreen extends Screen { // instrucciones gui.centeredText(mc.font, title, this.width / 2, this.height / 2 - mc.font.lineHeight, -1); 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()); // 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 // registrar dos teclas a la vez, pero resulta que no :P public void onKey(KeyEvent event) { - if (!(mc.screen == INSTANCE)) return; + if (!(mc.gui.screen() == INSTANCE)) return; if (event.getAction() == GLFW.GLFW_RELEASE) return; event.cancel(); @@ -165,7 +165,7 @@ public class HudEditorScreen extends Screen { if (event.getKey() == GLFW.GLFW_KEY_ESCAPE) { saveAllElementsToConfig(); selected = null; - mc.setScreen(null); + mc.gui.setScreen(null); } // movimiento de los elementos con las teclas de las flechas else if (hud.arrowMovement.getValue() && selected != null) { diff --git a/src/main/java/me/retucio/sputnik/ui/hud/HudRenderer.java b/src/main/java/me/retucio/sputnik/ui/hud/HudRenderer.java index 5e7a861..7cc4136 100644 --- a/src/main/java/me/retucio/sputnik/ui/hud/HudRenderer.java +++ b/src/main/java/me/retucio/sputnik/ui/hud/HudRenderer.java @@ -47,6 +47,7 @@ public class HudRenderer { addElement(new DynoElement(), positions, visibilities); addElement(new EchestElement(), positions, visibilities); addElement(new TotemsElement(), positions, visibilities); + addElement(new ArmorElement(), positions, visibilities); HudEditorScreen.INSTANCE.setElements(elements); } @@ -72,8 +73,9 @@ public class HudRenderer { public HudElement getElement(Class clazz) { for (HudElement element : elements) { - if (element.getClass() == clazz) + if (element.getClass() == clazz) { return element; + } } return null; @@ -110,7 +112,7 @@ public class HudRenderer { List toRemove = new ArrayList<>(); for (NotificationWidget notification : notifications) { notification.setIndex(notifications.indexOf(notification)); - notification.render(gui, 0, 0, 0); + if (!shouldSkipRendering()) notification.render(gui, 0, 0, 0); if (System.currentTimeMillis() >= notification.popTime) { toRemove.add(notification); } @@ -123,12 +125,12 @@ public class HudRenderer { return ModuleManager.INSTANCE == null || mc.player == null || mc.getCameraEntity() == null - || mc.screen instanceof TitleScreen - || mc.options.hideGui + || mc.gui.screen() instanceof TitleScreen + || mc.gui.hud.isHidden() || !hud.isEnabled() || (mc.debugEntries.isOverlayVisible() && !hud.showOnF3.getValue()) - || (mc.screen instanceof ChatScreen && !hud.showOnChat.getValue()) - || mc.screen instanceof HudEditorScreen; + || (mc.gui.screen() instanceof ChatScreen && !hud.showOnChat.getValue()) + || mc.gui.screen() instanceof HudEditorScreen; } public void pushNotification(String title, String desc) { diff --git a/src/main/java/me/retucio/sputnik/ui/hud/ImageHudElement.java b/src/main/java/me/retucio/sputnik/ui/hud/ImageHudElement.java index e3c47f5..4865c7d 100644 --- a/src/main/java/me/retucio/sputnik/ui/hud/ImageHudElement.java +++ b/src/main/java/me/retucio/sputnik/ui/hud/ImageHudElement.java @@ -7,6 +7,7 @@ import me.retucio.sputnik.util.Colors; import net.minecraft.client.gui.GuiGraphicsExtractor; import net.minecraft.client.renderer.RenderPipelines; import net.minecraft.client.renderer.texture.DynamicTexture; +import net.minecraft.network.chat.Component; import net.minecraft.resources.Identifier; @@ -60,10 +61,10 @@ public abstract class ImageHudElement extends HudElement { mc.getTextureManager().register(textureId, texture); 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) { - 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()); } } diff --git a/src/main/java/me/retucio/sputnik/ui/hud/elements/ArmorElement.java b/src/main/java/me/retucio/sputnik/ui/hud/elements/ArmorElement.java new file mode 100644 index 0000000..131b7c4 --- /dev/null +++ b/src/main/java/me/retucio/sputnik/ui/hud/elements/ArmorElement.java @@ -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 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 getTooltip() { + return List.of(Component.translatable("sputnik.hud.element.armor.desc")); + } + + private List getPreviewStacks() { + if (previewStacks == null) { + try { + List 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; + } +} diff --git a/src/main/java/me/retucio/sputnik/ui/hud/elements/CoordsElement.java b/src/main/java/me/retucio/sputnik/ui/hud/elements/CoordsElement.java index f6a6729..0c555f2 100644 --- a/src/main/java/me/retucio/sputnik/ui/hud/elements/CoordsElement.java +++ b/src/main/java/me/retucio/sputnik/ui/hud/elements/CoordsElement.java @@ -48,7 +48,7 @@ public class CoordsElement extends TextHudElement { public List getTooltip() { return List.of( Component.literal(getId()), - Component.literal("te muestra tu posición XYZ en el mundo") + Component.translatable("sputnik.hud.element.coords.desc") ); } } \ No newline at end of file diff --git a/src/main/java/me/retucio/sputnik/ui/hud/elements/CustomTextElement.java b/src/main/java/me/retucio/sputnik/ui/hud/elements/CustomTextElement.java index afe6a76..e5744c2 100644 --- a/src/main/java/me/retucio/sputnik/ui/hud/elements/CustomTextElement.java +++ b/src/main/java/me/retucio/sputnik/ui/hud/elements/CustomTextElement.java @@ -32,8 +32,8 @@ public class CustomTextElement extends TextHudElement { @Override public List getTooltip() { return List.of( - Component.literal("texto custom"), - Component.literal("texto que tú eliges") + Component.translatable("sputnik.hud.element.customtext.name"), + Component.translatable("sputnik.hud.element.customtext.desc") ); } diff --git a/src/main/java/me/retucio/sputnik/ui/hud/elements/DynoElement.java b/src/main/java/me/retucio/sputnik/ui/hud/elements/DynoElement.java index 594a2aa..9d1c6c2 100644 --- a/src/main/java/me/retucio/sputnik/ui/hud/elements/DynoElement.java +++ b/src/main/java/me/retucio/sputnik/ui/hud/elements/DynoElement.java @@ -35,8 +35,8 @@ public class DynoElement extends ImageHudElement { @Override public List getTooltip() { return List.of( - Component.literal("dinosaurio: " + dyno), - Component.literal("que viva el autismo joder") + Component.translatable("sputnik.hud.element.dyno.name", dyno), + Component.translatable("sputnik.hud.element.dyno.desc") ); } } diff --git a/src/main/java/me/retucio/sputnik/ui/hud/elements/EchestElement.java b/src/main/java/me/retucio/sputnik/ui/hud/elements/EchestElement.java index bf08225..a0eb989 100644 --- a/src/main/java/me/retucio/sputnik/ui/hud/elements/EchestElement.java +++ b/src/main/java/me/retucio/sputnik/ui/hud/elements/EchestElement.java @@ -86,8 +86,8 @@ public class EchestElement extends ImageHudElement { @Override public List getTooltip() { List tooltip = new ArrayList<>(); - tooltip.add(Component.literal("echest")); - tooltip.add(Component.literal("items en tu echest")); + tooltip.add(Component.translatable("sputnik.hud.element.echest.name")); + tooltip.add(Component.translatable("sputnik.hud.element.echest.desc")); return tooltip; } diff --git a/src/main/java/me/retucio/sputnik/ui/hud/elements/FpsElement.java b/src/main/java/me/retucio/sputnik/ui/hud/elements/FpsElement.java index c3b61da..0cbba36 100644 --- a/src/main/java/me/retucio/sputnik/ui/hud/elements/FpsElement.java +++ b/src/main/java/me/retucio/sputnik/ui/hud/elements/FpsElement.java @@ -26,8 +26,8 @@ public class FpsElement extends TextHudElement { @Override public List getTooltip() { return List.of( - Component.literal("FPS"), - Component.literal("te muestra los fotogramas por segundo a los que corre el juego") + Component.translatable("sputnik.hud.element.fps.name"), + Component.translatable("sputnik.hud.element.fps.desc") ); } } \ No newline at end of file diff --git a/src/main/java/me/retucio/sputnik/ui/hud/elements/PingElement.java b/src/main/java/me/retucio/sputnik/ui/hud/elements/PingElement.java index 6d05e95..321ad84 100644 --- a/src/main/java/me/retucio/sputnik/ui/hud/elements/PingElement.java +++ b/src/main/java/me/retucio/sputnik/ui/hud/elements/PingElement.java @@ -2,6 +2,7 @@ package me.retucio.sputnik.ui.hud.elements; import me.retucio.sputnik.module.modules.client.Hud; import me.retucio.sputnik.ui.hud.TextHudElement; +import me.retucio.sputnik.util.MiscUtil; import net.minecraft.client.multiplayer.PlayerInfo; import net.minecraft.network.chat.Component; @@ -17,7 +18,7 @@ public class PingElement extends TextHudElement { @Override public String getText(float delta, Hud hud) { 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()); return playerListEntry != null ? playerListEntry.getLatency() + " ms" : "? ms"; @@ -31,8 +32,8 @@ public class PingElement extends TextHudElement { @Override public List getTooltip() { return List.of( - Component.literal("ping"), - Component.literal("latencia entre cliente y servidor, en milisegundos") + Component.translatable("sputnik.hud.element.ping.name"), + Component.translatable("sputnik.hud.element.ping.desc") ); } } \ No newline at end of file diff --git a/src/main/java/me/retucio/sputnik/ui/hud/elements/RotationElement.java b/src/main/java/me/retucio/sputnik/ui/hud/elements/RotationElement.java index f363554..66486e9 100644 --- a/src/main/java/me/retucio/sputnik/ui/hud/elements/RotationElement.java +++ b/src/main/java/me/retucio/sputnik/ui/hud/elements/RotationElement.java @@ -32,7 +32,10 @@ public class RotationElement extends TextHudElement { @Override public List getTooltip() { - return List.of(); + return List.of( + Component.translatable("sputnik.hud.element.rotation.name"), + Component.translatable("sputnik.hud.element.rotation.desc") + ); } private String getDirection() { diff --git a/src/main/java/me/retucio/sputnik/ui/hud/elements/TimeElement.java b/src/main/java/me/retucio/sputnik/ui/hud/elements/TimeElement.java index dd4185e..c9565c4 100644 --- a/src/main/java/me/retucio/sputnik/ui/hud/elements/TimeElement.java +++ b/src/main/java/me/retucio/sputnik/ui/hud/elements/TimeElement.java @@ -27,8 +27,8 @@ public class TimeElement extends TextHudElement { @Override public List getTooltip() { return List.of( - Component.literal("hora"), - Component.literal("hora y minutos de la zona horaria seleccionada") + Component.translatable("sputnik.hud.element.time.name"), + Component.translatable("sputnik.hud.element.time.desc") ); } } \ No newline at end of file diff --git a/src/main/java/me/retucio/sputnik/ui/hud/elements/TotemsElement.java b/src/main/java/me/retucio/sputnik/ui/hud/elements/TotemsElement.java index 2bc60a3..7a21f5f 100644 --- a/src/main/java/me/retucio/sputnik/ui/hud/elements/TotemsElement.java +++ b/src/main/java/me/retucio/sputnik/ui/hud/elements/TotemsElement.java @@ -68,7 +68,7 @@ public class TotemsElement extends ImageHudElement { @Override public List getTooltip() { - return List.of(Component.literal("totems disponibles")); + return List.of(Component.translatable("sputnik.hud.element.totems.desc")); } private void drawItem(GuiGraphicsExtractor gui, ItemStack stack, int count) { @@ -95,7 +95,7 @@ public class TotemsElement extends ImageHudElement { try { TOTEM_PREVIEW = new ItemStack(Items.TOTEM_OF_UNDYING, 1); } catch (Exception e) { - return null; // registries not ready yet + return null; } } return TOTEM_PREVIEW; diff --git a/src/main/java/me/retucio/sputnik/ui/hud/elements/TpsElement.java b/src/main/java/me/retucio/sputnik/ui/hud/elements/TpsElement.java index 1887abd..434ec0c 100644 --- a/src/main/java/me/retucio/sputnik/ui/hud/elements/TpsElement.java +++ b/src/main/java/me/retucio/sputnik/ui/hud/elements/TpsElement.java @@ -27,8 +27,8 @@ public class TpsElement extends TextHudElement { @Override public List getTooltip() { return List.of( - Component.literal("TPS"), - Component.literal("te muestra la tasa de ticks por segundo del servidor (TPS óptimo: 20)") + Component.translatable("sputnik.hud.element.tps.name"), + Component.translatable("sputnik.hud.element.tps.desc") ); } } \ No newline at end of file diff --git a/src/main/java/me/retucio/sputnik/ui/hud/elements/UptimeElement.java b/src/main/java/me/retucio/sputnik/ui/hud/elements/UptimeElement.java index d891a6c..c859f6c 100644 --- a/src/main/java/me/retucio/sputnik/ui/hud/elements/UptimeElement.java +++ b/src/main/java/me/retucio/sputnik/ui/hud/elements/UptimeElement.java @@ -33,6 +33,6 @@ public class UptimeElement extends TextHudElement { @Override public List getTooltip() { - return List.of(Component.literal("tiempo jugando")); + return List.of(Component.translatable("sputnik.hud.element.uptime.desc")); } } diff --git a/src/main/java/me/retucio/sputnik/ui/screen/ClickGui.java b/src/main/java/me/retucio/sputnik/ui/screen/ClickGui.java index 5c241f8..28bf648 100644 --- a/src/main/java/me/retucio/sputnik/ui/screen/ClickGui.java +++ b/src/main/java/me/retucio/sputnik/ui/screen/ClickGui.java @@ -71,7 +71,7 @@ public class ClickGui extends Screen { private final List miscWidgets = List.of(scrollBar, searchBar); public ClickGui() { - super(Component.literal("interfaz")); + super(Component.translatable("sputnik.ui.clickgui.title")); Sputnik.EVENT_BUS.subscribe(this); int x = 4; @@ -245,7 +245,7 @@ public class ClickGui extends Screen { @EventListener public void onMouseMiddleButton(MouseClickEvent event) { // mover todos los paneles a un punto visible al presionar shift + la rueda del ratón - if (Sputnik.mc.screen != this || event.getButton() != 2 || !KeyUtil.isKeyDown(GLFW.GLFW_KEY_LEFT_SHIFT)) return; + if (Sputnik.mc.gui.screen() != this || event.getButton() != 2 || !KeyUtil.isKeyDown(GLFW.GLFW_KEY_LEFT_SHIFT)) return; int h = Sputnik.mc.getWindow().getGuiScaledHeight(); int minY = Math.min(modulePanels.stream().mapToInt(Panel::getY).min().getAsInt(), settingsPanels.stream().mapToInt(Panel::getY).min().getAsInt()); @@ -261,8 +261,12 @@ public class ClickGui extends Screen { } public void filterSearchResults() { - if (!clientSettings.searchBar.getValue()) return; - String searchInput = searchBar.getSearchInput().trim(); + // con la barra desactivada se filtra con la búsqueda vacía en vez de salir sin más: + // si no, lo que estuviera oculto se quedaba así, y encima ya no hay barra para vaciarla + String searchInput = clientSettings.searchBar.getValue() + ? searchBar.getSearchInput().trim() + : ""; + if (!clientSettings.matchCase.getValue()) { searchInput = searchInput.toLowerCase(); } @@ -272,13 +276,16 @@ public class ClickGui extends Screen { if (!(b instanceof ModuleButton mb)) continue; Module module = mb.getModule(); + // sin esto los módulos que no casaban se quedaban ocultos al vaciar la + // barra, porque nadie más vuelve a poner searchMatch a true if (searchInput.isEmpty()) { + module.setSearchMatch(true); continue; } - String name = MiscUtil.removeAccentMarks(module.getName()); - String description = MiscUtil.removeAccentMarks(module.getDescription()); - String category = MiscUtil.removeAccentMarks(module.getCategory().toString()); + String name = MiscUtil.removeAccentMarks(module.getDisplayName()); + String description = MiscUtil.removeAccentMarks(module.getDisplayDescription()); + String category = MiscUtil.removeAccentMarks(module.getCategory().getDisplayName()); if (!clientSettings.matchCase.getValue()) { name = name.toLowerCase(); diff --git a/src/main/java/me/retucio/sputnik/ui/screen/PreviewScreen.java b/src/main/java/me/retucio/sputnik/ui/screen/PreviewScreen.java index fb5f907..456c726 100644 --- a/src/main/java/me/retucio/sputnik/ui/screen/PreviewScreen.java +++ b/src/main/java/me/retucio/sputnik/ui/screen/PreviewScreen.java @@ -37,7 +37,7 @@ public class PreviewScreen extends Screen { private int focusedSlot; public PreviewScreen(ItemStack shulker, Screen parent) { - super(Component.literal("previsualización del shulker")); + super(Component.translatable("sputnik.ui.preview.shulker")); this.color = ShulkerPeek.SHULKER_COLORS.get(shulker.getItem()); this.title = shulker.getHoverName(); this.inventory = shulker.get(DataComponents.CONTAINER).allItemsCopyStream().toList(); @@ -46,9 +46,9 @@ public class PreviewScreen extends Screen { } public PreviewScreen(Container inventory, Screen parent) { - super(Component.literal("echest")); + super(Component.translatable("sputnik.ui.preview.echest")); this.color = Colors.PURPLE; - this.title = Component.literal("echest"); + this.title = Component.translatable("sputnik.ui.preview.echest"); this.inventory = new ArrayList<>(); this.parent = parent; this.type = PreviewType.ECHEST; @@ -119,7 +119,7 @@ public class PreviewScreen extends Screen { @Override public void onClose() { - minecraft.setScreen(parent); + minecraft.gui.setScreen(parent); } @Override diff --git a/src/main/java/me/retucio/sputnik/ui/screen/UpdateScreen.java b/src/main/java/me/retucio/sputnik/ui/screen/UpdateScreen.java index 2e8a040..a49d7f7 100644 --- a/src/main/java/me/retucio/sputnik/ui/screen/UpdateScreen.java +++ b/src/main/java/me/retucio/sputnik/ui/screen/UpdateScreen.java @@ -30,22 +30,23 @@ public class UpdateScreen extends Screen { + "/releases/latest" ); - private final Component outdatedText = Component.literal("version desactualizada: " + Sputnik.MOD_VERSION); - private final Component updateText = Component.literal("descarga la última versión (" + VersionChecker.INSTANCE.getLatestVersion() + ") desde aquí:"); + private final Component outdatedText = Component.translatable("sputnik.update.outdated", Sputnik.MOD_VERSION); + private final Component updateText = Component.translatable("sputnik.update.download", VersionChecker.INSTANCE.getLatestVersion()); private final Button idgafButton = Button.builder( - Component.literal("me la pela"), + Component.translatable("sputnik.update.idgaf"), button -> this.onClose() ).build(); private final Button updateButton = Button.builder( - Component.literal("CLIC AQUÍ"), + Component.translatable("sputnik.update.clickhere"), button -> clickUrlAction(mc, this, updateLink) ).build(); public UpdateScreen() { - super(Component.literal(ChatFormatting.BOLD + "actualizar")); + super(Component.literal(ChatFormatting.BOLD.toString()) + .append(Component.translatable("sputnik.update.title"))); } @Override diff --git a/src/main/java/me/retucio/sputnik/ui/widgets/buttons/ModuleButton.java b/src/main/java/me/retucio/sputnik/ui/widgets/buttons/ModuleButton.java index d7a0812..a8362c7 100644 --- a/src/main/java/me/retucio/sputnik/ui/widgets/buttons/ModuleButton.java +++ b/src/main/java/me/retucio/sputnik/ui/widgets/buttons/ModuleButton.java @@ -28,7 +28,7 @@ public class ModuleButton extends Button { determineColor(mouseX, mouseY)); gui.text( // dibujar el nombre del módulo - mc.font, module.getName(), + mc.font, module.getDisplayName(), parent.getX() + 5, parent.getRenderY() + offset + (height / 2) - (mc.font.lineHeight / 2) + 2, -1, true); @@ -40,7 +40,7 @@ public class ModuleButton extends Button { @Override public void drawTooltip(GuiGraphicsExtractor gui, int mouseX, int mouseY) { - gui.setTooltipForNextFrame(Component.literal(module.getDescription()), mouseX, mouseY + 20); + gui.setTooltipForNextFrame(Component.literal(module.getDisplayDescription()), mouseX, mouseY + 20); } @Override diff --git a/src/main/java/me/retucio/sputnik/ui/widgets/buttons/settings/BindButton.java b/src/main/java/me/retucio/sputnik/ui/widgets/buttons/settings/BindButton.java index cacda74..606bf51 100644 --- a/src/main/java/me/retucio/sputnik/ui/widgets/buttons/settings/BindButton.java +++ b/src/main/java/me/retucio/sputnik/ui/widgets/buttons/settings/BindButton.java @@ -13,6 +13,7 @@ import net.minecraft.client.KeyMapping; import net.minecraft.client.gui.GuiGraphicsExtractor; import net.minecraft.client.input.KeyEvent; import net.minecraft.client.resources.language.I18n; +import net.minecraft.network.chat.Component; import org.lwjgl.glfw.GLFW; import java.util.ArrayList; @@ -55,8 +56,8 @@ public class BindButton extends SettingButton { for (KeyMapping bind : keys) { if (bind.matches(new KeyEvent(button, 0, 0))) { if (!allowMultiple) { - ChatUtil.warn("esa tecla ya está cogida por " - + ChatFormatting.GREEN + "\"" + I18n.get(bind.getName()) + "\""); + ChatUtil.warn(Component.translatable("sputnik.commands.bind.keytaken", + ChatFormatting.GREEN + "\"" + I18n.get(bind.getName()) + "\"")); listening = false; return; } @@ -93,8 +94,8 @@ public class BindButton extends SettingButton { boolean allowMultiple = ClientSettingsPanel.clientSettings.multipleKeybinds.getValue(); if (keyAlreadyBound && !allowMultiple) { - ChatUtil.warn("esa tecla ya está cogida por " - + ChatFormatting.GREEN + "\"" + I18n.get(bind.getName()) + "\""); + ChatUtil.warn(Component.translatable("sputnik.commands.bind.keytaken", + ChatFormatting.GREEN + "\"" + I18n.get(bind.getName()) + "\"")); listening = false; return; } diff --git a/src/main/java/me/retucio/sputnik/ui/widgets/buttons/settings/CycleButton.java b/src/main/java/me/retucio/sputnik/ui/widgets/buttons/settings/CycleButton.java index 91f681f..13492a0 100644 --- a/src/main/java/me/retucio/sputnik/ui/widgets/buttons/settings/CycleButton.java +++ b/src/main/java/me/retucio/sputnik/ui/widgets/buttons/settings/CycleButton.java @@ -5,6 +5,7 @@ import me.retucio.sputnik.ui.screen.ClickGui; import me.retucio.sputnik.ui.widgets.buttons.SettingButton; import me.retucio.sputnik.ui.widgets.panels.SettingsPanel; import me.retucio.sputnik.util.Colors; +import me.retucio.sputnik.util.I18nUtil; import me.retucio.sputnik.util.KeyUtil; import net.minecraft.ChatFormatting; import net.minecraft.client.gui.GuiGraphicsExtractor; @@ -33,7 +34,7 @@ public class CycleButton> extends SettingButton gui.fill(x, y, x + w, y + h, bgColor); // texto del botón: nombre + valor de texto del enum - String label = setting.getName() + ": " + setting.getValue().toString(); + String label = setting.getName() + ": " + I18nUtil.enumName(setting.getValue()); gui.text(mc.font, label, x + 5, y + 3, -1, true); } @@ -56,19 +57,20 @@ public class CycleButton> extends SettingButton @Override public void drawTooltip(GuiGraphicsExtractor ctx, int mouseX, int mouseY) { if (isHovered(mouseX, mouseY)) { - Screen currentScreen = mc.screen; + Screen currentScreen = mc.gui.screen(); if (currentScreen != null) { if (KeyUtil.isShiftDown()) { // lista de opciones disponibles List lines = new ArrayList<>(); - lines.add(Component.literal("modos disponibles:")); + lines.add(Component.translatable("sputnik.ui.availablemodes")); for (Enum val : setting.getValues()) { + String name = I18nUtil.enumName(val); if (val == setting.getValue()) - lines.add(Component.literal("> " + val.toString() + " <").withStyle(ChatFormatting.GREEN)); + lines.add(Component.literal("> " + name + " <").withStyle(ChatFormatting.GREEN)); else - lines.add(Component.literal(val.toString())); + lines.add(Component.literal(name)); } ctx.setComponentTooltipForNextFrame(mc.font, lines, mouseX, mouseY + 20); diff --git a/src/main/java/me/retucio/sputnik/ui/widgets/buttons/settings/ListButton.java b/src/main/java/me/retucio/sputnik/ui/widgets/buttons/settings/ListButton.java index bb43a2f..52c00b7 100644 --- a/src/main/java/me/retucio/sputnik/ui/widgets/buttons/settings/ListButton.java +++ b/src/main/java/me/retucio/sputnik/ui/widgets/buttons/settings/ListButton.java @@ -32,10 +32,10 @@ public class ListButton extends SettingButton> { @Override public void onDisable() {} }; - // ocultar cosas innecesarias - dummy.getSettings().get(0).visibility(false); - dummy.getSettings().get(1).visibility(false); - dummy.getSettings().get(2).visibility(false); + // ocultar cosas innecesarias. aquí sólo están los ajustes de sgModule; ocultarlos todos + // en vez de los tres primeros a mano, que se dejaba fuera a notifyMode y se colaba en + // el marco de cada lista + dummy.getSettings().forEach(s -> s.visibility(false)); dummy.shouldSaveSettings(false); } @@ -55,10 +55,8 @@ public class ListButton extends SettingButton> { @Override public void drawTooltip(GuiGraphicsExtractor gui, int mouseX, int mouseY) { if (isHovered(mouseX, mouseY)) - gui.setTooltipForNextFrame(Component.literal( - setting.getDescription() - + " (" + countEnabled() + " de " - + setting.getOptions().size() + ")"), + gui.setTooltipForNextFrame(Component.translatable("sputnik.ui.list.tooltip", + setting.getDescription(), countEnabled(), setting.getOptions().size()), mouseX, mouseY); } diff --git a/src/main/java/me/retucio/sputnik/ui/widgets/misc/SearchBarWidget.java b/src/main/java/me/retucio/sputnik/ui/widgets/misc/SearchBarWidget.java index dda3d37..612b339 100644 --- a/src/main/java/me/retucio/sputnik/ui/widgets/misc/SearchBarWidget.java +++ b/src/main/java/me/retucio/sputnik/ui/widgets/misc/SearchBarWidget.java @@ -60,7 +60,10 @@ public class SearchBarWidget extends Widget { } // texto - Component label = Component.literal(focused ? buffer + "_" : (buffer.isEmpty() ? ChatFormatting.ITALIC + "\uD83D\uDD0D buscar..." : buffer.toString())); + Component label = (!focused && buffer.isEmpty()) + ? Component.literal(ChatFormatting.ITALIC + "\uD83D\uDD0D ") + .append(Component.translatable("sputnik.ui.searchbar.placeholder")) + : Component.literal(focused ? buffer + "_" : buffer.toString()); gui.text(mc.font, label, x + 24, renderY + h / 2 - mc.font.lineHeight / 2, (buffer.isEmpty() && !focused) ? Color.LIGHT_GRAY.getRGB() : -1, true); diff --git a/src/main/java/me/retucio/sputnik/ui/widgets/panels/ModulePanel.java b/src/main/java/me/retucio/sputnik/ui/widgets/panels/ModulePanel.java index 37a3339..b3cfee2 100644 --- a/src/main/java/me/retucio/sputnik/ui/widgets/panels/ModulePanel.java +++ b/src/main/java/me/retucio/sputnik/ui/widgets/panels/ModulePanel.java @@ -21,7 +21,7 @@ public class ModulePanel extends ExtendablePanel { public final Category category; public ModulePanel(Category category, int x, int y, int w, int h) { - super(category.toString(), x, y, w, h); + super(category.getDisplayName(), x, y, w, h); this.category = category; dragging = false; @@ -37,7 +37,7 @@ public class ModulePanel extends ExtendablePanel { protected void updateWidth() { int maxWidth = mc.font.width(title); for (ModuleButton button : buttons) { - int textWidth = mc.font.width(button.getModule().getName()); + int textWidth = mc.font.width(button.getModule().getDisplayName()); maxWidth = Math.max(maxWidth, textWidth); } this.w = maxWidth + 22; diff --git a/src/main/java/me/retucio/sputnik/ui/widgets/panels/SettingsPanel.java b/src/main/java/me/retucio/sputnik/ui/widgets/panels/SettingsPanel.java index a2770e2..ed62c4b 100644 --- a/src/main/java/me/retucio/sputnik/ui/widgets/panels/SettingsPanel.java +++ b/src/main/java/me/retucio/sputnik/ui/widgets/panels/SettingsPanel.java @@ -10,6 +10,7 @@ import me.retucio.sputnik.ui.screen.ClickGui; import me.retucio.sputnik.ui.widgets.buttons.*; import me.retucio.sputnik.ui.widgets.Panel; import me.retucio.sputnik.util.Colors; +import me.retucio.sputnik.util.I18nUtil; import net.minecraft.client.gui.GuiGraphicsExtractor; @@ -26,7 +27,7 @@ public class SettingsPanel extends CloseablePanel { friend.setName(name); @@ -67,7 +73,7 @@ public class FriendSettingsPanel extends SettingsPanel { gui.fill(x + PADDING, removeButtonY, x + w - PADDING, removeButtonY + buttonH, color); - String label = "eliminar amigo"; + String label = I18nUtil.orElse("sputnik.ui.friend.remove", "eliminar amigo"); gui.text(mc.font, label, x + w / 2 - mc.font.width(label) / 2, removeButtonY + (buttonH - mc.font.lineHeight) / 2, diff --git a/src/main/java/me/retucio/sputnik/util/ChatUtil.java b/src/main/java/me/retucio/sputnik/util/ChatUtil.java index 7e3dfca..959b413 100644 --- a/src/main/java/me/retucio/sputnik/util/ChatUtil.java +++ b/src/main/java/me/retucio/sputnik/util/ChatUtil.java @@ -40,7 +40,7 @@ public class ChatUtil { public static void addMessage(Component text) { if (!Sputnik.settingsApplied) return; - mc.gui.getChat().addClientSystemMessage(text); + mc.gui.hud.getChat().addClientSystemMessage(text); } public static void addMessageWithPrefix(String text) { diff --git a/src/main/java/me/retucio/sputnik/util/Colors.java b/src/main/java/me/retucio/sputnik/util/Colors.java index b213b01..16939da 100644 --- a/src/main/java/me/retucio/sputnik/util/Colors.java +++ b/src/main/java/me/retucio/sputnik/util/Colors.java @@ -1,6 +1,7 @@ package me.retucio.sputnik.util; import net.minecraft.ChatFormatting; +import net.minecraft.network.chat.TextColor; import java.awt.Color; @@ -120,9 +121,10 @@ public class Colors { double minDistance = Double.MAX_VALUE; for (ChatFormatting formatting : ChatFormatting.values()) { - if (formatting.getColor() == null) continue; // saltarse los modificadores + TextColor color = TextColor.fromLegacyFormat(formatting); + if (color == null) continue; // saltarse los modificadores - Color candidate = new Color(formatting.getColor()); + Color candidate = new Color(color.getValue()); double dist = colorDistance(input, candidate); if (dist < minDistance) { diff --git a/src/main/java/me/retucio/sputnik/util/I18nUtil.java b/src/main/java/me/retucio/sputnik/util/I18nUtil.java new file mode 100644 index 0000000..90f653d --- /dev/null +++ b/src/main/java/me/retucio/sputnik/util/I18nUtil.java @@ -0,0 +1,113 @@ +package me.retucio.sputnik.util; + +import me.retucio.sputnik.Sputnik; +import me.retucio.sputnik.module.Category; +import me.retucio.sputnik.module.Module; +import me.retucio.sputnik.module.ModuleManager; +import me.retucio.sputnik.module.setting.Setting; +import me.retucio.sputnik.module.setting.SettingGroup; +import me.retucio.sputnik.module.setting.settings.EnumSetting; +import me.retucio.sputnik.ui.widgets.panels.settings.ClientSettingsPanel; +import net.fabricmc.loader.api.FabricLoader; +import net.minecraft.client.resources.language.I18n; +import net.minecraft.locale.Language; + +import java.util.ArrayList; +import java.util.List; + +// ayuda para las claves de traducción +public class I18nUtil { + + private static final String PKG = "me.retucio.sputnik."; + + private I18nUtil() {} + + // los nombres internos (nombre de módulo / ajuste) son claves de la config. y no se traducen nunca. + // la clave de traducción se deriva de ellos, así que no pueden desincronizarse. + public static String slug(String text) { + return MiscUtil.removeAccentMarks(text) + .replace("Ñ", "N") + .replace("ñ", "n") + .toLowerCase() + .replaceAll("[^a-z0-9]", ""); + } + + // este código distingue ajustes con el mismo nombre a base de espacios al final + // ("color" / "color " / "color " en trayectoria). slug() se los comería y las claves + // chocarían, así que el número de espacios se conserva como sufijo + public static String paddedSlug(String raw) { + String base = slug(raw); + int padding = raw.length() - raw.strip().length(); + return padding > 0 ? base + padding : base; + } + + // devuelve la traducción, o el texto original si la clave no existe o el idioma aún no ha cargado + // (los módulos se construyen antes de que cargue el idioma, de ahí el fallback) + public static String orElse(String key, String fallback, Object... args) { + return Language.getInstance().has(key) ? I18n.get(key, args) : fallback; + } + + // nombre visible de una constante de enum. los EnumSetting se guardan por índice + // (ver ConfigManager#applyEnumSetting), así que su toString() es sólo texto y se traduce. + // la clave se deriva de la clase que la declara, así que dos enums con el mismo nombre + // simple en módulos distintos no chocan + public static String enumName(Enum value) { + return orElse(enumKey(value), value.toString()); + } + + public static String enumKey(Enum value) { + String path = value.getDeclaringClass().getName(); + if (path.startsWith(PKG)) path = path.substring(PKG.length()); + return "sputnik.enum." + path.replace('$', '.').toLowerCase() + + "." + value.name().toLowerCase(); + } + + // las claves se derivan de los nombres internos, así que un fallo aquí no peta: se muestra + // el español y ya. eso lo hace fácil de no notar, de ahí esta comprobación. sólo en dev, + // y hay que llamarla con el idioma ya cargado (ver Sputnik#onSetScreen) + public static void verifyKeys() { + if (!FabricLoader.getInstance().isDevelopmentEnvironment()) return; + + Language lang = Language.getInstance(); + List missing = new ArrayList<>(); + + for (Category category : Category.values()) + if (!lang.has("sputnik.category." + slug(category.toString()))) + missing.add("sputnik.category." + slug(category.toString())); + + for (Module module : ModuleManager.INSTANCE.getModules()) + checkModule(module, lang, missing); + + // no está en el ModuleManager, se construye aparte + checkModule(ClientSettingsPanel.clientSettings, lang, missing); + + if (missing.isEmpty()) { + Sputnik.LOGGER.info("i18n: todas las claves derivadas existen"); + return; + } + + Sputnik.LOGGER.warn("i18n: {} clave(s) derivada(s) sin entrada en el lang:", missing.size()); + missing.forEach(key -> Sputnik.LOGGER.warn(" - {}", key)); + } + + private static void checkModule(Module module, Language lang, List missing) { + for (String suffix : List.of(".name", ".desc")) + if (!lang.has(module.getTranslationKey() + suffix)) + missing.add(module.getTranslationKey() + suffix); + + for (SettingGroup sg : module.getSgs()) + if (!lang.has(sg.getTranslationKey())) + missing.add(sg.getTranslationKey()); + + for (Setting setting : module.getSettings()) { + for (String suffix : List.of(".name", ".desc")) + if (!lang.has(setting.getTranslationKey() + suffix)) + missing.add(setting.getTranslationKey() + suffix); + + if (setting instanceof EnumSetting enumSetting) + for (Enum value : enumSetting.getValues()) + if (!lang.has(enumKey(value))) + missing.add(enumKey(value)); + } + } +} diff --git a/src/main/java/me/retucio/sputnik/util/KeyUtil.java b/src/main/java/me/retucio/sputnik/util/KeyUtil.java index f6944d9..8cfd9f0 100644 --- a/src/main/java/me/retucio/sputnik/util/KeyUtil.java +++ b/src/main/java/me/retucio/sputnik/util/KeyUtil.java @@ -58,36 +58,46 @@ public class KeyUtil { } public static String getKeyName(int key) { - if (key == GLFW.GLFW_KEY_UNKNOWN) return "ninguna"; + if (key == GLFW.GLFW_KEY_UNKNOWN) return I18nUtil.orElse("sputnik.key.none", "ninguna"); String name = GLFW.glfwGetKeyName(key, 0); if (name != null) return name.toUpperCase(); // para teclas especiales return switch (key) { - case GLFW.GLFW_KEY_SPACE -> "espacio"; - case GLFW.GLFW_KEY_LEFT_SHIFT -> "shift izquierdo"; - case GLFW.GLFW_KEY_RIGHT_SHIFT -> "shift derecho"; - case GLFW.GLFW_KEY_LEFT_CONTROL -> "ctrl izquierdo"; - case GLFW.GLFW_KEY_RIGHT_CONTROL -> "ctrl derecho"; - case GLFW.GLFW_KEY_LEFT_ALT -> "alt izquierdo"; - case GLFW.GLFW_KEY_RIGHT_ALT -> "alt gr"; - case GLFW.GLFW_KEY_TAB -> "tab"; - case GLFW.GLFW_KEY_ENTER -> "enter"; - case GLFW.GLFW_KEY_BACKSPACE -> "borrar"; - case GLFW.GLFW_KEY_DELETE -> "suprimir"; - case GLFW.GLFW_KEY_UP -> "arriba"; - case GLFW.GLFW_KEY_DOWN -> "abajo"; - case GLFW.GLFW_KEY_LEFT -> "izquierda"; - case GLFW.GLFW_KEY_RIGHT -> "derecha"; - case GLFW.GLFW_KEY_PAGE_UP -> "pág. arriba"; - case GLFW.GLFW_KEY_PAGE_DOWN -> "pág. abajo"; - case GLFW.GLFW_KEY_CAPS_LOCK -> "bloq. mayús."; - case GLFW.GLFW_KEY_INSERT -> "insertar"; + case GLFW.GLFW_MOUSE_BUTTON_1 -> I18nUtil.orElse("sputnik.key.leftclick", "clic izquierdo"); + case GLFW.GLFW_MOUSE_BUTTON_2 -> I18nUtil.orElse("sputnik.key.rightclick", "clic derecho"); + case GLFW.GLFW_MOUSE_BUTTON_3 -> I18nUtil.orElse("sputnik.key.middleclick", "ruedita"); + case GLFW.GLFW_KEY_SPACE -> I18nUtil.orElse("sputnik.key.space", "espacio"); + case GLFW.GLFW_KEY_LEFT_SHIFT -> I18nUtil.orElse("sputnik.key.leftshift", "shift izquierdo"); + case GLFW.GLFW_KEY_RIGHT_SHIFT -> I18nUtil.orElse("sputnik.key.rightshift", "shift derecho"); + case GLFW.GLFW_KEY_LEFT_CONTROL -> I18nUtil.orElse("sputnik.key.leftctrl", "ctrl izquierdo"); + case GLFW.GLFW_KEY_RIGHT_CONTROL -> I18nUtil.orElse("sputnik.key.rightctrl", "ctrl derecho"); + case GLFW.GLFW_KEY_LEFT_ALT -> I18nUtil.orElse("sputnik.key.leftalt", "alt izquierdo"); + case GLFW.GLFW_KEY_RIGHT_ALT -> I18nUtil.orElse("sputnik.key.altgr", "alt gr"); + case GLFW.GLFW_KEY_TAB -> I18nUtil.orElse("sputnik.key.tab", "tab"); + case GLFW.GLFW_KEY_ENTER -> I18nUtil.orElse("sputnik.key.enter", "enter"); + case GLFW.GLFW_KEY_BACKSPACE -> I18nUtil.orElse("sputnik.key.backspace", "borrar"); + case GLFW.GLFW_KEY_DELETE -> I18nUtil.orElse("sputnik.key.delete", "suprimir"); + case GLFW.GLFW_KEY_UP -> I18nUtil.orElse("sputnik.key.up", "arriba"); + case GLFW.GLFW_KEY_DOWN -> I18nUtil.orElse("sputnik.key.down", "abajo"); + case GLFW.GLFW_KEY_LEFT -> I18nUtil.orElse("sputnik.key.left", "izquierda"); + case GLFW.GLFW_KEY_RIGHT -> I18nUtil.orElse("sputnik.key.right", "derecha"); + case GLFW.GLFW_KEY_PAGE_UP -> I18nUtil.orElse("sputnik.key.pageup", "pág. arriba"); + case GLFW.GLFW_KEY_PAGE_DOWN -> I18nUtil.orElse("sputnik.key.pagedown", "pág. abajo"); + case GLFW.GLFW_KEY_CAPS_LOCK -> I18nUtil.orElse("sputnik.key.capslock", "bloq. mayús."); + case GLFW.GLFW_KEY_INSERT -> I18nUtil.orElse("sputnik.key.insert", "insertar"); default -> { - if (key >= GLFW.GLFW_KEY_F1 && key <= GLFW.GLFW_KEY_F25) + if (key >= GLFW.GLFW_KEY_F1 && key <= GLFW.GLFW_KEY_F25) { yield "F" + (key - GLFW.GLFW_KEY_F1 + 1); // F1–F25 - yield "tecla " + key; // fallback + } else if (key >= GLFW.GLFW_MOUSE_BUTTON_4 && key <= GLFW.GLFW_MOUSE_BUTTON_8) { + // botones del ratón + yield I18nUtil.orElse("sputnik.key.mousebutton", + "botón del ratón " + (key + 1), key + 1); + } + + // fallback + yield I18nUtil.orElse("sputnik.key.unknown", "tecla " + key, key); } }; } diff --git a/src/main/java/me/retucio/sputnik/util/MiscUtil.java b/src/main/java/me/retucio/sputnik/util/MiscUtil.java index 9457d03..25dcb1f 100644 --- a/src/main/java/me/retucio/sputnik/util/MiscUtil.java +++ b/src/main/java/me/retucio/sputnik/util/MiscUtil.java @@ -5,6 +5,7 @@ import me.retucio.sputnik.event.TickEvent; import me.retucio.sputnik.module.ModuleManager; import me.retucio.sputnik.module.modules.client.Hud; import net.minecraft.client.gui.screens.Screen; +import net.minecraft.client.server.IntegratedServer; import net.minecraft.core.Vec3i; import net.minecraft.world.phys.Vec3; import org.joml.Vector3d; @@ -26,12 +27,18 @@ public class MiscUtil { @EventListener public static void onTick(TickEvent.Post event) { - if (screen != null && mc.screen == null) { - mc.setScreen(screen); + if (screen != null && mc.gui.screen() == null) { + mc.gui.setScreen(screen); screen = null; } } + // un mundo abierto a LAN no cuenta como un solo jugador + public static boolean isSingleplayer() { + IntegratedServer server = mc.getSingleplayerServer(); + return server != null && !server.isPublished(); + } + public static void copyVector(Vector3d dst, Vec3 src) { dst.x = src.x; dst.y = src.y; diff --git a/src/main/java/me/retucio/sputnik/util/NetworkUtil.java b/src/main/java/me/retucio/sputnik/util/NetworkUtil.java index 2584a10..5cbc6d2 100644 --- a/src/main/java/me/retucio/sputnik/util/NetworkUtil.java +++ b/src/main/java/me/retucio/sputnik/util/NetworkUtil.java @@ -161,7 +161,7 @@ public class NetworkUtil { // retorna la dirección desde la que el jugador colocará bloques public static Direction getPlaceSide(BlockPos blockPos) { - Vec3 lookVec = blockPos.getCenter().subtract(mc.player.getEyePosition()); + Vec3 lookVec = Vec3.atCenterOf(blockPos).subtract(mc.player.getEyePosition()); double bestRelevancy = -Double.MAX_VALUE; Direction bestSide = null; diff --git a/src/main/java/me/retucio/sputnik/util/misc/VersionChecker.java b/src/main/java/me/retucio/sputnik/util/misc/VersionChecker.java index e822cfa..17b03bd 100644 --- a/src/main/java/me/retucio/sputnik/util/misc/VersionChecker.java +++ b/src/main/java/me/retucio/sputnik/util/misc/VersionChecker.java @@ -2,6 +2,7 @@ package me.retucio.sputnik.util.misc; import me.retucio.sputnik.Sputnik; import net.fabricmc.loader.api.FabricLoader; +import net.minecraft.network.chat.Component; import java.net.URI; import java.net.http.HttpClient; @@ -41,20 +42,20 @@ public class VersionChecker { if (compareVersions(localVersion, remoteVersion) == -1) { updateAvailable = true; - Sputnik.LOGGER.info("actualización disponible. local: {}, más reciente: {}", - CURRENT_VERSION, latestRemoteVersion); + Sputnik.LOGGER.info(Component.translatable("sputnik.version.info.available", + CURRENT_VERSION, latestRemoteVersion).getString()); shouldShowScreen = true; } else if (compareVersions(localVersion, remoteVersion) == 0){ - Sputnik.LOGGER.info("el mod está al día: v{}", CURRENT_VERSION); + Sputnik.LOGGER.info(Component.translatable("sputnik.version.info.uptodate", CURRENT_VERSION).getString()); } else { - Sputnik.LOGGER.info("mod en estado de desarrollo: v{}", CURRENT_VERSION); + Sputnik.LOGGER.info(Component.translatable("sputnik.version.info.dev", CURRENT_VERSION).getString()); } } } else { - Sputnik.LOGGER.error("no se pudo comprobar la versión más reciente"); + Sputnik.LOGGER.error(Component.translatable("sputnik.version.error.fetch").getString()); } } catch (Exception e) { - Sputnik.LOGGER.warn("no se pudo comprobar si el mod está actualizado: {}", e.getMessage()); + Sputnik.LOGGER.warn(Component.translatable("sputnik.version.warn.check", e.getMessage()).getString()); } } @@ -74,7 +75,7 @@ public class VersionChecker { } } } catch (Exception e) { - Sputnik.LOGGER.error("no se pudo parsear el archivo gradle.properties: {}", e.getMessage()); + Sputnik.LOGGER.error(Component.translatable("sputnik.version.error.parse", e.getMessage()).getString()); } return null; } @@ -132,7 +133,7 @@ public class VersionChecker { return URI.create(rawUrl); } } catch (Exception e) { - Sputnik.LOGGER.warn("no se pudo construir gradle.properties desde la metadata", e); + Sputnik.LOGGER.warn(Component.translatable("sputnik.version.warn.metadata").getString(), e); } return null; } diff --git a/src/main/java/me/retucio/sputnik/util/render/GlintRenderType.java b/src/main/java/me/retucio/sputnik/util/render/GlintRenderType.java index bdc690d..d3f83ad 100644 --- a/src/main/java/me/retucio/sputnik/util/render/GlintRenderType.java +++ b/src/main/java/me/retucio/sputnik/util/render/GlintRenderType.java @@ -1,7 +1,5 @@ package me.retucio.sputnik.util.render; -import com.mojang.blaze3d.vertex.ByteBufferBuilder; -import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap; import me.retucio.sputnik.Sputnik; import me.retucio.sputnik.module.modules.render.GlintPlus; import net.minecraft.client.renderer.RenderPipelines; @@ -27,13 +25,6 @@ public class GlintRenderType { public static final List armorEntityGlintColor = newRenderList(GlintRenderType::buildArmorEntityGlintRenderType); public static final List glintTranslucentColor = newRenderList(GlintRenderType::buildGlintTranslucentRenderType); - public static void addGlintTypes(Object2ObjectLinkedOpenHashMap map) { - addGlintTypes(map, glintColor); - addGlintTypes(map, glintTranslucentColor); - addGlintTypes(map, entityGlintColor); - addGlintTypes(map, armorEntityGlintColor); - } - private static List newRenderList(Function func) { ArrayList list = new ArrayList<>(DyeColor.values().length + 2); @@ -46,12 +37,6 @@ public class GlintRenderType { return list; } - public static void addGlintTypes(Object2ObjectLinkedOpenHashMap map, List typeList) { - for (RenderType renderType : typeList) - if (!map.containsKey(renderType)) - map.put(renderType, new ByteBufferBuilder(renderType.bufferSize())); - } - private static RenderType buildGlintRenderType(String name) { final Identifier res = Identifier.fromNamespaceAndPath(Sputnik.MOD_ID, "textures/misc/glint_" + name.toLowerCase() + ".png"); return RenderType.create( diff --git a/src/main/java/me/retucio/sputnik/util/render/Pipelines.java b/src/main/java/me/retucio/sputnik/util/render/Pipelines.java index 869a1ba..25d82b0 100644 --- a/src/main/java/me/retucio/sputnik/util/render/Pipelines.java +++ b/src/main/java/me/retucio/sputnik/util/render/Pipelines.java @@ -1,5 +1,6 @@ package me.retucio.sputnik.util.render; +import com.mojang.blaze3d.PrimitiveTopology; import com.mojang.blaze3d.pipeline.RenderPipeline; import com.mojang.blaze3d.systems.GpuDevice; import com.mojang.blaze3d.systems.RenderSystem; @@ -9,6 +10,7 @@ import com.mojang.blaze3d.vertex.VertexFormat; import me.retucio.sputnik.Sputnik; import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.BindGroupLayouts; import net.minecraft.client.renderer.RenderPipelines; import net.minecraft.resources.Identifier; import net.minecraft.server.packs.resources.Resource; @@ -28,7 +30,8 @@ public class Pipelines { static final RenderPipeline LINES_PIPELINE = add(RenderPipeline.builder(RenderPipelines.LINES_SNIPPET) .withLocation(Identifier.fromNamespaceAndPath(Sputnik.MOD_ID, "pipeline/lines")) - .withVertexFormat(DefaultVertexFormat.POSITION_COLOR_NORMAL_LINE_WIDTH, VertexFormat.Mode.LINES) + .withVertexBinding(0, DefaultVertexFormat.POSITION_COLOR_NORMAL_LINE_WIDTH) + .withPrimitiveTopology(PrimitiveTopology.LINES) // .withDepthTestFunction(DepthTestFunction.NO_DEPTH_TEST) // .withDepthWrite(false) .withCull(false) @@ -36,7 +39,8 @@ public class Pipelines { static final RenderPipeline LINES_CULL_PIPELINE = add(RenderPipeline.builder(RenderPipelines.LINES_SNIPPET) .withLocation(Identifier.fromNamespaceAndPath(Sputnik.MOD_ID, "pipeline/lines_cull")) - .withVertexFormat(DefaultVertexFormat.POSITION_COLOR_NORMAL_LINE_WIDTH, VertexFormat.Mode.LINES) + .withVertexBinding(0, DefaultVertexFormat.POSITION_COLOR_NORMAL_LINE_WIDTH) + .withPrimitiveTopology(PrimitiveTopology.LINES) // .withDepthTestFunction(DepthTestFunction.LEQUAL_DEPTH_TEST) // .withDepthWrite(false) .withCull(true) @@ -44,7 +48,8 @@ public class Pipelines { static final RenderPipeline QUADS_PIPELINE = add(RenderPipeline.builder(RenderPipelines.DEBUG_FILLED_SNIPPET) .withLocation(Identifier.fromNamespaceAndPath(Sputnik.MOD_ID, "pipeline/quads")) - .withVertexFormat(DefaultVertexFormat.POSITION_COLOR, VertexFormat.Mode.QUADS) + .withVertexBinding(0, DefaultVertexFormat.POSITION_COLOR) + .withPrimitiveTopology(PrimitiveTopology.QUADS) // .withDepthTestFunction(DepthTestFunction.NO_DEPTH_TEST) // .withBlend(BlendFunction.TRANSLUCENT) // .withDepthWrite(false) @@ -53,7 +58,8 @@ public class Pipelines { static final RenderPipeline QUADS_CULL_PIPELINE = add(RenderPipeline.builder(RenderPipelines.DEBUG_FILLED_SNIPPET) .withLocation(Identifier.fromNamespaceAndPath(Sputnik.MOD_ID, "pipeline/quads_cull")) - .withVertexFormat(DefaultVertexFormat.POSITION_COLOR, VertexFormat.Mode.QUADS) + .withVertexBinding(0, DefaultVertexFormat.POSITION_COLOR) + .withPrimitiveTopology(PrimitiveTopology.QUADS) // .withDepthTestFunction(DepthTestFunction.LEQUAL_DEPTH_TEST) // .withBlend(BlendFunction.TRANSLUCENT) // .withDepthWrite(false) @@ -62,10 +68,14 @@ public class Pipelines { static final RenderPipeline TEXT_PIPELINE = add(RenderPipeline.builder(RenderPipelines.GUI_TEXTURED_SNIPPET) .withLocation(Identifier.fromNamespaceAndPath(Sputnik.MOD_ID, "pipeline/text")) - .withVertexFormat(DefaultVertexFormat.POSITION_TEX_COLOR, VertexFormat.Mode.TRIANGLES) + .withVertexBinding(0, DefaultVertexFormat.POSITION_TEX_COLOR) + .withPrimitiveTopology(PrimitiveTopology.TRIANGLES) .withVertexShader(Identifier.fromNamespaceAndPath(Sputnik.MOD_ID, "shaders/text.vert")) .withFragmentShader(Identifier.fromNamespaceAndPath(Sputnik.MOD_ID, "shaders/text.frag")) - .withSampler("u_Texture") + // 26.2 cambió los samplers por bind groups; ojo: los shaders de text.vert/frag + // siguen usando uniforms con nombre (u_Texture, u_ProjectionMatrix) y seguramente + // haya que reescribirlos para que casen con las convenciones nuevas + .withBindGroupLayout(BindGroupLayouts.SAMPLER0) // .withDepthTestFunction(DepthTestFunction.NO_DEPTH_TEST) // .withDepthWrite(false) // .withBlend(BlendFunction.TRANSLUCENT) diff --git a/src/main/java/me/retucio/sputnik/util/render/RenderUtil.java b/src/main/java/me/retucio/sputnik/util/render/RenderUtil.java index d9877f9..9485d1a 100644 --- a/src/main/java/me/retucio/sputnik/util/render/RenderUtil.java +++ b/src/main/java/me/retucio/sputnik/util/render/RenderUtil.java @@ -1,5 +1,6 @@ package me.retucio.sputnik.util.render; +import com.mojang.blaze3d.PrimitiveTopology; import com.mojang.blaze3d.vertex.*; import com.mojang.math.Axis; import net.minecraft.client.Camera; @@ -17,25 +18,24 @@ import java.awt.*; public class RenderUtil { private static final Minecraft mc = Minecraft.getInstance(); - private static final Tesselator tessellator = Tesselator.getInstance(); /* líneas */ public static void drawLine(PoseStack matrices, Vec3 from, Vec3 to, Color color, float lineWidth) { - BufferBuilder buffer = tessellator.begin(VertexFormat.Mode.LINES, DefaultVertexFormat.POSITION_COLOR_NORMAL_LINE_WIDTH); - Vec3 cam = mc.gameRenderer.getMainCamera().position(); + VertexConsumer buffer = SputnikBuffers.begin(DefaultVertexFormat.POSITION_COLOR_NORMAL_LINE_WIDTH, PrimitiveTopology.LINES); + Vec3 cam = mc.gameRenderer.mainCamera().position(); buffer.addVertex(matrices.last(), (float) (from.x - cam.x), (float) (from.y - cam.y), (float) (from.z - cam.z)).setColor(color.getRGB()).setNormal(-1, -1, -1).setLineWidth(lineWidth); buffer.addVertex(matrices.last(), (float) (to.x - cam.x), (float) (to.y - cam.y), (float) (to.z - cam.z)).setColor(color.getRGB()).setNormal(-1, -1, -1).setLineWidth(lineWidth); - SputnikRenderTypes.lines().draw(buffer.buildOrThrow()); + SputnikBuffers.draw(SputnikRenderTypes.lines()); } // https://github.com/TheF1xer/GateClient-1.12.2/blob/main/src/main/java/me/thef1xer/gateclient/util/RenderUtil.java public static void drawTracer(PoseStack matrices, Vec3 pos, Color color, float lineWidth) { - BufferBuilder buffer = tessellator.begin(VertexFormat.Mode.LINES, DefaultVertexFormat.POSITION_COLOR_NORMAL_LINE_WIDTH); - Camera cam = mc.gameRenderer.getMainCamera(); + VertexConsumer buffer = SputnikBuffers.begin(DefaultVertexFormat.POSITION_COLOR_NORMAL_LINE_WIDTH, PrimitiveTopology.LINES); + Camera cam = mc.gameRenderer.mainCamera(); Vector3f cameraVector = new Vector3f(0, 0, 1) .rotateX((float) Math.toRadians(cam.xRot())) @@ -43,11 +43,11 @@ public class RenderUtil { buffer.addVertex(matrices.last(), cameraVector.x, cameraVector.y, cameraVector.z).setColor(color.getRGB()).setNormal(-1, -1, -1).setLineWidth(lineWidth); buffer.addVertex(matrices.last(), (float) (pos.x - cam.position().x), (float) (pos.y - cam.position().y), (float) (pos.z - cam.position().z)).setColor(color.getRGB()).setNormal(-1, -1, -1).setLineWidth(lineWidth); - SputnikRenderTypes.lines().draw(buffer.buildOrThrow()); + SputnikBuffers.draw(SputnikRenderTypes.lines()); } public static void drawVector(PoseStack matrices, Vector3f start, Vec3 direction, Color c, float lineWidth) { - BufferBuilder buffer = tessellator.begin(VertexFormat.Mode.LINES, DefaultVertexFormat.POSITION_COLOR_NORMAL_LINE_WIDTH); + VertexConsumer buffer = SputnikBuffers.begin(DefaultVertexFormat.POSITION_COLOR_NORMAL_LINE_WIDTH, PrimitiveTopology.LINES); PoseStack.Pose pose = matrices.last(); int color = c.getRGB(); @@ -70,7 +70,7 @@ public class RenderUtil { .setNormal(pose, (float) direction.x, (float) direction.y, (float) direction.z) .setLineWidth(lineWidth); - SputnikRenderTypes.lines().draw(buffer.buildOrThrow()); + SputnikBuffers.draw(SputnikRenderTypes.lines()); } @@ -85,20 +85,20 @@ public class RenderUtil { matrices.pushPose(); matrices.translate(0, 0, 0); - BufferBuilder buffer = tessellator.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_COLOR); + VertexConsumer buffer = SputnikBuffers.begin(DefaultVertexFormat.POSITION_COLOR, PrimitiveTopology.QUADS); buffer.addVertex(matrices.last().pose(), x, y + height, 0).setColor(r, g, b, a); buffer.addVertex(matrices.last().pose(), x + width, y + height, 0).setColor(r, g, b, a); buffer.addVertex(matrices.last().pose(), x + width, y, 0).setColor(r, g, b, a); buffer.addVertex(matrices.last().pose(), x, y, 0).setColor(r, g, b, a); - SputnikRenderTypes.quads().draw(buffer.buildOrThrow()); + SputnikBuffers.draw(SputnikRenderTypes.quads()); matrices.popPose(); } public static void drawBlockFaceOutlines(PoseStack matrices, BlockPos pos, Direction face, Color color, float lineWidth, boolean cull) { if (lineWidth <= 0) return; - Vec3 cameraPos = mc.gameRenderer.getMainCamera().position(); + Vec3 cameraPos = mc.gameRenderer.mainCamera().position(); float minX = (float) (pos.getX() - cameraPos.x); float minY = (float) (pos.getY() - cameraPos.y); @@ -107,7 +107,7 @@ public class RenderUtil { float maxY = minY + 1; float maxZ = minZ + 1; - BufferBuilder buffer = tessellator.begin(VertexFormat.Mode.LINES, DefaultVertexFormat.POSITION_COLOR_NORMAL_LINE_WIDTH); + VertexConsumer buffer = SputnikBuffers.begin(DefaultVertexFormat.POSITION_COLOR_NORMAL_LINE_WIDTH, PrimitiveTopology.LINES); switch (face) { case UP: @@ -201,13 +201,13 @@ public class RenderUtil { break; } - if (cull) SputnikRenderTypes.linesCull().draw(buffer.buildOrThrow()); - else SputnikRenderTypes.lines().draw(buffer.buildOrThrow()); + if (cull) SputnikBuffers.draw(SputnikRenderTypes.linesCull()); + else SputnikBuffers.draw(SputnikRenderTypes.lines()); } // expand es para evitar z-fighting public static void drawBlockFaceFilled(PoseStack matrices, BlockPos pos, Direction face, Color color, float expand, boolean cull) { - Vec3 cameraPos = mc.gameRenderer.getMainCamera().position(); + Vec3 cameraPos = mc.gameRenderer.mainCamera().position(); float minX = (float) (pos.getX() - cameraPos.x); float minY = (float) (pos.getY() - cameraPos.y); @@ -232,7 +232,7 @@ public class RenderUtil { } } - BufferBuilder buffer = tessellator.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_COLOR); + VertexConsumer buffer = SputnikBuffers.begin(DefaultVertexFormat.POSITION_COLOR, PrimitiveTopology.QUADS); switch (face) { case DOWN: @@ -278,8 +278,8 @@ public class RenderUtil { break; } - if (cull) SputnikRenderTypes.quadsCull().draw(buffer.buildOrThrow()); - else SputnikRenderTypes.quads().draw(buffer.buildOrThrow()); + if (cull) SputnikBuffers.draw(SputnikRenderTypes.quadsCull()); + else SputnikBuffers.draw(SputnikRenderTypes.quads()); } @@ -289,18 +289,18 @@ public class RenderUtil { float b = color.getBlue() / 255f; float a = color.getAlpha() / 255f; - BufferBuilder buffer = tessellator.begin(VertexFormat.Mode.TRIANGLES, DefaultVertexFormat.POSITION_COLOR); + VertexConsumer buffer = SputnikBuffers.begin(DefaultVertexFormat.POSITION_COLOR, PrimitiveTopology.TRIANGLES); buffer.addVertex(matrices.last().pose(), x1, y1, 0).setColor(r, g, b, a); buffer.addVertex(matrices.last().pose(), x2, y2, 0).setColor(r, g, b, a); buffer.addVertex(matrices.last().pose(), x3, y3, 0).setColor(r, g, b, a); - SputnikRenderTypes.quads().draw(buffer.buildOrThrow()); + SputnikBuffers.draw(SputnikRenderTypes.quads()); } // cajas public static void drawOutlineBox(PoseStack matrices, AABB box, Color color, float lineWidth, boolean cull) { if (lineWidth <= 0) return; - Vec3 cameraPos = mc.gameRenderer.getMainCamera().position(); + Vec3 cameraPos = mc.gameRenderer.mainCamera().position(); float minX = (float) (box.minX - cameraPos.x); float minY = (float) (box.minY - cameraPos.y); @@ -309,7 +309,7 @@ public class RenderUtil { float maxY = (float) (box.maxY - cameraPos.y); float maxZ = (float) (box.maxZ - cameraPos.z); - BufferBuilder buffer = tessellator.begin(VertexFormat.Mode.LINES, DefaultVertexFormat.POSITION_COLOR_NORMAL_LINE_WIDTH); + VertexConsumer buffer = SputnikBuffers.begin(DefaultVertexFormat.POSITION_COLOR_NORMAL_LINE_WIDTH, PrimitiveTopology.LINES); // parte inferior buffer.addVertex(matrices.last(), minX, minY, minZ).setColor(color.getRGB()).setNormal(-1, -1, -1).setLineWidth(lineWidth); @@ -350,12 +350,12 @@ public class RenderUtil { buffer.addVertex(matrices.last(), minX, minY, maxZ).setColor(color.getRGB()).setNormal(-1, -1, -1).setLineWidth(lineWidth); buffer.addVertex(matrices.last(), minX, maxY, maxZ).setColor(color.getRGB()).setNormal(-1, -1, -1).setLineWidth(lineWidth); - if (cull) SputnikRenderTypes.linesCull().draw(buffer.buildOrThrow()); - else SputnikRenderTypes.lines().draw(buffer.buildOrThrow()); + if (cull) SputnikBuffers.draw(SputnikRenderTypes.linesCull()); + else SputnikBuffers.draw(SputnikRenderTypes.lines()); } public static void drawFilledBox(PoseStack matrices, AABB box, Color color, boolean cull) { - Vec3 cameraPos = mc.gameRenderer.getMainCamera().position(); + Vec3 cameraPos = mc.gameRenderer.mainCamera().position(); float minX = (float) (box.minX - cameraPos.x); float minY = (float) (box.minY - cameraPos.y); @@ -364,7 +364,7 @@ public class RenderUtil { float maxY = (float) (box.maxY - cameraPos.y); float maxZ = (float) (box.maxZ - cameraPos.z); - BufferBuilder buffer = tessellator.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_COLOR); + VertexConsumer buffer = SputnikBuffers.begin(DefaultVertexFormat.POSITION_COLOR, PrimitiveTopology.QUADS); buffer.addVertex(matrices.last().pose(), minX, minY, minZ).setColor(color.getRGB()); buffer.addVertex(matrices.last().pose(), maxX, minY, minZ).setColor(color.getRGB()); @@ -396,8 +396,8 @@ public class RenderUtil { buffer.addVertex(matrices.last().pose(), minX, maxY, maxZ).setColor(color.getRGB()); buffer.addVertex(matrices.last().pose(), minX, maxY, minZ).setColor(color.getRGB()); - if (cull) SputnikRenderTypes.quadsCull().draw(buffer.buildOrThrow()); - else SputnikRenderTypes.quads().draw(buffer.buildOrThrow()); + if (cull) SputnikBuffers.draw(SputnikRenderTypes.quadsCull()); + else SputnikBuffers.draw(SputnikRenderTypes.quads()); } @@ -450,7 +450,7 @@ public class RenderUtil { public static PoseStack matrixFrom(Vec3 pos) { PoseStack matrices = new PoseStack(); - Camera camera = mc.gameRenderer.getMainCamera(); + Camera camera = mc.gameRenderer.mainCamera(); Vec3 camPos = camera.position(); matrices.mulPose(Axis.XP.rotationDegrees(camera.yRot())); diff --git a/src/main/java/me/retucio/sputnik/util/render/SputnikBuffers.java b/src/main/java/me/retucio/sputnik/util/render/SputnikBuffers.java new file mode 100644 index 0000000..ce9c2ce --- /dev/null +++ b/src/main/java/me/retucio/sputnik/util/render/SputnikBuffers.java @@ -0,0 +1,60 @@ +package me.retucio.sputnik.util.render; + +import com.mojang.blaze3d.PrimitiveTopology; +import com.mojang.blaze3d.vertex.VertexConsumer; +import com.mojang.blaze3d.vertex.VertexFormat; +import me.retucio.sputnik.Sputnik; +import net.minecraft.client.renderer.StagedVertexBuffer; +import net.minecraft.client.renderer.rendertype.RenderType; + + +/** emula el antiguo Tesselator + RenderType.draw(MeshData), que 26.2 se cargó + *

+ * ahora los vértices se escriben en un StagedVertexBuffer: se pide un draw, se + * escriben los vértices, se sube todo a la gpu y se dibuja. el ciclo es + * appendDraw -> upload -> drawFromBuffer -> endDraw; upload() peta si se llama + * dos veces sin endDraw() de por medio. + *

+ * subimos y dibujamos en cada llamada (en vez de agrupar draws) para mantener el + * mismo orden de dibujado que antes; es menos eficiente pero se comporta igual. + */ +public class SputnikBuffers { + + private static StagedVertexBuffer buffer; + private static StagedVertexBuffer.Draw current; + + // lazy: al cargar la clase todavía puede no haber device + private static StagedVertexBuffer buffer() { + if (buffer == null) { + buffer = new StagedVertexBuffer(() -> Sputnik.MOD_ID, RenderType.SMALL_BUFFER_SIZE); + } + return buffer; + } + + public static VertexConsumer begin(VertexFormat format, PrimitiveTopology topology) { + if (current != null) buffer().endDraw(); // por si quedó un draw a medias + + current = buffer().appendDraw(format, topology); + return buffer().getVertexBuilder(current); + } + + public static void draw(RenderType type) { + if (current == null) return; + + if (!current.isEmpty()) { + buffer().upload(); + type.prepare().drawFromBuffer(buffer().getExecuteInfo(current)); + } + + buffer().endDraw(); + current = null; + } + + // devuelve los buffers al pool; una vez por frame + public static void endFrame() { + if (buffer == null) return; + + current = null; + buffer.endFrame(); + } +} diff --git a/src/main/resources/assets/sputnik/lang/en_us.json b/src/main/resources/assets/sputnik/lang/en_us.json new file mode 100644 index 0000000..909dfba --- /dev/null +++ b/src/main/resources/assets/sputnik/lang/en_us.json @@ -0,0 +1,1441 @@ +{ + "sputnik.args.entity.notfound": "entity \"%s\" not found", + "sputnik.args.enum.invalid": " invalid argument: %s", + "sputnik.args.module.notfound": "module \"%s\" not found", + "sputnik.args.player.notfound": "player \"%s\" doesn't exist", + "sputnik.category.camara": "camera", + "sputnik.category.cliente": "client", + "sputnik.category.combate": "combat", + "sputnik.category.inventario": "inventory", + "sputnik.category.jugador": "player", + "sputnik.category.misc": "misc.", + "sputnik.category.movimiento": "movement", + "sputnik.category.mundo": "world", + "sputnik.category.red": "network", + "sputnik.category.renderizado": "render", + "sputnik.commands.bind.desc": "binds a key to a module", + "sputnik.commands.bind.keybound": "key %s bound to module %s", + "sputnik.commands.bind.keyreset": "keybind for module %s reset to %s", + "sputnik.commands.bind.keytaken": "key already bound to module %s", + "sputnik.commands.bind.presskey": "press a key to bind it to module %s", + "sputnik.commands.clickslot.desc": "simulates clicking a slot", + "sputnik.commands.config.desc": "opens the settings panel of a module", + "sputnik.commands.copyscreenshot.desc": "copies the most recent screenshot to the clipboard", + "sputnik.commands.echest.desc": "shows the contents of your enderchest (view only)", + "sputnik.commands.echest.openfirst": "you need to open an enderchest once first", + "sputnik.commands.friend.added": "%s is now your friend :)", + "sputnik.commands.friend.desc": "friend management", + "sputnik.commands.friend.list": "friends:", + "sputnik.commands.friend.removed": "%s is not your friend anymore :(", + "sputnik.commands.gc.collected": "garbage collected", + "sputnik.commands.gc.desc": "frees up ram using the garbage collector (gc)", + "sputnik.commands.peek.desc": "peeks at another player's inventory", + "sputnik.commands.plugins.calmdown": "calm dooown", + "sputnik.commands.plugins.desc": "looks for the plugins the server has", + "sputnik.commands.plugins.erroranalyzingcommands": "error analyzing commands: %s", + "sputnik.commands.plugins.namespacesfound": "%s command namespace(s) found:", + "sputnik.commands.plugins.noplugins": "no plugins (probably)", + "sputnik.commands.plugins.pluginsfound": "%s plugin(s) found", + "sputnik.commands.plugins.singleplayer": "you are in singleplayer", + "sputnik.commands.prefix.changed": "prefix changed to %s", + "sputnik.commands.prefix.desc": "changes the command prefix", + "sputnik.commands.purge.desc": "removes messages from the chat", + "sputnik.commands.repeat.desc": "repeats a command x times", + "sputnik.commands.repeatwait.desc": "combination of $repeat and $wait", + "sputnik.commands.savescreenshot.desc": "saves the most recent screenshot locally", + "sputnik.commands.savescreenshot.error": "the screenshot could not be saved", + "sputnik.commands.send.desc": "sends a message in the chat", + "sputnik.commands.spectate.desc": "lets you take the point of view of an entity", + "sputnik.commands.toggle.desc": "toggles modules on / off", + "sputnik.commands.wait.desc": "waits a given amount of time before running another command", + "sputnik.config.autosaving.desc": "saving settings...", + "sputnik.config.autosaving.title": "autosaving...", + "sputnik.config.error.empty": "config file empty or nonexistent", + "sputnik.config.error.invalidformat": "invalid file format: %s", + "sputnik.config.error.invalidversion": "invalid version: %s", + "sputnik.config.error.json": "error loading json, using defaults", + "sputnik.config.error.loading": "error loading settings, trying json", + "sputnik.config.error.saving": "error saving settings", + "sputnik.config.error.serialization": "error serializing settings", + "sputnik.config.error.toosmall": "file too small to be valid", + "sputnik.config.info.applied": "settings applied", + "sputnik.config.info.clientsettings": "client settings applied", + "sputnik.config.info.extendablepanels": "extendable panel positions applied", + "sputnik.config.info.friends": "friends applied", + "sputnik.config.info.json": "json settings loaded (migration)", + "sputnik.config.info.loaded": "settings loaded", + "sputnik.config.info.loading": "loading settings...", + "sputnik.config.info.modulesettings": "module settings applied", + "sputnik.config.info.modulestates": "module states applied", + "sputnik.config.info.saved": "settings saved", + "sputnik.config.info.searchbar": "search bar position applied", + "sputnik.config.info.settingspanels": "settings panel states applied", + "sputnik.config.warn.nullmodule": "\"null\" as a module (\"%s\")", + "sputnik.config.warn.thread": "the saving thread did not finish in time", + "sputnik.config.warn.unknownsetting": "watafak izzat: %s", + "sputnik.enum.module.module.keymode.hold": "hold", + "sputnik.enum.module.module.keymode.toggle": "toggle", + "sputnik.enum.module.module.notifymode.chat": "chat", + "sputnik.enum.module.module.notifymode.widget": "widget", + "sputnik.enum.module.modules.camera.autism.rotationdirection.clockwise": "clockwise", + "sputnik.enum.module.modules.camera.autism.rotationdirection.counterclockwise": "counterclockwise", + "sputnik.enum.module.modules.camera.freelook.cameramode.camera": "camera", + "sputnik.enum.module.modules.camera.freelook.cameramode.player": "player", + "sputnik.enum.module.modules.camera.fullbright.modes.gamma": "gamma", + "sputnik.enum.module.modules.camera.fullbright.modes.potion": "potion", + "sputnik.enum.module.modules.client.discordrpc.activitytypes.competing": "competing", + "sputnik.enum.module.modules.client.discordrpc.activitytypes.custom": "custom", + "sputnik.enum.module.modules.client.discordrpc.activitytypes.listening": "listening to", + "sputnik.enum.module.modules.client.discordrpc.activitytypes.playing": "playing", + "sputnik.enum.module.modules.client.discordrpc.activitytypes.streaming": "streaming", + "sputnik.enum.module.modules.client.discordrpc.activitytypes.watching": "watching", + "sputnik.enum.module.modules.client.hud.coordsmode.both": "both", + "sputnik.enum.module.modules.client.hud.coordsmode.nether": "nether", + "sputnik.enum.module.modules.client.hud.coordsmode.overworld": "surface", + "sputnik.enum.module.modules.client.hud.dynosaurs.ankylosaurus": "ankylosaurus", + "sputnik.enum.module.modules.client.hud.dynosaurs.pterodactyl": "pterodactyl", + "sputnik.enum.module.modules.client.hud.dynosaurs.spinosaurus": "spinosaurus", + "sputnik.enum.module.modules.client.hud.dynosaurs.trex": "t-rex", + "sputnik.enum.module.modules.client.hud.dynosaurs.triceratops": "triceratops", + "sputnik.enum.module.modules.client.hud.dynosaurs.velocirraptor": "velociraptor", + "sputnik.enum.module.modules.client.hud.timeformat.twelve_hour": "12h", + "sputnik.enum.module.modules.client.hud.timeformat.twenty_four_hour": "24h", + "sputnik.enum.module.modules.combat.projectiletrajectories.trajectorystyle.dashed": "dashed", + "sputnik.enum.module.modules.combat.projectiletrajectories.trajectorystyle.dotted": "points", + "sputnik.enum.module.modules.combat.projectiletrajectories.trajectorystyle.solid": "solid", + "sputnik.enum.module.modules.combat.projectiletrajectories.trajectorytargets.blocks": "blocks", + "sputnik.enum.module.modules.combat.projectiletrajectories.trajectorytargets.both": "both", + "sputnik.enum.module.modules.combat.projectiletrajectories.trajectorytargets.entities": "entities", + "sputnik.enum.module.modules.combat.projectiletrajectories.trajectorytargets.none": "none", + "sputnik.enum.module.modules.misc.anvilfont.fontmode.circled": "round", + "sputnik.enum.module.modules.misc.anvilfont.fontmode.cursed": "well weird", + "sputnik.enum.module.modules.misc.anvilfont.fontmode.greek": "greek", + "sputnik.enum.module.modules.misc.anvilfont.fontmode.normal": "normal", + "sputnik.enum.module.modules.misc.anvilfont.fontmode.uppercase": "uppercase", + "sputnik.enum.module.modules.misc.screenshotplus.screenshotactions.copy": "copy to clipboard", + "sputnik.enum.module.modules.misc.screenshotplus.screenshotactions.none": "do nothing", + "sputnik.enum.module.modules.misc.screenshotplus.screenshotactions.save": "save file", + "sputnik.enum.module.modules.movement.jesus.jesusmode.solid": "solid", + "sputnik.enum.module.modules.movement.jesus.jesusmode.vibrate": "vibrator", + "sputnik.enum.module.modules.movement.scaffold.listmode.blacklist": "blacklist (exclude)", + "sputnik.enum.module.modules.movement.scaffold.listmode.whitelist": "whitelist (include)", + "sputnik.enum.module.modules.network.packetdelay.directions.both": "both", + "sputnik.enum.module.modules.network.packetdelay.directions.c2s": "client to server", + "sputnik.enum.module.modules.network.packetdelay.directions.s2c": "server to client", + "sputnik.enum.module.modules.network.packetdelay.packets.all": "all", + "sputnik.enum.module.modules.network.packetdelay.packets.keep_alive": "KeepAlive packets", + "sputnik.enum.module.modules.network.packetdelay.packets.others": "all but KeepAlive", + "sputnik.enum.module.modules.network.packetmine.clickaction.add_priority": "add priority", + "sputnik.enum.module.modules.network.packetmine.clickaction.none": "nothing", + "sputnik.enum.module.modules.network.packetmine.clickaction.unselect": "unselect", + "sputnik.enum.module.modules.network.packetmine.rotatemode.both": "both", + "sputnik.enum.module.modules.network.packetmine.rotatemode.client": "camera", + "sputnik.enum.module.modules.network.packetmine.rotatemode.none": "no", + "sputnik.enum.module.modules.network.packetmine.rotatemode.server": "via packets", + "sputnik.enum.module.modules.player.nofall.nofallmode.clutch": "waterdrop", + "sputnik.enum.module.modules.player.nofall.nofallmode.packet": "packets", + "sputnik.enum.module.modules.render.breakingprogress.breakmode.inwards": "inwards", + "sputnik.enum.module.modules.render.breakingprogress.breakmode.outwards": "outwards", + "sputnik.enum.module.modules.render.entityesp.espmode.box": "3d box", + "sputnik.enum.module.modules.render.entityesp.espmode.glow": "glow effect", + "sputnik.enum.module.modules.render.glintplus.glintcolors.black": "black", + "sputnik.enum.module.modules.render.glintplus.glintcolors.blue": "blue", + "sputnik.enum.module.modules.render.glintplus.glintcolors.brown": "brown", + "sputnik.enum.module.modules.render.glintplus.glintcolors.cyan": "cyan", + "sputnik.enum.module.modules.render.glintplus.glintcolors.gray": "gray", + "sputnik.enum.module.modules.render.glintplus.glintcolors.green": "green", + "sputnik.enum.module.modules.render.glintplus.glintcolors.light_blue": "light blue", + "sputnik.enum.module.modules.render.glintplus.glintcolors.light_gray": "silver", + "sputnik.enum.module.modules.render.glintplus.glintcolors.lime": "lime", + "sputnik.enum.module.modules.render.glintplus.glintcolors.magenta": "magenta", + "sputnik.enum.module.modules.render.glintplus.glintcolors.none": "off", + "sputnik.enum.module.modules.render.glintplus.glintcolors.orange": "orange", + "sputnik.enum.module.modules.render.glintplus.glintcolors.pink": "pink", + "sputnik.enum.module.modules.render.glintplus.glintcolors.purple": "purple", + "sputnik.enum.module.modules.render.glintplus.glintcolors.rainbow": "gay.", + "sputnik.enum.module.modules.render.glintplus.glintcolors.red": "red", + "sputnik.enum.module.modules.render.glintplus.glintcolors.white": "white", + "sputnik.enum.module.modules.render.glintplus.glintcolors.yellow": "yellow", + "sputnik.enum.module.modules.render.nametags.healthmode.hearts": "hearts", + "sputnik.enum.module.modules.render.nametags.healthmode.points": "hp (health points)", + "sputnik.enum.module.modules.render.norender.colors.aqua": "teal", + "sputnik.enum.module.modules.render.norender.colors.black": "black", + "sputnik.enum.module.modules.render.norender.colors.blue": "blue", + "sputnik.enum.module.modules.render.norender.colors.dark_aqua": "cyan", + "sputnik.enum.module.modules.render.norender.colors.dark_blue": "dark blue", + "sputnik.enum.module.modules.render.norender.colors.dark_gray": "dark gray", + "sputnik.enum.module.modules.render.norender.colors.dark_green": "green", + "sputnik.enum.module.modules.render.norender.colors.dark_purple": "purple", + "sputnik.enum.module.modules.render.norender.colors.dark_red": "maroon", + "sputnik.enum.module.modules.render.norender.colors.default": "default", + "sputnik.enum.module.modules.render.norender.colors.gold": "orange", + "sputnik.enum.module.modules.render.norender.colors.gray": "light gray", + "sputnik.enum.module.modules.render.norender.colors.green": "lime", + "sputnik.enum.module.modules.render.norender.colors.light_purple": "purple", + "sputnik.enum.module.modules.render.norender.colors.red": "red", + "sputnik.enum.module.modules.render.norender.colors.white": "white", + "sputnik.enum.module.modules.render.norender.colors.yellow": "yellow", + "sputnik.enum.module.modules.world.blockinfo.copymode.command": "copy /setblock command", + "sputnik.enum.module.modules.world.blockinfo.copymode.dont": "don't copy", + "sputnik.enum.module.modules.world.blockinfo.copymode.json": "copy json contents", + "sputnik.enum.module.modules.world.timechanger.moonphases.default": "default", + "sputnik.enum.module.modules.world.timechanger.moonphases.first_quarter": "first quarter", + "sputnik.enum.module.modules.world.timechanger.moonphases.full_moon": "full moon", + "sputnik.enum.module.modules.world.timechanger.moonphases.new_moon": "new moon", + "sputnik.enum.module.modules.world.timechanger.moonphases.third_quarter": "last quarter", + "sputnik.enum.module.modules.world.timechanger.moonphases.waning_crescent": "waning crescent", + "sputnik.enum.module.modules.world.timechanger.moonphases.waning_gibbous": "waning gibbous", + "sputnik.enum.module.modules.world.timechanger.moonphases.waxing_crescent": "waxing crescent", + "sputnik.enum.module.modules.world.timechanger.moonphases.waxing_gibbous": "waxing gibbous", + "sputnik.group.andamios.bloques": "blocks", + "sputnik.group.andamios.puente": "bridge", + "sputnik.group.andamios.renderizado": "render", + "sputnik.group.auradecristales.colocar": "place", + "sputnik.group.auradecristales.renderizado": "render", + "sputnik.group.auradecristales.reventar": "pop", + "sputnik.group.autopesca.recast": "recast", + "sputnik.group.camaralibre.velocidad": "speed", + "sputnik.group.capturasdepantalla.botones": "buttons", + "sputnik.group.chatplus.funcionamientodelchat": "chat behavior", + "sputnik.group.cielocustom.cuerposceleste": "celestial bodies", + "sputnik.group.colocarenaire.renderizado": "render", + "sputnik.group.colocarenaire.scrolleo": "scrolling", + "sputnik.group.common.general": "general", + "sputnik.group.common.module": "module", + "sputnik.group.criticos.aspecto": "look", + "sputnik.group.criticos.funcionamiento": "behavior", + "sputnik.group.discordrpc.boton": "button", + "sputnik.group.discordrpc.imagenes": "images", + "sputnik.group.hud.editor": "editor", + "sputnik.group.hud.elementos": "elements", + "sputnik.group.hud.visualizacion": "display", + "sputnik.group.interfaz.chat": "chat", + "sputnik.group.interfaz.interfaz": "gui", + "sputnik.group.interfaz.misc": "misc.", + "sputnik.group.interfaz.widgets": "widgets", + "sputnik.group.jesus.bloques": "blocks", + "sputnik.group.jkrowling.libro": "book", + "sputnik.group.manos.animaciones": "animations", + "sputnik.group.manos.brazo": "arm", + "sputnik.group.manos.manoprincipal": "main hand", + "sputnik.group.manos.manosecundaria": "offhand", + "sputnik.group.moro.teclas": "keys", + "sputnik.group.nametags.infoadicional": "extra info", + "sputnik.group.norender.ambiente": "ambient", + "sputnik.group.norender.efectos": "effects", + "sputnik.group.norender.interfaz": "gui", + "sputnik.group.norender.misc": "misc.", + "sputnik.group.norender.overlays": "overlays", + "sputnik.group.norender.texto": "text", + "sputnik.group.notificaciones.bajadurabilidad": "low durability", + "sputnik.group.notificaciones.jugadorenrango": "player in range", + "sputnik.group.notificaciones.sonido": "sound", + "sputnik.group.particulas.desplazamiento": "offset", + "sputnik.group.particulas.dispersion": "spread", + "sputnik.group.perspectivaplus.scrolleo": "scrolling", + "sputnik.group.progresodeminado.contorno": "outline", + "sputnik.group.progresodeminado.relleno": "fill", + "sputnik.group.puntosdedesconexion.contorno": "outline", + "sputnik.group.puntosdedesconexion.misc": "misc.", + "sputnik.group.puntosdedesconexion.relleno": "fill", + "sputnik.group.resaltadodebloques.busqueda": "search", + "sputnik.group.resaltadodebloques.contorno": "outline", + "sputnik.group.resaltadodebloques.relleno": "fill", + "sputnik.group.resaltadodeentidades.cajas": "boxes", + "sputnik.group.retroceso.tipos": "types", + "sputnik.group.selecciondeminado.renderizado": "render", + "sputnik.group.superposiciondeluz.colores": "colors", + "sputnik.group.superposiciondeluz.deteccion": "detection", + "sputnik.group.superposiciondeluz.optimizacion": "optimization", + "sputnik.group.trayectoria.contorno": "outline", + "sputnik.group.trayectoria.resaltado": "highlight", + "sputnik.group.trayectoria.trayectoria": "trajectory", + "sputnik.group.trazos.colores": "colors", + "sputnik.group.zoom.camara": "camera", + "sputnik.group.zoom.scrolleo": "scrolling", + "sputnik.group.zoom.visual": "visual", + "sputnik.hud.disabled": "the HUD is disabled, genius", + "sputnik.hud.editor.instructions": "drag to move · right click for visibility · ESC to save and exit · shift + right click to reset", + "sputnik.hud.editor.title": "HUD editor", + "sputnik.hud.element.armor.desc": "armor status", + "sputnik.hud.element.coords.desc": "shows your XYZ position in the world", + "sputnik.hud.element.customtext.desc": "text of your choosing", + "sputnik.hud.element.customtext.name": "custom text", + "sputnik.hud.element.dyno.desc": "long live autism goddamn", + "sputnik.hud.element.dyno.name": "dinosaur: %s", + "sputnik.hud.element.echest.desc": "items in your echest", + "sputnik.hud.element.echest.name": "echest", + "sputnik.hud.element.fps.desc": "shows the frames per second the game is running at", + "sputnik.hud.element.fps.name": "FPS", + "sputnik.hud.element.ping.desc": "latency between client and server, in milliseconds", + "sputnik.hud.element.ping.name": "ping", + "sputnik.hud.element.rotation.desc": "shows your current rotation", + "sputnik.hud.element.rotation.name": "rotations", + "sputnik.hud.element.time.desc": "hours and minutes in the selected timezone", + "sputnik.hud.element.time.name": "time", + "sputnik.hud.element.totems.desc": "totems available", + "sputnik.hud.element.tps.desc": "shows the server's ticks per second (optimal TPS: 20)", + "sputnik.hud.element.tps.name": "TPS", + "sputnik.hud.element.uptime.desc": "time played", + "sputnik.hud.error.texture": "could not load the texture for HUD element %s: %s", + "sputnik.hud.info.textureloaded": "texture for HUD element %s loaded", + "sputnik.key.altgr": "alt gr", + "sputnik.key.backspace": "backspace", + "sputnik.key.capslock": "caps lock", + "sputnik.key.delete": "delete", + "sputnik.key.down": "down", + "sputnik.key.enter": "enter", + "sputnik.key.insert": "insert", + "sputnik.key.left": "left", + "sputnik.key.leftalt": "left alt", + "sputnik.key.leftclick": "left click", + "sputnik.key.leftctrl": "left ctrl", + "sputnik.key.leftshift": "left shift", + "sputnik.key.middleclick": "middle click", + "sputnik.key.mousebutton": "mouse button %s", + "sputnik.key.none": "none", + "sputnik.key.pagedown": "page down", + "sputnik.key.pageup": "page up", + "sputnik.key.right": "right", + "sputnik.key.rightclick": "right click", + "sputnik.key.rightctrl": "right ctrl", + "sputnik.key.rightshift": "right shift", + "sputnik.key.space": "space", + "sputnik.key.tab": "tab", + "sputnik.key.unknown": "key %s", + "sputnik.key.up": "up", + "sputnik.module.aliviarcpu.desc": "avoids rendering things on screen if the window is not focused", + "sputnik.module.aliviarcpu.name": "cpu saver", + "sputnik.module.amigos.desc": "friend system to avoid attacking certain players with combat modules", + "sputnik.module.amigos.name": "friends", + "sputnik.module.andamios.desc": "automatically places blocks under your feet", + "sputnik.module.andamios.name": "scaffold", + "sputnik.module.antihambre.desc": "prevents hunger by making the server think you never sprint", + "sputnik.module.antihambre.name": "no hunger", + "sputnik.module.antiinvis.desc": "lets you see invisible players", + "sputnik.module.antiinvis.name": "anti invis", + "sputnik.module.apilarbossbars.desc": "stacks bossbars to reduce the space they take up on screen", + "sputnik.module.apilarbossbars.name": "stack bossbars", + "sputnik.module.attributeswapper.desc": "uses \"attribute swapping\" between two tools to negate durability damage or apply extra enchantments to them", + "sputnik.module.attributeswapper.name": "attribute-swapper", + "sputnik.module.auradecristales.desc": "places and pops end crystals for you", + "sputnik.module.auradecristales.name": "crystal aura", + "sputnik.module.autismo.desc": "hehe", + "sputnik.module.autismo.name": "autism", + "sputnik.module.autocartel.desc": "lets you place signs with the same text without typing it out one by one", + "sputnik.module.autocartel.name": "auto sign", + "sputnik.module.autofish.rodbreaking": "the rod is about to break", + "sputnik.module.autoherramienta.desc": "automatically switches to the right tool", + "sputnik.module.autoherramienta.name": "auto tool", + "sputnik.module.autopechera.desc": "switches to a chestplate before hitting with the mace", + "sputnik.module.autopechera.name": "auto chestplate", + "sputnik.module.autopesca.desc": "fishes for you", + "sputnik.module.autopesca.name": "auto fish", + "sputnik.module.autosign.placefirst": "place a first sign to copy the contents from", + "sputnik.module.avioneta.desc": "fly forever, taking advantage of the broken system mojang made (you need to drop from about 50 blocks up)", + "sputnik.module.avioneta.name": "little plane", + "sputnik.module.barcovolador.desc": "turns your acacia boat into a Lockheed F-117 Nighthawk", + "sputnik.module.barcovolador.name": "flying boat", + "sputnik.module.blockinfo.noblock": "you're not looking at any block", + "sputnik.module.blockinfo.noproperties": "this block has no properties to copy", + "sputnik.module.bookbot.created": "created book no. %s", + "sputnik.module.bookbot.nobook": "no book found", + "sputnik.module.brillibrilli.desc": "disables darkness (and applies colors to shaders)", + "sputnik.module.brillibrilli.name": "bling bling", + "sputnik.module.bungeespoofer.invalidip": "invalid IP address", + "sputnik.module.burglar.dump": "dump", + "sputnik.module.burglar.steal": "steal", + "sputnik.module.bypassearpacks.desc": "lets you skip resource packs forced by servers", + "sputnik.module.bypassearpacks.name": "bypass packs", + "sputnik.module.camaralibre.desc": "lets the camera move independently from the player. useful for scouting around", + "sputnik.module.camaralibre.name": "freecam", + "sputnik.module.capas.desc": "choose which cape to wear (only visible to you)", + "sputnik.module.capas.name": "capes", + "sputnik.module.capturasdepantalla.desc": "choose what to do after taking a screenshot", + "sputnik.module.capturasdepantalla.name": "screenshots", + "sputnik.module.cartelesgays.desc": "lets you use a symbol of your choice as § to format them.", + "sputnik.module.cartelesgays.name": "gay signs", + "sputnik.module.chatplus.coordswarn": "careful with those coords, kiddo", + "sputnik.module.chatplus.desc": "chat improvements", + "sputnik.module.chatplus.name": "chat plus", + "sputnik.module.chatplus.sendanyway": "[I DON'T GIVE A DAMN]", + "sputnik.module.chatplus.sendanyway.hint": "send anyway:", + "sputnik.module.chestplateswitch.nochestplate": "no chestplate found in the hotbar", + "sputnik.module.cielocustom.desc": "lets you visually change the time of day, among other things", + "sputnik.module.cielocustom.name": "custom sky", + "sputnik.module.cocaina.desc": "changes the speed of everything in the game", + "sputnik.module.cocaina.name": "cocaine", + "sputnik.module.colocarenaire.desc": "lets you place blocks in the air", + "sputnik.module.colocarenaire.name": "place in air", + "sputnik.module.conejo.desc": "do the elytra bounce by holding space", + "sputnik.module.conejo.name": "rabbit", + "sputnik.module.confetti.desc": "changes the color of the totem pop particles", + "sputnik.module.confetti.name": "confetti", + "sputnik.module.contorno.desc": "customizes the block outline", + "sputnik.module.contorno.name": "outline", + "sputnik.module.criticos.desc": "changes the look of crits to your liking", + "sputnik.module.criticos.name": "crits", + "sputnik.module.delaydepaquetes.desc": "applies a delay to packets", + "sputnik.module.delaydepaquetes.name": "packet delay", + "sputnik.module.delfin.desc": "*dolphin noise*", + "sputnik.module.delfin.name": "dolphin", + "sputnik.module.destellodeenchants.desc": "changes the color of the enchantment glint", + "sputnik.module.destellodeenchants.name": "enchant glint", + "sputnik.module.desyncdehitbox.desc": "chinese exploit", + "sputnik.module.desyncdehitbox.name": "hitbox desync", + "sputnik.module.discordrpc.desc": "customizes your activity on dishcord", + "sputnik.module.discordrpc.disconnected": "disconnected: %s - %s", + "sputnik.module.discordrpc.error": "error: %s - %s", + "sputnik.module.discordrpc.initerror": "error initializing rpc: %s", + "sputnik.module.discordrpc.name": "discordRPC", + "sputnik.module.discordrpc.notanumber": "enter a NUMBER (or leave it empty)", + "sputnik.module.discordrpc.notoken": "set the bot token first", + "sputnik.module.discordrpc.unsupportedos": "unsupported operating system", + "sputnik.module.discordrpc.updateerror": "error updating rpc: %s", + "sputnik.module.donquijote.desc": "cheats for the spear", + "sputnik.module.donquijote.name": "don quixote", + "sputnik.module.dupedebundle.desc": "dupes items using a bundle and a book", + "sputnik.module.dupedebundle.name": "bundle dupe", + "sputnik.module.elytras.desc": "fly with elytra", + "sputnik.module.elytras.name": "elytra", + "sputnik.module.escalerasveloces.desc": "climb ladders faster", + "sputnik.module.escalerasveloces.name": "fast ladders", + "sputnik.module.escalones.desc": "makes the step-up height whatever you want", + "sputnik.module.escalones.name": "step", + "sputnik.module.escalonesinversos.desc": "step but downwards", + "sputnik.module.escalonesinversos.name": "reverse step", + "sputnik.module.estampaescrotos.desc": "stamp other people's ballsacks", + "sputnik.module.estampaescrotos.name": "ballsack stamper", + "sputnik.module.freecam.damagedisable": "freecam was disabled because you took damage", + "sputnik.module.friends.already": "%s is already your friend", + "sputnik.module.friends.notplayer": "%s could not be added as a friend", + "sputnik.module.fuentes.desc": "changes the font used when rendering text", + "sputnik.module.fuentes.name": "fonts", + "sputnik.module.headhitters.desc": "hold space to headhit without having to spam it", + "sputnik.module.headhitters.name": "headhitters", + "sputnik.module.hitboxes.desc": "changes how hitboxes are rendered with F3+B", + "sputnik.module.hitboxes.name": "hitboxes", + "sputnik.module.hotkeysinvcreativo.desc": "lets you keep using the hotbar keys to move items in the creative search tab instead of typing in the bar", + "sputnik.module.hotkeysinvcreativo.name": "creative inv. hotkeys", + "sputnik.module.hud.desc": "screen overlay with extra info", + "sputnik.module.hud.name": "HUD", + "sputnik.module.infodebloque.desc": "shows the nbt contents of the block you're looking at", + "sputnik.module.infodebloque.name": "block info", + "sputnik.module.interfaz.desc": "gui settings, and other miscellaneous ones", + "sputnik.module.interfaz.name": "gui", + "sputnik.module.interfazenportales.desc": "lets you open guis inside portals, like the chat or the inventory", + "sputnik.module.interfazenportales.name": "gui in portals", + "sputnik.module.inventarioplus.desc": "moves inventory items using only the keyboard", + "sputnik.module.inventarioplus.name": "inventory plus", + "sputnik.module.jesus.desc": "lets you walk on water", + "sputnik.module.jesus.name": "jesus", + "sputnik.module.jkrowling.desc": "fills books with crap", + "sputnik.module.jkrowling.name": "j. k. rowling", + "sputnik.module.jugadorfalso.desc": "spawns a fake player entity for testing purposes", + "sputnik.module.jugadorfalso.name": "fake player", + "sputnik.module.keypearl.nopearls": "you have no pearls", + "sputnik.module.macekill.oops": "oops: %s", + "sputnik.module.manos.desc": "changes the way hands are rendered", + "sputnik.module.manos.name": "hands", + "sputnik.module.manosecundaria.desc": "automatically equips an item in the offhand", + "sputnik.module.manosecundaria.name": "offhand", + "sputnik.module.minarsininterrupcion.desc": "lets you mine blocks through entities", + "sputnik.module.minarsininterrupcion.name": "mine without interruption", + "sputnik.module.miraplus.desc": "customizes the crosshair", + "sputnik.module.miraplus.name": "crosshair plus", + "sputnik.module.mochila.desc": "lets you carry items in the crafting slots", + "sputnik.module.mochila.name": "backpack", + "sputnik.module.moro.desc": "steal chests more easily", + "sputnik.module.moro.name": "moor", + "sputnik.module.moverseeninterfaz.desc": "lets you keep using the movement keys while in certain guis", + "sputnik.module.moverseeninterfaz.name": "move in gui", + "sputnik.module.muletas.desc": "helps you not fall off blocks, without sneaking", + "sputnik.module.muletas.name": "crutches", + "sputnik.module.nametags.desc": "changes the way nametags are rendered", + "sputnik.module.nametags.name": "nametags", + "sputnik.module.nofall.nocushion": "no cushion (water, etc.) found", + "sputnik.module.nofall.packetmode": "switched to packet mode", + "sputnik.module.norender.desc": "customizes what gets rendered and what doesn't", + "sputnik.module.norender.name": "no render", + "sputnik.module.notificaciones.desc": "notifies you when certain events happen", + "sputnik.module.notificaciones.name": "notifications", + "sputnik.module.packetdelay.singleplayer": "packet delay doesn't work in singleplayer", + "sputnik.module.packetmine.pickbreaking": "the pickaxe is about to break", + "sputnik.module.parkour.desc": "automatically jumps on the last possible tick, at the block's edge", + "sputnik.module.parkour.name": "parkour", + "sputnik.module.particulas.desc": "emits artificial particles", + "sputnik.module.particulas.name": "particles", + "sputnik.module.patinaje.desc": "adds a thin layer of cum to the blocks you walk on", + "sputnik.module.patinaje.name": "skating", + "sputnik.module.perspectivalibre.desc": "lets you move the perspective camera without moving the player's, or vice versa", + "sputnik.module.perspectivalibre.name": "freelook", + "sputnik.module.perspectivaplus.desc": "adds cool little things to the perspective switch", + "sputnik.module.perspectivaplus.name": "perspective plus", + "sputnik.module.precoz.desc": "does things like using items or placing blocks faster", + "sputnik.module.precoz.name": "early", + "sputnik.module.prevdeshulkers.desc": "lets you preview shulker contents from the inventory", + "sputnik.module.prevdeshulkers.name": "shulker preview", + "sputnik.module.progresodeminado.desc": "shows you a block's mining progress more visibly", + "sputnik.module.progresodeminado.name": "mining progress", + "sputnik.module.puntosdedesconexion.desc": "shows you the spots where other players log out", + "sputnik.module.puntosdedesconexion.name": "logout spots", + "sputnik.module.racismo.desc": "gimme a smoke bro", + "sputnik.module.racismo.name": "racism", + "sputnik.module.reconectar.desc": "adds a button to reconnect to a server after being disconnected", + "sputnik.module.reconectar.name": "reconnect", + "sputnik.module.reconnect.button": "reconnect", + "sputnik.module.recorrido.desc": "shows your trail", + "sputnik.module.recorrido.name": "trail", + "sputnik.module.reponer.desc": "automatically refills items as they get used up", + "sputnik.module.reponer.name": "refill", + "sputnik.module.resaltadodebloques.desc": "shows you where a certain kind of block is by rendering a box with its shape", + "sputnik.module.resaltadodebloques.name": "block highlight", + "sputnik.module.resaltadodeentidades.desc": "highlights the outline of the selected entities through blocks", + "sputnik.module.resaltadodeentidades.name": "entity highlight", + "sputnik.module.retroceso.desc": "makes you fat", + "sputnik.module.retroceso.name": "knockback", + "sputnik.module.rotaciones.desc": "lets you force a specific rotation", + "sputnik.module.rotaciones.name": "rotations", + "sputnik.module.screenshot.button.copy": "[COPY]", + "sputnik.module.screenshot.button.discard": "[DISCARD]", + "sputnik.module.screenshot.button.open": "[OPEN]", + "sputnik.module.screenshot.button.open.hint": "open the image file", + "sputnik.module.screenshot.button.save": "[SAVE]", + "sputnik.module.screenshot.copied": "screenshot copied to the clipboard", + "sputnik.module.screenshot.copyfailed": "the screenshot could not be copied to the clipboard", + "sputnik.module.screenshot.savedas": "screenshot saved as: ", + "sputnik.module.screenshot.taken": "screenshot taken", + "sputnik.module.selecciondeminado.desc": "selects blocks to mine with packets", + "sputnik.module.selecciondeminado.name": "packet mine", + "sputnik.module.shulkerpeek.empty": "empty", + "sputnik.module.shulkerpeek.holdtopreview": "hold %s to preview", + "sputnik.module.shulkerpeek.openechest": "open an enderchest first", + "sputnik.module.spooferdebungeecord.desc": "lets you connect to the backend servers of a badly configured bungeecord server", + "sputnik.module.spooferdebungeecord.name": "bungeecord spoofer", + "sputnik.module.stronghold.error.different": "the eyes point to different strongholds", + "sputnik.module.stronghold.error.move": "move, will you", + "sputnik.module.stronghold.error.parallel": "the eyes form parallel or overlapping lines", + "sputnik.module.stronghold.found": "stronghold roughly at: %s", + "sputnik.module.stronghold.moreaccurate": "the farther you move, the more accurate the result", + "sputnik.module.stronghold.movenow": "now move about 200 blocks in a direction other than the eye's to throw the second one", + "sputnik.module.stronghold.oops": "oops", + "sputnik.module.stronghold.standstill": "stand still when throwing the eyes, or the calculated position may come out wrong", + "sputnik.module.stronghold.throwfirst": "to start, throw an eye of ender", + "sputnik.module.superposiciondedano.desc": "changes the color the damage overlay is rendered in", + "sputnik.module.superposiciondedano.name": "damage overlay", + "sputnik.module.superposiciondeluz.desc": "shows you the light level on blocks, to prevent mob spawns", + "sputnik.module.superposiciondeluz.name": "light overlay", + "sputnik.module.tecladeperla.desc": "throws a pearl with a key", + "sputnik.module.tecladeperla.name": "pearl key", + "sputnik.module.tenedormagico.desc": "bro thinks he's Poseidon", + "sputnik.module.tenedormagico.name": "magic fork", + "sputnik.module.tobillosfuertes.desc": "avoids fall damage", + "sputnik.module.tobillosfuertes.name": "strong ankles", + "sputnik.module.toggled.off": "%s was disabled", + "sputnik.module.toggled.on": "%s was enabled", + "sputnik.module.trayectoria.desc": "shows the trajectory of projectiles", + "sputnik.module.trayectoria.name": "trajectory", + "sputnik.module.trazos.desc": "draw lines from the camera to the selected entities", + "sputnik.module.trazos.name": "trails", + "sputnik.module.trianguladordestrongholds.desc": "uses fancy math to work out where the closest stronghold is", + "sputnik.module.trianguladordestrongholds.name": "stronghold triangulator", + "sputnik.module.yunquesconpluma.desc": "lets you use different typefaces when renaming items in an anvil", + "sputnik.module.yunquesconpluma.name": "anvils with a quill", + "sputnik.module.zoom.desc": "magnifying glass", + "sputnik.module.zoom.name": "zoom", + "sputnik.setting.amigos.general.prevenirataques.desc": "don't let you attack them manually", + "sputnik.setting.amigos.general.prevenirataques.name": "prevent attacks", + "sputnik.setting.amigos.general.rueditaparaanadiramigo.desc": "press the middle mouse button to (un)mark a player as a friend", + "sputnik.setting.amigos.general.rueditaparaanadiramigo.name": "middle click to add friend", + "sputnik.setting.andamios.bloques.autoselect.desc": "automatically select the closest slot with blocks", + "sputnik.setting.andamios.bloques.autoselect.name": "autoselect", + "sputnik.setting.andamios.bloques.bloques.desc": "blocks to apply the filter to", + "sputnik.setting.andamios.bloques.bloques.name": "blocks", + "sputnik.setting.andamios.bloques.filtro.desc": "filter type to use", + "sputnik.setting.andamios.bloques.filtro.name": "filter", + "sputnik.setting.andamios.general.rotar.desc": "move the head", + "sputnik.setting.andamios.general.rotar.name": "rotate", + "sputnik.setting.andamios.puente.descender.desc": "sneak to descend", + "sputnik.setting.andamios.puente.descender.name": "descend", + "sputnik.setting.andamios.puente.distanciaaextender.desc": "how far to extend", + "sputnik.setting.andamios.puente.distanciaaextender.name": "distance to extend", + "sputnik.setting.andamios.puente.extender.desc": "place blocks in front while walking", + "sputnik.setting.andamios.puente.extender.name": "extend", + "sputnik.setting.andamios.puente.headhitter.desc": "place blocks above your head", + "sputnik.setting.andamios.puente.headhitter.name": "headhitter", + "sputnik.setting.andamios.puente.mjbridge.desc": "make jumping not raise the bridge's y level", + "sputnik.setting.andamios.puente.mjbridge.name": "mj bridge", + "sputnik.setting.andamios.puente.torre.desc": "make cool vertical towers", + "sputnik.setting.andamios.puente.torre.name": "tower", + "sputnik.setting.andamios.puente.torremoviendose.desc": "lets you tower up while moving", + "sputnik.setting.andamios.puente.torremoviendose.name": "tower while moving", + "sputnik.setting.andamios.puente.velocidaddetorre.desc": "how fast to tower up", + "sputnik.setting.andamios.puente.velocidaddetorre.name": "tower speed", + "sputnik.setting.andamios.renderizado.colordelcontorno.desc": "color to use when rendering the outline", + "sputnik.setting.andamios.renderizado.colordelcontorno.name": "outline color", + "sputnik.setting.andamios.renderizado.colordelrelleno.desc": "color to use when rendering the fill", + "sputnik.setting.andamios.renderizado.colordelrelleno.name": "fill color", + "sputnik.setting.andamios.renderizado.contorno.desc": "render the placed block's outline", + "sputnik.setting.andamios.renderizado.contorno.name": "outline", + "sputnik.setting.andamios.renderizado.esperanzadevida.desc": "lifespan of the last placed blocks (rendering)", + "sputnik.setting.andamios.renderizado.esperanzadevida.name": "lifespan", + "sputnik.setting.andamios.renderizado.gradiente.desc": "opacity gradient for the last placed blocks", + "sputnik.setting.andamios.renderizado.gradiente.name": "gradient", + "sputnik.setting.andamios.renderizado.grosordelinea.desc": "outline line thickness", + "sputnik.setting.andamios.renderizado.grosordelinea.name": "line thickness", + "sputnik.setting.andamios.renderizado.mostrarultimosbloques.desc": "show the last placed blocks", + "sputnik.setting.andamios.renderizado.mostrarultimosbloques.name": "show last blocks", + "sputnik.setting.andamios.renderizado.movermano.desc": "move the hand when placing blocks", + "sputnik.setting.andamios.renderizado.movermano.name": "move hand", + "sputnik.setting.andamios.renderizado.relleno.desc": "render the placed block's fill", + "sputnik.setting.andamios.renderizado.relleno.name": "fill", + "sputnik.setting.apilarbossbars.general.apilarbarras.desc": "stack the bossbars", + "sputnik.setting.apilarbossbars.general.apilarbarras.name": "stack bars", + "sputnik.setting.apilarbossbars.general.escondernombres.desc": "doesn't render boss names", + "sputnik.setting.apilarbossbars.general.escondernombres.name": "hide names", + "sputnik.setting.apilarbossbars.general.reducciondeespacio.desc": "how much to reduce the space between bossbars", + "sputnik.setting.apilarbossbars.general.reducciondeespacio.name": "space reduction", + "sputnik.setting.attributeswapper.general.cambiardevuelta.desc": "go back to the original slot after swapping", + "sputnik.setting.attributeswapper.general.cambiardevuelta.name": "switch back", + "sputnik.setting.attributeswapper.general.delaydecambiodevuelta.desc": "time it takes to go back to the original slot", + "sputnik.setting.attributeswapper.general.delaydecambiodevuelta.name": "switch back delay", + "sputnik.setting.attributeswapper.general.slot.desc": "slot to switch to", + "sputnik.setting.attributeswapper.general.slot.name": "slot", + "sputnik.setting.auradecristales.colocar.autoseleccionar.desc": "select crystals automatically", + "sputnik.setting.auradecristales.colocar.autoseleccionar.name": "auto select", + "sputnik.setting.auradecristales.colocar.colocar.desc": "place the crystals", + "sputnik.setting.auradecristales.colocar.colocar.name": "place", + "sputnik.setting.auradecristales.colocar.colocarobsidiana.desc": "place obsidian if needed", + "sputnik.setting.auradecristales.colocar.colocarobsidiana.name": "place obsidian", + "sputnik.setting.auradecristales.colocar.delay.desc": "delay between crystals", + "sputnik.setting.auradecristales.colocar.delay.name": "delay", + "sputnik.setting.auradecristales.colocar.rango1.desc": "max range to place crystals", + "sputnik.setting.auradecristales.colocar.rango1.name": "range", + "sputnik.setting.auradecristales.colocar.rotar.desc": "rotate to place crystals", + "sputnik.setting.auradecristales.colocar.rotar.name": "rotate", + "sputnik.setting.auradecristales.general.entidades.desc": "entities to attack", + "sputnik.setting.auradecristales.general.entidades.name": "entities", + "sputnik.setting.auradecristales.general.ignoraramigos.desc": "don't target friends", + "sputnik.setting.auradecristales.general.ignoraramigos.name": "ignore friends", + "sputnik.setting.auradecristales.general.rango.desc": "target detection range", + "sputnik.setting.auradecristales.general.rango.name": "range", + "sputnik.setting.auradecristales.renderizado.colordelcontorno.desc": "outline color", + "sputnik.setting.auradecristales.renderizado.colordelcontorno.name": "outline color", + "sputnik.setting.auradecristales.renderizado.colordelrelleno.desc": "fill color", + "sputnik.setting.auradecristales.renderizado.colordelrelleno.name": "fill color", + "sputnik.setting.auradecristales.renderizado.contorno.desc": "render the outline of the block the crystals get placed on", + "sputnik.setting.auradecristales.renderizado.contorno.name": "outline", + "sputnik.setting.auradecristales.renderizado.grosordelcontorno.desc": "outline thickness", + "sputnik.setting.auradecristales.renderizado.grosordelcontorno.name": "outline thickness", + "sputnik.setting.auradecristales.renderizado.relleno.desc": "render the fill of the block the crystals get placed on", + "sputnik.setting.auradecristales.renderizado.relleno.name": "fill", + "sputnik.setting.auradecristales.reventar.delay1.desc": "delay between crystals", + "sputnik.setting.auradecristales.reventar.delay1.name": "delay", + "sputnik.setting.auradecristales.reventar.reventar.desc": "pop the crystals", + "sputnik.setting.auradecristales.reventar.reventar.name": "pop", + "sputnik.setting.auradecristales.reventar.rotar.desc": "rotate to pop crystals", + "sputnik.setting.auradecristales.reventar.rotar.name": "rotate", + "sputnik.setting.autismo.general.direccion.desc": "rotation direction", + "sputnik.setting.autismo.general.direccion.name": "direction", + "sputnik.setting.autismo.general.intervalo.desc": "rotation interval", + "sputnik.setting.autismo.general.intervalo.name": "interval", + "sputnik.setting.autoherramienta.general.cambiardevuelta.desc": "switch back to the original tool", + "sputnik.setting.autoherramienta.general.cambiardevuelta.name": "switch back", + "sputnik.setting.autoherramienta.general.delay.desc": "delay when switching tools", + "sputnik.setting.autoherramienta.general.delay.name": "delay", + "sputnik.setting.autoherramienta.general.delaydelcambiodevuelta.desc": "delay in ticks before switching back to the original tool", + "sputnik.setting.autoherramienta.general.delaydelcambiodevuelta.name": "switch back delay", + "sputnik.setting.autopechera.general.cambiardevuelta.desc": "switch back to elytra, if they were equipped", + "sputnik.setting.autopechera.general.cambiardevuelta.name": "switch back", + "sputnik.setting.autopesca.general.evitarromper.desc": "avoid breaking the rod if it's about to go", + "sputnik.setting.autopesca.general.evitarromper.name": "avoid breaking", + "sputnik.setting.autopesca.recast.delay1.desc": "delay between catching a fish and recasting the rod", + "sputnik.setting.autopesca.recast.delay1.name": "delay", + "sputnik.setting.autopesca.recast.distanciadelagua.desc": "max distance the water you're looking at can be", + "sputnik.setting.autopesca.recast.distanciadelagua.name": "water distance", + "sputnik.setting.autopesca.recast.recast.desc": "automatically recast the rod after catching something", + "sputnik.setting.autopesca.recast.recast.name": "recast", + "sputnik.setting.autopesca.recast.solosimirandoalagua.desc": "only recast if you're looking at water", + "sputnik.setting.autopesca.recast.solosimirandoalagua.name": "only if looking at water", + "sputnik.setting.avioneta.general.cabeceoabajo.desc": "bobbing when going down", + "sputnik.setting.avioneta.general.cabeceoabajo.name": "bobbing (down)", + "sputnik.setting.avioneta.general.cabeceoarriba.desc": "bobbing when going up", + "sputnik.setting.avioneta.general.cabeceoarriba.name": "bobbing (up)", + "sputnik.setting.avioneta.general.precauciondecolision.desc": "collision caution in ticks", + "sputnik.setting.avioneta.general.precauciondecolision.name": "collision caution", + "sputnik.setting.avioneta.general.velocidaddecabeceoabajo.desc": "bobbing speed when going down", + "sputnik.setting.avioneta.general.velocidaddecabeceoabajo.name": "bobbing speed (down)", + "sputnik.setting.avioneta.general.velocidaddecabeceoarriba.desc": "bobbing speed when going up", + "sputnik.setting.avioneta.general.velocidaddecabeceoarriba.name": "bobbing speed (up)", + "sputnik.setting.barcovolador.general.alturadeescalonado.desc": "like step but for the boat", + "sputnik.setting.barcovolador.general.alturadeescalonado.name": "step height", + "sputnik.setting.barcovolador.general.cancelarpaquetes.desc": "cancel boat movement packets sent by the server", + "sputnik.setting.barcovolador.general.cancelarpaquetes.name": "cancel packets", + "sputnik.setting.barcovolador.general.velocidadhorizontal.desc": "speed to move horizontally at", + "sputnik.setting.barcovolador.general.velocidadhorizontal.name": "horizontal speed", + "sputnik.setting.barcovolador.general.velocidadvertical.desc": "speed to move vertically at", + "sputnik.setting.barcovolador.general.velocidadvertical.name": "vertical speed", + "sputnik.setting.brillibrilli.general.filtro.desc": "color filter", + "sputnik.setting.brillibrilli.general.filtro.name": "filter", + "sputnik.setting.brillibrilli.general.modo.desc": "which lighting mode to use (use potion with shaders)", + "sputnik.setting.brillibrilli.general.modo.name": "mode", + "sputnik.setting.camaralibre.general.cancelarpaquetes.desc": "avoids flagging the anticheat when interacting with blocks / entities", + "sputnik.setting.camaralibre.general.cancelarpaquetes.name": "cancel packets", + "sputnik.setting.camaralibre.general.contornodebloques.desc": "show the block outline while in freecam", + "sputnik.setting.camaralibre.general.contornodebloques.name": "block outline", + "sputnik.setting.camaralibre.general.desactivaralrecibirdano.desc": "disables the module after taking damage", + "sputnik.setting.camaralibre.general.desactivaralrecibirdano.name": "disable on damage", + "sputnik.setting.camaralibre.general.manosvisibles.desc": "decides whether the hands are rendered while the camera is free", + "sputnik.setting.camaralibre.general.manosvisibles.name": "visible hands", + "sputnik.setting.camaralibre.general.mantenerseagachado.desc": "keep the player sneaking after entering freecam", + "sputnik.setting.camaralibre.general.mantenerseagachado.name": "stay sneaking", + "sputnik.setting.camaralibre.general.recargarchunks.desc": "reload chunks to fix cave culling", + "sputnik.setting.camaralibre.general.recargarchunks.name": "reload chunks", + "sputnik.setting.camaralibre.general.visionestatica.desc": "disables settings that move the camera", + "sputnik.setting.camaralibre.general.visionestatica.name": "static view", + "sputnik.setting.camaralibre.velocidad.sensibilidaddelscroll.desc": "mouse wheel sensitivity for changing the speed, 0 to disable", + "sputnik.setting.camaralibre.velocidad.sensibilidaddelscroll.name": "scroll sensitivity", + "sputnik.setting.camaralibre.velocidad.tecladelscroll.desc": "key to hold to change the speed with the scroll wheel", + "sputnik.setting.camaralibre.velocidad.tecladelscroll.name": "scroll key", + "sputnik.setting.camaralibre.velocidad.velocidad.desc": "camera movement speed", + "sputnik.setting.camaralibre.velocidad.velocidad.name": "speed", + "sputnik.setting.capas.general.capa.desc": "which cape to wear", + "sputnik.setting.capas.general.capa.name": "cape", + "sputnik.setting.capturasdepantalla.botones.botondeabrir.desc": "show a button to open the screenshot file", + "sputnik.setting.capturasdepantalla.botones.botondeabrir.name": "open button", + "sputnik.setting.capturasdepantalla.botones.botondecopiar.desc": "show a button to copy the screenshot to the clipboard", + "sputnik.setting.capturasdepantalla.botones.botondecopiar.name": "copy button", + "sputnik.setting.capturasdepantalla.botones.botondedescartar.desc": "show a button to discard the screenshot", + "sputnik.setting.capturasdepantalla.botones.botondedescartar.name": "discard button", + "sputnik.setting.capturasdepantalla.botones.botondeguardar.desc": "show a button to save the screenshot locally", + "sputnik.setting.capturasdepantalla.botones.botondeguardar.name": "save button", + "sputnik.setting.capturasdepantalla.general.pordefecto.desc": "what action to take by default", + "sputnik.setting.capturasdepantalla.general.pordefecto.name": "default", + "sputnik.setting.cartelesgays.general.simbolo.desc": "symbol to replace with \"§\"", + "sputnik.setting.cartelesgays.general.simbolo.name": "symbol", + "sputnik.setting.chatplus.funcionamientodelchat.expandirchat.desc": "how many lines to add to the chat history", + "sputnik.setting.chatplus.funcionamientodelchat.expandirchat.name": "expand chat", + "sputnik.setting.chatplus.funcionamientodelchat.noborrarchat.desc": "don't clear the chat after disconnecting", + "sputnik.setting.chatplus.funcionamientodelchat.noborrarchat.name": "no chat clear", + "sputnik.setting.chatplus.funcionamientodelchat.protegercoordenadas.desc": "avoid sending coordinates in chat", + "sputnik.setting.chatplus.funcionamientodelchat.protegercoordenadas.name": "protect coordinates", + "sputnik.setting.chatplus.funcionamientodelchat.quitarlimitedecaracteres.desc": "lets you write messages as long as you want", + "sputnik.setting.chatplus.funcionamientodelchat.quitarlimitedecaracteres.name": "remove character limit", + "sputnik.setting.chatplus.funcionamientodelchat.registro.desc": "stops a server from clearing your chat", + "sputnik.setting.chatplus.funcionamientodelchat.registro.name": "log", + "sputnik.setting.chatplus.general.cabezas.desc": "shows the player's head next to their message", + "sputnik.setting.chatplus.general.cabezas.name": "heads", + "sputnik.setting.chatplus.general.mostrarsegundos.desc": "also shows seconds in the timestamp", + "sputnik.setting.chatplus.general.mostrarsegundos.name": "show seconds", + "sputnik.setting.chatplus.general.sellodetiempo.desc": "shows what time a message was sent at", + "sputnik.setting.chatplus.general.sellodetiempo.name": "timestamp", + "sputnik.setting.cielocustom.cuerposceleste.estrellas.desc": "whether there are stars or not", + "sputnik.setting.cielocustom.cuerposceleste.estrellas.name": "stars", + "sputnik.setting.cielocustom.cuerposceleste.faselunar.desc": "current moon phase", + "sputnik.setting.cielocustom.cuerposceleste.faselunar.name": "moon phase", + "sputnik.setting.cielocustom.cuerposceleste.luna.desc": "whether there's a moon or not", + "sputnik.setting.cielocustom.cuerposceleste.luna.name": "moon", + "sputnik.setting.cielocustom.cuerposceleste.sol.desc": "whether there's a sun or not", + "sputnik.setting.cielocustom.cuerposceleste.sol.name": "sun", + "sputnik.setting.cielocustom.general.hora.desc": "in-game time", + "sputnik.setting.cielocustom.general.hora.name": "time", + "sputnik.setting.cocaina.general.multi.desc": "like in Balatro", + "sputnik.setting.cocaina.general.multi.name": "multi", + "sputnik.setting.colocarenaire.general.colocarconnormalidad.desc": "place normally if already looking at a block in range", + "sputnik.setting.colocarenaire.general.colocarconnormalidad.name": "place normally", + "sputnik.setting.colocarenaire.general.rango.desc": "distance to place the block at", + "sputnik.setting.colocarenaire.general.rango.name": "range", + "sputnik.setting.colocarenaire.renderizado.colordelcontorno.desc": "color to use when drawing the outline", + "sputnik.setting.colocarenaire.renderizado.colordelcontorno.name": "outline color", + "sputnik.setting.colocarenaire.renderizado.colordelrelleno.desc": "color to use when drawing the fill", + "sputnik.setting.colocarenaire.renderizado.colordelrelleno.name": "fill color", + "sputnik.setting.colocarenaire.renderizado.contorno.desc": "render the preview box outline", + "sputnik.setting.colocarenaire.renderizado.contorno.name": "outline", + "sputnik.setting.colocarenaire.renderizado.grosordelinea.desc": "outline line thickness", + "sputnik.setting.colocarenaire.renderizado.grosordelinea.name": "line thickness", + "sputnik.setting.colocarenaire.renderizado.relleno.desc": "render the preview box fill", + "sputnik.setting.colocarenaire.renderizado.relleno.name": "fill", + "sputnik.setting.colocarenaire.scrolleo.sensdelscroll.desc": "scroll wheel sensitivity (0 to disable)", + "sputnik.setting.colocarenaire.scrolleo.sensdelscroll.name": "scroll sens.", + "sputnik.setting.colocarenaire.scrolleo.tecladelscroll.desc": "key to hold for scrolling to work", + "sputnik.setting.colocarenaire.scrolleo.tecladelscroll.name": "scroll key", + "sputnik.setting.color.rainbow": "rainbow", + "sputnik.setting.common.bind.desc": "key bound to the module, ESC to unbind", + "sputnik.setting.common.bind.name": "key", + "sputnik.setting.common.keymode.desc": "how to interpret the bound key", + "sputnik.setting.common.keymode.name": "key mode", + "sputnik.setting.common.notify.desc": "notify when toggling on / off", + "sputnik.setting.common.notify.name": "notify", + "sputnik.setting.common.notifymode.desc": "how to notify when toggling on / off", + "sputnik.setting.common.notifymode.name": "notify mode", + "sputnik.setting.confetti.general.color1.desc": "instead of yellow", + "sputnik.setting.confetti.general.color1.name": "color 1", + "sputnik.setting.confetti.general.color2.desc": "instead of green", + "sputnik.setting.confetti.general.color2.name": "color 2", + "sputnik.setting.contorno.general.color.desc": "block outline color", + "sputnik.setting.contorno.general.color.name": "color", + "sputnik.setting.contorno.general.grosor.desc": "line thickness", + "sputnik.setting.contorno.general.grosor.name": "thickness", + "sputnik.setting.criticos.aspecto.color.desc": "particle color", + "sputnik.setting.criticos.aspecto.color.name": "color", + "sputnik.setting.criticos.aspecto.escala.desc": "size", + "sputnik.setting.criticos.aspecto.escala.name": "scale", + "sputnik.setting.criticos.aspecto.multiplo.desc": "number to multiply the amount of spawned particles by", + "sputnik.setting.criticos.aspecto.multiplo.name": "multiple", + "sputnik.setting.criticos.funcionamiento.colisionar.desc": "collide with blocks", + "sputnik.setting.criticos.funcionamiento.colisionar.name": "collide", + "sputnik.setting.criticos.funcionamiento.dispersion.desc": "spread speed multiplier", + "sputnik.setting.criticos.funcionamiento.dispersion.name": "spread", + "sputnik.setting.criticos.funcionamiento.gravedad.desc": "gravity strength multiplier", + "sputnik.setting.criticos.funcionamiento.gravedad.name": "gravity", + "sputnik.setting.criticos.funcionamiento.vidamaxima.desc": "how long the particle lasts", + "sputnik.setting.criticos.funcionamiento.vidamaxima.name": "max health", + "sputnik.setting.delaydepaquetes.general.delay.desc": "delay to add to packets, in milliseconds", + "sputnik.setting.delaydepaquetes.general.delay.name": "delay", + "sputnik.setting.delaydepaquetes.general.direccion.desc": "direction of the packets to delay", + "sputnik.setting.delaydepaquetes.general.direccion.name": "direction", + "sputnik.setting.delaydepaquetes.general.paquetes.desc": "packets to apply the delay to", + "sputnik.setting.delaydepaquetes.general.paquetes.name": "packets", + "sputnik.setting.destellodeenchants.general.armadura.desc": "modify the enchantment glint on armor", + "sputnik.setting.destellodeenchants.general.armadura.name": "armor", + "sputnik.setting.destellodeenchants.general.colores.desc": "glint color", + "sputnik.setting.destellodeenchants.general.colores.name": "colors", + "sputnik.setting.destellodeenchants.general.items.desc": "modify the enchantment glint on items", + "sputnik.setting.destellodeenchants.general.items.name": "items", + "sputnik.setting.discordrpc.boton.textodelboton.desc": "text to show on the button", + "sputnik.setting.discordrpc.boton.textodelboton.name": "button text", + "sputnik.setting.discordrpc.boton.urldelboton.desc": "rickroll in big 26 :wilted_rose:", + "sputnik.setting.discordrpc.boton.urldelboton.name": "button url", + "sputnik.setting.discordrpc.general.detalles.desc": "title", + "sputnik.setting.discordrpc.general.detalles.name": "details", + "sputnik.setting.discordrpc.general.estado.desc": "subtitle", + "sputnik.setting.discordrpc.general.estado.name": "state", + "sputnik.setting.discordrpc.general.iddelbot.desc": "id of the bot to use (get it from discord.dev)", + "sputnik.setting.discordrpc.general.iddelbot.name": "bot id", + "sputnik.setting.discordrpc.general.sellodetiempo.desc": "timestamp of when the activity started, in unix epoch (leave empty for now)", + "sputnik.setting.discordrpc.general.sellodetiempo.name": "timestamp", + "sputnik.setting.discordrpc.general.tipodeactividad.desc": "what kind of activity is going on", + "sputnik.setting.discordrpc.general.tipodeactividad.name": "activity type", + "sputnik.setting.discordrpc.imagenes.imagengrande.desc": "large image key", + "sputnik.setting.discordrpc.imagenes.imagengrande.name": "large image", + "sputnik.setting.discordrpc.imagenes.imagenpequena.desc": "small image key", + "sputnik.setting.discordrpc.imagenes.imagenpequena.name": "small image", + "sputnik.setting.discordrpc.imagenes.textodelaimagengrande.desc": "text shown next to the large image", + "sputnik.setting.discordrpc.imagenes.textodelaimagengrande.name": "large image text", + "sputnik.setting.discordrpc.imagenes.textodelaimagenpequena.desc": "text shown next to the small image", + "sputnik.setting.discordrpc.imagenes.textodelaimagenpequena.name": "small image text", + "sputnik.setting.donquijote.general.ignoraramigos.desc": "don't target friends", + "sputnik.setting.donquijote.general.ignoraramigos.name": "ignore friends", + "sputnik.setting.donquijote.general.solojugadores.desc": "only target players", + "sputnik.setting.donquijote.general.solojugadores.name": "players only", + "sputnik.setting.donquijote.general.velocidad.desc": "boost speed", + "sputnik.setting.donquijote.general.velocidad.name": "speed", + "sputnik.setting.dupedebundle.general.paquetes.desc": "packets to send", + "sputnik.setting.dupedebundle.general.paquetes.name": "packets", + "sputnik.setting.dupedebundle.general.tiempodeespera.desc": "time to wait in seconds before getting kicked", + "sputnik.setting.dupedebundle.general.tiempodeespera.name": "wait time", + "sputnik.setting.elytras.general.velocidad.desc": "my mother is partially a hobo", + "sputnik.setting.elytras.general.velocidad.name": "speed", + "sputnik.setting.escalerasveloces.general.soloalcorrer.desc": "only jump while sprinting", + "sputnik.setting.escalerasveloces.general.soloalcorrer.name": "only while sprinting", + "sputnik.setting.escalerasveloces.general.soloalhabermasescaleras.desc": "only jump when the next block is stairs too", + "sputnik.setting.escalerasveloces.general.soloalhabermasescaleras.name": "only when there are more stairs", + "sputnik.setting.escalones.general.altura.desc": "max height to climb", + "sputnik.setting.escalones.general.altura.name": "height", + "sputnik.setting.escalonesinversos.general.altura.desc": "max height to descend", + "sputnik.setting.escalonesinversos.general.altura.name": "height", + "sputnik.setting.escalonesinversos.general.desactivarenagua.desc": ".", + "sputnik.setting.escalonesinversos.general.desactivarenagua.name": "disable in water", + "sputnik.setting.escalonesinversos.general.saltar.desc": "allow jumping", + "sputnik.setting.escalonesinversos.general.saltar.name": "jump", + "sputnik.setting.escalonesinversos.general.velocidad.desc": "speed to fall at", + "sputnik.setting.escalonesinversos.general.velocidad.name": "speed", + "sputnik.setting.estampaescrotos.general.altura.desc": "height to simulate the fall from", + "sputnik.setting.estampaescrotos.general.altura.name": "height", + "sputnik.setting.estampaescrotos.general.maximapotencia.desc": "simulate a fall from the closest air gap within 170 blocks", + "sputnik.setting.estampaescrotos.general.maximapotencia.name": "max power", + "sputnik.setting.estampaescrotos.general.prevenirmuerte.desc": "prevent death from fall damage if the attack was blocked, by cancelling the movement packets", + "sputnik.setting.estampaescrotos.general.prevenirmuerte.name": "prevent death", + "sputnik.setting.friend.nickname.desc": "what name to save the friend under", + "sputnik.setting.friend.nickname.name": "name", + "sputnik.setting.fuentes.general.fuente.desc": "font to use", + "sputnik.setting.fuentes.general.fuente.name": "font", + "sputnik.setting.fuentes.general.recargar.desc": "reload automatically", + "sputnik.setting.fuentes.general.recargar.name": "reload", + "sputnik.setting.headhitters.general.delay.desc": "jump delay", + "sputnik.setting.headhitters.general.delay.name": "delay", + "sputnik.setting.hitboxes.general.color.desc": "color to render the egg boxes in", + "sputnik.setting.hitboxes.general.color.name": "color", + "sputnik.setting.hitboxes.general.grosor.desc": "line thickness", + "sputnik.setting.hitboxes.general.grosor.name": "thickness", + "sputnik.setting.hud.editor.cuantomoverconlasflechas.desc": "how many pixels to move the selected element with the arrow keys", + "sputnik.setting.hud.editor.cuantomoverconlasflechas.name": "how far to move with the arrow keys", + "sputnik.setting.hud.editor.movimientoaxial.desc": "lets you move elements along the axes more easily", + "sputnik.setting.hud.editor.movimientoaxial.name": "axial movement", + "sputnik.setting.hud.editor.movimientoconflechas.desc": "lets you move the selected element with the arrow keys", + "sputnik.setting.hud.editor.movimientoconflechas.name": "arrow key movement", + "sputnik.setting.hud.editor.offsetdelosejes.desc": "offset to take into account when using axial movement", + "sputnik.setting.hud.editor.offsetdelosejes.name": "axis offset", + "sputnik.setting.hud.editor.tecladeleditor.desc": "key bound to the hud element editor", + "sputnik.setting.hud.editor.tecladeleditor.name": "editor key", + "sputnik.setting.hud.elementos.dinosaurio.desc": "which dinosaur to show", + "sputnik.setting.hud.elementos.dinosaurio.name": "dinosaur", + "sputnik.setting.hud.elementos.formatodelahora.desc": "12h or 24h", + "sputnik.setting.hud.elementos.formatodelahora.name": "time format", + "sputnik.setting.hud.elementos.mododecoordenadas.desc": "which coordinates to show", + "sputnik.setting.hud.elementos.mododecoordenadas.name": "coords mode", + "sputnik.setting.hud.elementos.textocustom.desc": "watermark (leave empty to remove)", + "sputnik.setting.hud.elementos.textocustom.name": "custom text", + "sputnik.setting.hud.elementos.zonahoraria.desc": "timezone as UTC+n", + "sputnik.setting.hud.elementos.zonahoraria.name": "timezone", + "sputnik.setting.hud.visualizacion.color.desc": "text color of the HUD elements", + "sputnik.setting.hud.visualizacion.color.name": "color", + "sputnik.setting.hud.visualizacion.mostrarenchat.desc": "render the HUD on the chat screen", + "sputnik.setting.hud.visualizacion.mostrarenchat.name": "show in chat", + "sputnik.setting.hud.visualizacion.mostrarenf3.desc": "render the HUD in the debug menu", + "sputnik.setting.hud.visualizacion.mostrarenf3.name": "show in F3", + "sputnik.setting.hud.visualizacion.sombra.desc": "text with shadow", + "sputnik.setting.hud.visualizacion.sombra.name": "shadow", + "sputnik.setting.infodebloque.general.copiar.desc": "copy to clipboard", + "sputnik.setting.infodebloque.general.copiar.name": "copy", + "sputnik.setting.infodebloque.general.liquidos.desc": "also include liquids in the raycast", + "sputnik.setting.infodebloque.general.liquidos.name": "liquids", + "sputnik.setting.infodebloque.general.tecla.desc": "key to press to get the info", + "sputnik.setting.infodebloque.general.tecla.name": "key", + "sputnik.setting.interfaz.chat.nombre.desc": "what name to use in chat notifications", + "sputnik.setting.interfaz.chat.nombre.name": "name", + "sputnik.setting.interfaz.chat.prefijo.desc": "command prefix", + "sputnik.setting.interfaz.chat.prefijo.name": "prefix", + "sputnik.setting.interfaz.general.color.desc": "main color of the gui and the mod", + "sputnik.setting.interfaz.general.color.name": "color", + "sputnik.setting.interfaz.interfaz.desenfoque.desc": "blur the background while the gui is open", + "sputnik.setting.interfaz.interfaz.desenfoque.name": "blur", + "sputnik.setting.interfaz.interfaz.marcadeagua.desc": "watermark for guis (leave empty to disable)", + "sputnik.setting.interfaz.interfaz.marcadeagua.name": "watermark", + "sputnik.setting.interfaz.misc.autoguardado.desc": "autosave settings every so often", + "sputnik.setting.interfaz.misc.autoguardado.name": "autosave", + "sputnik.setting.interfaz.misc.intervalodeautoguardado.desc": "how many seconds between autosaves", + "sputnik.setting.interfaz.misc.intervalodeautoguardado.name": "autosave interval", + "sputnik.setting.interfaz.misc.teclasmultimodulo.desc": "allow binding the same key to more than one module or action", + "sputnik.setting.interfaz.misc.teclasmultimodulo.name": "multi-module keys", + "sputnik.setting.interfaz.misc.titulo.desc": "window title", + "sputnik.setting.interfaz.misc.titulo.name": "title", + "sputnik.setting.interfaz.widgets.barradebusqueda.desc": "render a search bar that filters results across all open panels", + "sputnik.setting.interfaz.widgets.barradebusqueda.name": "search bar", + "sputnik.setting.interfaz.widgets.barradedesplazamiento.desc": "render a scrollbar on the right side of the gui", + "sputnik.setting.interfaz.widgets.barradedesplazamiento.name": "scrollbar", + "sputnik.setting.interfaz.widgets.distinguirmayusculas.desc": "the search is case sensitive", + "sputnik.setting.interfaz.widgets.distinguirmayusculas.name": "match case", + "sputnik.setting.interfaz.widgets.sensibilidaddelscroll.desc": "how sensitive the gui is to the mouse wheel", + "sputnik.setting.interfaz.widgets.sensibilidaddelscroll.name": "scroll sensitivity", + "sputnik.setting.inventarioplus.general.fila1.desc": "key to move items to the first row", + "sputnik.setting.inventarioplus.general.fila1.name": "row 1", + "sputnik.setting.inventarioplus.general.fila2.desc": "key to move items to the second row", + "sputnik.setting.inventarioplus.general.fila2.name": "row 2", + "sputnik.setting.inventarioplus.general.fila3.desc": "key to move items to the third row", + "sputnik.setting.inventarioplus.general.fila3.name": "row 3", + "sputnik.setting.jesus.bloques.agua.desc": "allow walking on water", + "sputnik.setting.jesus.bloques.agua.name": "water", + "sputnik.setting.jesus.bloques.lava.desc": "allow walking on lava", + "sputnik.setting.jesus.bloques.lava.name": "lava", + "sputnik.setting.jesus.bloques.nieveenpolvo.desc": "allow walking on powder snow", + "sputnik.setting.jesus.bloques.nieveenpolvo.name": "powder snow", + "sputnik.setting.jesus.general.distanciadecaida.desc": "min fall distance to dive in instead of hitting the ground", + "sputnik.setting.jesus.general.distanciadecaida.name": "fall distance", + "sputnik.setting.jesus.general.modo.desc": "how to walk", + "sputnik.setting.jesus.general.modo.name": "mode", + "sputnik.setting.jesus.general.permitiragacharse.desc": "lets you use the sneak button to dive into water", + "sputnik.setting.jesus.general.permitiragacharse.name": "allow sneaking", + "sputnik.setting.jkrowling.general.delay.desc": "delay between writing books", + "sputnik.setting.jkrowling.general.delay.name": "delay", + "sputnik.setting.jkrowling.general.desactivaraldesconectarse.desc": ".", + "sputnik.setting.jkrowling.general.desactivaraldesconectarse.name": "disable on disconnect", + "sputnik.setting.jkrowling.libro.contar.desc": "count the books and add the number at the end of the name", + "sputnik.setting.jkrowling.libro.contar.name": "count", + "sputnik.setting.jkrowling.libro.firmar.desc": "sign the book", + "sputnik.setting.jkrowling.libro.firmar.name": "sign", + "sputnik.setting.jkrowling.libro.nombre.desc": "name to use for the books", + "sputnik.setting.jkrowling.libro.nombre.name": "name", + "sputnik.setting.jkrowling.libro.paginas.desc": "number of pages to fill with crap", + "sputnik.setting.jkrowling.libro.paginas.name": "pages", + "sputnik.setting.jkrowling.libro.soloascii.desc": "only use ascii characters", + "sputnik.setting.jkrowling.libro.soloascii.name": "ascii only", + "sputnik.setting.jugadorfalso.general.nombre.desc": "what name to give the player", + "sputnik.setting.jugadorfalso.general.nombre.name": "name", + "sputnik.setting.key.reset": "keybind for module %s reset", + "sputnik.setting.manos.animaciones.animacionesviejas.desc": "like the 1.8 ones, when hitting", + "sputnik.setting.manos.animaciones.animacionesviejas.name": "old animations", + "sputnik.setting.manos.animaciones.nocomer.desc": "doesn't render the eating animation", + "sputnik.setting.manos.animaciones.nocomer.name": "no eating", + "sputnik.setting.manos.animaciones.noswap.desc": "skips the item swap animation", + "sputnik.setting.manos.animaciones.noswap.name": "no swap", + "sputnik.setting.manos.brazo.escaladelbrazox.desc": ".", + "sputnik.setting.manos.brazo.escaladelbrazox.name": "arm scale (X)", + "sputnik.setting.manos.brazo.escaladelbrazoy.desc": ".", + "sputnik.setting.manos.brazo.escaladelbrazoy.name": "arm scale (Y)", + "sputnik.setting.manos.brazo.escaladelbrazoz.desc": ".", + "sputnik.setting.manos.brazo.escaladelbrazoz.name": "arm scale (Z)", + "sputnik.setting.manos.brazo.posiciondelbrazox.desc": ".", + "sputnik.setting.manos.brazo.posiciondelbrazox.name": "arm position (X)", + "sputnik.setting.manos.brazo.posiciondelbrazoy.desc": ".", + "sputnik.setting.manos.brazo.posiciondelbrazoy.name": "arm position (Y)", + "sputnik.setting.manos.brazo.posiciondelbrazoz.desc": ".", + "sputnik.setting.manos.brazo.posiciondelbrazoz.name": "arm position (Z)", + "sputnik.setting.manos.brazo.rotaciondelbrazox.desc": ".", + "sputnik.setting.manos.brazo.rotaciondelbrazox.name": "arm rotation (X)", + "sputnik.setting.manos.brazo.rotaciondelbrazoy.desc": ".", + "sputnik.setting.manos.brazo.rotaciondelbrazoy.name": "arm rotation (Y)", + "sputnik.setting.manos.brazo.rotaciondelbrazoz.desc": ".", + "sputnik.setting.manos.brazo.rotaciondelbrazoz.name": "arm rotation (Z)", + "sputnik.setting.manos.manoprincipal.escaladelamanoprincipalx.desc": ".", + "sputnik.setting.manos.manoprincipal.escaladelamanoprincipalx.name": "main hand scale (X)", + "sputnik.setting.manos.manoprincipal.escaladelamanoprincipaly.desc": ".", + "sputnik.setting.manos.manoprincipal.escaladelamanoprincipaly.name": "main hand scale (Y)", + "sputnik.setting.manos.manoprincipal.escaladelamanoprincipalz.desc": ".", + "sputnik.setting.manos.manoprincipal.escaladelamanoprincipalz.name": "main hand scale (Z)", + "sputnik.setting.manos.manoprincipal.posiciondelamanoprincipalx.desc": ".", + "sputnik.setting.manos.manoprincipal.posiciondelamanoprincipalx.name": "main hand position (X)", + "sputnik.setting.manos.manoprincipal.posiciondelamanoprincipaly.desc": ".", + "sputnik.setting.manos.manoprincipal.posiciondelamanoprincipaly.name": "main hand position (Y)", + "sputnik.setting.manos.manoprincipal.posiciondelamanoprincipalz.desc": ".", + "sputnik.setting.manos.manoprincipal.posiciondelamanoprincipalz.name": "main hand position (Z)", + "sputnik.setting.manos.manoprincipal.rotaciondelamanoprincipalx.desc": ".", + "sputnik.setting.manos.manoprincipal.rotaciondelamanoprincipalx.name": "main hand rotation (X)", + "sputnik.setting.manos.manoprincipal.rotaciondelamanoprincipaly.desc": ".", + "sputnik.setting.manos.manoprincipal.rotaciondelamanoprincipaly.name": "main hand rotation (Y)", + "sputnik.setting.manos.manoprincipal.rotaciondelamanoprincipalz.desc": ".", + "sputnik.setting.manos.manoprincipal.rotaciondelamanoprincipalz.name": "main hand rotation (Z)", + "sputnik.setting.manos.manosecundaria.escaladelamanosecundariax.desc": ".", + "sputnik.setting.manos.manosecundaria.escaladelamanosecundariax.name": "offhand scale (X)", + "sputnik.setting.manos.manosecundaria.escaladelamanosecundariay.desc": ".", + "sputnik.setting.manos.manosecundaria.escaladelamanosecundariay.name": "offhand scale (Y)", + "sputnik.setting.manos.manosecundaria.escaladelamanosecundariaz.desc": ".", + "sputnik.setting.manos.manosecundaria.escaladelamanosecundariaz.name": "offhand scale (Z)", + "sputnik.setting.manos.manosecundaria.posiciondelamanosecundariax.desc": ".", + "sputnik.setting.manos.manosecundaria.posiciondelamanosecundariax.name": "offhand position (X)", + "sputnik.setting.manos.manosecundaria.posiciondelamanosecundariay.desc": ".", + "sputnik.setting.manos.manosecundaria.posiciondelamanosecundariay.name": "offhand position (Y)", + "sputnik.setting.manos.manosecundaria.posiciondelamanosecundariaz.desc": ".", + "sputnik.setting.manos.manosecundaria.posiciondelamanosecundariaz.name": "offhand position (Z)", + "sputnik.setting.manos.manosecundaria.rotaciondelamanosecundariax.desc": ".", + "sputnik.setting.manos.manosecundaria.rotaciondelamanosecundariax.name": "offhand rotation (X)", + "sputnik.setting.manos.manosecundaria.rotaciondelamanosecundariay.desc": ".", + "sputnik.setting.manos.manosecundaria.rotaciondelamanosecundariay.name": "offhand rotation (Y)", + "sputnik.setting.manos.manosecundaria.rotaciondelamanosecundariaz.desc": ".", + "sputnik.setting.manos.manosecundaria.rotaciondelamanosecundariaz.name": "offhand rotation (Z)", + "sputnik.setting.manosecundaria.general.anular.desc": "ignores that there's already an item in the offhand", + "sputnik.setting.manosecundaria.general.anular.name": "cancel", + "sputnik.setting.manosecundaria.general.delay.desc": "swap delay (in ticks)", + "sputnik.setting.manosecundaria.general.delay.name": "delay", + "sputnik.setting.manosecundaria.general.item.desc": "item to equip", + "sputnik.setting.manosecundaria.general.item.name": "item", + "sputnik.setting.minarsininterrupcion.general.entidades.desc": "entities to ignore", + "sputnik.setting.minarsininterrupcion.general.entidades.name": "entities", + "sputnik.setting.minarsininterrupcion.general.soloconpico.desc": "ignore entities only while holding a pickaxe", + "sputnik.setting.minarsininterrupcion.general.soloconpico.name": "only with a pickaxe", + "sputnik.setting.miraplus.general.altura.desc": "crosshair height", + "sputnik.setting.miraplus.general.altura.name": "height", + "sputnik.setting.miraplus.general.anchura.desc": "crosshair width", + "sputnik.setting.miraplus.general.anchura.name": "width", + "sputnik.setting.miraplus.general.color.desc": "crosshair color", + "sputnik.setting.miraplus.general.color.name": "color", + "sputnik.setting.moro.general.mostrarbotondedejar.desc": "show a button to dump everything in container inventories", + "sputnik.setting.moro.general.mostrarbotondedejar.name": "show dump button", + "sputnik.setting.moro.general.mostrarbotonderobar.desc": "show a button to steal everything in container inventories", + "sputnik.setting.moro.general.mostrarbotonderobar.name": "show steal button", + "sputnik.setting.moro.teclas.dejar.desc": "dump all key", + "sputnik.setting.moro.teclas.dejar.name": "dump", + "sputnik.setting.moro.teclas.robar.desc": "steal all key", + "sputnik.setting.moro.teclas.robar.name": "steal", + "sputnik.setting.moro.teclas.teclaactivadora.desc": "key to hold for the other keys to work", + "sputnik.setting.moro.teclas.teclaactivadora.name": "trigger key", + "sputnik.setting.moverseeninterfaz.general.interfaces.desc": "guis you'll be able to move in", + "sputnik.setting.moverseeninterfaz.general.interfaces.name": "guis", + "sputnik.setting.muletas.general.distanciadecaida.desc": "max allowed fall distance", + "sputnik.setting.muletas.general.distanciadecaida.name": "fall distance", + "sputnik.setting.nametags.general.entidades.desc": "entities whose nametag will be visible", + "sputnik.setting.nametags.general.entidades.name": "entities", + "sputnik.setting.nametags.general.items.desc": "lets you choose which items have their name visible", + "sputnik.setting.nametags.general.items.name": "items", + "sputnik.setting.nametags.general.mostrarpropio.desc": "show own nametag", + "sputnik.setting.nametags.general.mostrarpropio.name": "show own", + "sputnik.setting.nametags.general.mostrarvida.desc": "shows an entity's health in its nametag", + "sputnik.setting.nametags.general.mostrarvida.name": "show health", + "sputnik.setting.nametags.general.mostrarvidaen.desc": "how to show health", + "sputnik.setting.nametags.general.mostrarvidaen.name": "show health as", + "sputnik.setting.nametags.general.motes.desc": "use friend nicknames", + "sputnik.setting.nametags.general.motes.name": "nicknames", + "sputnik.setting.nametags.general.siempremostrarnametags.desc": "show the nametag when the player is sneaking or invisible", + "sputnik.setting.nametags.general.siempremostrarnametags.name": "always show nametags", + "sputnik.setting.nametags.infoadicional.contaritems.desc": "shows how much of an item there is in a dropped stack", + "sputnik.setting.nametags.infoadicional.contaritems.name": "count items", + "sputnik.setting.nametags.infoadicional.danodelproyectil.desc": "shows how much damage a projectile does in its nametag", + "sputnik.setting.nametags.infoadicional.danodelproyectil.name": "projectile damage", + "sputnik.setting.nametags.infoadicional.distinguirbebes.desc": "changes the nametag when an entity is a baby", + "sputnik.setting.nametags.infoadicional.distinguirbebes.name": "distinguish babies", + "sputnik.setting.nametags.infoadicional.mostrardueno.desc": "shows a pet's owner (doesn't work on cracked servers)", + "sputnik.setting.nametags.infoadicional.mostrardueno.name": "show owner", + "sputnik.setting.nametags.infoadicional.temporizadordetnt.desc": "shows the time left before a TNT block goes off", + "sputnik.setting.nametags.infoadicional.temporizadordetnt.name": "TNT timer", + "sputnik.setting.norender.ambiente.flashesdelend.desc": "render the recently added end flashes", + "sputnik.setting.norender.ambiente.flashesdelend.name": "end flashes", + "sputnik.setting.norender.ambiente.lluvia.desc": "r a i n", + "sputnik.setting.norender.ambiente.lluvia.name": "rain", + "sputnik.setting.norender.ambiente.nieve.desc": "s n o w", + "sputnik.setting.norender.ambiente.nieve.name": "snow", + "sputnik.setting.norender.ambiente.particulas.desc": "list of particles that get rendered", + "sputnik.setting.norender.ambiente.particulas.name": "particles", + "sputnik.setting.norender.efectos.ceguera.desc": "render myopia", + "sputnik.setting.norender.efectos.ceguera.name": "blindness", + "sputnik.setting.norender.efectos.nausea.desc": "render drunkenness", + "sputnik.setting.norender.efectos.nausea.name": "nausea", + "sputnik.setting.norender.efectos.oscuridad.desc": "render fear of the dark", + "sputnik.setting.norender.efectos.oscuridad.name": "darkness", + "sputnik.setting.norender.interfaz.marcador.desc": "show scoreboard on the right", + "sputnik.setting.norender.interfaz.marcador.name": "scoreboard", + "sputnik.setting.norender.interfaz.titulos.desc": "show titles (from the /title command)", + "sputnik.setting.norender.interfaz.titulos.name": "titles", + "sputnik.setting.norender.interfaz.totem.desc": "render the totem pop", + "sputnik.setting.norender.interfaz.totem.name": "totem", + "sputnik.setting.norender.misc.flechasclavadas.desc": "render arrows stuck in players", + "sputnik.setting.norender.misc.flechasclavadas.name": "stuck arrows", + "sputnik.setting.norender.overlays.calabaza.desc": "renders the carved pumpkin overlay", + "sputnik.setting.norender.overlays.calabaza.name": "pumpkin", + "sputnik.setting.norender.overlays.catalejo.desc": "render the spyglass overlay", + "sputnik.setting.norender.overlays.catalejo.name": "spyglass", + "sputnik.setting.norender.overlays.fluidos.desc": "render fluids over the camera, like water, lava or powder snow (even though it isn't a fluid)", + "sputnik.setting.norender.overlays.fluidos.name": "fluids", + "sputnik.setting.norender.overlays.fuego.desc": "render flames over the camera", + "sputnik.setting.norender.overlays.fuego.name": "fire", + "sputnik.setting.norender.overlays.portal.desc": "render the nether portal overlay", + "sputnik.setting.norender.overlays.portal.name": "portal", + "sputnik.setting.norender.texto.colores.desc": "§cp§4r§6o§eu§ad§2 §9g§1a§5y§d", + "sputnik.setting.norender.texto.colores.name": "colors", + "sputnik.setting.norender.texto.garabato.desc": "scramble text (or whatever it's called) (§klike this§r)", + "sputnik.setting.norender.texto.garabato.name": "obfuscated", + "sputnik.setting.norender.texto.negrita.desc": "text but §lbold", + "sputnik.setting.norender.texto.negrita.name": "bold", + "sputnik.setting.norender.texto.subrayado.desc": "text but §nunderlined", + "sputnik.setting.norender.texto.subrayado.name": "underlined", + "sputnik.setting.norender.texto.tachado.desc": "text but §mcrossed out", + "sputnik.setting.norender.texto.tachado.name": "strikethrough", + "sputnik.setting.notificaciones.bajadurabilidad.bajadurabilidad.desc": "notify when the tool in use has low durability", + "sputnik.setting.notificaciones.bajadurabilidad.bajadurabilidad.name": "low durability", + "sputnik.setting.notificaciones.bajadurabilidad.itemsaexcluir.desc": "don't warn about low durability on these", + "sputnik.setting.notificaciones.bajadurabilidad.itemsaexcluir.name": "items to exclude", + "sputnik.setting.notificaciones.bajadurabilidad.porcentaje.desc": "remaining durability percentage you get warned at", + "sputnik.setting.notificaciones.bajadurabilidad.porcentaje.name": "percentage", + "sputnik.setting.notificaciones.general.duracion.desc": "notification duration in seconds", + "sputnik.setting.notificaciones.general.duracion.name": "duration", + "sputnik.setting.notificaciones.general.popup.desc": "show notification pop-up", + "sputnik.setting.notificaciones.general.popup.name": "pop-up", + "sputnik.setting.notificaciones.jugadorenrango.ignorarjugadorfalso.desc": "ignore the \"fake player\" dummy", + "sputnik.setting.notificaciones.jugadorenrango.ignorarjugadorfalso.name": "ignore fake player", + "sputnik.setting.notificaciones.jugadorenrango.jugadorenrango.desc": "notify when a player comes into range", + "sputnik.setting.notificaciones.jugadorenrango.jugadorenrango.name": "player in range", + "sputnik.setting.notificaciones.jugadorenrango.rangodejugadores.desc": "range to take into account when notifying", + "sputnik.setting.notificaciones.jugadorenrango.rangodejugadores.name": "player range", + "sputnik.setting.notificaciones.sonido.frecuencia.desc": "sound pitch", + "sputnik.setting.notificaciones.sonido.frecuencia.name": "frequency", + "sputnik.setting.notificaciones.sonido.sonido.desc": "sound to play with the notifications", + "sputnik.setting.notificaciones.sonido.sonido.name": "sound", + "sputnik.setting.notificaciones.sonido.volumen.desc": "sound volume", + "sputnik.setting.notificaciones.sonido.volumen.name": "volume", + "sputnik.setting.parkour.general.noalagacharse.desc": "don't jump while sneaking", + "sputnik.setting.parkour.general.noalagacharse.name": "not while sneaking", + "sputnik.setting.parkour.general.offset.desc": "how early to jump", + "sputnik.setting.parkour.general.offset.name": "offset", + "sputnik.setting.parkour.general.soloalcorrer.desc": "only jump while sprinting", + "sputnik.setting.parkour.general.soloalcorrer.name": "only while sprinting", + "sputnik.setting.particulas.desplazamiento.desplazamientoposx.desc": "offset on the X axis relative to the player", + "sputnik.setting.particulas.desplazamiento.desplazamientoposx.name": "pos. X offset", + "sputnik.setting.particulas.desplazamiento.desplazamientoposy.desc": "offset on the Y axis relative to the player", + "sputnik.setting.particulas.desplazamiento.desplazamientoposy.name": "pos. Y offset", + "sputnik.setting.particulas.desplazamiento.desplazamientoposz.desc": "offset on the Z axis relative to the player", + "sputnik.setting.particulas.desplazamiento.desplazamientoposz.name": "pos. Z offset", + "sputnik.setting.particulas.dispersion.aleatoriedadposicion.desc": "random variation in position", + "sputnik.setting.particulas.dispersion.aleatoriedadposicion.name": "position randomness", + "sputnik.setting.particulas.dispersion.aleatoriedadvelocidad.desc": "random variation in speed", + "sputnik.setting.particulas.dispersion.aleatoriedadvelocidad.name": "speed randomness", + "sputnik.setting.particulas.dispersion.dispersionx.desc": "horizontal position spread", + "sputnik.setting.particulas.dispersion.dispersionx.name": "X spread", + "sputnik.setting.particulas.dispersion.dispersiony.desc": "vertical position spread", + "sputnik.setting.particulas.dispersion.dispersiony.name": "Y spread", + "sputnik.setting.particulas.dispersion.dispersionz.desc": "position depth spread", + "sputnik.setting.particulas.dispersion.dispersionz.name": "Z spread", + "sputnik.setting.particulas.dispersion.velocidad.desc": "spread speed multiplier", + "sputnik.setting.particulas.dispersion.velocidad.name": "speed", + "sputnik.setting.particulas.general.cantidad.desc": "particles per spawn", + "sputnik.setting.particulas.general.cantidad.name": "amount", + "sputnik.setting.particulas.general.intervalo.desc": "interval between spawns (in ticks)", + "sputnik.setting.particulas.general.intervalo.name": "interval", + "sputnik.setting.particulas.general.particulas.desc": "particles to spawn", + "sputnik.setting.particulas.general.particulas.name": "particles", + "sputnik.setting.patinaje.general.cantidaddesemen.desc": "how much cum to add to the blocks you walk over", + "sputnik.setting.patinaje.general.cantidaddesemen.name": "cum amount", + "sputnik.setting.perspectivalibre.general.camaraamover.desc": "choose which camera the mouse moves and which one stays static", + "sputnik.setting.perspectivalibre.general.camaraamover.name": "camera to move", + "sputnik.setting.perspectivalibre.general.sensibilidaddelasflechas.desc": "how much the arrow keys rotate the static camera (0 to disable)", + "sputnik.setting.perspectivalibre.general.sensibilidaddelasflechas.name": "arrow key sensitivity", + "sputnik.setting.perspectivalibre.general.sensibilidaddelraton.desc": ".", + "sputnik.setting.perspectivalibre.general.sensibilidaddelraton.name": "mouse sensitivity", + "sputnik.setting.perspectivaplus.general.clip.desc": "clip the camera through blocks", + "sputnik.setting.perspectivaplus.general.clip.name": "clip", + "sputnik.setting.perspectivaplus.general.distancia.desc": "default distance from the camera to the player", + "sputnik.setting.perspectivaplus.general.distancia.name": "distance", + "sputnik.setting.perspectivaplus.scrolleo.sensibilidaddelscroll.desc": "mouse wheel sensitivity (0 to disable)", + "sputnik.setting.perspectivaplus.scrolleo.sensibilidaddelscroll.name": "scroll sensitivity", + "sputnik.setting.perspectivaplus.scrolleo.tecladelscroll.desc": "which key to hold to use the mouse wheel", + "sputnik.setting.perspectivaplus.scrolleo.tecladelscroll.name": "scroll key", + "sputnik.setting.precoz.general.bloques.desc": "place blocks early", + "sputnik.setting.precoz.general.bloques.name": "blocks", + "sputnik.setting.precoz.general.cooldownalminar.desc": "cooldown between breaking blocks, in ticks", + "sputnik.setting.precoz.general.cooldownalminar.name": "mining cooldown", + "sputnik.setting.precoz.general.cooldowndebloques.desc": "cooldown for placing blocks, in ticks", + "sputnik.setting.precoz.general.cooldowndebloques.name": "block cooldown", + "sputnik.setting.precoz.general.cooldowndeitems.desc": "cooldown for using items, in ticks", + "sputnik.setting.precoz.general.cooldowndeitems.name": "item cooldown", + "sputnik.setting.precoz.general.items.desc": "use items early", + "sputnik.setting.precoz.general.items.name": "items", + "sputnik.setting.precoz.general.minar.desc": "mine early", + "sputnik.setting.precoz.general.minar.name": "mine", + "sputnik.setting.prevdeshulkers.general.mostrartooltips.desc": "add text to shulker tooltips", + "sputnik.setting.prevdeshulkers.general.mostrartooltips.name": "show tooltips", + "sputnik.setting.prevdeshulkers.general.tecladeprevisualizacion.desc": "key to hold to preview", + "sputnik.setting.prevdeshulkers.general.tecladeprevisualizacion.name": "preview key", + "sputnik.setting.progresodeminado.contorno.colordelcontorno.desc": "outline color", + "sputnik.setting.progresodeminado.contorno.colordelcontorno.name": "outline color", + "sputnik.setting.progresodeminado.contorno.contorno.desc": "render outline", + "sputnik.setting.progresodeminado.contorno.contorno.name": "outline", + "sputnik.setting.progresodeminado.contorno.grosordelinea.desc": "outline line thickness", + "sputnik.setting.progresodeminado.contorno.grosordelinea.name": "line thickness", + "sputnik.setting.progresodeminado.general.mododeminado.desc": "choose whether the box shrinks or expands", + "sputnik.setting.progresodeminado.general.mododeminado.name": "mining mode", + "sputnik.setting.progresodeminado.relleno.colordelrelleno.desc": "fill color", + "sputnik.setting.progresodeminado.relleno.colordelrelleno.name": "fill color", + "sputnik.setting.progresodeminado.relleno.relleno.desc": "render fill", + "sputnik.setting.progresodeminado.relleno.relleno.name": "fill", + "sputnik.setting.puntosdedesconexion.contorno.colordelcontorno.desc": "line color", + "sputnik.setting.puntosdedesconexion.contorno.colordelcontorno.name": "outline color", + "sputnik.setting.puntosdedesconexion.contorno.contorno.desc": "render the box outline (sides)", + "sputnik.setting.puntosdedesconexion.contorno.contorno.name": "outline", + "sputnik.setting.puntosdedesconexion.contorno.grosordelinea.desc": "outline line thickness", + "sputnik.setting.puntosdedesconexion.contorno.grosordelinea.name": "line thickness", + "sputnik.setting.puntosdedesconexion.misc.hitboxcompleta.desc": "render the full hitbox box, or just mark the position", + "sputnik.setting.puntosdedesconexion.misc.hitboxcompleta.name": "full hitbox", + "sputnik.setting.puntosdedesconexion.misc.monigote.desc": "spawn a dummy to mark the position", + "sputnik.setting.puntosdedesconexion.misc.monigote.name": "dummy", + "sputnik.setting.puntosdedesconexion.relleno.colordelrelleno.desc": "side color", + "sputnik.setting.puntosdedesconexion.relleno.colordelrelleno.name": "fill color", + "sputnik.setting.puntosdedesconexion.relleno.relleno.desc": "render the box fill (faces)", + "sputnik.setting.puntosdedesconexion.relleno.relleno.name": "fill", + "sputnik.setting.recorrido.general.color.desc": "color to use", + "sputnik.setting.recorrido.general.color.name": "color", + "sputnik.setting.recorrido.general.esperanzadevida.desc": "how long the trails last", + "sputnik.setting.recorrido.general.esperanzadevida.name": "lifespan", + "sputnik.setting.recorrido.general.gradiente.desc": "opacity gradient of the trail based on elapsed time", + "sputnik.setting.recorrido.general.gradiente.name": "gradient", + "sputnik.setting.recorrido.general.grosor.desc": "line thickness", + "sputnik.setting.recorrido.general.grosor.name": "thickness", + "sputnik.setting.reponer.general.delay.desc": "refill delay, in ticks", + "sputnik.setting.reponer.general.delay.name": "delay", + "sputnik.setting.reponer.general.itemsexcluidos.desc": "items that won't be refilled", + "sputnik.setting.reponer.general.itemsexcluidos.name": "excluded items", + "sputnik.setting.reponer.general.manosecundaria.desc": "refill the offhand too", + "sputnik.setting.reponer.general.manosecundaria.name": "offhand", + "sputnik.setting.reponer.general.minimodeitems.desc": "item count threshold to start refilling", + "sputnik.setting.reponer.general.minimodeitems.name": "min items", + "sputnik.setting.reponer.general.nostackeables.desc": "refill non-stackable items", + "sputnik.setting.reponer.general.nostackeables.name": "non-stackables", + "sputnik.setting.resaltadodebloques.busqueda.busquedaasincrona.desc": "searches for blocks on a separate thread (optimization)", + "sputnik.setting.resaltadodebloques.busqueda.busquedaasincrona.name": "async search", + "sputnik.setting.resaltadodebloques.busqueda.distanciaamoverse.desc": "distance to move before updating the blocks", + "sputnik.setting.resaltadodebloques.busqueda.distanciaamoverse.name": "distance to move", + "sputnik.setting.resaltadodebloques.busqueda.intervalo.desc": "search interval in ticks", + "sputnik.setting.resaltadodebloques.busqueda.intervalo.name": "interval", + "sputnik.setting.resaltadodebloques.busqueda.radio.desc": "block search radius", + "sputnik.setting.resaltadodebloques.busqueda.radio.name": "radius", + "sputnik.setting.resaltadodebloques.contorno.colordelcontorno.desc": "outline color", + "sputnik.setting.resaltadodebloques.contorno.colordelcontorno.name": "outline color", + "sputnik.setting.resaltadodebloques.contorno.contorno.desc": "render block outline", + "sputnik.setting.resaltadodebloques.contorno.contorno.name": "outline", + "sputnik.setting.resaltadodebloques.contorno.grosordelcontorno.desc": "outline line thickness", + "sputnik.setting.resaltadodebloques.contorno.grosordelcontorno.name": "outline thickness", + "sputnik.setting.resaltadodebloques.general.bloques.desc": "blocks to highlight", + "sputnik.setting.resaltadodebloques.general.bloques.name": "blocks", + "sputnik.setting.resaltadodebloques.general.maxbloques.desc": "max number of blocks to highlight", + "sputnik.setting.resaltadodebloques.general.maxbloques.name": "max blocks", + "sputnik.setting.resaltadodebloques.relleno.colordelrelleno.desc": "fill color", + "sputnik.setting.resaltadodebloques.relleno.colordelrelleno.name": "fill color", + "sputnik.setting.resaltadodebloques.relleno.relleno.desc": "render block fill", + "sputnik.setting.resaltadodebloques.relleno.relleno.name": "fill", + "sputnik.setting.resaltadodeentidades.cajas.color.desc": "glow color", + "sputnik.setting.resaltadodeentidades.cajas.color.name": "color", + "sputnik.setting.resaltadodeentidades.cajas.colordelcontorno.desc": "color for the outline", + "sputnik.setting.resaltadodeentidades.cajas.colordelcontorno.name": "outline color", + "sputnik.setting.resaltadodeentidades.cajas.colordelrelleno.desc": "color for the fill", + "sputnik.setting.resaltadodeentidades.cajas.colordelrelleno.name": "fill color", + "sputnik.setting.resaltadodeentidades.cajas.contorno.desc": "box outline", + "sputnik.setting.resaltadodeentidades.cajas.contorno.name": "outline", + "sputnik.setting.resaltadodeentidades.cajas.relleno.desc": "box fill", + "sputnik.setting.resaltadodeentidades.cajas.relleno.name": "fill", + "sputnik.setting.resaltadodeentidades.general.entidades.desc": "entities to highlight", + "sputnik.setting.resaltadodeentidades.general.entidades.name": "entities", + "sputnik.setting.resaltadodeentidades.general.modo.desc": "render mode", + "sputnik.setting.resaltadodeentidades.general.modo.name": "mode", + "sputnik.setting.retroceso.general.explosiones.desc": "take knockback from explosions", + "sputnik.setting.retroceso.general.explosiones.name": "explosions", + "sputnik.setting.retroceso.general.horizontal.desc": "percentage of knockback to take on the Z axis", + "sputnik.setting.retroceso.general.horizontal.name": "horizontal (%)", + "sputnik.setting.retroceso.general.x.desc": "percentage of knockback to take on the X axis", + "sputnik.setting.retroceso.general.x.name": "X (%)", + "sputnik.setting.retroceso.general.y.desc": "percentage of vertical (Y) knockback to take", + "sputnik.setting.retroceso.general.y.name": "Y (%)", + "sputnik.setting.retroceso.tipos.empujar.desc": "take knockback from being pushed by an entity", + "sputnik.setting.retroceso.tipos.empujar.name": "push", + "sputnik.setting.retroceso.tipos.hits.desc": "take knockback from hits", + "sputnik.setting.retroceso.tipos.hits.name": "hits", + "sputnik.setting.rotaciones.general.cabeceo.desc": "horizontal axis - vertical turn (pitch)", + "sputnik.setting.rotaciones.general.cabeceo.name": "bobbing", + "sputnik.setting.rotaciones.general.evitarmovimiento.desc": "cancels all camera movement", + "sputnik.setting.rotaciones.general.evitarmovimiento.name": "avoid movement", + "sputnik.setting.rotaciones.general.guinada.desc": "vertical axis - horizontal turn (yaw)", + "sputnik.setting.rotaciones.general.guinada.name": "yaw", + "sputnik.setting.rotaciones.general.serverside.desc": "spams rotation packets to the server", + "sputnik.setting.rotaciones.general.serverside.name": "serverside", + "sputnik.setting.selecciondeminado.general.acciondebloqueseleccionado.desc": "action to take when clicking an already selected block", + "sputnik.setting.selecciondeminado.general.acciondebloqueseleccionado.name": "selected block action", + "sputnik.setting.selecciondeminado.general.cancelarfueradealcance.desc": "cancel packets that try to break blocks out of the player's reach, to avoid flagging the anticheat", + "sputnik.setting.selecciondeminado.general.cancelarfueradealcance.name": "cancel out of reach", + "sputnik.setting.selecciondeminado.general.delay.desc": "delay between mining retries", + "sputnik.setting.selecciondeminado.general.delay.name": "delay", + "sputnik.setting.selecciondeminado.general.delay1.desc": "delay between block selections", + "sputnik.setting.selecciondeminado.general.delay1.name": "delay", + "sputnik.setting.selecciondeminado.general.enorden.desc": "force breaking the blocks in order", + "sputnik.setting.selecciondeminado.general.enorden.name": "in order", + "sputnik.setting.selecciondeminado.general.noromperpico.desc": "avoids breaking your pickaxe", + "sputnik.setting.selecciondeminado.general.noromperpico.name": "don't break pickaxe", + "sputnik.setting.selecciondeminado.general.rotar.desc": "rotate when mining blocks through the module", + "sputnik.setting.selecciondeminado.general.rotar.name": "rotate", + "sputnik.setting.selecciondeminado.renderizado.color.desc": "rendered outline color", + "sputnik.setting.selecciondeminado.renderizado.color.name": "color", + "sputnik.setting.selecciondeminado.renderizado.grosor.desc": "outline line thickness", + "sputnik.setting.selecciondeminado.renderizado.grosor.name": "thickness", + "sputnik.setting.selecciondeminado.renderizado.renderizar.desc": "render an outline around the blocks being mined", + "sputnik.setting.selecciondeminado.renderizado.renderizar.name": "render", + "sputnik.setting.spooferdebungeecord.general.direccion.desc": "the IP address that will be sent to the server", + "sputnik.setting.spooferdebungeecord.general.direccion.name": "direction", + "sputnik.setting.superposiciondedano.general.color.desc": "color", + "sputnik.setting.superposiciondedano.general.color.name": "color", + "sputnik.setting.superposiciondeluz.colores.colordelaluz.desc": "color for lit blocks", + "sputnik.setting.superposiciondeluz.colores.colordelaluz.name": "light color", + "sputnik.setting.superposiciondeluz.colores.colordeoscuridad.desc": "color for blocks with 0 light", + "sputnik.setting.superposiciondeluz.colores.colordeoscuridad.name": "darkness color", + "sputnik.setting.superposiciondeluz.deteccion.enagua.desc": "also show blocks covered in water", + "sputnik.setting.superposiciondeluz.deteccion.enagua.name": "in water", + "sputnik.setting.superposiciondeluz.deteccion.evitarcullingenagua.desc": "show the overlay through blocks so you can see it from out of the water", + "sputnik.setting.superposiciondeluz.deteccion.evitarcullingenagua.name": "avoid culling in water", + "sputnik.setting.superposiciondeluz.deteccion.radio.desc": "radius to take into account when rendering the overlay", + "sputnik.setting.superposiciondeluz.deteccion.radio.name": "radius", + "sputnik.setting.superposiciondeluz.deteccion.rangovertical.desc": "vertical distance to take into account", + "sputnik.setting.superposiciondeluz.deteccion.rangovertical.name": "vertical range", + "sputnik.setting.superposiciondeluz.optimizacion.actualizacionesincrementales.desc": "only update new / removed blocks instead of recalculating everything", + "sputnik.setting.superposiciondeluz.optimizacion.actualizacionesincrementales.name": "incremental updates", + "sputnik.setting.superposiciondeluz.optimizacion.busquedaasincrona.desc": "search for blocks on a separate thread (reduces lag)", + "sputnik.setting.superposiciondeluz.optimizacion.busquedaasincrona.name": "async search", + "sputnik.setting.superposiciondeluz.optimizacion.intervalodebusqueda.desc": "how many ticks between block search updates", + "sputnik.setting.superposiciondeluz.optimizacion.intervalodebusqueda.name": "search interval", + "sputnik.setting.superposiciondeluz.optimizacion.umbraldemovimiento.desc": "distance the player must move before forcing an update", + "sputnik.setting.superposiciondeluz.optimizacion.umbraldemovimiento.name": "movement threshold", + "sputnik.setting.tecladeperla.general.cambiardevuelta.desc": "move the item back to its place or select the original slot", + "sputnik.setting.tecladeperla.general.cambiardevuelta.name": "switch back", + "sputnik.setting.tenedormagico.general.boost.desc": "movement multiplier", + "sputnik.setting.tenedormagico.general.boost.name": "boost", + "sputnik.setting.tenedormagico.general.fueradelagua.desc": "allow using the water propulsion out of water", + "sputnik.setting.tenedormagico.general.fueradelagua.name": "out of water", + "sputnik.setting.tobillosfuertes.general.centrarjugador.desc": "center the player on the block below them", + "sputnik.setting.tobillosfuertes.general.centrarjugador.name": "center player", + "sputnik.setting.tobillosfuertes.general.distancia.desc": "min fall distance to apply the cushioning", + "sputnik.setting.tobillosfuertes.general.distancia.name": "distance", + "sputnik.setting.tobillosfuertes.general.items.desc": "items to cushion the fall with", + "sputnik.setting.tobillosfuertes.general.items.name": "items", + "sputnik.setting.tobillosfuertes.general.modo.desc": "how to avoid fall damage", + "sputnik.setting.tobillosfuertes.general.modo.name": "mode", + "sputnik.setting.tobillosfuertes.general.salvada.desc": "switch to packet mode if no bucket is available", + "sputnik.setting.tobillosfuertes.general.salvada.name": "clutch", + "sputnik.setting.trayectoria.contorno.color1.desc": "outline color", + "sputnik.setting.trayectoria.contorno.color1.name": "color", + "sputnik.setting.trayectoria.contorno.contorno.desc": "which targets to render the box outline for", + "sputnik.setting.trayectoria.contorno.contorno.name": "outline", + "sputnik.setting.trayectoria.contorno.grosor.desc": "outline line thickness", + "sputnik.setting.trayectoria.contorno.grosor.name": "thickness", + "sputnik.setting.trayectoria.general.manosecundaria.desc": "predict the trajectory of offhand projectiles", + "sputnik.setting.trayectoria.general.manosecundaria.name": "offhand", + "sputnik.setting.trayectoria.resaltado.color2.desc": "outline color", + "sputnik.setting.trayectoria.resaltado.color2.name": "color", + "sputnik.setting.trayectoria.resaltado.relleno.desc": "which targets to render the box fill for", + "sputnik.setting.trayectoria.resaltado.relleno.name": "fill", + "sputnik.setting.trayectoria.trayectoria.color.desc": "trajectory color", + "sputnik.setting.trayectoria.trayectoria.color.name": "color", + "sputnik.setting.trayectoria.trayectoria.estilo.desc": "visual style of the trajectory", + "sputnik.setting.trayectoria.trayectoria.estilo.name": "style", + "sputnik.setting.trayectoria.trayectoria.grosor.desc": "trajectory line thickness", + "sputnik.setting.trayectoria.trayectoria.grosor.name": "thickness", + "sputnik.setting.trayectoria.trayectoria.puntodeimpacto.desc": "show the impact point", + "sputnik.setting.trayectoria.trayectoria.puntodeimpacto.name": "impact point", + "sputnik.setting.trazos.colores.agua.desc": "color for water critters", + "sputnik.setting.trazos.colores.agua.name": "water", + "sputnik.setting.trazos.colores.ambiente.desc": "color for ambient entities", + "sputnik.setting.trazos.colores.ambiente.name": "ambient", + "sputnik.setting.trazos.colores.animales.desc": "color for passive animals", + "sputnik.setting.trazos.colores.animales.name": "animals", + "sputnik.setting.trazos.colores.jugadores.desc": "color for players", + "sputnik.setting.trazos.colores.jugadores.name": "players", + "sputnik.setting.trazos.colores.misc.desc": "color for miscellaneous entities", + "sputnik.setting.trazos.colores.misc.name": "misc.", + "sputnik.setting.trazos.colores.monstruos.desc": "color for monsters", + "sputnik.setting.trazos.colores.monstruos.name": "monsters", + "sputnik.setting.trazos.general.entidades.desc": "entities to aim at", + "sputnik.setting.trazos.general.entidades.name": "entities", + "sputnik.setting.trazos.general.grosordelinea.desc": "line thickness", + "sputnik.setting.trazos.general.grosordelinea.name": "line thickness", + "sputnik.setting.trazos.general.unomismo.desc": "target yourself in freecam and such", + "sputnik.setting.trazos.general.unomismo.name": "self", + "sputnik.setting.yunquesconpluma.general.tipografia.desc": "which typeface to use", + "sputnik.setting.yunquesconpluma.general.tipografia.name": "typeface", + "sputnik.setting.zoom.camara.camaracinematica.desc": "uses the cinematic camera while zooming", + "sputnik.setting.zoom.camara.camaracinematica.name": "cinematic camera", + "sputnik.setting.zoom.camara.sensibilidad.desc": "mouse sensitivity multiplier", + "sputnik.setting.zoom.camara.sensibilidad.name": "sensitivity", + "sputnik.setting.zoom.general.zoom.desc": "zoom amount", + "sputnik.setting.zoom.general.zoom.name": "zoom", + "sputnik.setting.zoom.scrolleo.sensibilidaddelscroll.desc": "mouse wheel sensitivity (0 to disable)", + "sputnik.setting.zoom.scrolleo.sensibilidaddelscroll.name": "scroll sensitivity", + "sputnik.setting.zoom.scrolleo.tecladelscroll.desc": "which key to hold to use the mouse wheel", + "sputnik.setting.zoom.scrolleo.tecladelscroll.name": "scroll key", + "sputnik.setting.zoom.visual.mostrarhud.desc": "hides or shows the on-screen hud", + "sputnik.setting.zoom.visual.mostrarhud.name": "show HUD", + "sputnik.setting.zoom.visual.mostrarmanos.desc": "hides or shows the hands while zooming", + "sputnik.setting.zoom.visual.mostrarmanos.name": "show hands", + "sputnik.ui.availablemodes": "available modes:", + "sputnik.ui.clickgui.title": "gui", + "sputnik.ui.friend.manage": "manage %s", + "sputnik.ui.friend.remove": "remove friend", + "sputnik.ui.list.tooltip": "%s (%s of %s)", + "sputnik.ui.preview.echest": "echest", + "sputnik.ui.preview.shulker": "shulker preview", + "sputnik.ui.searchbar.placeholder": "search...", + "sputnik.ui.settingsof": "%s settings", + "sputnik.update.clickhere": "CLICK HERE", + "sputnik.update.download": "download the latest version (%s) from here:", + "sputnik.update.idgaf": "i don't care", + "sputnik.update.outdated": "outdated version: %s", + "sputnik.update.title": "update", + "sputnik.version.error.fetch": "could not check the latest version", + "sputnik.version.error.parse": "could not parse the gradle.properties file: %s", + "sputnik.version.info.available": "update available. local: %s, latest: %s", + "sputnik.version.info.dev": "mod in a development state: v%s", + "sputnik.version.info.uptodate": "the mod is up to date: v%s", + "sputnik.version.warn.check": "could not check whether the mod is up to date: %s", + "sputnik.version.warn.metadata": "could not build gradle.properties from the metadata" +} diff --git a/src/main/resources/assets/sputnik/lang/es_es.json b/src/main/resources/assets/sputnik/lang/es_es.json new file mode 100644 index 0000000..54acb50 --- /dev/null +++ b/src/main/resources/assets/sputnik/lang/es_es.json @@ -0,0 +1,1441 @@ +{ + "sputnik.args.entity.notfound": "entidad \"%s\" no encontrada", + "sputnik.args.enum.invalid": " argumento inválido: %s", + "sputnik.args.module.notfound": "módulo \"%s\" no encontrado", + "sputnik.args.player.notfound": "el jugador \"%s\" no existe", + "sputnik.category.camara": "cámara", + "sputnik.category.cliente": "cliente", + "sputnik.category.combate": "combate", + "sputnik.category.inventario": "inventario", + "sputnik.category.jugador": "jugador", + "sputnik.category.misc": "misc.", + "sputnik.category.movimiento": "movimiento", + "sputnik.category.mundo": "mundo", + "sputnik.category.red": "red", + "sputnik.category.renderizado": "renderizado", + "sputnik.commands.bind.desc": "asigna una tecla a un módulo", + "sputnik.commands.bind.keybound": "la tecla %s ha sido asignada al módulo %s", + "sputnik.commands.bind.keyreset": "tecla para el módulo %s restablecida a %s", + "sputnik.commands.bind.keytaken": "esa tecla ya está cogida por %s", + "sputnik.commands.bind.presskey": "presiona una tecla para asignarla al módulo %s", + "sputnik.commands.clickslot.desc": "simula un clic a un slot", + "sputnik.commands.config.desc": "abre el marco de ajustes de un módulo", + "sputnik.commands.copyscreenshot.desc": "copia la captura más reciente al portapapeles", + "sputnik.commands.echest.desc": "muestra el contenido de tu enderchest (solo de ver)", + "sputnik.commands.echest.openfirst": "necesitas abrir un enderchest una vez primero", + "sputnik.commands.friend.added": "%s ahora es tu amigo :)", + "sputnik.commands.friend.desc": "gestión de amigos", + "sputnik.commands.friend.list": "amigos:", + "sputnik.commands.friend.removed": "%s ya no es tu amigo :(", + "sputnik.commands.gc.collected": "basura recolectada", + "sputnik.commands.gc.desc": "limpia la ram mediante el recolector de basura (gc)", + "sputnik.commands.peek.desc": "cotillea el inventario de otro jugador", + "sputnik.commands.plugins.calmdown": "calmaaa", + "sputnik.commands.plugins.desc": "busca los plugins que tenga el server", + "sputnik.commands.plugins.erroranalyzingcommands": "error analizando comandos: %s", + "sputnik.commands.plugins.namespacesfound": "%s namespace(s) encontrado(s) de comandos:", + "sputnik.commands.plugins.noplugins": "sin plugins (probablemente)", + "sputnik.commands.plugins.pluginsfound": "%s plugin(s) encontrado(s)", + "sputnik.commands.plugins.singleplayer": "estás en un solo jugador", + "sputnik.commands.prefix.changed": "prefijo cambiado a %s", + "sputnik.commands.prefix.desc": "cambia el prefijo de los comandos", + "sputnik.commands.purge.desc": "elimina mensajes del chat", + "sputnik.commands.repeat.desc": "repite un comando x veces", + "sputnik.commands.repeatwait.desc": "combinación de $repetir y $esperar", + "sputnik.commands.savescreenshot.desc": "guarda localmente la captura más reciente", + "sputnik.commands.savescreenshot.error": "no se pudo guardar la captura", + "sputnik.commands.send.desc": "manda un mensaje en el chat", + "sputnik.commands.spectate.desc": "te permite adquirir el punto de vista de una entidad", + "sputnik.commands.toggle.desc": "enciende / apaga módulos", + "sputnik.commands.wait.desc": "espera un tiempo determinado antes de ejecutar otro comando", + "sputnik.config.autosaving.desc": "guardando configuración...", + "sputnik.config.autosaving.title": "autoguardando...", + "sputnik.config.error.empty": "archivo de config. vacío o inexistente", + "sputnik.config.error.invalidformat": "formato de archivo inválido: %s", + "sputnik.config.error.invalidversion": "versión inválida: %s", + "sputnik.config.error.json": "error cargando json, usando defaults", + "sputnik.config.error.loading": "error cargando ajustes, intentando json", + "sputnik.config.error.saving": "error al guardar ajustes", + "sputnik.config.error.serialization": "error al serializar ajustes", + "sputnik.config.error.toosmall": "archivo demasiado pequeño para ser válido", + "sputnik.config.info.applied": "ajustes aplicados", + "sputnik.config.info.clientsettings": "ajustes del cliente aplicados", + "sputnik.config.info.extendablepanels": "posiciones de marcos extendibles aplicadas", + "sputnik.config.info.friends": "amigos aplicados", + "sputnik.config.info.json": "ajustes json cargados (migración)", + "sputnik.config.info.loaded": "ajustes cargados", + "sputnik.config.info.loading": "cargando ajustes...", + "sputnik.config.info.modulesettings": "ajustes de módulos aplicados", + "sputnik.config.info.modulestates": "estados de módulos aplicados", + "sputnik.config.info.saved": "ajustes guardados", + "sputnik.config.info.searchbar": "posición de la barra de búsqueda aplicada", + "sputnik.config.info.settingspanels": "estados de marcos de ajustes aplicados", + "sputnik.config.warn.nullmodule": "\"null\" como módulo (\"%s\")", + "sputnik.config.warn.thread": "el hilo de guardado no terminó a tiempo", + "sputnik.config.warn.unknownsetting": "watafac queseso: %s", + "sputnik.enum.module.module.keymode.hold": "mantener", + "sputnik.enum.module.module.keymode.toggle": "alternar", + "sputnik.enum.module.module.notifymode.chat": "por chat", + "sputnik.enum.module.module.notifymode.widget": "por widget", + "sputnik.enum.module.modules.camera.autism.rotationdirection.clockwise": "sentido horario", + "sputnik.enum.module.modules.camera.autism.rotationdirection.counterclockwise": "sentido antihorario", + "sputnik.enum.module.modules.camera.freelook.cameramode.camera": "cámara", + "sputnik.enum.module.modules.camera.freelook.cameramode.player": "jugador", + "sputnik.enum.module.modules.camera.fullbright.modes.gamma": "gamma", + "sputnik.enum.module.modules.camera.fullbright.modes.potion": "poción", + "sputnik.enum.module.modules.client.discordrpc.activitytypes.competing": "compitiendo", + "sputnik.enum.module.modules.client.discordrpc.activitytypes.custom": "custom", + "sputnik.enum.module.modules.client.discordrpc.activitytypes.listening": "escuchando", + "sputnik.enum.module.modules.client.discordrpc.activitytypes.playing": "jugando", + "sputnik.enum.module.modules.client.discordrpc.activitytypes.streaming": "streameando", + "sputnik.enum.module.modules.client.discordrpc.activitytypes.watching": "viendo", + "sputnik.enum.module.modules.client.hud.coordsmode.both": "ambas", + "sputnik.enum.module.modules.client.hud.coordsmode.nether": "nether", + "sputnik.enum.module.modules.client.hud.coordsmode.overworld": "superficie", + "sputnik.enum.module.modules.client.hud.dynosaurs.ankylosaurus": "anquilosaurio", + "sputnik.enum.module.modules.client.hud.dynosaurs.pterodactyl": "ptetodáctilo", + "sputnik.enum.module.modules.client.hud.dynosaurs.spinosaurus": "espinosaurio", + "sputnik.enum.module.modules.client.hud.dynosaurs.trex": "t-rex", + "sputnik.enum.module.modules.client.hud.dynosaurs.triceratops": "tricerátops", + "sputnik.enum.module.modules.client.hud.dynosaurs.velocirraptor": "velocirráptor", + "sputnik.enum.module.modules.client.hud.timeformat.twelve_hour": "12h", + "sputnik.enum.module.modules.client.hud.timeformat.twenty_four_hour": "24h", + "sputnik.enum.module.modules.combat.projectiletrajectories.trajectorystyle.dashed": "discontinua", + "sputnik.enum.module.modules.combat.projectiletrajectories.trajectorystyle.dotted": "puntos", + "sputnik.enum.module.modules.combat.projectiletrajectories.trajectorystyle.solid": "continua", + "sputnik.enum.module.modules.combat.projectiletrajectories.trajectorytargets.blocks": "bloques", + "sputnik.enum.module.modules.combat.projectiletrajectories.trajectorytargets.both": "ambos", + "sputnik.enum.module.modules.combat.projectiletrajectories.trajectorytargets.entities": "entidades", + "sputnik.enum.module.modules.combat.projectiletrajectories.trajectorytargets.none": "ninguna", + "sputnik.enum.module.modules.misc.anvilfont.fontmode.circled": "redondo", + "sputnik.enum.module.modules.misc.anvilfont.fontmode.cursed": "to raro", + "sputnik.enum.module.modules.misc.anvilfont.fontmode.greek": "griego", + "sputnik.enum.module.modules.misc.anvilfont.fontmode.normal": "normal", + "sputnik.enum.module.modules.misc.anvilfont.fontmode.uppercase": "mayúsculas", + "sputnik.enum.module.modules.misc.screenshotplus.screenshotactions.copy": "copiar al portapapeles", + "sputnik.enum.module.modules.misc.screenshotplus.screenshotactions.none": "no hacer nada", + "sputnik.enum.module.modules.misc.screenshotplus.screenshotactions.save": "guardar archivo", + "sputnik.enum.module.modules.movement.jesus.jesusmode.solid": "sólido", + "sputnik.enum.module.modules.movement.jesus.jesusmode.vibrate": "vibrador", + "sputnik.enum.module.modules.movement.scaffold.listmode.blacklist": "lista negra (excluir)", + "sputnik.enum.module.modules.movement.scaffold.listmode.whitelist": "lista blanca (incluir)", + "sputnik.enum.module.modules.network.packetdelay.directions.both": "ambos", + "sputnik.enum.module.modules.network.packetdelay.directions.c2s": "cliente a server", + "sputnik.enum.module.modules.network.packetdelay.directions.s2c": "server a cliente", + "sputnik.enum.module.modules.network.packetdelay.packets.all": "todos", + "sputnik.enum.module.modules.network.packetdelay.packets.keep_alive": "paquetes KeepAlive", + "sputnik.enum.module.modules.network.packetdelay.packets.others": "todos menos KeepAlive", + "sputnik.enum.module.modules.network.packetmine.clickaction.add_priority": "agregar prioridad", + "sputnik.enum.module.modules.network.packetmine.clickaction.none": "nada", + "sputnik.enum.module.modules.network.packetmine.clickaction.unselect": "deseleccionar", + "sputnik.enum.module.modules.network.packetmine.rotatemode.both": "ambos", + "sputnik.enum.module.modules.network.packetmine.rotatemode.client": "cámara", + "sputnik.enum.module.modules.network.packetmine.rotatemode.none": "no", + "sputnik.enum.module.modules.network.packetmine.rotatemode.server": "mediante paquetes", + "sputnik.enum.module.modules.player.nofall.nofallmode.clutch": "waterdrop", + "sputnik.enum.module.modules.player.nofall.nofallmode.packet": "paquetes", + "sputnik.enum.module.modules.render.breakingprogress.breakmode.inwards": "para dentro", + "sputnik.enum.module.modules.render.breakingprogress.breakmode.outwards": "para fuera", + "sputnik.enum.module.modules.render.entityesp.espmode.box": "caja 3d", + "sputnik.enum.module.modules.render.entityesp.espmode.glow": "efecto de brillo", + "sputnik.enum.module.modules.render.glintplus.glintcolors.black": "negro", + "sputnik.enum.module.modules.render.glintplus.glintcolors.blue": "azul", + "sputnik.enum.module.modules.render.glintplus.glintcolors.brown": "marrón", + "sputnik.enum.module.modules.render.glintplus.glintcolors.cyan": "cian", + "sputnik.enum.module.modules.render.glintplus.glintcolors.gray": "gris", + "sputnik.enum.module.modules.render.glintplus.glintcolors.green": "verde", + "sputnik.enum.module.modules.render.glintplus.glintcolors.light_blue": "celeste", + "sputnik.enum.module.modules.render.glintplus.glintcolors.light_gray": "plata", + "sputnik.enum.module.modules.render.glintplus.glintcolors.lime": "lima", + "sputnik.enum.module.modules.render.glintplus.glintcolors.magenta": "magenta", + "sputnik.enum.module.modules.render.glintplus.glintcolors.none": "desactivado", + "sputnik.enum.module.modules.render.glintplus.glintcolors.orange": "naranja", + "sputnik.enum.module.modules.render.glintplus.glintcolors.pink": "rosa", + "sputnik.enum.module.modules.render.glintplus.glintcolors.purple": "morado", + "sputnik.enum.module.modules.render.glintplus.glintcolors.rainbow": "gay.", + "sputnik.enum.module.modules.render.glintplus.glintcolors.red": "rojo", + "sputnik.enum.module.modules.render.glintplus.glintcolors.white": "blanco", + "sputnik.enum.module.modules.render.glintplus.glintcolors.yellow": "amarillo", + "sputnik.enum.module.modules.render.nametags.healthmode.hearts": "corazones", + "sputnik.enum.module.modules.render.nametags.healthmode.points": "hp (puntos de vida)", + "sputnik.enum.module.modules.render.norender.colors.aqua": "turquesa", + "sputnik.enum.module.modules.render.norender.colors.black": "negro", + "sputnik.enum.module.modules.render.norender.colors.blue": "azul", + "sputnik.enum.module.modules.render.norender.colors.dark_aqua": "cian", + "sputnik.enum.module.modules.render.norender.colors.dark_blue": "azul oscuro", + "sputnik.enum.module.modules.render.norender.colors.dark_gray": "gris oscuro", + "sputnik.enum.module.modules.render.norender.colors.dark_green": "verde", + "sputnik.enum.module.modules.render.norender.colors.dark_purple": "morado", + "sputnik.enum.module.modules.render.norender.colors.dark_red": "granate", + "sputnik.enum.module.modules.render.norender.colors.default": "por defecto", + "sputnik.enum.module.modules.render.norender.colors.gold": "naranja", + "sputnik.enum.module.modules.render.norender.colors.gray": "gris claro", + "sputnik.enum.module.modules.render.norender.colors.green": "lima", + "sputnik.enum.module.modules.render.norender.colors.light_purple": "lila", + "sputnik.enum.module.modules.render.norender.colors.red": "rojo", + "sputnik.enum.module.modules.render.norender.colors.white": "blanco", + "sputnik.enum.module.modules.render.norender.colors.yellow": "amarillo", + "sputnik.enum.module.modules.world.blockinfo.copymode.command": "copiar comando /setblock", + "sputnik.enum.module.modules.world.blockinfo.copymode.dont": "no copiar", + "sputnik.enum.module.modules.world.blockinfo.copymode.json": "copiar contenido json", + "sputnik.enum.module.modules.world.timechanger.moonphases.default": "por defecto", + "sputnik.enum.module.modules.world.timechanger.moonphases.first_quarter": "cuarto creciente", + "sputnik.enum.module.modules.world.timechanger.moonphases.full_moon": "luna llena", + "sputnik.enum.module.modules.world.timechanger.moonphases.new_moon": "luna nueva", + "sputnik.enum.module.modules.world.timechanger.moonphases.third_quarter": "cuarto menguante", + "sputnik.enum.module.modules.world.timechanger.moonphases.waning_crescent": "luna vieja", + "sputnik.enum.module.modules.world.timechanger.moonphases.waning_gibbous": "menguante gibosa", + "sputnik.enum.module.modules.world.timechanger.moonphases.waxing_crescent": "creciente", + "sputnik.enum.module.modules.world.timechanger.moonphases.waxing_gibbous": "creciente gibosa", + "sputnik.group.andamios.bloques": "bloques", + "sputnik.group.andamios.puente": "puente", + "sputnik.group.andamios.renderizado": "renderizado", + "sputnik.group.auradecristales.colocar": "colocar", + "sputnik.group.auradecristales.renderizado": "renderizado", + "sputnik.group.auradecristales.reventar": "reventar", + "sputnik.group.autopesca.recast": "recast", + "sputnik.group.camaralibre.velocidad": "velocidad", + "sputnik.group.capturasdepantalla.botones": "botones", + "sputnik.group.chatplus.funcionamientodelchat": "funcionamiento del chat", + "sputnik.group.cielocustom.cuerposceleste": "cuerpos celeste", + "sputnik.group.colocarenaire.renderizado": "renderizado", + "sputnik.group.colocarenaire.scrolleo": "scrolleo", + "sputnik.group.common.general": "general", + "sputnik.group.common.module": "módulo", + "sputnik.group.criticos.aspecto": "aspecto", + "sputnik.group.criticos.funcionamiento": "funcionamiento", + "sputnik.group.discordrpc.boton": "botón", + "sputnik.group.discordrpc.imagenes": "imágenes", + "sputnik.group.hud.editor": "editor", + "sputnik.group.hud.elementos": "elementos", + "sputnik.group.hud.visualizacion": "visualización", + "sputnik.group.interfaz.chat": "chat", + "sputnik.group.interfaz.interfaz": "interfaz", + "sputnik.group.interfaz.misc": "misc.", + "sputnik.group.interfaz.widgets": "widgets", + "sputnik.group.jesus.bloques": "bloques", + "sputnik.group.jkrowling.libro": "libro", + "sputnik.group.manos.animaciones": "animaciones", + "sputnik.group.manos.brazo": "brazo", + "sputnik.group.manos.manoprincipal": "mano principal", + "sputnik.group.manos.manosecundaria": "mano secundaria", + "sputnik.group.moro.teclas": "teclas", + "sputnik.group.nametags.infoadicional": "info. adicional", + "sputnik.group.norender.ambiente": "ambiente", + "sputnik.group.norender.efectos": "efectos", + "sputnik.group.norender.interfaz": "interfaz", + "sputnik.group.norender.misc": "misc.", + "sputnik.group.norender.overlays": "overlays", + "sputnik.group.norender.texto": "texto", + "sputnik.group.notificaciones.bajadurabilidad": "baja durabilidad", + "sputnik.group.notificaciones.jugadorenrango": "jugador en rango", + "sputnik.group.notificaciones.sonido": "sonido", + "sputnik.group.particulas.desplazamiento": "desplazamiento", + "sputnik.group.particulas.dispersion": "dispersión", + "sputnik.group.perspectivaplus.scrolleo": "scrolleo", + "sputnik.group.progresodeminado.contorno": "contorno", + "sputnik.group.progresodeminado.relleno": "relleno", + "sputnik.group.puntosdedesconexion.contorno": "contorno", + "sputnik.group.puntosdedesconexion.misc": "misc.", + "sputnik.group.puntosdedesconexion.relleno": "relleno", + "sputnik.group.resaltadodebloques.busqueda": "búsqueda", + "sputnik.group.resaltadodebloques.contorno": "contorno", + "sputnik.group.resaltadodebloques.relleno": "relleno", + "sputnik.group.resaltadodeentidades.cajas": "cajas", + "sputnik.group.retroceso.tipos": "tipos", + "sputnik.group.selecciondeminado.renderizado": "renderizado", + "sputnik.group.superposiciondeluz.colores": "colores", + "sputnik.group.superposiciondeluz.deteccion": "detección", + "sputnik.group.superposiciondeluz.optimizacion": "optimización", + "sputnik.group.trayectoria.contorno": "contorno", + "sputnik.group.trayectoria.resaltado": "resaltado", + "sputnik.group.trayectoria.trayectoria": "trayectoria", + "sputnik.group.trazos.colores": "colores", + "sputnik.group.zoom.camara": "cámara", + "sputnik.group.zoom.scrolleo": "scrolleo", + "sputnik.group.zoom.visual": "visual", + "sputnik.hud.disabled": "HUD está desactivado, lumbreras", + "sputnik.hud.editor.instructions": "arrastrar para mover · clic derecho para visibilidad · ESC para guardar y salir · shift + clic derecho para restablecer", + "sputnik.hud.editor.title": "editor del HUD", + "sputnik.hud.element.armor.desc": "estado de la armadura", + "sputnik.hud.element.coords.desc": "te muestra tu posición XYZ en el mundo", + "sputnik.hud.element.customtext.desc": "texto que tú eliges", + "sputnik.hud.element.customtext.name": "texto custom", + "sputnik.hud.element.dyno.desc": "que viva el autismo joder", + "sputnik.hud.element.dyno.name": "dinosaurio: %s", + "sputnik.hud.element.echest.desc": "items en tu echest", + "sputnik.hud.element.echest.name": "echest", + "sputnik.hud.element.fps.desc": "te muestra los fotogramas por segundo a los que corre el juego", + "sputnik.hud.element.fps.name": "FPS", + "sputnik.hud.element.ping.desc": "latencia entre cliente y servidor, en milisegundos", + "sputnik.hud.element.ping.name": "ping", + "sputnik.hud.element.rotation.desc": "te muestra tu rotación actual", + "sputnik.hud.element.rotation.name": "rotaciones", + "sputnik.hud.element.time.desc": "hora y minutos de la zona horaria seleccionada", + "sputnik.hud.element.time.name": "hora", + "sputnik.hud.element.totems.desc": "totems disponibles", + "sputnik.hud.element.tps.desc": "te muestra la tasa de ticks por segundo del servidor (TPS óptimo: 20)", + "sputnik.hud.element.tps.name": "TPS", + "sputnik.hud.element.uptime.desc": "tiempo jugando", + "sputnik.hud.error.texture": "no se pudo cargar la textura para el elemento del HUD %s: %s", + "sputnik.hud.info.textureloaded": "textura para el elemento del HUD %s cargada", + "sputnik.key.altgr": "alt gr", + "sputnik.key.backspace": "borrar", + "sputnik.key.capslock": "bloq. mayús.", + "sputnik.key.delete": "suprimir", + "sputnik.key.down": "abajo", + "sputnik.key.enter": "enter", + "sputnik.key.insert": "insertar", + "sputnik.key.left": "izquierda", + "sputnik.key.leftalt": "alt izquierdo", + "sputnik.key.leftclick": "clic izquierdo", + "sputnik.key.leftctrl": "ctrl izquierdo", + "sputnik.key.leftshift": "shift izquierdo", + "sputnik.key.middleclick": "ruedita", + "sputnik.key.mousebutton": "botón del ratón %s", + "sputnik.key.none": "ninguna", + "sputnik.key.pagedown": "pág. abajo", + "sputnik.key.pageup": "pág. arriba", + "sputnik.key.right": "derecha", + "sputnik.key.rightclick": "clic derecho", + "sputnik.key.rightctrl": "ctrl derecho", + "sputnik.key.rightshift": "shift derecho", + "sputnik.key.space": "espacio", + "sputnik.key.tab": "tab", + "sputnik.key.unknown": "tecla %s", + "sputnik.key.up": "arriba", + "sputnik.module.aliviarcpu.desc": "evita renderizar objetos en pantalla si la ventana no está seleccionada", + "sputnik.module.aliviarcpu.name": "aliviar cpu", + "sputnik.module.amigos.desc": "sistema de amigos para evitar atacar a ciertos jugadores con módulos de combate", + "sputnik.module.amigos.name": "amigos", + "sputnik.module.andamios.desc": "pone bloques bajo tus pies de manera automática", + "sputnik.module.andamios.name": "andamios", + "sputnik.module.antihambre.desc": "previene el hambre, haciéndole creer al server que nunca corres", + "sputnik.module.antihambre.name": "anti hambre", + "sputnik.module.antiinvis.desc": "te permite ver a los jugadores invisibles", + "sputnik.module.antiinvis.name": "anti invis", + "sputnik.module.apilarbossbars.desc": "apila bossbars para reducir el espacio que ocupan en pantalla", + "sputnik.module.apilarbossbars.name": "apilar bossbars", + "sputnik.module.attributeswapper.desc": "utiliza el \"attribute swapping\" entre dos herramientas para negar daño de durabilidad o aplicar encantamientos adicionales a estas", + "sputnik.module.attributeswapper.name": "attribute-swapper", + "sputnik.module.auradecristales.desc": "coloca y revienta cristales del end por ti", + "sputnik.module.auradecristales.name": "aura de cristales", + "sputnik.module.autismo.desc": "jeje", + "sputnik.module.autismo.name": "autismo", + "sputnik.module.autocartel.desc": "te permite colocar carteles con el mismo texto sin tener que escribirlo uno por uno", + "sputnik.module.autocartel.name": "autocartel", + "sputnik.module.autofish.rodbreaking": "caña a punto de romperse", + "sputnik.module.autoherramienta.desc": "cambia a la herramienta adecuada automáticamente", + "sputnik.module.autoherramienta.name": "auto herramienta", + "sputnik.module.autopechera.desc": "cambia a pechera antes de pegar con el mazo", + "sputnik.module.autopechera.name": "autopechera", + "sputnik.module.autopesca.desc": "pesca por ti", + "sputnik.module.autopesca.name": "auto pesca", + "sputnik.module.autosign.placefirst": "coloca un primer cartel, del cual copiar el contenido", + "sputnik.module.avioneta.desc": "vuela infinitamente, aprovechándose el sistema defectuoso que hizo mojang (hace falta tirarse de unos 50 bloques de altura)", + "sputnik.module.avioneta.name": "avioneta", + "sputnik.module.barcovolador.desc": "convierte tu bote de acacia en un Lockheed F-117 Nighthawk", + "sputnik.module.barcovolador.name": "barco volador", + "sputnik.module.blockinfo.noblock": "no estás apuntando a ningún bloque", + "sputnik.module.blockinfo.noproperties": "no hay propiedades que copiar para este bloque", + "sputnik.module.bookbot.created": "creado libro n. %s", + "sputnik.module.bookbot.nobook": "no se encontró ningún libro", + "sputnik.module.brillibrilli.desc": "deshabilita la oscuridad (y aplica colores a los shaders)", + "sputnik.module.brillibrilli.name": "brilli brilli", + "sputnik.module.bungeespoofer.invalidip": "dirección IP inválida", + "sputnik.module.burglar.dump": "dejar", + "sputnik.module.burglar.steal": "robar", + "sputnik.module.bypassearpacks.desc": "te permite omitir packs de recursos forzados por servers", + "sputnik.module.bypassearpacks.name": "bypassear packs", + "sputnik.module.camaralibre.desc": "permite a la cámara moverse independientemente del jugador. útil para explorar alrededores", + "sputnik.module.camaralibre.name": "cámara libre", + "sputnik.module.capas.desc": "elige qué capa llevar (solo visible para ti)", + "sputnik.module.capas.name": "capas", + "sputnik.module.capturasdepantalla.desc": "elige qué hacer tras tomar una captura de pantalla", + "sputnik.module.capturasdepantalla.name": "capturas de pantalla", + "sputnik.module.cartelesgays.desc": "te permite usar un símbolo a elegir como § para añadir formato a estos.", + "sputnik.module.cartelesgays.name": "carteles gays", + "sputnik.module.chatplus.coordswarn": "cuidadito con las coordenadas chavalín", + "sputnik.module.chatplus.desc": "mejoras para el chat", + "sputnik.module.chatplus.name": "chat plus", + "sputnik.module.chatplus.sendanyway": "[ME LA SUDA]", + "sputnik.module.chatplus.sendanyway.hint": "enviar de todos modos:", + "sputnik.module.chestplateswitch.nochestplate": "no se encontró una pechera en la hotbar", + "sputnik.module.cielocustom.desc": "te deja cambiar visualmente el progreso del día, entre otras cosas", + "sputnik.module.cielocustom.name": "cielo custom", + "sputnik.module.cocaina.desc": "cambia la velocidad de todo el en juego", + "sputnik.module.cocaina.name": "cocaína", + "sputnik.module.colocarenaire.desc": "te permite colocar bloques en el aire", + "sputnik.module.colocarenaire.name": "colocar en aire", + "sputnik.module.conejo.desc": "haz el elytra-bounce manteniendo el espacio", + "sputnik.module.conejo.name": "conejo", + "sputnik.module.confetti.desc": "cambia el color de las partículas del pop del tótem", + "sputnik.module.confetti.name": "confetti", + "sputnik.module.contorno.desc": "customiza el contorno de los bloques", + "sputnik.module.contorno.name": "contorno", + "sputnik.module.criticos.desc": "cambia la apariencia de los críticos al gusto", + "sputnik.module.criticos.name": "críticos", + "sputnik.module.delaydepaquetes.desc": "aplica un delay a los paquetes", + "sputnik.module.delaydepaquetes.name": "delay de paquetes", + "sputnik.module.delfin.desc": "*ruido de delfín*", + "sputnik.module.delfin.name": "delfín", + "sputnik.module.destellodeenchants.desc": "modifica el color del brillo de los encantamientos", + "sputnik.module.destellodeenchants.name": "destello de enchants.", + "sputnik.module.desyncdehitbox.desc": "exploit chino", + "sputnik.module.desyncdehitbox.name": "desync de hitbox", + "sputnik.module.discordrpc.desc": "personaliza la actividad de tu perfil en dishkor", + "sputnik.module.discordrpc.disconnected": "desconectado: %s - %s", + "sputnik.module.discordrpc.error": "error: %s - %s", + "sputnik.module.discordrpc.initerror": "error al inicializar rpc: %s", + "sputnik.module.discordrpc.name": "discordRPC", + "sputnik.module.discordrpc.notanumber": "introduce un NÚMERO (o déjalo vacío)", + "sputnik.module.discordrpc.notoken": "configura el token del bot primero", + "sputnik.module.discordrpc.unsupportedos": "sistema operativo no soportado", + "sputnik.module.discordrpc.updateerror": "error al actualizar rpc: %s", + "sputnik.module.donquijote.desc": "chits para la lanza", + "sputnik.module.donquijote.name": "don quijote", + "sputnik.module.dupedebundle.desc": "dupea items usando un bundle y un libro", + "sputnik.module.dupedebundle.name": "dupe de bundle", + "sputnik.module.elytras.desc": "vuela con elytras", + "sputnik.module.elytras.name": "elytras", + "sputnik.module.escalerasveloces.desc": "sube escaleras más rápidamente", + "sputnik.module.escalerasveloces.name": "escaleras veloces", + "sputnik.module.escalones.desc": "hace que el bloque de subida de escalón sea la distancia deseada", + "sputnik.module.escalones.name": "escalones", + "sputnik.module.escalonesinversos.desc": "escalones pero pabajo", + "sputnik.module.escalonesinversos.name": "escalones inversos", + "sputnik.module.estampaescrotos.desc": "estampa escrotos ajenos", + "sputnik.module.estampaescrotos.name": "estampaescrotos", + "sputnik.module.freecam.damagedisable": "cámara libre se ha desactivado porque has recibido daño", + "sputnik.module.friends.already": "%s ya es tu amigo", + "sputnik.module.friends.notplayer": "no se pudo añadir a %s como amigo", + "sputnik.module.fuentes.desc": "modifica el tipo de letra utilizado al renderizar texto", + "sputnik.module.fuentes.name": "fuentes", + "sputnik.module.headhitters.desc": "mantén pulsado el espacio para hacer headhitting sin tener que espamearlo", + "sputnik.module.headhitters.name": "headhitters", + "sputnik.module.hitboxes.desc": "modifica cómo se renderizan las hitboxes con F3+B", + "sputnik.module.hitboxes.name": "hitboxes", + "sputnik.module.hotkeysinvcreativo.desc": "te permite seguir usando teclas de la hotbar para mover items en la pestaña de búsqueda del creativo en vez de escribir en la barra", + "sputnik.module.hotkeysinvcreativo.name": "hotkeys inv. creativo", + "sputnik.module.hud.desc": "superposición de la pantalla con info. adicional", + "sputnik.module.hud.name": "HUD", + "sputnik.module.infodebloque.desc": "muestra el contenido nbt del bloque al que se está apuntando", + "sputnik.module.infodebloque.name": "info. de bloque", + "sputnik.module.interfaz.desc": "ajustes de la interfaz, y otros misceláneos", + "sputnik.module.interfaz.name": "interfaz", + "sputnik.module.interfazenportales.desc": "te permite abrir interfaces dentro de portales, como el chat o el inventario", + "sputnik.module.interfazenportales.name": "interfaz en portales", + "sputnik.module.inventarioplus.desc": "mueve ítems del inventario usando solo el teclado", + "sputnik.module.inventarioplus.name": "inventario plus", + "sputnik.module.jesus.desc": "te permite caminar sobre el agua", + "sputnik.module.jesus.name": "jesús", + "sputnik.module.jkrowling.desc": "rellena libros con caca", + "sputnik.module.jkrowling.name": "j. k. rowling", + "sputnik.module.jugadorfalso.desc": "invoca una entidad de jugador falsa por motivos de testeo", + "sputnik.module.jugadorfalso.name": "jugador falso", + "sputnik.module.keypearl.nopearls": "no tienes perlas", + "sputnik.module.macekill.oops": "upsi: %s", + "sputnik.module.manos.desc": "modifica la manera en la que se renderizan las manos", + "sputnik.module.manos.name": "manos", + "sputnik.module.manosecundaria.desc": "automáticamente equipa un ítem en la mano secundaria", + "sputnik.module.manosecundaria.name": "mano secundaria", + "sputnik.module.minarsininterrupcion.desc": "te permite minar bloques a través de entidades", + "sputnik.module.minarsininterrupcion.name": "minar sin interrupción", + "sputnik.module.miraplus.desc": "customiza la mira (crosshair)", + "sputnik.module.miraplus.name": "mira plus", + "sputnik.module.mochila.desc": "te permite llevar items en los slots de crafteo", + "sputnik.module.mochila.name": "mochila", + "sputnik.module.moro.desc": "roba cofres con más facilidad", + "sputnik.module.moro.name": "moro", + "sputnik.module.moverseeninterfaz.desc": "te permite seguir usando las teclas de movimiento aún estando en ciertas interfaces", + "sputnik.module.moverseeninterfaz.name": "moverse en interfaz", + "sputnik.module.muletas.desc": "te ayuda a no caerte de bloques, sin agacharte", + "sputnik.module.muletas.name": "muletas", + "sputnik.module.nametags.desc": "modifica la manera en la que se renderizan los nametags", + "sputnik.module.nametags.name": "nametags", + "sputnik.module.nofall.nocushion": "amortiguador (agua, etc.) no encontrado", + "sputnik.module.nofall.packetmode": "cambiado a modo de paquetes", + "sputnik.module.norender.desc": "customiza qué se renderiza y qué no", + "sputnik.module.norender.name": "no render", + "sputnik.module.notificaciones.desc": "te notifica cuando sucedan ciertos eventos", + "sputnik.module.notificaciones.name": "notificaciones", + "sputnik.module.packetdelay.singleplayer": "delay de paquetes no funciona en un solo jugador", + "sputnik.module.packetmine.pickbreaking": "pico por romperse", + "sputnik.module.parkour.desc": "salta automáticamente en el último tick posible, en la esquina del bloque", + "sputnik.module.parkour.name": "parkour", + "sputnik.module.particulas.desc": "emite particulas artificiales", + "sputnik.module.particulas.name": "partículas", + "sputnik.module.patinaje.desc": "añade una fina capa de semen a los bloques que pisas", + "sputnik.module.patinaje.name": "patinaje", + "sputnik.module.perspectivalibre.desc": "te permite mover la cámara de la perspectiva sin mover la del jugador, o vice versa", + "sputnik.module.perspectivalibre.name": "perspectiva libre", + "sputnik.module.perspectivaplus.desc": "añade cositas chulas al cambio de perspectiva", + "sputnik.module.perspectivaplus.name": "perspectiva plus", + "sputnik.module.precoz.desc": "hace cosas como usar items o colocar bloques más rápido", + "sputnik.module.precoz.name": "precoz", + "sputnik.module.prevdeshulkers.desc": "te permite previsualizar el contenido de shulkers desde el inventario", + "sputnik.module.prevdeshulkers.name": "prev. de shulkers", + "sputnik.module.progresodeminado.desc": "te muestra el progreso de minado de un bloque de manera más visible", + "sputnik.module.progresodeminado.name": "progreso de minado", + "sputnik.module.puntosdedesconexion.desc": "te muestra los puntos donde otros jugadores se desconectan", + "sputnik.module.puntosdedesconexion.name": "puntos de desconexión", + "sputnik.module.racismo.desc": "amego segarro", + "sputnik.module.racismo.name": "racismo", + "sputnik.module.reconectar.desc": "añade un botón para reconectarse a un servidor tras ser desconectado", + "sputnik.module.reconectar.name": "reconectar", + "sputnik.module.reconnect.button": "reconectarse", + "sputnik.module.recorrido.desc": "muestra tu recorrido", + "sputnik.module.recorrido.name": "recorrido", + "sputnik.module.reponer.desc": "repone items a medida que se consumen de manera automática", + "sputnik.module.reponer.name": "reponer", + "sputnik.module.resaltadodebloques.desc": "te muestra la posición de cierto tipo de bloque renderizando una caja con su forma", + "sputnik.module.resaltadodebloques.name": "resaltado de bloques", + "sputnik.module.resaltadodeentidades.desc": "resalta el contorno de las entidades seleccionadas a través de bloques", + "sputnik.module.resaltadodeentidades.name": "resaltado de entidades", + "sputnik.module.retroceso.desc": "te hace estar gordo", + "sputnik.module.retroceso.name": "retroceso", + "sputnik.module.rotaciones.desc": "te permite forzar una rotación específica", + "sputnik.module.rotaciones.name": "rotaciones", + "sputnik.module.screenshot.button.copy": "[COPIAR]", + "sputnik.module.screenshot.button.discard": "[DESCARTAR]", + "sputnik.module.screenshot.button.open": "[ABRIR]", + "sputnik.module.screenshot.button.open.hint": "abrir archivo de imagen", + "sputnik.module.screenshot.button.save": "[GUARDAR]", + "sputnik.module.screenshot.copied": "captura copiada al portapapeles", + "sputnik.module.screenshot.copyfailed": "no se pudo copiar la captura al portapapeles", + "sputnik.module.screenshot.savedas": "captura guardada como: ", + "sputnik.module.screenshot.taken": "captura de pantalla tomada", + "sputnik.module.selecciondeminado.desc": "selecciona bloques a minar con paquetes", + "sputnik.module.selecciondeminado.name": "selección de minado", + "sputnik.module.shulkerpeek.empty": "vacío", + "sputnik.module.shulkerpeek.holdtopreview": "mantén %s para previsualizar", + "sputnik.module.shulkerpeek.openechest": "abre un enderchest primero", + "sputnik.module.spooferdebungeecord.desc": "te permite conectarte a los servidores backend de un server bungeecord mal configurado", + "sputnik.module.spooferdebungeecord.name": "spoofer de bungeecord", + "sputnik.module.stronghold.error.different": "los ojos apuntan a strongholds distintas", + "sputnik.module.stronghold.error.move": "pero muévete", + "sputnik.module.stronghold.error.parallel": "los ojos forman líneas paralelas o coincidentes", + "sputnik.module.stronghold.found": "stronghold aproximadamente en: %s", + "sputnik.module.stronghold.moreaccurate": "cuanta más distancia te separes, más preciso será el resultado", + "sputnik.module.stronghold.movenow": "ahora muévete unos 200 bloques en una dirección distinta a la del ojo para lanzar el segundo", + "sputnik.module.stronghold.oops": "upsi", + "sputnik.module.stronghold.standstill": "al lanzar los ojos, quédate quieto, o puede que la posición calculada salga errónea", + "sputnik.module.stronghold.throwfirst": "para empezar, lanza un ojo de ender", + "sputnik.module.superposiciondedano.desc": "modifica el color en el que se renderiza la superposición de recibir daño", + "sputnik.module.superposiciondedano.name": "superposición de daño", + "sputnik.module.superposiciondeluz.desc": "te muestra el nivel de luz en bloques, para prevenir mob spawns", + "sputnik.module.superposiciondeluz.name": "superposición de luz", + "sputnik.module.tecladeperla.desc": "lanza una perla con una tecla", + "sputnik.module.tecladeperla.name": "tecla de perla", + "sputnik.module.tenedormagico.desc": "hermano se piensa que es Poseidón", + "sputnik.module.tenedormagico.name": "tenedor mágico", + "sputnik.module.tobillosfuertes.desc": "evita el daño de caída", + "sputnik.module.tobillosfuertes.name": "tobillos fuertes", + "sputnik.module.toggled.off": "%s fue desactivado", + "sputnik.module.toggled.on": "%s fue activado", + "sputnik.module.trayectoria.desc": "muestra la trayectoria de los proyectiles", + "sputnik.module.trayectoria.name": "trayectoria", + "sputnik.module.trazos.desc": "trazar líneas de la cámara a las entidades seleccionadas", + "sputnik.module.trazos.name": "trazos", + "sputnik.module.trianguladordestrongholds.desc": "usa josecadas para calcular la posición de la stronghold más cercana", + "sputnik.module.trianguladordestrongholds.name": "triangulador de strongholds", + "sputnik.module.yunquesconpluma.desc": "te permite tipografías distintas al renombrar items en un yunque", + "sputnik.module.yunquesconpluma.name": "yunques con pluma", + "sputnik.module.zoom.desc": "lupa", + "sputnik.module.zoom.name": "zoom", + "sputnik.setting.amigos.general.prevenirataques.desc": "no dejar que les ataques manualmente", + "sputnik.setting.amigos.general.prevenirataques.name": "prevenir ataques", + "sputnik.setting.amigos.general.rueditaparaanadiramigo.desc": "pulsara la ruedita del ratón para (des)marcar a un jugador como amigo", + "sputnik.setting.amigos.general.rueditaparaanadiramigo.name": "ruedita para añadir amigo", + "sputnik.setting.andamios.bloques.autoselect.desc": "seleccionar slot más cercano con bloques automáticamente", + "sputnik.setting.andamios.bloques.autoselect.name": "autoselect", + "sputnik.setting.andamios.bloques.bloques.desc": "bloques a aplicar al filtro", + "sputnik.setting.andamios.bloques.bloques.name": "bloques", + "sputnik.setting.andamios.bloques.filtro.desc": "tipo de filtro a usar", + "sputnik.setting.andamios.bloques.filtro.name": "filtro", + "sputnik.setting.andamios.general.rotar.desc": "mover la cabeza", + "sputnik.setting.andamios.general.rotar.name": "rotar", + "sputnik.setting.andamios.puente.descender.desc": "agacharse para descender", + "sputnik.setting.andamios.puente.descender.name": "descender", + "sputnik.setting.andamios.puente.distanciaaextender.desc": "cuánto extender", + "sputnik.setting.andamios.puente.distanciaaextender.name": "distancia a extender", + "sputnik.setting.andamios.puente.extender.desc": "poner bloques en frente al caminar", + "sputnik.setting.andamios.puente.extender.name": "extender", + "sputnik.setting.andamios.puente.headhitter.desc": "poner bloques sobre tu cabeza", + "sputnik.setting.andamios.puente.headhitter.name": "headhitter", + "sputnik.setting.andamios.puente.mjbridge.desc": "hacer que saltar no eleve el nivel y del puente", + "sputnik.setting.andamios.puente.mjbridge.name": "mj bridge", + "sputnik.setting.andamios.puente.torre.desc": "hacer torres verticales chulas", + "sputnik.setting.andamios.puente.torre.name": "torre", + "sputnik.setting.andamios.puente.torremoviendose.desc": "te permite hacer una torre mientras te mueves", + "sputnik.setting.andamios.puente.torremoviendose.name": "torre moviéndose", + "sputnik.setting.andamios.puente.velocidaddetorre.desc": "a qué velocidad hacer la torre", + "sputnik.setting.andamios.puente.velocidaddetorre.name": "velocidad de torre", + "sputnik.setting.andamios.renderizado.colordelcontorno.desc": "color a usar al renderizar el contorno", + "sputnik.setting.andamios.renderizado.colordelcontorno.name": "color del contorno", + "sputnik.setting.andamios.renderizado.colordelrelleno.desc": "color a uisar al renderizar el relleno", + "sputnik.setting.andamios.renderizado.colordelrelleno.name": "color del relleno", + "sputnik.setting.andamios.renderizado.contorno.desc": "renderizar contorno del bloque colocado", + "sputnik.setting.andamios.renderizado.contorno.name": "contorno", + "sputnik.setting.andamios.renderizado.esperanzadevida.desc": "esperanza de vida de los últimos bloques colocados (renderizado)", + "sputnik.setting.andamios.renderizado.esperanzadevida.name": "esperanza de vida", + "sputnik.setting.andamios.renderizado.gradiente.desc": "gradiente de opacidad de los últimos bloques colocados", + "sputnik.setting.andamios.renderizado.gradiente.name": "gradiente", + "sputnik.setting.andamios.renderizado.grosordelinea.desc": "grosor de línea del contorno", + "sputnik.setting.andamios.renderizado.grosordelinea.name": "grosor de línea", + "sputnik.setting.andamios.renderizado.mostrarultimosbloques.desc": "mostrar los últimos bloques colocados", + "sputnik.setting.andamios.renderizado.mostrarultimosbloques.name": "mostrar últimos bloques", + "sputnik.setting.andamios.renderizado.movermano.desc": "mover la mano al colocar bloques", + "sputnik.setting.andamios.renderizado.movermano.name": "mover mano", + "sputnik.setting.andamios.renderizado.relleno.desc": "renderizar relleno del bloque colocado", + "sputnik.setting.andamios.renderizado.relleno.name": "relleno", + "sputnik.setting.apilarbossbars.general.apilarbarras.desc": "apilar las bossbars", + "sputnik.setting.apilarbossbars.general.apilarbarras.name": "apilar barras", + "sputnik.setting.apilarbossbars.general.escondernombres.desc": "no renderiza el nombre de los bosses", + "sputnik.setting.apilarbossbars.general.escondernombres.name": "esconder nombres", + "sputnik.setting.apilarbossbars.general.reducciondeespacio.desc": "cuánto reducir el espacio entre bossbars", + "sputnik.setting.apilarbossbars.general.reducciondeespacio.name": "reducción de espacio", + "sputnik.setting.attributeswapper.general.cambiardevuelta.desc": "volver al slot inicial tras haber aplicado el swapping", + "sputnik.setting.attributeswapper.general.cambiardevuelta.name": "cambiar de vuelta", + "sputnik.setting.attributeswapper.general.delaydecambiodevuelta.desc": "tiempo que se tarda en volver al slot inicial", + "sputnik.setting.attributeswapper.general.delaydecambiodevuelta.name": "delay de cambio de vuelta", + "sputnik.setting.attributeswapper.general.slot.desc": "slot al que cambiar", + "sputnik.setting.attributeswapper.general.slot.name": "slot", + "sputnik.setting.auradecristales.colocar.autoseleccionar.desc": "seleccionar cristales automáticamente", + "sputnik.setting.auradecristales.colocar.autoseleccionar.name": "autoseleccionar", + "sputnik.setting.auradecristales.colocar.colocar.desc": "colocar los cristales", + "sputnik.setting.auradecristales.colocar.colocar.name": "colocar", + "sputnik.setting.auradecristales.colocar.colocarobsidiana.desc": "colocar obsidiana si es necesario", + "sputnik.setting.auradecristales.colocar.colocarobsidiana.name": "colocar obsidiana", + "sputnik.setting.auradecristales.colocar.delay.desc": "delay entre cristal y cristal", + "sputnik.setting.auradecristales.colocar.delay.name": "delay", + "sputnik.setting.auradecristales.colocar.rango1.desc": "rango máximo para colocar cristales", + "sputnik.setting.auradecristales.colocar.rango1.name": "rango ", + "sputnik.setting.auradecristales.colocar.rotar.desc": "rotar para colocar cristales", + "sputnik.setting.auradecristales.colocar.rotar.name": "rotar", + "sputnik.setting.auradecristales.general.entidades.desc": "entidades a las que atacar", + "sputnik.setting.auradecristales.general.entidades.name": "entidades", + "sputnik.setting.auradecristales.general.ignoraramigos.desc": "no targetear amigos", + "sputnik.setting.auradecristales.general.ignoraramigos.name": "ignorar amigos", + "sputnik.setting.auradecristales.general.rango.desc": "rango de detección de blancos", + "sputnik.setting.auradecristales.general.rango.name": "rango", + "sputnik.setting.auradecristales.renderizado.colordelcontorno.desc": "color del contorno", + "sputnik.setting.auradecristales.renderizado.colordelcontorno.name": "color del contorno", + "sputnik.setting.auradecristales.renderizado.colordelrelleno.desc": "color del relleno", + "sputnik.setting.auradecristales.renderizado.colordelrelleno.name": "color del relleno", + "sputnik.setting.auradecristales.renderizado.contorno.desc": "renderizar contorno del bloque donde se colocan los cristales", + "sputnik.setting.auradecristales.renderizado.contorno.name": "contorno", + "sputnik.setting.auradecristales.renderizado.grosordelcontorno.desc": "grosor del contorno", + "sputnik.setting.auradecristales.renderizado.grosordelcontorno.name": "grosor del contorno", + "sputnik.setting.auradecristales.renderizado.relleno.desc": "renderizar relleno del bloque donde se colocan los cristales", + "sputnik.setting.auradecristales.renderizado.relleno.name": "relleno", + "sputnik.setting.auradecristales.reventar.delay1.desc": "delay entre cristal y cristal", + "sputnik.setting.auradecristales.reventar.delay1.name": "delay ", + "sputnik.setting.auradecristales.reventar.reventar.desc": "reventar los cristales", + "sputnik.setting.auradecristales.reventar.reventar.name": "reventar", + "sputnik.setting.auradecristales.reventar.rotar.desc": "rotar para reventar cristales", + "sputnik.setting.auradecristales.reventar.rotar.name": "rotar", + "sputnik.setting.autismo.general.direccion.desc": "dirección de la rotación", + "sputnik.setting.autismo.general.direccion.name": "dirección", + "sputnik.setting.autismo.general.intervalo.desc": "intervalo de rotación", + "sputnik.setting.autismo.general.intervalo.name": "intervalo", + "sputnik.setting.autoherramienta.general.cambiardevuelta.desc": "cambiar de vuelta a la herramienta inicial", + "sputnik.setting.autoherramienta.general.cambiardevuelta.name": "cambiar de vuelta", + "sputnik.setting.autoherramienta.general.delay.desc": "delay al cambiar de herramienta", + "sputnik.setting.autoherramienta.general.delay.name": "delay", + "sputnik.setting.autoherramienta.general.delaydelcambiodevuelta.desc": "delay en ticks para cambiar de vuelta a la herramienta inicial", + "sputnik.setting.autoherramienta.general.delaydelcambiodevuelta.name": "delay del cambio de vuelta", + "sputnik.setting.autopechera.general.cambiardevuelta.desc": "cambiar de vuelta a elytras, si estaban puestas", + "sputnik.setting.autopechera.general.cambiardevuelta.name": "cambiar de vuelta", + "sputnik.setting.autopesca.general.evitarromper.desc": "evitar romper la caña si está en las últimas", + "sputnik.setting.autopesca.general.evitarromper.name": "evitar romper", + "sputnik.setting.autopesca.recast.delay1.desc": "delay entre que se pesca un pez y se vuelve a lanzar la caña", + "sputnik.setting.autopesca.recast.delay1.name": "delay ", + "sputnik.setting.autopesca.recast.distanciadelagua.desc": "distancia máxima a la que puede estar el agua al que estás mirando", + "sputnik.setting.autopesca.recast.distanciadelagua.name": "distancia del agua", + "sputnik.setting.autopesca.recast.recast.desc": "relanzar la caña automáticamente al pescar algo", + "sputnik.setting.autopesca.recast.recast.name": "recast", + "sputnik.setting.autopesca.recast.solosimirandoalagua.desc": "solamente hacer recast si se está mirando al agua", + "sputnik.setting.autopesca.recast.solosimirandoalagua.name": "solo si mirando al agua", + "sputnik.setting.avioneta.general.cabeceoabajo.desc": "cabeceo al ir hacia abajo", + "sputnik.setting.avioneta.general.cabeceoabajo.name": "cabeceo (abajo)", + "sputnik.setting.avioneta.general.cabeceoarriba.desc": "cabeceo al ir hacia arriba", + "sputnik.setting.avioneta.general.cabeceoarriba.name": "cabeceo (arriba)", + "sputnik.setting.avioneta.general.precauciondecolision.desc": "precaución de colisión en ticks", + "sputnik.setting.avioneta.general.precauciondecolision.name": "precaución de colisión", + "sputnik.setting.avioneta.general.velocidaddecabeceoabajo.desc": "velocidad del cabeceo al ir hacia abajo", + "sputnik.setting.avioneta.general.velocidaddecabeceoabajo.name": "velocidad de cabeceo (abajo)", + "sputnik.setting.avioneta.general.velocidaddecabeceoarriba.desc": "velocidad del cabeceo al ir hacia arriba", + "sputnik.setting.avioneta.general.velocidaddecabeceoarriba.name": "velocidad de cabeceo (arriba)", + "sputnik.setting.barcovolador.general.alturadeescalonado.desc": "como escalones pero pal barco", + "sputnik.setting.barcovolador.general.alturadeescalonado.name": "altura de escalonado", + "sputnik.setting.barcovolador.general.cancelarpaquetes.desc": "cancelar paquetes de movimiento del barco enviados por el servidor", + "sputnik.setting.barcovolador.general.cancelarpaquetes.name": "cancelar paquetes", + "sputnik.setting.barcovolador.general.velocidadhorizontal.desc": "velocidad a la que moverse horizontalmente", + "sputnik.setting.barcovolador.general.velocidadhorizontal.name": "velocidad horizontal", + "sputnik.setting.barcovolador.general.velocidadvertical.desc": "velocidad a la que moverse verticalmente", + "sputnik.setting.barcovolador.general.velocidadvertical.name": "velocidad vertical", + "sputnik.setting.brillibrilli.general.filtro.desc": "filtro de color", + "sputnik.setting.brillibrilli.general.filtro.name": "filtro", + "sputnik.setting.brillibrilli.general.modo.desc": "qué modo de iluminación emplear (usar poción con shaders)", + "sputnik.setting.brillibrilli.general.modo.name": "modo", + "sputnik.setting.camaralibre.general.cancelarpaquetes.desc": "evita flaggear el anticheat al interactuar con bloques / entidades", + "sputnik.setting.camaralibre.general.cancelarpaquetes.name": "cancelar paquetes", + "sputnik.setting.camaralibre.general.contornodebloques.desc": "mostrar el contorno de los bloques estando en el modo de cámara libre", + "sputnik.setting.camaralibre.general.contornodebloques.name": "contorno de bloques", + "sputnik.setting.camaralibre.general.desactivaralrecibirdano.desc": "desactiva el módulo tras recibir daño", + "sputnik.setting.camaralibre.general.desactivaralrecibirdano.name": "desactivar al recibir daño", + "sputnik.setting.camaralibre.general.manosvisibles.desc": "decide si se renderizan las manos mientras la cámara esté libre", + "sputnik.setting.camaralibre.general.manosvisibles.name": "manos visibles", + "sputnik.setting.camaralibre.general.mantenerseagachado.desc": "mantener al jugador agachado tras entrar en el modo de cámara libre", + "sputnik.setting.camaralibre.general.mantenerseagachado.name": "mantenerse agachado", + "sputnik.setting.camaralibre.general.recargarchunks.desc": "recargar chunks para arreglar el culling de las cuevas", + "sputnik.setting.camaralibre.general.recargarchunks.name": "recargar chunks", + "sputnik.setting.camaralibre.general.visionestatica.desc": "desactiva ajustes que muevan la cámara", + "sputnik.setting.camaralibre.general.visionestatica.name": "visión estática", + "sputnik.setting.camaralibre.velocidad.sensibilidaddelscroll.desc": "sensibilidad de la rueda del ratón para modificar la velocidad, 0 para desactivar", + "sputnik.setting.camaralibre.velocidad.sensibilidaddelscroll.name": "sensibilidad del scroll", + "sputnik.setting.camaralibre.velocidad.tecladelscroll.desc": "tecla a mantener pulsada para cambiar velocidad con el scroll", + "sputnik.setting.camaralibre.velocidad.tecladelscroll.name": "tecla del scroll", + "sputnik.setting.camaralibre.velocidad.velocidad.desc": "velocidad de movimiento de la cámara", + "sputnik.setting.camaralibre.velocidad.velocidad.name": "velocidad", + "sputnik.setting.capas.general.capa.desc": "qué capa llevar puesta", + "sputnik.setting.capas.general.capa.name": "capa", + "sputnik.setting.capturasdepantalla.botones.botondeabrir.desc": "mostrar botón para abrir el archivo de la captura", + "sputnik.setting.capturasdepantalla.botones.botondeabrir.name": "botón de abrir", + "sputnik.setting.capturasdepantalla.botones.botondecopiar.desc": "mostrar botón para copiar la captura al portapapeles", + "sputnik.setting.capturasdepantalla.botones.botondecopiar.name": "botón de copiar", + "sputnik.setting.capturasdepantalla.botones.botondedescartar.desc": "mostrar botón para descartar la captura", + "sputnik.setting.capturasdepantalla.botones.botondedescartar.name": "botón de descartar", + "sputnik.setting.capturasdepantalla.botones.botondeguardar.desc": "mostrar botón para guardar la captura localmente", + "sputnik.setting.capturasdepantalla.botones.botondeguardar.name": "botón de guardar", + "sputnik.setting.capturasdepantalla.general.pordefecto.desc": "qué acción tomar por defecto", + "sputnik.setting.capturasdepantalla.general.pordefecto.name": "por defecto", + "sputnik.setting.cartelesgays.general.simbolo.desc": "símbolo a reemplazar por \"§\"", + "sputnik.setting.cartelesgays.general.simbolo.name": "símbolo", + "sputnik.setting.chatplus.funcionamientodelchat.expandirchat.desc": "cuántas líneas añadir al historial del chat", + "sputnik.setting.chatplus.funcionamientodelchat.expandirchat.name": "expandir chat", + "sputnik.setting.chatplus.funcionamientodelchat.noborrarchat.desc": "no borrar el chat tras desconectarse", + "sputnik.setting.chatplus.funcionamientodelchat.noborrarchat.name": "no borrar chat", + "sputnik.setting.chatplus.funcionamientodelchat.protegercoordenadas.desc": "evitar enviar coordenadas por el chat", + "sputnik.setting.chatplus.funcionamientodelchat.protegercoordenadas.name": "proteger coordenadas", + "sputnik.setting.chatplus.funcionamientodelchat.quitarlimitedecaracteres.desc": "te deja escribir mensajes tan largos como desees", + "sputnik.setting.chatplus.funcionamientodelchat.quitarlimitedecaracteres.name": "quitar límite de caracteres", + "sputnik.setting.chatplus.funcionamientodelchat.registro.desc": "evita que se borre el chat de un server", + "sputnik.setting.chatplus.funcionamientodelchat.registro.name": "registro", + "sputnik.setting.chatplus.general.cabezas.desc": "muestra la cabeza del jugador junto a su mensaje", + "sputnik.setting.chatplus.general.cabezas.name": "cabezas", + "sputnik.setting.chatplus.general.mostrarsegundos.desc": "muestra segundos también en el sello de tiempo", + "sputnik.setting.chatplus.general.mostrarsegundos.name": "mostrar segundos", + "sputnik.setting.chatplus.general.sellodetiempo.desc": "muestra a qué hora se ha enviado un mensaje", + "sputnik.setting.chatplus.general.sellodetiempo.name": "sello de tiempo", + "sputnik.setting.cielocustom.cuerposceleste.estrellas.desc": "que hayan estrellas o no", + "sputnik.setting.cielocustom.cuerposceleste.estrellas.name": "estrellas", + "sputnik.setting.cielocustom.cuerposceleste.faselunar.desc": "fase lunar actual", + "sputnik.setting.cielocustom.cuerposceleste.faselunar.name": "fase lunar", + "sputnik.setting.cielocustom.cuerposceleste.luna.desc": "que haya luna o no", + "sputnik.setting.cielocustom.cuerposceleste.luna.name": "luna", + "sputnik.setting.cielocustom.cuerposceleste.sol.desc": "que haya sol o no", + "sputnik.setting.cielocustom.cuerposceleste.sol.name": "sol", + "sputnik.setting.cielocustom.general.hora.desc": "hora del juego", + "sputnik.setting.cielocustom.general.hora.name": "hora", + "sputnik.setting.cocaina.general.multi.desc": "como en el Balatro", + "sputnik.setting.cocaina.general.multi.name": "multi", + "sputnik.setting.colocarenaire.general.colocarconnormalidad.desc": "colocar con normalidad si ya se está mirando a un bloque en rango", + "sputnik.setting.colocarenaire.general.colocarconnormalidad.name": "colocar con normalidad", + "sputnik.setting.colocarenaire.general.rango.desc": "distancia a la que colocar el bloque", + "sputnik.setting.colocarenaire.general.rango.name": "rango", + "sputnik.setting.colocarenaire.renderizado.colordelcontorno.desc": "color a utilizar al dibujar el contorno", + "sputnik.setting.colocarenaire.renderizado.colordelcontorno.name": "color del contorno", + "sputnik.setting.colocarenaire.renderizado.colordelrelleno.desc": "color a utilizar al dibujar el relleno", + "sputnik.setting.colocarenaire.renderizado.colordelrelleno.name": "color del relleno", + "sputnik.setting.colocarenaire.renderizado.contorno.desc": "renderizar contorno de la caja de prev.", + "sputnik.setting.colocarenaire.renderizado.contorno.name": "contorno", + "sputnik.setting.colocarenaire.renderizado.grosordelinea.desc": "grosor de las líneas del contorno", + "sputnik.setting.colocarenaire.renderizado.grosordelinea.name": "grosor de línea", + "sputnik.setting.colocarenaire.renderizado.relleno.desc": "renderizar relleno de la caja de prev.", + "sputnik.setting.colocarenaire.renderizado.relleno.name": "relleno", + "sputnik.setting.colocarenaire.scrolleo.sensdelscroll.desc": "sensibilidad de la rueda del scroll (0 para desactivar)", + "sputnik.setting.colocarenaire.scrolleo.sensdelscroll.name": "sens. del scroll", + "sputnik.setting.colocarenaire.scrolleo.tecladelscroll.desc": "tecla a mantener para que el scroll funcione", + "sputnik.setting.colocarenaire.scrolleo.tecladelscroll.name": "tecla del scroll", + "sputnik.setting.color.rainbow": "arcoíris", + "sputnik.setting.common.bind.desc": "tecla asignada al módulo, ESC para desactivar", + "sputnik.setting.common.bind.name": "tecla", + "sputnik.setting.common.keymode.desc": "cómo interpretar la tecla configurada", + "sputnik.setting.common.keymode.name": "modo de tecla", + "sputnik.setting.common.notify.desc": "notificar al activar / desactivar", + "sputnik.setting.common.notify.name": "notificar", + "sputnik.setting.common.notifymode.desc": "cómo notificar cuando se activa / desactiva", + "sputnik.setting.common.notifymode.name": "modo de notificación", + "sputnik.setting.confetti.general.color1.desc": "en vez de amarillo", + "sputnik.setting.confetti.general.color1.name": "color 1", + "sputnik.setting.confetti.general.color2.desc": "en vez de verde", + "sputnik.setting.confetti.general.color2.name": "color 2", + "sputnik.setting.contorno.general.color.desc": "color del contorno de los bloques", + "sputnik.setting.contorno.general.color.name": "color", + "sputnik.setting.contorno.general.grosor.desc": "grosor de las líneas", + "sputnik.setting.contorno.general.grosor.name": "grosor", + "sputnik.setting.criticos.aspecto.color.desc": "color de las partículas", + "sputnik.setting.criticos.aspecto.color.name": "color", + "sputnik.setting.criticos.aspecto.escala.desc": "tamaño", + "sputnik.setting.criticos.aspecto.escala.name": "escala", + "sputnik.setting.criticos.aspecto.multiplo.desc": "número por el que multiplicar la cantidad de partículas generadas", + "sputnik.setting.criticos.aspecto.multiplo.name": "múltiplo", + "sputnik.setting.criticos.funcionamiento.colisionar.desc": "colisionar con bloques", + "sputnik.setting.criticos.funcionamiento.colisionar.name": "colisionar", + "sputnik.setting.criticos.funcionamiento.dispersion.desc": "multiplicador de la velocidad de dispersión", + "sputnik.setting.criticos.funcionamiento.dispersion.name": "dispersión", + "sputnik.setting.criticos.funcionamiento.gravedad.desc": "multiplicador de fuerza de gravedad", + "sputnik.setting.criticos.funcionamiento.gravedad.name": "gravedad", + "sputnik.setting.criticos.funcionamiento.vidamaxima.desc": "cuánto persiste la partícula", + "sputnik.setting.criticos.funcionamiento.vidamaxima.name": "vida máxima", + "sputnik.setting.delaydepaquetes.general.delay.desc": "delay a añadir a los paquetes, en milisegundos", + "sputnik.setting.delaydepaquetes.general.delay.name": "delay", + "sputnik.setting.delaydepaquetes.general.direccion.desc": "dirección de los paquetes a los que añadir delay", + "sputnik.setting.delaydepaquetes.general.direccion.name": "dirección", + "sputnik.setting.delaydepaquetes.general.paquetes.desc": "paquetes a los que aplicar el delay", + "sputnik.setting.delaydepaquetes.general.paquetes.name": "paquetes", + "sputnik.setting.destellodeenchants.general.armadura.desc": "modificar el destello de encantamiento de la armadura", + "sputnik.setting.destellodeenchants.general.armadura.name": "armadura", + "sputnik.setting.destellodeenchants.general.colores.desc": "color del glint", + "sputnik.setting.destellodeenchants.general.colores.name": "colores", + "sputnik.setting.destellodeenchants.general.items.desc": "modificar el destello de encantamiento de los items", + "sputnik.setting.destellodeenchants.general.items.name": "items", + "sputnik.setting.discordrpc.boton.textodelboton.desc": "texto a mostrar en el botón", + "sputnik.setting.discordrpc.boton.textodelboton.name": "texto del botón", + "sputnik.setting.discordrpc.boton.urldelboton.desc": "rickroll en gran 26 :wilted_rose:", + "sputnik.setting.discordrpc.boton.urldelboton.name": "url del botón", + "sputnik.setting.discordrpc.general.detalles.desc": "título", + "sputnik.setting.discordrpc.general.detalles.name": "detalles", + "sputnik.setting.discordrpc.general.estado.desc": "subtítulo", + "sputnik.setting.discordrpc.general.estado.name": "estado", + "sputnik.setting.discordrpc.general.iddelbot.desc": "id del bot a usar (obtener de discord.dev)", + "sputnik.setting.discordrpc.general.iddelbot.name": "id del bot", + "sputnik.setting.discordrpc.general.sellodetiempo.desc": "sello de tiempo del comienzo de la actividad, siguiendo el unix epoch (dejar vacío para ahora)", + "sputnik.setting.discordrpc.general.sellodetiempo.name": "sello de tiempo", + "sputnik.setting.discordrpc.general.tipodeactividad.desc": "qué tipo de actividad se está llevando a cabo", + "sputnik.setting.discordrpc.general.tipodeactividad.name": "tipo de actividad", + "sputnik.setting.discordrpc.imagenes.imagengrande.desc": "clave de la imagen grande", + "sputnik.setting.discordrpc.imagenes.imagengrande.name": "imagen grande", + "sputnik.setting.discordrpc.imagenes.imagenpequena.desc": "clave de la imagen pequeña", + "sputnik.setting.discordrpc.imagenes.imagenpequena.name": "imagen pequeña", + "sputnik.setting.discordrpc.imagenes.textodelaimagengrande.desc": "texto mostrado junto a la imagen grande", + "sputnik.setting.discordrpc.imagenes.textodelaimagengrande.name": "texto de la imagen grande", + "sputnik.setting.discordrpc.imagenes.textodelaimagenpequena.desc": "texto mostrado junto a la imagen pequeña", + "sputnik.setting.discordrpc.imagenes.textodelaimagenpequena.name": "texto de la imagen pequeña", + "sputnik.setting.donquijote.general.ignoraramigos.desc": "no targetear amigos", + "sputnik.setting.donquijote.general.ignoraramigos.name": "ignorar amigos", + "sputnik.setting.donquijote.general.solojugadores.desc": "tener de objetivo solamente jugadores", + "sputnik.setting.donquijote.general.solojugadores.name": "solo jugadores", + "sputnik.setting.donquijote.general.velocidad.desc": "velocidad del impulso", + "sputnik.setting.donquijote.general.velocidad.name": "velocidad", + "sputnik.setting.dupedebundle.general.paquetes.desc": "paquetes a enviar", + "sputnik.setting.dupedebundle.general.paquetes.name": "paquetes", + "sputnik.setting.dupedebundle.general.tiempodeespera.desc": "tiempo a esperar en segundos antes de ser kickeado", + "sputnik.setting.dupedebundle.general.tiempodeespera.name": "tiempo de espera", + "sputnik.setting.elytras.general.velocidad.desc": "mi madre es parcialmente vagabunda", + "sputnik.setting.elytras.general.velocidad.name": "velocidad", + "sputnik.setting.escalerasveloces.general.soloalcorrer.desc": "solo saltar al estar esprintando", + "sputnik.setting.escalerasveloces.general.soloalcorrer.name": "solo al correr", + "sputnik.setting.escalerasveloces.general.soloalhabermasescaleras.desc": "solo saltar cuando el siguiente bloque también son escaleras", + "sputnik.setting.escalerasveloces.general.soloalhabermasescaleras.name": "solo al haber más escaleras", + "sputnik.setting.escalones.general.altura.desc": "altura máxima a subir", + "sputnik.setting.escalones.general.altura.name": "altura", + "sputnik.setting.escalonesinversos.general.altura.desc": "altura máxima a bajar", + "sputnik.setting.escalonesinversos.general.altura.name": "altura", + "sputnik.setting.escalonesinversos.general.desactivarenagua.desc": ".", + "sputnik.setting.escalonesinversos.general.desactivarenagua.name": "desactivar en agua", + "sputnik.setting.escalonesinversos.general.saltar.desc": "permitir saltar", + "sputnik.setting.escalonesinversos.general.saltar.name": "saltar", + "sputnik.setting.escalonesinversos.general.velocidad.desc": "velocidad a la que caer", + "sputnik.setting.escalonesinversos.general.velocidad.name": "velocidad", + "sputnik.setting.estampaescrotos.general.altura.desc": "altura de la que simular la caída", + "sputnik.setting.estampaescrotos.general.altura.name": "altura", + "sputnik.setting.estampaescrotos.general.maximapotencia.desc": "simular caída desde el hueco con aire más cercano en un rango de 170 bloques", + "sputnik.setting.estampaescrotos.general.maximapotencia.name": "máxima potencia", + "sputnik.setting.estampaescrotos.general.prevenirmuerte.desc": "prevenir la muerte por daño de caída si el ataque fue bloqueado, cancelando los paquetes de movimiento", + "sputnik.setting.estampaescrotos.general.prevenirmuerte.name": "prevenir muerte", + "sputnik.setting.friend.nickname.desc": "con qué nombre guardar al amigo", + "sputnik.setting.friend.nickname.name": "nombre", + "sputnik.setting.fuentes.general.fuente.desc": "fuente a emplear", + "sputnik.setting.fuentes.general.fuente.name": "fuente", + "sputnik.setting.fuentes.general.recargar.desc": "recargar automáticamente", + "sputnik.setting.fuentes.general.recargar.name": "recargar", + "sputnik.setting.headhitters.general.delay.desc": "delay de saltos", + "sputnik.setting.headhitters.general.delay.name": "delay", + "sputnik.setting.hitboxes.general.color.desc": "color del que renderizar las cajas de los huevos", + "sputnik.setting.hitboxes.general.color.name": "color", + "sputnik.setting.hitboxes.general.grosor.desc": "grosor de las líneas", + "sputnik.setting.hitboxes.general.grosor.name": "grosor", + "sputnik.setting.hud.editor.cuantomoverconlasflechas.desc": "cuántos píxeles mover el elemento seleccionado al usar las flechas", + "sputnik.setting.hud.editor.cuantomoverconlasflechas.name": "cuánto mover con las flechas", + "sputnik.setting.hud.editor.movimientoaxial.desc": "te permite mover los elementos sobre los ejes más fácilmente", + "sputnik.setting.hud.editor.movimientoaxial.name": "movimiento axial", + "sputnik.setting.hud.editor.movimientoconflechas.desc": "te permite mover el elemento seleccionado con las teclas de las flechas", + "sputnik.setting.hud.editor.movimientoconflechas.name": "movimiento con flechas", + "sputnik.setting.hud.editor.offsetdelosejes.desc": "offset a tener en cuenta al usar el movimiento axial", + "sputnik.setting.hud.editor.offsetdelosejes.name": "offset de los ejes", + "sputnik.setting.hud.editor.tecladeleditor.desc": "tecla asignada al editor de elementos del hud", + "sputnik.setting.hud.editor.tecladeleditor.name": "tecla del editor", + "sputnik.setting.hud.elementos.dinosaurio.desc": "qué dinosaurio mostrar", + "sputnik.setting.hud.elementos.dinosaurio.name": "dinosaurio", + "sputnik.setting.hud.elementos.formatodelahora.desc": "12h o 24h", + "sputnik.setting.hud.elementos.formatodelahora.name": "formato de la hora", + "sputnik.setting.hud.elementos.mododecoordenadas.desc": "qué coordenadas mostrar", + "sputnik.setting.hud.elementos.mododecoordenadas.name": "modo de coordenadas", + "sputnik.setting.hud.elementos.textocustom.desc": "marca de agua (dejar vacío para quitar)", + "sputnik.setting.hud.elementos.textocustom.name": "texto custom", + "sputnik.setting.hud.elementos.zonahoraria.desc": "zona horaria en UTC+n", + "sputnik.setting.hud.elementos.zonahoraria.name": "zona horaria", + "sputnik.setting.hud.visualizacion.color.desc": "color del texto de los elementos del HUD", + "sputnik.setting.hud.visualizacion.color.name": "color", + "sputnik.setting.hud.visualizacion.mostrarenchat.desc": "renderizar HUD en la pantalla del chat", + "sputnik.setting.hud.visualizacion.mostrarenchat.name": "mostrar en chat", + "sputnik.setting.hud.visualizacion.mostrarenf3.desc": "renderizar HUD en el menú de debug", + "sputnik.setting.hud.visualizacion.mostrarenf3.name": "mostrar en F3", + "sputnik.setting.hud.visualizacion.sombra.desc": "texto con sombra", + "sputnik.setting.hud.visualizacion.sombra.name": "sombra", + "sputnik.setting.infodebloque.general.copiar.desc": "copiar al portapapeles", + "sputnik.setting.infodebloque.general.copiar.name": "copiar", + "sputnik.setting.infodebloque.general.liquidos.desc": "también incluir líquidos en el raycast", + "sputnik.setting.infodebloque.general.liquidos.name": "líquidos", + "sputnik.setting.infodebloque.general.tecla.desc": "tecla a pulsar para obtener la info.", + "sputnik.setting.infodebloque.general.tecla.name": "tecla", + "sputnik.setting.interfaz.chat.nombre.desc": "qué nombre usar en notificaciones por el chat", + "sputnik.setting.interfaz.chat.nombre.name": "nombre", + "sputnik.setting.interfaz.chat.prefijo.desc": "prefijo de los comandos", + "sputnik.setting.interfaz.chat.prefijo.name": "prefijo", + "sputnik.setting.interfaz.general.color.desc": "color principal de la interfaz y el mod", + "sputnik.setting.interfaz.general.color.name": "color", + "sputnik.setting.interfaz.interfaz.desenfoque.desc": "desenfocar el fondo mientras la interfaz está abierta", + "sputnik.setting.interfaz.interfaz.desenfoque.name": "desenfoque", + "sputnik.setting.interfaz.interfaz.marcadeagua.desc": "marca de agua para interfaces (dejar vacío para desactivar)", + "sputnik.setting.interfaz.interfaz.marcadeagua.name": "marca de agua", + "sputnik.setting.interfaz.misc.autoguardado.desc": "autoguardar ajustes cada cierto intervalo de tiempo", + "sputnik.setting.interfaz.misc.autoguardado.name": "autoguardado", + "sputnik.setting.interfaz.misc.intervalodeautoguardado.desc": "cada cuántos segundos autoguardar", + "sputnik.setting.interfaz.misc.intervalodeautoguardado.name": "intervalo de autoguardado", + "sputnik.setting.interfaz.misc.teclasmultimodulo.desc": "permitir asignar la misma tecla a más de un módulo o acción", + "sputnik.setting.interfaz.misc.teclasmultimodulo.name": "teclas multimódulo", + "sputnik.setting.interfaz.misc.titulo.desc": "título de la ventana", + "sputnik.setting.interfaz.misc.titulo.name": "título", + "sputnik.setting.interfaz.widgets.barradebusqueda.desc": "renderizar una barra de búsqueda que filtra resultados en todos los marcos abiertos", + "sputnik.setting.interfaz.widgets.barradebusqueda.name": "barra de búsqueda", + "sputnik.setting.interfaz.widgets.barradedesplazamiento.desc": "renderizar una barra de desplazamiento a la derecha de la interfaz", + "sputnik.setting.interfaz.widgets.barradedesplazamiento.name": "barra de desplazamiento", + "sputnik.setting.interfaz.widgets.distinguirmayusculas.desc": "la búsqueda es sensible a mayúsculas y minúsculas", + "sputnik.setting.interfaz.widgets.distinguirmayusculas.name": "distinguir mayúsculas", + "sputnik.setting.interfaz.widgets.sensibilidaddelscroll.desc": "qué tan sensible es la interfaz a la rueda del ratón", + "sputnik.setting.interfaz.widgets.sensibilidaddelscroll.name": "sensibilidad del scroll", + "sputnik.setting.inventarioplus.general.fila1.desc": "tecla para mover items a la primera fila", + "sputnik.setting.inventarioplus.general.fila1.name": "fila 1", + "sputnik.setting.inventarioplus.general.fila2.desc": "tecla para mover items a la segunda fila", + "sputnik.setting.inventarioplus.general.fila2.name": "fila 2", + "sputnik.setting.inventarioplus.general.fila3.desc": "tecla para mover items a la tercera fila", + "sputnik.setting.inventarioplus.general.fila3.name": "fila 3", + "sputnik.setting.jesus.bloques.agua.desc": "permitir caminar en agua", + "sputnik.setting.jesus.bloques.agua.name": "agua", + "sputnik.setting.jesus.bloques.lava.desc": "permitir caminar en lava", + "sputnik.setting.jesus.bloques.lava.name": "lava", + "sputnik.setting.jesus.bloques.nieveenpolvo.desc": "permitir caminar en nieve en polvo", + "sputnik.setting.jesus.bloques.nieveenpolvo.name": "nieve en polvo", + "sputnik.setting.jesus.general.distanciadecaida.desc": "distancia de caída mínima para sumergirse en vez de impactar", + "sputnik.setting.jesus.general.distanciadecaida.name": "distancia de caída", + "sputnik.setting.jesus.general.modo.desc": "cómo caminar", + "sputnik.setting.jesus.general.modo.name": "modo", + "sputnik.setting.jesus.general.permitiragacharse.desc": "te permite usar el botón de agacharse para sumergirte en el agua", + "sputnik.setting.jesus.general.permitiragacharse.name": "permitir agacharse", + "sputnik.setting.jkrowling.general.delay.desc": "delay entre la escritura de libros", + "sputnik.setting.jkrowling.general.delay.name": "delay", + "sputnik.setting.jkrowling.general.desactivaraldesconectarse.desc": ".", + "sputnik.setting.jkrowling.general.desactivaraldesconectarse.name": "desactivar al desconectarse", + "sputnik.setting.jkrowling.libro.contar.desc": "contar los libros y añadir el número al final del nombre", + "sputnik.setting.jkrowling.libro.contar.name": "contar", + "sputnik.setting.jkrowling.libro.firmar.desc": "firmar el libro", + "sputnik.setting.jkrowling.libro.firmar.name": "firmar", + "sputnik.setting.jkrowling.libro.nombre.desc": "nombre a usar para los libros", + "sputnik.setting.jkrowling.libro.nombre.name": "nombre", + "sputnik.setting.jkrowling.libro.paginas.desc": "número de páginas a llenar con mierda", + "sputnik.setting.jkrowling.libro.paginas.name": "páginas", + "sputnik.setting.jkrowling.libro.soloascii.desc": "usar solamente caracteres ascii", + "sputnik.setting.jkrowling.libro.soloascii.name": "solo ascii", + "sputnik.setting.jugadorfalso.general.nombre.desc": "qué nombre asignarle al jugador", + "sputnik.setting.jugadorfalso.general.nombre.name": "nombre", + "sputnik.setting.key.reset": "tecla del módulo %s restablecida", + "sputnik.setting.manos.animaciones.animacionesviejas.desc": "como las de la 1.8, al pegar", + "sputnik.setting.manos.animaciones.animacionesviejas.name": "animaciones viejas", + "sputnik.setting.manos.animaciones.nocomer.desc": "no renderiza la animación de comer", + "sputnik.setting.manos.animaciones.nocomer.name": "no comer", + "sputnik.setting.manos.animaciones.noswap.desc": "se salta la animación de cambiar items de mano", + "sputnik.setting.manos.animaciones.noswap.name": "no swap", + "sputnik.setting.manos.brazo.escaladelbrazox.desc": ".", + "sputnik.setting.manos.brazo.escaladelbrazox.name": "escala del brazo (X)", + "sputnik.setting.manos.brazo.escaladelbrazoy.desc": ".", + "sputnik.setting.manos.brazo.escaladelbrazoy.name": "escala del brazo (Y)", + "sputnik.setting.manos.brazo.escaladelbrazoz.desc": ".", + "sputnik.setting.manos.brazo.escaladelbrazoz.name": "escala del brazo (Z)", + "sputnik.setting.manos.brazo.posiciondelbrazox.desc": ".", + "sputnik.setting.manos.brazo.posiciondelbrazox.name": "posición del brazo (X)", + "sputnik.setting.manos.brazo.posiciondelbrazoy.desc": ".", + "sputnik.setting.manos.brazo.posiciondelbrazoy.name": "posición del brazo (Y)", + "sputnik.setting.manos.brazo.posiciondelbrazoz.desc": ".", + "sputnik.setting.manos.brazo.posiciondelbrazoz.name": "posición del brazo (Z)", + "sputnik.setting.manos.brazo.rotaciondelbrazox.desc": ".", + "sputnik.setting.manos.brazo.rotaciondelbrazox.name": "rotación del brazo (X)", + "sputnik.setting.manos.brazo.rotaciondelbrazoy.desc": ".", + "sputnik.setting.manos.brazo.rotaciondelbrazoy.name": "rotación del brazo (Y)", + "sputnik.setting.manos.brazo.rotaciondelbrazoz.desc": ".", + "sputnik.setting.manos.brazo.rotaciondelbrazoz.name": "rotación del brazo (Z)", + "sputnik.setting.manos.manoprincipal.escaladelamanoprincipalx.desc": ".", + "sputnik.setting.manos.manoprincipal.escaladelamanoprincipalx.name": "escala de la mano principal (X)", + "sputnik.setting.manos.manoprincipal.escaladelamanoprincipaly.desc": ".", + "sputnik.setting.manos.manoprincipal.escaladelamanoprincipaly.name": "escala de la mano principal (Y)", + "sputnik.setting.manos.manoprincipal.escaladelamanoprincipalz.desc": ".", + "sputnik.setting.manos.manoprincipal.escaladelamanoprincipalz.name": "escala de la mano principal (Z)", + "sputnik.setting.manos.manoprincipal.posiciondelamanoprincipalx.desc": ".", + "sputnik.setting.manos.manoprincipal.posiciondelamanoprincipalx.name": "posición de la mano principal (X)", + "sputnik.setting.manos.manoprincipal.posiciondelamanoprincipaly.desc": ".", + "sputnik.setting.manos.manoprincipal.posiciondelamanoprincipaly.name": "posición de la mano principal (Y)", + "sputnik.setting.manos.manoprincipal.posiciondelamanoprincipalz.desc": ".", + "sputnik.setting.manos.manoprincipal.posiciondelamanoprincipalz.name": "posición de la mano principal (Z)", + "sputnik.setting.manos.manoprincipal.rotaciondelamanoprincipalx.desc": ".", + "sputnik.setting.manos.manoprincipal.rotaciondelamanoprincipalx.name": "rotación de la mano principal (X)", + "sputnik.setting.manos.manoprincipal.rotaciondelamanoprincipaly.desc": ".", + "sputnik.setting.manos.manoprincipal.rotaciondelamanoprincipaly.name": "rotación de la mano principal (Y)", + "sputnik.setting.manos.manoprincipal.rotaciondelamanoprincipalz.desc": ".", + "sputnik.setting.manos.manoprincipal.rotaciondelamanoprincipalz.name": "rotación de la mano principal (Z)", + "sputnik.setting.manos.manosecundaria.escaladelamanosecundariax.desc": ".", + "sputnik.setting.manos.manosecundaria.escaladelamanosecundariax.name": "escala de la mano secundaria (X)", + "sputnik.setting.manos.manosecundaria.escaladelamanosecundariay.desc": ".", + "sputnik.setting.manos.manosecundaria.escaladelamanosecundariay.name": "escala de la mano secundaria (Y)", + "sputnik.setting.manos.manosecundaria.escaladelamanosecundariaz.desc": ".", + "sputnik.setting.manos.manosecundaria.escaladelamanosecundariaz.name": "escala de la mano secundaria (Z)", + "sputnik.setting.manos.manosecundaria.posiciondelamanosecundariax.desc": ".", + "sputnik.setting.manos.manosecundaria.posiciondelamanosecundariax.name": "posición de la mano secundaria (X)", + "sputnik.setting.manos.manosecundaria.posiciondelamanosecundariay.desc": ".", + "sputnik.setting.manos.manosecundaria.posiciondelamanosecundariay.name": "posición de la mano secundaria (Y)", + "sputnik.setting.manos.manosecundaria.posiciondelamanosecundariaz.desc": ".", + "sputnik.setting.manos.manosecundaria.posiciondelamanosecundariaz.name": "posición de la mano secundaria (Z)", + "sputnik.setting.manos.manosecundaria.rotaciondelamanosecundariax.desc": ".", + "sputnik.setting.manos.manosecundaria.rotaciondelamanosecundariax.name": "rotación de la mano secundaria (X)", + "sputnik.setting.manos.manosecundaria.rotaciondelamanosecundariay.desc": ".", + "sputnik.setting.manos.manosecundaria.rotaciondelamanosecundariay.name": "rotación de la mano secundaria (Y)", + "sputnik.setting.manos.manosecundaria.rotaciondelamanosecundariaz.desc": ".", + "sputnik.setting.manos.manosecundaria.rotaciondelamanosecundariaz.name": "rotación de la mano secundaria (Z)", + "sputnik.setting.manosecundaria.general.anular.desc": "ignora que ya haya un ítem en la mano secundaria", + "sputnik.setting.manosecundaria.general.anular.name": "anular", + "sputnik.setting.manosecundaria.general.delay.desc": "delay del cambiazo (en ticks)", + "sputnik.setting.manosecundaria.general.delay.name": "delay", + "sputnik.setting.manosecundaria.general.item.desc": "ítem a equipar", + "sputnik.setting.manosecundaria.general.item.name": "ítem", + "sputnik.setting.minarsininterrupcion.general.entidades.desc": "entidades a ignorar", + "sputnik.setting.minarsininterrupcion.general.entidades.name": "entidades", + "sputnik.setting.minarsininterrupcion.general.soloconpico.desc": "ignorar entidades solamente cuando se sujeta un pico", + "sputnik.setting.minarsininterrupcion.general.soloconpico.name": "solo con pico", + "sputnik.setting.miraplus.general.altura.desc": "altura de la mira", + "sputnik.setting.miraplus.general.altura.name": "altura", + "sputnik.setting.miraplus.general.anchura.desc": "anchura de la mira", + "sputnik.setting.miraplus.general.anchura.name": "anchura", + "sputnik.setting.miraplus.general.color.desc": "color de la mira", + "sputnik.setting.miraplus.general.color.name": "color", + "sputnik.setting.moro.general.mostrarbotondedejar.desc": "mostrar un botón para dejar todo en los inventarios de contenedores", + "sputnik.setting.moro.general.mostrarbotondedejar.name": "mostrar botón de dejar", + "sputnik.setting.moro.general.mostrarbotonderobar.desc": "mostrar un botón para robar todo en los inventarios de contenedores", + "sputnik.setting.moro.general.mostrarbotonderobar.name": "mostrar botón de robar", + "sputnik.setting.moro.teclas.dejar.desc": "tecla para dejar todo", + "sputnik.setting.moro.teclas.dejar.name": "dejar", + "sputnik.setting.moro.teclas.robar.desc": "tecla para robar todo", + "sputnik.setting.moro.teclas.robar.name": "robar", + "sputnik.setting.moro.teclas.teclaactivadora.desc": "tecla a mantener para que las otras teclas funcionen", + "sputnik.setting.moro.teclas.teclaactivadora.name": "tecla activadora", + "sputnik.setting.moverseeninterfaz.general.interfaces.desc": "interfaces en las que te podrás mover", + "sputnik.setting.moverseeninterfaz.general.interfaces.name": "interfaces", + "sputnik.setting.muletas.general.distanciadecaida.desc": "distancia de caída máxima permitida", + "sputnik.setting.muletas.general.distanciadecaida.name": "distancia de caída", + "sputnik.setting.nametags.general.entidades.desc": "entidades cuyo nametag será visible", + "sputnik.setting.nametags.general.entidades.name": "entidades", + "sputnik.setting.nametags.general.items.desc": "te permite elegir cuáles items tienen su nombre visible", + "sputnik.setting.nametags.general.items.name": "items", + "sputnik.setting.nametags.general.mostrarpropio.desc": "mostrar nametag propio", + "sputnik.setting.nametags.general.mostrarpropio.name": "mostrar propio", + "sputnik.setting.nametags.general.mostrarvida.desc": "muestra la vida de una entidad en su nametag", + "sputnik.setting.nametags.general.mostrarvida.name": "mostrar vida", + "sputnik.setting.nametags.general.mostrarvidaen.desc": "de qué manera mostrar la vida", + "sputnik.setting.nametags.general.mostrarvidaen.name": "mostrar vida en", + "sputnik.setting.nametags.general.motes.desc": "usar los motes de amigos", + "sputnik.setting.nametags.general.motes.name": "motes", + "sputnik.setting.nametags.general.siempremostrarnametags.desc": "mostrar nametag cuando el jugador está agachado o es invisible", + "sputnik.setting.nametags.general.siempremostrarnametags.name": "siempre mostrar nametags", + "sputnik.setting.nametags.infoadicional.contaritems.desc": "muestra cuánto de un item hay en un stack dropeado", + "sputnik.setting.nametags.infoadicional.contaritems.name": "contar items", + "sputnik.setting.nametags.infoadicional.danodelproyectil.desc": "muestra cuánto daño hace un proyectil en su nametag", + "sputnik.setting.nametags.infoadicional.danodelproyectil.name": "daño del proyectil", + "sputnik.setting.nametags.infoadicional.distinguirbebes.desc": "cambia el nametag cuando una entidad está en su fase bebé", + "sputnik.setting.nametags.infoadicional.distinguirbebes.name": "distinguir bebés", + "sputnik.setting.nametags.infoadicional.mostrardueno.desc": "muestra el dueño de una mascota (no funciona en servers no premium)", + "sputnik.setting.nametags.infoadicional.mostrardueno.name": "mostrar dueño", + "sputnik.setting.nametags.infoadicional.temporizadordetnt.desc": "muestra el tiempo restante para que un bloque de TNT se detone", + "sputnik.setting.nametags.infoadicional.temporizadordetnt.name": "temporizador de TNT", + "sputnik.setting.norender.ambiente.flashesdelend.desc": "renderizar los recientemente añadidos flashes en el end", + "sputnik.setting.norender.ambiente.flashesdelend.name": "flashes del end", + "sputnik.setting.norender.ambiente.lluvia.desc": "l l u v i a", + "sputnik.setting.norender.ambiente.lluvia.name": "lluvia", + "sputnik.setting.norender.ambiente.nieve.desc": "n i e v e", + "sputnik.setting.norender.ambiente.nieve.name": "nieve", + "sputnik.setting.norender.ambiente.particulas.desc": "lista de partículas que se renderizan", + "sputnik.setting.norender.ambiente.particulas.name": "partículas", + "sputnik.setting.norender.efectos.ceguera.desc": "renderizar miopía", + "sputnik.setting.norender.efectos.ceguera.name": "ceguera", + "sputnik.setting.norender.efectos.nausea.desc": "renderizar borrachera", + "sputnik.setting.norender.efectos.nausea.name": "náusea", + "sputnik.setting.norender.efectos.oscuridad.desc": "renderizar miedo a la oscuridad", + "sputnik.setting.norender.efectos.oscuridad.name": "oscuridad", + "sputnik.setting.norender.interfaz.marcador.desc": "mostrar marcador a la derecha", + "sputnik.setting.norender.interfaz.marcador.name": "marcador", + "sputnik.setting.norender.interfaz.titulos.desc": "mostrar títulos (del comando /title)", + "sputnik.setting.norender.interfaz.titulos.name": "títulos", + "sputnik.setting.norender.interfaz.totem.desc": "renderizar el pop del tótem", + "sputnik.setting.norender.interfaz.totem.name": "tótem", + "sputnik.setting.norender.misc.flechasclavadas.desc": "renderizar flechas clavadas en jugadores", + "sputnik.setting.norender.misc.flechasclavadas.name": "flechas clavadas", + "sputnik.setting.norender.overlays.calabaza.desc": "renderiza el overlay de la calabaza tallada", + "sputnik.setting.norender.overlays.calabaza.name": "calabaza", + "sputnik.setting.norender.overlays.catalejo.desc": "renderizar overlay del catalejo", + "sputnik.setting.norender.overlays.catalejo.name": "catalejo", + "sputnik.setting.norender.overlays.fluidos.desc": "renderizar fluídos sobre la cámara como el agua, lava o nieve en polvo (aunque no sea un fluído)", + "sputnik.setting.norender.overlays.fluidos.name": "fluídos", + "sputnik.setting.norender.overlays.fuego.desc": "renderizar llamas sobre la cámara", + "sputnik.setting.norender.overlays.fuego.name": "fuego", + "sputnik.setting.norender.overlays.portal.desc": "renderizar el overlay del portal del nether", + "sputnik.setting.norender.overlays.portal.name": "portal", + "sputnik.setting.norender.texto.colores.desc": "§co§4r§6g§eu§al§2l§9o §1g§5a§dy", + "sputnik.setting.norender.texto.colores.name": "colores", + "sputnik.setting.norender.texto.garabato.desc": "engarabatar texto (o como se diga) (§kasí§r)", + "sputnik.setting.norender.texto.garabato.name": "garabato", + "sputnik.setting.norender.texto.negrita.desc": "letra pero §lgorda", + "sputnik.setting.norender.texto.negrita.name": "negrita", + "sputnik.setting.norender.texto.subrayado.desc": "letra pero §nen el suelo", + "sputnik.setting.norender.texto.subrayado.name": "subrayado", + "sputnik.setting.norender.texto.tachado.desc": "letra pero §mdiscriminada", + "sputnik.setting.norender.texto.tachado.name": "tachado", + "sputnik.setting.notificaciones.bajadurabilidad.bajadurabilidad.desc": "notificar cuando la herramienta en uso tiene baja durabilidad", + "sputnik.setting.notificaciones.bajadurabilidad.bajadurabilidad.name": "baja durabilidad", + "sputnik.setting.notificaciones.bajadurabilidad.itemsaexcluir.desc": "no avisar de la baja durabilidad de estos", + "sputnik.setting.notificaciones.bajadurabilidad.itemsaexcluir.name": "items a excluir", + "sputnik.setting.notificaciones.bajadurabilidad.porcentaje.desc": "porcentaje de durabilidad restante a la que se te avisa", + "sputnik.setting.notificaciones.bajadurabilidad.porcentaje.name": "porcentaje", + "sputnik.setting.notificaciones.general.duracion.desc": "duración de las notis en segundos", + "sputnik.setting.notificaciones.general.duracion.name": "duración", + "sputnik.setting.notificaciones.general.popup.desc": "mostrar pop-up de notificación", + "sputnik.setting.notificaciones.general.popup.name": "pop-up", + "sputnik.setting.notificaciones.jugadorenrango.ignorarjugadorfalso.desc": "ignorar al muñeco de \"jugador falso\"", + "sputnik.setting.notificaciones.jugadorenrango.ignorarjugadorfalso.name": "ignorar jugador falso", + "sputnik.setting.notificaciones.jugadorenrango.jugadorenrango.desc": "notificar cuando un jugador entre en rango", + "sputnik.setting.notificaciones.jugadorenrango.jugadorenrango.name": "jugador en rango", + "sputnik.setting.notificaciones.jugadorenrango.rangodejugadores.desc": "rango a tener en cuenta al notificar", + "sputnik.setting.notificaciones.jugadorenrango.rangodejugadores.name": "rango de jugadores", + "sputnik.setting.notificaciones.sonido.frecuencia.desc": "altura del sonido", + "sputnik.setting.notificaciones.sonido.frecuencia.name": "frecuencia", + "sputnik.setting.notificaciones.sonido.sonido.desc": "sonido a reproducir con las notis", + "sputnik.setting.notificaciones.sonido.sonido.name": "sonido", + "sputnik.setting.notificaciones.sonido.volumen.desc": "volumen del sonido", + "sputnik.setting.notificaciones.sonido.volumen.name": "volumen", + "sputnik.setting.parkour.general.noalagacharse.desc": "no saltar al estar agachado", + "sputnik.setting.parkour.general.noalagacharse.name": "no al agacharse", + "sputnik.setting.parkour.general.offset.desc": "cuán antes saltar", + "sputnik.setting.parkour.general.offset.name": "offset", + "sputnik.setting.parkour.general.soloalcorrer.desc": "solo aplicar salto al estar esprintando", + "sputnik.setting.parkour.general.soloalcorrer.name": "solo al correr", + "sputnik.setting.particulas.desplazamiento.desplazamientoposx.desc": "desplazamiento en el eje X respecto al jugador", + "sputnik.setting.particulas.desplazamiento.desplazamientoposx.name": "desplazamiento pos. X", + "sputnik.setting.particulas.desplazamiento.desplazamientoposy.desc": "desplazamiento en el eje Y respecto al jugador", + "sputnik.setting.particulas.desplazamiento.desplazamientoposy.name": "desplazamiento pos. Y", + "sputnik.setting.particulas.desplazamiento.desplazamientoposz.desc": "desplazamiento en el eje Z respecto al jugador", + "sputnik.setting.particulas.desplazamiento.desplazamientoposz.name": "desplazamiento pos. Z", + "sputnik.setting.particulas.dispersion.aleatoriedadposicion.desc": "variación aleatoria en la posición", + "sputnik.setting.particulas.dispersion.aleatoriedadposicion.name": "aleatoriedad posición", + "sputnik.setting.particulas.dispersion.aleatoriedadvelocidad.desc": "variación aleatoria en la velocidad", + "sputnik.setting.particulas.dispersion.aleatoriedadvelocidad.name": "aleatoriedad velocidad", + "sputnik.setting.particulas.dispersion.dispersionx.desc": "dispersión horizontal de posición", + "sputnik.setting.particulas.dispersion.dispersionx.name": "dispersión X", + "sputnik.setting.particulas.dispersion.dispersiony.desc": "dispersión vertical de posición", + "sputnik.setting.particulas.dispersion.dispersiony.name": "dispersión Y", + "sputnik.setting.particulas.dispersion.dispersionz.desc": "dispersión de profundidad de posición", + "sputnik.setting.particulas.dispersion.dispersionz.name": "dispersión Z", + "sputnik.setting.particulas.dispersion.velocidad.desc": "multiplicador de la velocidad de dispersión", + "sputnik.setting.particulas.dispersion.velocidad.name": "velocidad", + "sputnik.setting.particulas.general.cantidad.desc": "partículas por generación", + "sputnik.setting.particulas.general.cantidad.name": "cantidad", + "sputnik.setting.particulas.general.intervalo.desc": "intervalo entre generaciones (en ticks)", + "sputnik.setting.particulas.general.intervalo.name": "intervalo", + "sputnik.setting.particulas.general.particulas.desc": "partículas a generar", + "sputnik.setting.particulas.general.particulas.name": "partículas", + "sputnik.setting.patinaje.general.cantidaddesemen.desc": "cuánto semen agregar a los bloques por los que pasas", + "sputnik.setting.patinaje.general.cantidaddesemen.name": "cantidad de semen", + "sputnik.setting.perspectivalibre.general.camaraamover.desc": "elige cual cámara mover con el ratón y cuál se queda estática", + "sputnik.setting.perspectivalibre.general.camaraamover.name": "cámara a mover", + "sputnik.setting.perspectivalibre.general.sensibilidaddelasflechas.desc": "cuánto rotan la cámara estática las flechas (0 para desactivar)", + "sputnik.setting.perspectivalibre.general.sensibilidaddelasflechas.name": "sensibilidad de las flechas", + "sputnik.setting.perspectivalibre.general.sensibilidaddelraton.desc": ".", + "sputnik.setting.perspectivalibre.general.sensibilidaddelraton.name": "sensibilidad del ratón", + "sputnik.setting.perspectivaplus.general.clip.desc": "atravesar bloques con la cámara", + "sputnik.setting.perspectivaplus.general.clip.name": "clip", + "sputnik.setting.perspectivaplus.general.distancia.desc": "distancia a la que está la cámara del jugador por defecto", + "sputnik.setting.perspectivaplus.general.distancia.name": "distancia", + "sputnik.setting.perspectivaplus.scrolleo.sensibilidaddelscroll.desc": "sensibilidad de la rueda del ratón (0 para desactivar)", + "sputnik.setting.perspectivaplus.scrolleo.sensibilidaddelscroll.name": "sensibilidad del scroll", + "sputnik.setting.perspectivaplus.scrolleo.tecladelscroll.desc": "qué tecla mantener para usar la rueda del ratón", + "sputnik.setting.perspectivaplus.scrolleo.tecladelscroll.name": "tecla del scroll", + "sputnik.setting.precoz.general.bloques.desc": "colocar bloques precozmente", + "sputnik.setting.precoz.general.bloques.name": "bloques", + "sputnik.setting.precoz.general.cooldownalminar.desc": "cooldown entre rotura de bloques en ticks", + "sputnik.setting.precoz.general.cooldownalminar.name": "cooldown al minar", + "sputnik.setting.precoz.general.cooldowndebloques.desc": "cooldown para colocar bloques en ticks", + "sputnik.setting.precoz.general.cooldowndebloques.name": "cooldown de bloques", + "sputnik.setting.precoz.general.cooldowndeitems.desc": "cooldown para usar items en ticks", + "sputnik.setting.precoz.general.cooldowndeitems.name": "cooldown de items", + "sputnik.setting.precoz.general.items.desc": "usar items precozmente", + "sputnik.setting.precoz.general.items.name": "items", + "sputnik.setting.precoz.general.minar.desc": "minar precozmente", + "sputnik.setting.precoz.general.minar.name": "minar", + "sputnik.setting.prevdeshulkers.general.mostrartooltips.desc": "añadir texto a los tooltips (cajas de texto) de los shulkers", + "sputnik.setting.prevdeshulkers.general.mostrartooltips.name": "mostrar tooltips", + "sputnik.setting.prevdeshulkers.general.tecladeprevisualizacion.desc": "tecla a mantener para previsualizar", + "sputnik.setting.prevdeshulkers.general.tecladeprevisualizacion.name": "tecla de previsualización", + "sputnik.setting.progresodeminado.contorno.colordelcontorno.desc": "color del contorno", + "sputnik.setting.progresodeminado.contorno.colordelcontorno.name": "color del contorno", + "sputnik.setting.progresodeminado.contorno.contorno.desc": "renderizar contorno", + "sputnik.setting.progresodeminado.contorno.contorno.name": "contorno", + "sputnik.setting.progresodeminado.contorno.grosordelinea.desc": "grosor de las líneas del contorno", + "sputnik.setting.progresodeminado.contorno.grosordelinea.name": "grosor de línea", + "sputnik.setting.progresodeminado.general.mododeminado.desc": "elige si el cubo se encoge o se dilata", + "sputnik.setting.progresodeminado.general.mododeminado.name": "modo de minado", + "sputnik.setting.progresodeminado.relleno.colordelrelleno.desc": "color del relleno", + "sputnik.setting.progresodeminado.relleno.colordelrelleno.name": "color del relleno", + "sputnik.setting.progresodeminado.relleno.relleno.desc": "renderizar relleno", + "sputnik.setting.progresodeminado.relleno.relleno.name": "relleno", + "sputnik.setting.puntosdedesconexion.contorno.colordelcontorno.desc": "Color de las líneas", + "sputnik.setting.puntosdedesconexion.contorno.colordelcontorno.name": "color del contorno", + "sputnik.setting.puntosdedesconexion.contorno.contorno.desc": "renderizar contorno de la caja (lados)", + "sputnik.setting.puntosdedesconexion.contorno.contorno.name": "contorno", + "sputnik.setting.puntosdedesconexion.contorno.grosordelinea.desc": "grosor de las líneas del contorno", + "sputnik.setting.puntosdedesconexion.contorno.grosordelinea.name": "grosor de línea", + "sputnik.setting.puntosdedesconexion.misc.hitboxcompleta.desc": "renderizar la caja completa de la hitbox, o solo marcar la posición", + "sputnik.setting.puntosdedesconexion.misc.hitboxcompleta.name": "hitbox completa", + "sputnik.setting.puntosdedesconexion.misc.monigote.desc": "spawnear un monigote para marcar la posición", + "sputnik.setting.puntosdedesconexion.misc.monigote.name": "monigote", + "sputnik.setting.puntosdedesconexion.relleno.colordelrelleno.desc": "Color de los lados", + "sputnik.setting.puntosdedesconexion.relleno.colordelrelleno.name": "color del relleno", + "sputnik.setting.puntosdedesconexion.relleno.relleno.desc": "renderizar relleno de la caja (caras)", + "sputnik.setting.puntosdedesconexion.relleno.relleno.name": "relleno", + "sputnik.setting.recorrido.general.color.desc": "color a usar", + "sputnik.setting.recorrido.general.color.name": "color", + "sputnik.setting.recorrido.general.esperanzadevida.desc": "cuánto duran los trazos", + "sputnik.setting.recorrido.general.esperanzadevida.name": "esperanza de vida", + "sputnik.setting.recorrido.general.gradiente.desc": "gradiente de opacidad del recorrido basado en el tiempo pasado", + "sputnik.setting.recorrido.general.gradiente.name": "gradiente", + "sputnik.setting.recorrido.general.grosor.desc": "grosor de las líneas", + "sputnik.setting.recorrido.general.grosor.name": "grosor", + "sputnik.setting.reponer.general.delay.desc": "delay al reponer, en ticks", + "sputnik.setting.reponer.general.delay.name": "delay", + "sputnik.setting.reponer.general.itemsexcluidos.desc": "items que no se reponen", + "sputnik.setting.reponer.general.itemsexcluidos.name": "items excluídos", + "sputnik.setting.reponer.general.manosecundaria.desc": "reponer la mano secundaria también", + "sputnik.setting.reponer.general.manosecundaria.name": "mano secundaria", + "sputnik.setting.reponer.general.minimodeitems.desc": "límite de cantidad de items para empezar a reponer", + "sputnik.setting.reponer.general.minimodeitems.name": "mínimo de items", + "sputnik.setting.reponer.general.nostackeables.desc": "reponer items no stackeables", + "sputnik.setting.reponer.general.nostackeables.name": "no stackeables", + "sputnik.setting.resaltadodebloques.busqueda.busquedaasincrona.desc": "busca los bloques en un hilo separado (optimización)", + "sputnik.setting.resaltadodebloques.busqueda.busquedaasincrona.name": "búsqueda asíncrona", + "sputnik.setting.resaltadodebloques.busqueda.distanciaamoverse.desc": "distancia a moverse antes de actualizar los bloques", + "sputnik.setting.resaltadodebloques.busqueda.distanciaamoverse.name": "distancia a moverse", + "sputnik.setting.resaltadodebloques.busqueda.intervalo.desc": "intervalo de búsqueda en ticks", + "sputnik.setting.resaltadodebloques.busqueda.intervalo.name": "intervalo", + "sputnik.setting.resaltadodebloques.busqueda.radio.desc": "radio de búsqueda de bloques", + "sputnik.setting.resaltadodebloques.busqueda.radio.name": "radio", + "sputnik.setting.resaltadodebloques.contorno.colordelcontorno.desc": "color del contorno", + "sputnik.setting.resaltadodebloques.contorno.colordelcontorno.name": "color del contorno", + "sputnik.setting.resaltadodebloques.contorno.contorno.desc": "renderizar contorno de bloques", + "sputnik.setting.resaltadodebloques.contorno.contorno.name": "contorno", + "sputnik.setting.resaltadodebloques.contorno.grosordelcontorno.desc": "grosor de las líneas del contorno", + "sputnik.setting.resaltadodebloques.contorno.grosordelcontorno.name": "grosor del contorno", + "sputnik.setting.resaltadodebloques.general.bloques.desc": "bloques a resaltar", + "sputnik.setting.resaltadodebloques.general.bloques.name": "bloques", + "sputnik.setting.resaltadodebloques.general.maxbloques.desc": "número máximo de bloques a resaltar", + "sputnik.setting.resaltadodebloques.general.maxbloques.name": "máx. bloques", + "sputnik.setting.resaltadodebloques.relleno.colordelrelleno.desc": "color del relleno", + "sputnik.setting.resaltadodebloques.relleno.colordelrelleno.name": "color del relleno", + "sputnik.setting.resaltadodebloques.relleno.relleno.desc": "renderizar relleno de bloques", + "sputnik.setting.resaltadodebloques.relleno.relleno.name": "relleno", + "sputnik.setting.resaltadodeentidades.cajas.color.desc": "color del brillo", + "sputnik.setting.resaltadodeentidades.cajas.color.name": "color", + "sputnik.setting.resaltadodeentidades.cajas.colordelcontorno.desc": "color para el contorno", + "sputnik.setting.resaltadodeentidades.cajas.colordelcontorno.name": "color del contorno", + "sputnik.setting.resaltadodeentidades.cajas.colordelrelleno.desc": "color para el relleno", + "sputnik.setting.resaltadodeentidades.cajas.colordelrelleno.name": "color del relleno", + "sputnik.setting.resaltadodeentidades.cajas.contorno.desc": "contorno de las cajas", + "sputnik.setting.resaltadodeentidades.cajas.contorno.name": "contorno", + "sputnik.setting.resaltadodeentidades.cajas.relleno.desc": "relleno de las cajas", + "sputnik.setting.resaltadodeentidades.cajas.relleno.name": "relleno", + "sputnik.setting.resaltadodeentidades.general.entidades.desc": "entidades a resaltar", + "sputnik.setting.resaltadodeentidades.general.entidades.name": "entidades", + "sputnik.setting.resaltadodeentidades.general.modo.desc": "modo de renderizado", + "sputnik.setting.resaltadodeentidades.general.modo.name": "modo", + "sputnik.setting.retroceso.general.explosiones.desc": "tomar retroceso de explosiones", + "sputnik.setting.retroceso.general.explosiones.name": "explosiones", + "sputnik.setting.retroceso.general.horizontal.desc": "porcentaje de retroceso en el eje Z a tomar", + "sputnik.setting.retroceso.general.horizontal.name": "horizontal (%)", + "sputnik.setting.retroceso.general.x.desc": "porcentaje de retroceso en el eje X a tomar", + "sputnik.setting.retroceso.general.x.name": "X (%)", + "sputnik.setting.retroceso.general.y.desc": "porcentaje de retroceso vertical (Y) a tomar", + "sputnik.setting.retroceso.general.y.name": "Y (%)", + "sputnik.setting.retroceso.tipos.empujar.desc": "tomar retroceso de cuando te empuja una entidad", + "sputnik.setting.retroceso.tipos.empujar.name": "empujar", + "sputnik.setting.retroceso.tipos.hits.desc": "tomar retroceso de golpes", + "sputnik.setting.retroceso.tipos.hits.name": "hits", + "sputnik.setting.rotaciones.general.cabeceo.desc": "eje horizontal - giro vertical (pitch)", + "sputnik.setting.rotaciones.general.cabeceo.name": "cabeceo", + "sputnik.setting.rotaciones.general.evitarmovimiento.desc": "cancela todo movimiento de la cámara", + "sputnik.setting.rotaciones.general.evitarmovimiento.name": "evitar movimiento", + "sputnik.setting.rotaciones.general.guinada.desc": "eje vertical - giro horizontal (yaw)", + "sputnik.setting.rotaciones.general.guinada.name": "guiñada", + "sputnik.setting.rotaciones.general.serverside.desc": "espamea paquetes de rotación al servidor", + "sputnik.setting.rotaciones.general.serverside.name": "serverside", + "sputnik.setting.selecciondeminado.general.acciondebloqueseleccionado.desc": "acción a llevar a cabo al clicar sobre un bloque ya seleccionado", + "sputnik.setting.selecciondeminado.general.acciondebloqueseleccionado.name": "acción de bloque seleccionado", + "sputnik.setting.selecciondeminado.general.cancelarfueradealcance.desc": "cancelar aquellos paquetes que intenten romper bloques fuera del alcance del jugador, para evitar flaggear el anticheat", + "sputnik.setting.selecciondeminado.general.cancelarfueradealcance.name": "cancelar fuera de alcance", + "sputnik.setting.selecciondeminado.general.delay.desc": "delay entre reintentos de minado", + "sputnik.setting.selecciondeminado.general.delay.name": "delay", + "sputnik.setting.selecciondeminado.general.delay1.desc": "delay entre selecciones de bloques", + "sputnik.setting.selecciondeminado.general.delay1.name": "delay ", + "sputnik.setting.selecciondeminado.general.enorden.desc": "romper los bloques en orden forzosamente", + "sputnik.setting.selecciondeminado.general.enorden.name": "en orden", + "sputnik.setting.selecciondeminado.general.noromperpico.desc": "evita romper el pico", + "sputnik.setting.selecciondeminado.general.noromperpico.name": "no romper pico", + "sputnik.setting.selecciondeminado.general.rotar.desc": "rotar al minar bloques mediante el módulo", + "sputnik.setting.selecciondeminado.general.rotar.name": "rotar", + "sputnik.setting.selecciondeminado.renderizado.color.desc": "color del contorno renderizado", + "sputnik.setting.selecciondeminado.renderizado.color.name": "color", + "sputnik.setting.selecciondeminado.renderizado.grosor.desc": "grosor de las líneas del contorno", + "sputnik.setting.selecciondeminado.renderizado.grosor.name": "grosor", + "sputnik.setting.selecciondeminado.renderizado.renderizar.desc": "renderizar un contorno alrededor de los bloques que están siendo minados", + "sputnik.setting.selecciondeminado.renderizado.renderizar.name": "renderizar", + "sputnik.setting.spooferdebungeecord.general.direccion.desc": "la dirección IP que será enviada al server", + "sputnik.setting.spooferdebungeecord.general.direccion.name": "dirección", + "sputnik.setting.superposiciondedano.general.color.desc": "color", + "sputnik.setting.superposiciondedano.general.color.name": "color", + "sputnik.setting.superposiciondeluz.colores.colordelaluz.desc": "color de los bloques con luz", + "sputnik.setting.superposiciondeluz.colores.colordelaluz.name": "color de la luz", + "sputnik.setting.superposiciondeluz.colores.colordeoscuridad.desc": "color de bloques con 0 luz", + "sputnik.setting.superposiciondeluz.colores.colordeoscuridad.name": "color de oscuridad", + "sputnik.setting.superposiciondeluz.deteccion.enagua.desc": "mostrar también bloques cubiertos en agua", + "sputnik.setting.superposiciondeluz.deteccion.enagua.name": "en agua", + "sputnik.setting.superposiciondeluz.deteccion.evitarcullingenagua.desc": "mostrar superposición a través de bloques para poder verla desde fuera del agua", + "sputnik.setting.superposiciondeluz.deteccion.evitarcullingenagua.name": "evitar culling en agua", + "sputnik.setting.superposiciondeluz.deteccion.radio.desc": "radio a tener en cuenta al renderizar superposición", + "sputnik.setting.superposiciondeluz.deteccion.radio.name": "radio", + "sputnik.setting.superposiciondeluz.deteccion.rangovertical.desc": "distancia vertical a tener en cuenta", + "sputnik.setting.superposiciondeluz.deteccion.rangovertical.name": "rango vertical", + "sputnik.setting.superposiciondeluz.optimizacion.actualizacionesincrementales.desc": "actualizar solo los bloques nuevos / eliminados en lugar de recalcular todo", + "sputnik.setting.superposiciondeluz.optimizacion.actualizacionesincrementales.name": "actualizaciones incrementales", + "sputnik.setting.superposiciondeluz.optimizacion.busquedaasincrona.desc": "buscar bloques en un hilo separado (reduce lag)", + "sputnik.setting.superposiciondeluz.optimizacion.busquedaasincrona.name": "búsqueda asíncrona", + "sputnik.setting.superposiciondeluz.optimizacion.intervalodebusqueda.desc": "cada cuántos ticks actualizar la búsqueda de bloques", + "sputnik.setting.superposiciondeluz.optimizacion.intervalodebusqueda.name": "intervalo de búsqueda", + "sputnik.setting.superposiciondeluz.optimizacion.umbraldemovimiento.desc": "distancia que debe moverse el jugador antes de forzar una actualización", + "sputnik.setting.superposiciondeluz.optimizacion.umbraldemovimiento.name": "umbral de movimiento", + "sputnik.setting.tecladeperla.general.cambiardevuelta.desc": "cambiar el ítem de vuelta a su lugar o seleccionar el slot original", + "sputnik.setting.tecladeperla.general.cambiardevuelta.name": "cambiar de vuelta", + "sputnik.setting.tenedormagico.general.boost.desc": "multiplicador del movimiento", + "sputnik.setting.tenedormagico.general.boost.name": "boost", + "sputnik.setting.tenedormagico.general.fueradelagua.desc": "permitir el uso de la propulsión acuática fuera del agua", + "sputnik.setting.tenedormagico.general.fueradelagua.name": "fuera del agua", + "sputnik.setting.tobillosfuertes.general.centrarjugador.desc": "centrar jugador respecto al bloque que tenga debajo", + "sputnik.setting.tobillosfuertes.general.centrarjugador.name": "centrar jugador", + "sputnik.setting.tobillosfuertes.general.distancia.desc": "distancia mínima de caída para aplicar la amortiguación", + "sputnik.setting.tobillosfuertes.general.distancia.name": "distancia", + "sputnik.setting.tobillosfuertes.general.items.desc": "items con los que amortiguar la caída", + "sputnik.setting.tobillosfuertes.general.items.name": "items", + "sputnik.setting.tobillosfuertes.general.modo.desc": "de qué manera evitar el daño de caída", + "sputnik.setting.tobillosfuertes.general.modo.name": "modo", + "sputnik.setting.tobillosfuertes.general.salvada.desc": "cambiar a modo paquete si no se encuentra un cubo disponible", + "sputnik.setting.tobillosfuertes.general.salvada.name": "salvada", + "sputnik.setting.trayectoria.contorno.color1.desc": "color del contorno", + "sputnik.setting.trayectoria.contorno.color1.name": "color ", + "sputnik.setting.trayectoria.contorno.contorno.desc": "a qué objetivos renderizar el contorno de la caja", + "sputnik.setting.trayectoria.contorno.contorno.name": "contorno", + "sputnik.setting.trayectoria.contorno.grosor.desc": "grosor de las líneas del contorno", + "sputnik.setting.trayectoria.contorno.grosor.name": "grosor", + "sputnik.setting.trayectoria.general.manosecundaria.desc": "predecir trayectoria de proyectiles de la mano secundaria", + "sputnik.setting.trayectoria.general.manosecundaria.name": "mano secundaria", + "sputnik.setting.trayectoria.resaltado.color2.desc": "color del contorno", + "sputnik.setting.trayectoria.resaltado.color2.name": "color ", + "sputnik.setting.trayectoria.resaltado.relleno.desc": "a qué objetivos renderizar el relleno de la caja", + "sputnik.setting.trayectoria.resaltado.relleno.name": "relleno", + "sputnik.setting.trayectoria.trayectoria.color.desc": "color de la trayectoria", + "sputnik.setting.trayectoria.trayectoria.color.name": "color", + "sputnik.setting.trayectoria.trayectoria.estilo.desc": "estilo visual de la trayectoria", + "sputnik.setting.trayectoria.trayectoria.estilo.name": "estilo", + "sputnik.setting.trayectoria.trayectoria.grosor.desc": "grosor de línea de la trayectoria", + "sputnik.setting.trayectoria.trayectoria.grosor.name": "grosor", + "sputnik.setting.trayectoria.trayectoria.puntodeimpacto.desc": "mostrar el punto de impacto", + "sputnik.setting.trayectoria.trayectoria.puntodeimpacto.name": "punto de impacto", + "sputnik.setting.trazos.colores.agua.desc": "color para bichos del agua", + "sputnik.setting.trazos.colores.agua.name": "agua", + "sputnik.setting.trazos.colores.ambiente.desc": "color para entidades ambiente", + "sputnik.setting.trazos.colores.ambiente.name": "ambiente", + "sputnik.setting.trazos.colores.animales.desc": "color para animales pasivos", + "sputnik.setting.trazos.colores.animales.name": "animales", + "sputnik.setting.trazos.colores.jugadores.desc": "color para jugadores", + "sputnik.setting.trazos.colores.jugadores.name": "jugadores", + "sputnik.setting.trazos.colores.misc.desc": "color para entidades misceláneas", + "sputnik.setting.trazos.colores.misc.name": "misc.", + "sputnik.setting.trazos.colores.monstruos.desc": "color para monstruos", + "sputnik.setting.trazos.colores.monstruos.name": "monstruos", + "sputnik.setting.trazos.general.entidades.desc": "entidades a las que apuntar", + "sputnik.setting.trazos.general.entidades.name": "entidades", + "sputnik.setting.trazos.general.grosordelinea.desc": "grosor de las líneas", + "sputnik.setting.trazos.general.grosordelinea.name": "grosor de línea", + "sputnik.setting.trazos.general.unomismo.desc": "apuntarse a uno mismo en cámara libre o así", + "sputnik.setting.trazos.general.unomismo.name": "uno mismo", + "sputnik.setting.yunquesconpluma.general.tipografia.desc": "qué tipografía utilizar", + "sputnik.setting.yunquesconpluma.general.tipografia.name": "tipografía", + "sputnik.setting.zoom.camara.camaracinematica.desc": "usa la cámara cinemática mientras hagas zoom", + "sputnik.setting.zoom.camara.camaracinematica.name": "cámara cinemática", + "sputnik.setting.zoom.camara.sensibilidad.desc": "multiplicador de la sensibilidad del ratón", + "sputnik.setting.zoom.camara.sensibilidad.name": "sensibilidad", + "sputnik.setting.zoom.general.zoom.desc": "cantidad de zoom", + "sputnik.setting.zoom.general.zoom.name": "zoom", + "sputnik.setting.zoom.scrolleo.sensibilidaddelscroll.desc": "sensibilidad de la rueda del ratón (0 para desactivar)", + "sputnik.setting.zoom.scrolleo.sensibilidaddelscroll.name": "sensibilidad del scroll", + "sputnik.setting.zoom.scrolleo.tecladelscroll.desc": "qué tecla mantener para usar la rueda del ratón", + "sputnik.setting.zoom.scrolleo.tecladelscroll.name": "tecla del scroll", + "sputnik.setting.zoom.visual.mostrarhud.desc": "esconde o muestra los indicadores en pantalla", + "sputnik.setting.zoom.visual.mostrarhud.name": "mostrar HUD", + "sputnik.setting.zoom.visual.mostrarmanos.desc": "esconde o muestra las manos al hacer zoom", + "sputnik.setting.zoom.visual.mostrarmanos.name": "mostrar manos", + "sputnik.ui.availablemodes": "modos disponibles:", + "sputnik.ui.clickgui.title": "interfaz", + "sputnik.ui.friend.manage": "gestiona a %s", + "sputnik.ui.friend.remove": "eliminar amigo", + "sputnik.ui.list.tooltip": "%s (%s de %s)", + "sputnik.ui.preview.echest": "echest", + "sputnik.ui.preview.shulker": "previsualización del shulker", + "sputnik.ui.searchbar.placeholder": "buscar...", + "sputnik.ui.settingsof": "ajustes de %s", + "sputnik.update.clickhere": "CLIC AQUÍ", + "sputnik.update.download": "descarga la última versión (%s) desde aquí:", + "sputnik.update.idgaf": "me la pela", + "sputnik.update.outdated": "version desactualizada: %s", + "sputnik.update.title": "actualizar", + "sputnik.version.error.fetch": "no se pudo comprobar la versión más reciente", + "sputnik.version.error.parse": "no se pudo parsear el archivo gradle.properties: %s", + "sputnik.version.info.available": "actualización disponible. local: %s, más reciente: %s", + "sputnik.version.info.dev": "mod en estado de desarrollo: v%s", + "sputnik.version.info.uptodate": "el mod está al día: v%s", + "sputnik.version.warn.check": "no se pudo comprobar si el mod está actualizado: %s", + "sputnik.version.warn.metadata": "no se pudo construir gradle.properties desde la metadata" +} diff --git a/src/main/resources/sputnik.accesswidener b/src/main/resources/sputnik.accesswidener index cf207b3..76ff8ba 100644 --- a/src/main/resources/sputnik.accesswidener +++ b/src/main/resources/sputnik.accesswidener @@ -49,3 +49,4 @@ accessible method net/minecraft/client/Minecraft startUseItem ()V accessible class net/minecraft/world/entity/projectile/FishingHook$FishHookState accessible method net/minecraft/client/KeyboardHandler keyPress (JILnet/minecraft/client/input/KeyEvent;)V accessible method net/minecraft/client/renderer/entity/layers/WingsLayer getPlayerElytraTexture (Lnet/minecraft/client/renderer/entity/state/HumanoidRenderState;)Lnet/minecraft/resources/Identifier; +accessible method net/minecraft/client/gui/GuiGraphicsExtractor itemBar (Lnet/minecraft/world/item/ItemStack;II)V diff --git a/src/main/resources/sputnik.mixins.json b/src/main/resources/sputnik.mixins.json index 3179f27..f19392f 100644 --- a/src/main/resources/sputnik.mixins.json +++ b/src/main/resources/sputnik.mixins.json @@ -51,6 +51,7 @@ "mixins.hud.GuiMessageLineMixin", "mixins.hud.GuiMessageMixin", "mixins.hud.GuiMixin", + "mixins.hud.HudMixin", "mixins.io.KeyboardHandlerMixin", "mixins.io.MouseHandlerMixin", "mixins.io.ScreenshotMixin",