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

No files matched your search

+1
View File
@@ -44,3 +44,4 @@ replay_*.log
todo.txt
cambios.md
remappedSrc/
.claude/
+20 -5
View File
@@ -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
- los nombres de los módulos y de los ajustes se guardan en la config. en español, se ponga el idioma
que se ponga. es a propósito: son la clave con la que se guardan, así que traducirlos resetearía
los ajustes de todo el mundo al cambiar de idioma
+5 -5
View File
@@ -1,15 +1,15 @@
org.gradle.jvmargs=-Xmx2G
org.gradle.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
+1 -1
View File
@@ -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
+30 -19
View File
@@ -47,6 +47,7 @@ import net.minecraft.client.gui.screens.TitleScreen;
import net.minecraft.client.gui.screens.inventory.AbstractCommandBlockEditScreen;
import net.minecraft.client.gui.screens.inventory.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()));
}
}
}
@@ -25,7 +25,7 @@ public class EntityArgumentType implements ArgumentType<Entity> {
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<String> EXAMPLES = List.of(
"AdlerHitdolf",
@@ -15,7 +15,8 @@ import java.util.concurrent.CompletableFuture;
public class EnumArgumentType<T extends Enum<T>> implements ArgumentType<T> {
private static final DynamicCommandExceptionType NO_SUCH_TYPE = new DynamicCommandExceptionType((value) -> Component.nullToEmpty(" argumento inválido: " + value));
private static final DynamicCommandExceptionType NO_SUCH_TYPE = new DynamicCommandExceptionType(
(value) -> Component.translatable("sputnik.args.enum.invalid", value));
private final T[] values;
@@ -33,8 +34,10 @@ public class EnumArgumentType<T extends Enum<T>> implements ArgumentType<T> {
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)
);
@@ -22,15 +22,15 @@ public class ModuleArgumentType implements ArgumentType<Module> {
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<String> 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<Module> {
@Override
public <S> CompletableFuture<Suggestions> listSuggestions(CommandContext<S> 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
@@ -21,7 +21,8 @@ import static me.retucio.sputnik.Sputnik.mc;
public class PlayerArgumentType implements ArgumentType<Player> {
public static final PlayerArgumentType INSTANCE = new PlayerArgumentType();
private static final DynamicCommandExceptionType NO_SUCH_PLAYER = new DynamicCommandExceptionType(name -> Component.literal("Player with name " + name + " doesn't exist."));
private static final DynamicCommandExceptionType NO_SUCH_PLAYER = new DynamicCommandExceptionType(
name -> Component.translatable("sputnik.args.player.notfound", name));
private static final Collection<String> EXAMPLES = List.of("retucio", "prepucio", "postpucio", "pucio", "adler hitdolf");
@@ -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<KeyMapping> 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;
@@ -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<SharedSuggestionProvider> 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);
@@ -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<SharedSuggestionProvider> 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<SharedSuggestionProvider> 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);
@@ -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
@@ -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));
}
}
}
@@ -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());
}
@@ -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<SharedSuggestionProvider> builder) {
builder.executes(context -> {
System.gc();
ChatUtil.info(Component.nullToEmpty("basura recolectada"));
ChatUtil.info(Component.translatable("sputnik.commands.gc.collected"));
return SUCCESS;
});
}
@@ -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
@@ -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<SharedSuggestionProvider> 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;
@@ -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<SharedSuggestionProvider> 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;
}));
}
}
@@ -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<GuiMessage.Line> visibleMessages = ((IChatComponent) chatHud).sputnik$getVisibleMessages();
@@ -6,11 +6,12 @@ import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import me.retucio.sputnik.command.Command;
import me.retucio.sputnik.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
@@ -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
@@ -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"));
}
}
});
@@ -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(
@@ -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<SharedSuggestionProvider> 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);
@@ -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
@@ -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
@@ -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();
@@ -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()));
@@ -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;
}
@@ -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();
@@ -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;
}
@@ -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 = "<init>", at = @At("TAIL"))
private void getModules(CallbackInfo ci) {
noRender = ModuleManager.INSTANCE.getModuleByClass(NoRender.class);
}
@Inject(method = "extractRenderState", at = @At("TAIL"))
private void onRenderHud(GuiGraphicsExtractor gui, DeltaTracker dt, CallbackInfo ci) {
Sputnik.EVENT_BUS.post(new Render2DEvent(gui, dt));
}
// norender
@Inject(method = "extractScoreboardSidebar", at = @At("HEAD"), cancellable = true)
private void noRenderScoreboard(CallbackInfo ci) {
if (noRender.isEnabled() && !noRender.scoreboard.getValue()) ci.cancel();
}
@Inject(method = "extractTitle", at = @At("HEAD"), cancellable = true)
private void noRenderTitles(GuiGraphicsExtractor graphics, DeltaTracker deltaTracker, CallbackInfo ci) {
if (noRender.isEnabled() && !noRender.titles.getValue()) ci.cancel();
}
@Inject(method = "extractConfusionOverlay", at = @At("HEAD"), cancellable = true)
private void noRenderNausea(GuiGraphicsExtractor graphics, float strength, CallbackInfo ci) {
if (noRender.isEnabled() && !noRender.nauseaEffect.getValue()) ci.cancel();
}
@Inject(method = "extractSpyglassOverlay", at = @At("HEAD"), cancellable = true)
private void noRenderSpyglass(GuiGraphicsExtractor graphics, float scale, CallbackInfo ci) {
if (noRender.isEnabled() && !noRender.spyglassOverlay.getValue()) ci.cancel();
}
@Inject(method = "extractPortalOverlay", at = @At("HEAD"), cancellable = true)
private void noRenderPortal(GuiGraphicsExtractor graphics, float alpha, CallbackInfo ci) {
if (noRender.isEnabled() && !noRender.portalOverlay.getValue()) ci.cancel();
}
@Inject(method = "extractTextureOverlay", at = @At("HEAD"), cancellable = true)
private void noRenderPumpkinBlur(GuiGraphicsExtractor graphics, Identifier texture, float alpha, CallbackInfo ci) {
if (noRender.isEnabled() && !noRender.pumpkinOverlay.getValue() && texture.getPath().equals("textures/misc/pumpkinblur.png")) ci.cancel();
}
// otros
@Inject(method = "extractRenderState", at = @At("RETURN"))
private void renderHUD(GuiGraphicsExtractor gui, DeltaTracker dt, CallbackInfo ci) {
HudRenderer.INSTANCE.render(gui, dt);
}
@Redirect(method = "extractCrosshair", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/GuiGraphicsExtractor;blitSprite(Lcom/mojang/blaze3d/pipeline/RenderPipeline;Lnet/minecraft/resources/Identifier;IIII)V", ordinal = 0))
private void onRenderCrosshair(GuiGraphicsExtractor gui, RenderPipeline pipeline, Identifier id, int x, int y, int width, int height) {
// dangerous abbreviation
CrosshairPlus cp = ModuleManager.INSTANCE.getModuleByClass(CrosshairPlus.class);
int color = cp.isEnabled() ? cp.color.getRGB() : -1;
int w = cp.isEnabled() ? cp.width.getIntValue() : width;
int h = cp.isEnabled() ? cp.height.getIntValue() : height;
gui.blitSprite(pipeline, id, (gui.guiWidth() - w) / 2, (gui.guiHeight() - h) / 2, w, h, color);
}
@ModifyExpressionValue(method = "extractCrosshair", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/CameraType;isFirstPerson()Z"))
private boolean alwaysRenderCrosshairInFreecam(boolean firstPerson) {
return ModuleManager.INSTANCE.getModuleByClass(Freecam.class).isEnabled() || firstPerson;
}
@Inject(method = "onDisconnected", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/components/ChatComponent;clearMessages(Z)V"), cancellable = true)
private void onClear(CallbackInfo ci) {
ChatPlus chatPlus = ModuleManager.INSTANCE.getModuleByClass(ChatPlus.class);
if (chatPlus.isEnabled() && chatPlus.keepHistory.getValue()) ci.cancel();
@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();
}
}
@@ -0,0 +1,104 @@
package me.retucio.sputnik.mixin.mixins.hud;
import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
import com.mojang.blaze3d.pipeline.RenderPipeline;
import me.retucio.sputnik.Sputnik;
import me.retucio.sputnik.event.render.Render2DEvent;
import me.retucio.sputnik.module.ModuleManager;
import me.retucio.sputnik.module.modules.camera.CrosshairPlus;
import me.retucio.sputnik.module.modules.misc.ChatPlus;
import me.retucio.sputnik.module.modules.camera.Freecam;
import me.retucio.sputnik.module.modules.render.NoRender;
import me.retucio.sputnik.ui.hud.HudRenderer;
import net.minecraft.client.DeltaTracker;
import net.minecraft.client.gui.GuiGraphicsExtractor;
import net.minecraft.client.gui.Hud;
import net.minecraft.resources.Identifier;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
// 26.2 partió Gui en Gui (pantallas) y Hud (el hud en sí); todo esto vivía en GuiMixin
@Mixin(Hud.class)
public abstract class HudMixin {
@Unique
NoRender noRender;
@Inject(method = "<init>", at = @At("TAIL"))
private void getModules(CallbackInfo ci) {
noRender = ModuleManager.INSTANCE.getModuleByClass(NoRender.class);
}
@Inject(method = "extractRenderState", at = @At("TAIL"))
private void onRenderHud(GuiGraphicsExtractor gui, DeltaTracker dt, CallbackInfo ci) {
Sputnik.EVENT_BUS.post(new Render2DEvent(gui, dt));
}
// norender
@Inject(method = "extractScoreboardSidebar", at = @At("HEAD"), cancellable = true)
private void noRenderScoreboard(CallbackInfo ci) {
if (noRender.isEnabled() && !noRender.scoreboard.getValue()) ci.cancel();
}
@Inject(method = "extractTitle", at = @At("HEAD"), cancellable = true)
private void noRenderTitles(GuiGraphicsExtractor graphics, DeltaTracker deltaTracker, CallbackInfo ci) {
if (noRender.isEnabled() && !noRender.titles.getValue()) ci.cancel();
}
@Inject(method = "extractConfusionOverlay", at = @At("HEAD"), cancellable = true)
private void noRenderNausea(GuiGraphicsExtractor graphics, float strength, CallbackInfo ci) {
if (noRender.isEnabled() && !noRender.nauseaEffect.getValue()) ci.cancel();
}
@Inject(method = "extractSpyglassOverlay", at = @At("HEAD"), cancellable = true)
private void noRenderSpyglass(GuiGraphicsExtractor graphics, float scale, CallbackInfo ci) {
if (noRender.isEnabled() && !noRender.spyglassOverlay.getValue()) ci.cancel();
}
@Inject(method = "extractPortalOverlay", at = @At("HEAD"), cancellable = true)
private void noRenderPortal(GuiGraphicsExtractor graphics, float alpha, CallbackInfo ci) {
if (noRender.isEnabled() && !noRender.portalOverlay.getValue()) ci.cancel();
}
@Inject(method = "extractTextureOverlay", at = @At("HEAD"), cancellable = true)
private void noRenderPumpkinBlur(GuiGraphicsExtractor graphics, Identifier texture, float alpha, CallbackInfo ci) {
if (noRender.isEnabled() && !noRender.pumpkinOverlay.getValue() && texture.getPath().equals("textures/misc/pumpkinblur.png")) ci.cancel();
}
// otros
@Inject(method = "extractRenderState", at = @At("RETURN"))
private void renderHUD(GuiGraphicsExtractor gui, DeltaTracker dt, CallbackInfo ci) {
HudRenderer.INSTANCE.render(gui, dt);
}
@Redirect(method = "extractCrosshair", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/GuiGraphicsExtractor;blitSprite(Lcom/mojang/blaze3d/pipeline/RenderPipeline;Lnet/minecraft/resources/Identifier;IIII)V", ordinal = 0))
private void onRenderCrosshair(GuiGraphicsExtractor gui, RenderPipeline pipeline, Identifier id, int x, int y, int width, int height) {
// dangerous abbreviation
CrosshairPlus cp = ModuleManager.INSTANCE.getModuleByClass(CrosshairPlus.class);
int color = cp.isEnabled() ? cp.color.getRGB() : -1;
int w = cp.isEnabled() ? cp.width.getIntValue() : width;
int h = cp.isEnabled() ? cp.height.getIntValue() : height;
gui.blitSprite(pipeline, id, (gui.guiWidth() - w) / 2, (gui.guiHeight() - h) / 2, w, h, color);
}
@ModifyExpressionValue(method = "extractCrosshair", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/CameraType;isFirstPerson()Z"))
private boolean alwaysRenderCrosshairInFreecam(boolean firstPerson) {
return ModuleManager.INSTANCE.getModuleByClass(Freecam.class).isEnabled() || firstPerson;
}
@Inject(method = "onDisconnected", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/components/ChatComponent;clearMessages(Z)V"), cancellable = true)
private void onClear(CallbackInfo ci) {
ChatPlus chatPlus = ModuleManager.INSTANCE.getModuleByClass(ChatPlus.class);
if (chatPlus.isEnabled() && chatPlus.keepHistory.getValue()) ci.cancel();
}
}
@@ -27,13 +27,13 @@ public abstract class ItemMixin {
if (stack.getItem() instanceof BlockItem blockItem && blockItem.getBlock() instanceof ShulkerBoxBlock) {
if (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)
);
}
@@ -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));
@@ -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();
@@ -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();
}
@@ -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;
@@ -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()) {
@@ -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 = "<init>", at = @At("TAIL"))
private void getModules(Minecraft minecraft, ItemInHandRenderer itemInHandRenderer, RenderBuffers renderBuffers, ModelManager modelManager, CallbackInfo ci) {
private void getModules(Minecraft minecraft, ItemInHandRenderer itemInHandRenderer, ModelManager modelManager, CallbackInfo ci) {
zoom = ModuleManager.INSTANCE.getModuleByClass(Zoom.class);;
freecam = ModuleManager.INSTANCE.getModuleByClass(Freecam.class);
noRender = ModuleManager.INSTANCE.getModuleByClass(NoRender.class);
@@ -15,21 +15,14 @@ public abstract class ItemFeatureRendererMixin {
// obtener módulo en cada redirect, ya que tiene un inicializador estático
@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();
@@ -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));
}
@@ -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());
}
}
@@ -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();
@@ -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<T extends LivingEntity> {
@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;
}
@@ -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 = "<init>", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/MultiBufferSource;immediateWithBuffers(Ljava/util/SequencedMap;Lcom/mojang/blaze3d/vertex/ByteBufferBuilder;)Lnet/minecraft/client/renderer/MultiBufferSource$BufferSource;", ordinal = 0))
private MultiBufferSource.BufferSource injectGlintBuffers(SequencedMap<RenderType, ByteBufferBuilder> fixedBuffers, ByteBufferBuilder sharedBuffer) {
if (fixedBuffers instanceof Object2ObjectLinkedOpenHashMap<RenderType, ByteBufferBuilder> 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();
}
}
@@ -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();
}
}
@@ -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()) {
@@ -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);
@@ -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());
}
@@ -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();
}
}
@@ -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);
}
}
@@ -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> keyMode = new EnumSetting<>(
protected EnumSetting<KeyMode> keyMode = new EnumSetting<KeyMode>(
"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> notifyMode = new EnumSetting<>(
protected EnumSetting<NotifyMode> notifyMode = new EnumSetting<NotifyMode>(
"modo de notificación",
"cómo notificar cuando se activa / desactiva",
NotifyMode.class, NotifyMode.WIDGET
);
).translationKey("sputnik.setting.common.notifymode");
protected final List<SettingGroup> 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;
}
@@ -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;
}
@@ -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();
}
}
@@ -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);
@@ -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();
}
}
@@ -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();
}
}
@@ -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));
}
}
}
@@ -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;
}
@@ -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<EntityType<?>> 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));
}
@@ -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()));
}
}
}
@@ -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<Vec3> 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);
@@ -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);
}
@@ -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;
@@ -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) {
@@ -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) {
@@ -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);
}
}
@@ -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);
@@ -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);
@@ -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());
@@ -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"));
}
});
}
@@ -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();
}
@@ -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;
}
@@ -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;
@@ -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;
}
@@ -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<Item> 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<Item> 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<Block> 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<Block> 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<NoFallMode> 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;
@@ -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<Map.Entry<BlockPos, VoxelShape>> iterator = cachedBlocks.entrySet().iterator();
@@ -19,6 +19,7 @@ import net.minecraft.util.Mth;
import net.minecraft.world.damagesource.DamageSource;
import net.minecraft.world.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));
});
}
@@ -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()); }
}
}
@@ -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);
}
@@ -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();
}
@@ -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;
}
@@ -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;
@@ -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) {}
}
@@ -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<T> {
// OJO: `name` es la clave de la config. (ver ConfigManager#getSettingKey). nunca se muestra
// ni se traduce; cambiarlo resetea el ajuste a todos los usuarios. lo que se ve es getName().
protected final String name;
protected final String 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<T> {
return (S) this;
}
// fija la clave a mano en vez de derivarla, para compartir texto entre módulos
@SuppressWarnings("unchecked")
public <S extends Setting<T>> S translationKey(String key) {
this.translationKey = key;
return (S) this;
}
public boolean isSearchMatch() {
return searchMatch;
}
@@ -57,14 +72,32 @@ public abstract class Setting<T> {
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() {
@@ -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<Setting<?>> {
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<Setting<?>> settings = new ArrayList<>(1);
public SettingGroup(String name, boolean extended) {
@@ -22,6 +26,11 @@ public class SettingGroup implements Iterable<Setting<?>> {
this.extended = extended;
}
public SettingGroup(String name, boolean extended, String translationKey) {
this(name, extended);
this.translationKey = translationKey;
}
@Override
public @NotNull Iterator<Setting<?>> iterator() {
return settings.iterator();
@@ -40,9 +49,10 @@ public class SettingGroup implements Iterable<Setting<?>> {
}
}
// busca por nombre interno, no por el traducido
public Setting<?> getSetting(String name) {
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<Setting<?>> {
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() {
@@ -228,7 +228,7 @@ public class ColorSetting extends Setting<Color> {
}
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));
}
@@ -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<Integer> {
@@ -22,15 +24,21 @@ public class KeySetting extends Setting<Integer> {
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()));
}
}
@@ -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) {
@@ -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<? extends HudElement> 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<NotificationWidget> 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) {
@@ -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());
}
}
@@ -0,0 +1,90 @@
package me.retucio.sputnik.ui.hud.elements;
import me.retucio.sputnik.module.modules.client.Hud;
import me.retucio.sputnik.ui.hud.ImageHudElement;
import me.retucio.sputnik.util.ChatUtil;
import net.minecraft.client.gui.GuiGraphicsExtractor;
import net.minecraft.network.chat.Component;
import net.minecraft.world.entity.EquipmentSlot;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import java.util.List;
public class ArmorElement extends ImageHudElement {
private final EquipmentSlot[] armorSlots;
private List<ItemStack> previewStacks = null;
public ArmorElement() {
super("armor", mc.getWindow().getGuiScaledWidth() - 16, (mc.getWindow().getGuiScaledHeight() - 16 * 4) / 2);
this.w = 16;
this.h = 16 * 4;
armorSlots = new EquipmentSlot[]{
EquipmentSlot.HEAD,
EquipmentSlot.CHEST,
EquipmentSlot.LEGS,
EquipmentSlot.FEET
};
reloadTexture();
}
@Override
public void renderInGame(GuiGraphicsExtractor gui, float d, Hud hud) {
if (!isVisible()) return;
for (EquipmentSlot slot : List.of(armorSlots)) {
ItemStack stack = mc.player.getItemBySlot(slot);
int y = this.y + 16 * (3 - slot.getIndex());
gui.item(stack, x, y);
gui.itemBar(stack, x, y + 2);
}
}
@Override
public void renderInEditor(GuiGraphicsExtractor gui, Hud hud) {
if (mc.player != null && mc.level != null) {
drawEditorBackground(gui);
renderInGame(gui, 0, hud);
return;
}
drawEditorBackground(gui);
for (ItemStack stack : getPreviewStacks()) {
int y = this.y + 16 * getPreviewStacks().indexOf(stack);
gui.item(stack, x, y);
gui.itemBar(stack, x, y + 2);
}
}
@Override
protected String getImagePath() { return ""; }
@Override
public List<Component> getTooltip() {
return List.of(Component.translatable("sputnik.hud.element.armor.desc"));
}
private List<ItemStack> getPreviewStacks() {
if (previewStacks == null) {
try {
List<ItemStack> stacks = List.of(
new ItemStack(Items.DIAMOND_HELMET),
new ItemStack(Items.DIAMOND_CHESTPLATE),
new ItemStack(Items.DIAMOND_LEGGINGS),
new ItemStack(Items.DIAMOND_BOOTS)
);
for (ItemStack stack : stacks) {
stack.setDamageValue(stack.getMaxDamage() / 2);
}
previewStacks = stacks;
} catch (Exception e) {
return List.of(); // not ready yet, return empty
}
}
return previewStacks;
}
}
@@ -48,7 +48,7 @@ public class CoordsElement extends TextHudElement {
public List<Component> getTooltip() {
return List.of(
Component.literal(getId()),
Component.literal("te muestra tu posición XYZ en el mundo")
Component.translatable("sputnik.hud.element.coords.desc")
);
}
}
@@ -32,8 +32,8 @@ public class CustomTextElement extends TextHudElement {
@Override
public List<Component> 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")
);
}
@@ -35,8 +35,8 @@ public class DynoElement extends ImageHudElement {
@Override
public List<Component> 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")
);
}
}
@@ -86,8 +86,8 @@ public class EchestElement extends ImageHudElement {
@Override
public List<Component> getTooltip() {
List<Component> 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;
}
@@ -26,8 +26,8 @@ public class FpsElement extends TextHudElement {
@Override
public List<Component> 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")
);
}
}
@@ -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<Component> 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")
);
}
}
Loaded 100 of 131 files, more files were not shown because too many files have changed in this diff. Show more