diff --git a/README.en.md b/README.en.md index 719183a..3251c6d 100644 --- a/README.en.md +++ b/README.en.md @@ -5,7 +5,7 @@ # jenny's mod 2 (100% real) -> Minecraft Fabric 26.2 mod that adds some "QOL" features, mostly related to the camera. +> Minecraft Fabric 26.3 mod that adds some "QOL" features, mostly related to the camera. ## installation @@ -16,7 +16,7 @@ 4. move it to your mods dir (prolly `%appdata%/.minecraft/mods`) -make sure to have a Minecraft and Fabric version compatible with the mod (MC `26.2`; Fabric `0.19.3`) +make sure to have a Minecraft and Fabric version compatible with the mod (MC `26.3`; Fabric `0.19.5`) issues could arise when using it with other mods, especially other clients, since they could conflict diff --git a/README.md b/README.md index 65d268d..55bccf5 100644 --- a/README.md +++ b/README.md @@ -5,17 +5,17 @@ # jenny's mod 2 100% real -> mod para Minecraft Fabric 26.2 que añade algunas cosas "QOL", mayormente relacionadas a la cámara. +> mod para Minecraft Fabric 26.3 que añade algunas cosas "QOL", mayormente relacionadas a la cámara. ## instalación ### para gente normal: 1. ir a [lanzamientos](https://codeberg.org/retucio/sputnik/releases) -2. selecionar la versión más reciente +2. seleccionar la versión más reciente 3. descargar el .jar 4. moverlo a tu directorio de mods (probablemente `%appdata%/.minecraft/mods`) -asegúrate de tener una version de Minecraft y Fabric compatibles con el mod (MC `26.2`; Fabric `0.19.3`) +asegúrate de tener una version de Minecraft y Fabric compatibles con el mod (MC `26.3`; Fabric `0.19.5`) es posible que haya problemas al usarlo junto a otros mods, especialmente junto a otros clientes, pues pueden conflictar entre ellos. ### para frikis de 200 de iq diff --git a/cambios.md b/cambios.md index 7c1ac45..7968147 100644 --- a/cambios.md +++ b/cambios.md @@ -1,13 +1,17 @@ -# v6.5 +# v6.6 ## novedades +- actualizado a 26.3, un verdadero grano en el culo + ### adiciones +- pestaña de ajustes del mod +- macros de tecla + ### arreglos / mejoras -- opción para cancelar la animación original para `progreso de minado` -- ahora los amigos se muestran en una pestaña separada en la interfaz +- algún que otro bugfix ## problemas reconocidos diff --git a/gradle.properties b/gradle.properties index 51ea4f8..81c1c92 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,15 +1,15 @@ org.gradle.jvmargs=-Xmx2G org.gradle.parallel=true -minecraft_version=26.2 -loader_version=0.19.3 -loom_version=1.17-SNAPSHOT +minecraft_version=26.3 +loader_version=0.19.5 +loom_version=1.18-SNAPSHOT -fabric_api_version=0.154.0+26.2 +fabric_api_version=0.160.7+26.3 discord_rpc_version=1.0.3 neutrino_version=1.1.0 jdk_version=25 -mod_version=6.5 +mod_version=6.6 maven_group=me.retucio -archives_base_name=sputnik \ No newline at end of file +archives_base_name=sputnik diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 2df7990..9905efc 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ #Sat Aug 29 22:10:52 CEST 2026 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-9.7.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.8.0-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/src/main/java/me/retucio/sputnik/Sputnik.java b/src/main/java/me/retucio/sputnik/Sputnik.java index 80e3145..04f274b 100644 --- a/src/main/java/me/retucio/sputnik/Sputnik.java +++ b/src/main/java/me/retucio/sputnik/Sputnik.java @@ -2,6 +2,7 @@ package me.retucio.sputnik; import com.github.retucio.neutrino.EventBus; import com.github.retucio.neutrino.EventListener; +import com.mojang.blaze3d.platform.InputConstants; import me.retucio.sputnik.cape.CapeManager; import me.retucio.sputnik.command.CommandManager; import me.retucio.sputnik.command.commands.BindCommand; @@ -55,8 +56,6 @@ import net.minecraft.network.chat.Component; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import org.lwjgl.glfw.GLFW; - public class Sputnik implements ClientModInitializer { @@ -118,7 +117,7 @@ public class Sputnik implements ClientModInitializer { CapeManager.INSTANCE = new CapeManager(); EVENT_BUS.post(new LoadCapeManagerEvent()); - ModuleManager.INSTANCE = new ModuleManager(); + ModuleManager.INSTANCE = new ModuleManager(); EVENT_BUS.post(new LoadModuleManagerEvent()); CommandManager.INSTANCE = new CommandManager(); @@ -157,32 +156,64 @@ public class Sputnik implements ClientModInitializer { // se ejecuta cada vez que se presiona una tecla public void onInput(int key, int action) { + // En SDL el valor 0 es UNKNOWN (y los botones del ratón empiezan en 1). + if (key == InputConstants.UNKNOWN.getValue() || key == -1) return; // prevenir interrumpir combos de F3 - if (key == GLFW.GLFW_KEY_F3) return; + if (key == InputConstants.KEY_F3) return; boolean anyFocused = isAnySettingButtonFocused() || ClickGui.INSTANCE.isCapturingInput(); ClickGui.INSTANCE.setAnyFocused(anyFocused); - if (action != GLFW.GLFW_RELEASE) { + // Las KeySetting y los campos de texto reciben el mismo código SDL scancode que + // guardan sus valores; procesarlos antes evita que el bind capturado dispare un módulo. + if (anyFocused) handleSettingButtonsKey(key, action); + + if (action != InputConstants.RELEASE) { if (BindCommand.onKeyPress(key)) return; - if (action == GLFW.GLFW_PRESS && MacroManager.INSTANCE.onKeyPress(key)) return; - if (action == GLFW.GLFW_PRESS) { + if (action == InputConstants.PRESS && MacroManager.INSTANCE.onKeyPress(key)) return; + if (action == InputConstants.PRESS) { handleModuleToggle(key, anyFocused); handleClickGuiKey(key, anyFocused); handleHudEditorKey(key, anyFocused); } - // solo reenviar teclas del teclado - if (key >= 32) { - handleSettingButtonsKey(key, action); - } } else if (!anyFocused) { handleModuleRelease(key); } } + public boolean onMouseInput(int button, int action) { + KeyUtil.setMouseButtonDown(button, action == InputConstants.PRESS); + + boolean captured = false; + for (Button settingButton : ClickGui.INSTANCE.getClientSettingsPanel().getButtons()) { + if (settingButton instanceof BindButton bindButton && bindButton.isFocused()) { + bindButton.onMouse(button, action); + captured = true; + } + } + for (SettingsPanel panel : ClickGui.INSTANCE.getSettingsPanels()) { + for (Button settingButton : panel.getButtons()) { + if (settingButton instanceof BindButton bindButton && bindButton.isFocused()) { + bindButton.onMouse(button, action); + captured = true; + } + } + } + + if (captured) return true; + onInput(KeyUtil.encodeMouseButton(button), action); + return false; + } + // verifica si algún botón de ajustes está escuchando private boolean isAnySettingButtonFocused() { if (ClickGui.INSTANCE == null) return false; + for (Button button : ClickGui.INSTANCE.getClientSettingsPanel().getButtons()) + if ((button instanceof BindButton bindButton && bindButton.isFocused()) + || (button instanceof TextButton textButton && textButton.isFocused()) + || (button instanceof FileButton fileButton && fileButton.isFocused())) { + return true; + } for (SettingsPanel sf : ClickGui.INSTANCE.getSettingsPanels()) for (Button sb : sf.getButtons()) if ((sb instanceof BindButton b && b.isFocused()) @@ -200,7 +231,7 @@ public class Sputnik implements ClientModInitializer { for (Module module : ModuleManager.INSTANCE.getModules()) { // evitar interrumpir combinaciones de teclas del F3 - if (key != module.getKey() || anyFocused || KeyUtil.isKeyDown(GLFW.GLFW_KEY_F3)) continue; + if (key != module.getKey() || anyFocused || KeyUtil.isKeyDown(InputConstants.KEY_F3)) continue; if (module.shouldToggleOnBindRelease() && !module.isEnabled()) module.setEnabled(true); @@ -211,6 +242,7 @@ public class Sputnik implements ClientModInitializer { // se ocupa de hacer los botones de ajustes que lo necesiten escuchar teclas private void handleSettingButtonsKey(int key, int action) { + ClickGui.INSTANCE.getClientSettingsPanel().onKey(key, action); for (SettingsPanel sf : ClickGui.INSTANCE.getSettingsPanels()) { for (SettingButton sb : sf.getButtons()) { if (sb instanceof BindButton bb) bb.onKey(key, action); @@ -296,4 +328,4 @@ public class Sputnik implements ClientModInitializer { public static String getVersionName() { return MOD_ID + "_v" + MOD_VERSION + "_" + SharedConstants.getCurrentVersion().name(); } -} \ No newline at end of file +} diff --git a/src/main/java/me/retucio/sputnik/command/Command.java b/src/main/java/me/retucio/sputnik/command/Command.java index 0a4bd53..e95e4ba 100644 --- a/src/main/java/me/retucio/sputnik/command/Command.java +++ b/src/main/java/me/retucio/sputnik/command/Command.java @@ -16,7 +16,7 @@ import java.util.List; public abstract class Command { // utilizar los "registries" ya existentes de Brigadier para el autocompletado - protected static final CommandBuildContext REGISTRY_ACCESS = Commands.createValidationContext(VanillaRegistries.createLookup()); + protected static final CommandBuildContext REGISTRY_ACCESS = Commands.createValidationContext(VanillaRegistries.createWorldLookup()); protected static final int SUCCESS = com.mojang.brigadier.Command.SINGLE_SUCCESS; protected static final Minecraft mc = Minecraft.getInstance(); diff --git a/src/main/java/me/retucio/sputnik/command/commands/MacroCommand.java b/src/main/java/me/retucio/sputnik/command/commands/MacroCommand.java index 645e7ad..6a2a929 100644 --- a/src/main/java/me/retucio/sputnik/command/commands/MacroCommand.java +++ b/src/main/java/me/retucio/sputnik/command/commands/MacroCommand.java @@ -36,11 +36,12 @@ public class MacroCommand extends Command { list(); return SUCCESS; })) + // por ahora "add" solo crea macros de chat .then(literal("add") .then(argument("nombre", StringArgumentType.word()).executes(ctx -> { String name = ctx.getArgument("nombre", String.class); - if (MacroManager.INSTANCE.add(new Macro(name))) + if (MacroManager.INSTANCE.add(new Macro.Chat(name))) ChatUtil.info(Component.translatable("sputnik.commands.macro.added", ChatFormatting.AQUA + name)); else @@ -60,7 +61,7 @@ public class MacroCommand extends Command { .then(literal("line") .then(argument("nombre", StringArgumentType.word()).suggests(MACROS) .then(argument("línea", StringArgumentType.greedyString()).executes(ctx -> { - Macro macro = get(ctx.getArgument("nombre", String.class)); + Macro.Chat macro = getChat(ctx.getArgument("nombre", String.class)); if (macro == null) return SUCCESS; String line = ctx.getArgument("línea", String.class); @@ -73,7 +74,7 @@ public class MacroCommand extends Command { })))) .then(literal("clear") .then(argument("nombre", StringArgumentType.word()).suggests(MACROS).executes(ctx -> { - Macro macro = get(ctx.getArgument("nombre", String.class)); + Macro.Chat macro = getChat(ctx.getArgument("nombre", String.class)); if (macro == null) return SUCCESS; macro.getLines().clear(); @@ -97,6 +98,19 @@ public class MacroCommand extends Command { return macro; } + // para los subcomandos que solo tienen sentido con líneas de chat (line, clear): si la + // macro existe pero es de otro tipo, avisa y devuelve null + private static Macro.Chat getChat(String name) { + Macro macro = get(name); + if (macro == null) return null; + + if (!(macro instanceof Macro.Chat chat)) { + ChatUtil.error(Component.translatable("sputnik.commands.macro.notchat", macro.getName())); + return null; + } + return chat; + } + private static void list() { List macros = MacroManager.INSTANCE.getMacros(); @@ -106,9 +120,17 @@ public class MacroCommand extends Command { } ChatUtil.info(Component.translatable("sputnik.commands.macro.list", macros.size())); - for (Macro macro : macros) + for (Macro macro : macros) { + // líneas en las de chat, teclas en las Keybind + int count = switch (macro) { + case Macro.Chat chat -> chat.getLines().size(); + case Macro.Keybind keybind -> keybind.getKeys().size(); + default -> 0; + }; + ChatUtil.addMessage(ChatFormatting.GRAY + " - " + macro.getName() + ChatFormatting.DARK_GRAY + " [" + KeyUtil.getKeyName(macro.getKey()) + "] " - + macro.getLines().size()); + + count); + } } -} +} \ No newline at end of file diff --git a/src/main/java/me/retucio/sputnik/command/commands/SendCommand.java b/src/main/java/me/retucio/sputnik/command/commands/SendCommand.java index 8178b6f..4072192 100644 --- a/src/main/java/me/retucio/sputnik/command/commands/SendCommand.java +++ b/src/main/java/me/retucio/sputnik/command/commands/SendCommand.java @@ -50,7 +50,7 @@ public class SendCommand extends Command { message, instant, salt, - messageSignature, + java.util.Optional.ofNullable(messageSignature), lastSeenMessages.update() )); } @@ -58,4 +58,4 @@ public class SendCommand extends Command { return SUCCESS; })); } -} \ No newline at end of file +} diff --git a/src/main/java/me/retucio/sputnik/command/commands/SpectateCommand.java b/src/main/java/me/retucio/sputnik/command/commands/SpectateCommand.java index 715f8d7..8369e1c 100644 --- a/src/main/java/me/retucio/sputnik/command/commands/SpectateCommand.java +++ b/src/main/java/me/retucio/sputnik/command/commands/SpectateCommand.java @@ -8,7 +8,7 @@ import me.retucio.sputnik.event.input.KeyEvent; import me.retucio.sputnik.util.EntityUtil; import net.minecraft.commands.SharedSuggestionProvider; import net.minecraft.world.entity.Entity; -import org.lwjgl.glfw.GLFW; +import com.mojang.blaze3d.platform.InputConstants; import java.awt.*; @@ -43,7 +43,7 @@ public class SpectateCommand extends Command { @EventListener public void onKey(KeyEvent event) { if (mc.getCameraEntity() != mc.player && mc.gui.screen() == null - && event.getKey() == GLFW.GLFW_KEY_ESCAPE && event.getAction() != GLFW.GLFW_RELEASE ) { + && event.getKey() == InputConstants.KEY_ESCAPE && event.getAction() != InputConstants.RELEASE ) { event.cancel(); mc.setCameraEntity(mc.player); } diff --git a/src/main/java/me/retucio/sputnik/config/BinarySerializer.java b/src/main/java/me/retucio/sputnik/config/BinarySerializer.java index ab90edd..b558256 100644 --- a/src/main/java/me/retucio/sputnik/config/BinarySerializer.java +++ b/src/main/java/me/retucio/sputnik/config/BinarySerializer.java @@ -1,6 +1,7 @@ package me.retucio.sputnik.config; import me.retucio.sputnik.util.I18nUtil; +import me.retucio.sputnik.util.KeyUtil; import java.io.*; import java.nio.charset.StandardCharsets; @@ -14,7 +15,7 @@ import java.util.Map; public class BinarySerializer { private static final int MAGIC_NUMBER = 0x53505554; // "SPUT" - private static final int VERSION = 4; + private static final int VERSION = 6; private static final int MIN_VERSION = 2; private static final byte TYPE_NULL = 0; @@ -26,6 +27,9 @@ public class BinarySerializer { private static final byte TYPE_INT_ARRAY = 6; private static final byte TYPE_FRAME_DATA = 7; + private static final byte MACRO_CHAT = 0; + private static final byte MACRO_KEYBIND = 1; + public static void writeConfig(ClientConfig config, File file) throws IOException { byte[] bytes = toBytes(config); writeBytes(bytes, file); @@ -127,7 +131,12 @@ public class BinarySerializer { ? readFriendsMap(in) : migrateFriendsMap(readStringStringMap(in)); - List macros = version >= 3 ? readMacros(in) : new ArrayList<>(); + // v3 y v4: macros sin tipo (todas eran de chat). v5+: con tipo + List macros; + if (version >= 5) macros = readMacros(in); + else if (version >= 3) macros = readLegacyMacros(in); + else macros = new ArrayList<>(); + String currentProfile = version >= 3 ? readString(in) : ""; // leer pos. de la barra de búsqueda @@ -147,11 +156,22 @@ public class BinarySerializer { config.macros = macros; config.currentProfile = currentProfile == null ? "" : currentProfile; if (searchBarPosition != null) config.searchBarPosition = searchBarPosition; + config.legacyKeyCodes = version < 6; return config; } } + public static void migrateLegacyKeyCodes(ClientConfig config) { + config.macros = config.macros.stream().map(macro -> { + int key = KeyUtil.fromLegacyGlfwKey(macro.key()); + List keys = macro.keys() == null ? List.of() : macro.keys().stream() + .map(entry -> new ClientConfig.KeyData(KeyUtil.fromLegacyGlfwKey(entry.key()), entry.action())) + .toList(); + return new ClientConfig.MacroData(macro.type(), macro.name(), key, macro.lines(), keys); + }).toList(); + } + private static void writeStringBooleanMap(DataOutputStream out, Map map) throws IOException { if (map == null) { @@ -371,7 +391,7 @@ public class BinarySerializer { } private static void writeStringStringMap(DataOutputStream out, Map map) - throws IOException { + throws IOException { if (map == null) { out.writeInt(0); return; @@ -384,7 +404,7 @@ public class BinarySerializer { } private static Map readStringStringMap(DataInputStream in) - throws IOException { + throws IOException { int size = in.readInt(); Map map = new HashMap<>(size); for (int i = 0; i < size; i++) { @@ -395,6 +415,9 @@ public class BinarySerializer { return map; } + // v5+: por macro va un id de tipo, luego nombre y tecla, y por último lo propio del tipo + // (líneas en las de chat, pares tecla/acción en las Keybind). los null (que pueden venir + // de un json antiguo) se tratan como chat / lista vacía private static void writeMacros(DataOutputStream out, List macros) throws IOException { if (macros == null) { @@ -403,14 +426,59 @@ public class BinarySerializer { } out.writeInt(macros.size()); for (ClientConfig.MacroData macro : macros) { + boolean keybind = macro.type() == ClientConfig.MacroType.KEYBIND; + + out.writeByte(keybind ? MACRO_KEYBIND : MACRO_CHAT); writeString(out, macro.name()); out.writeInt(macro.key()); - out.writeInt(macro.lines().size()); - for (String line : macro.lines()) writeString(out, line); + + if (keybind) { + List keys = macro.keys() == null ? List.of() : macro.keys(); + out.writeInt(keys.size()); + for (ClientConfig.KeyData k : keys) { + out.writeInt(k.key()); + out.writeInt(k.action()); + } + } else { + List lines = macro.lines() == null ? List.of() : macro.lines(); + out.writeInt(lines.size()); + for (String line : lines) writeString(out, line); + } } } private static List readMacros(DataInputStream in) throws IOException { + int size = in.readInt(); + List macros = new ArrayList<>(size); + for (int i = 0; i < size; i++) { + byte type = in.readByte(); + String name = readString(in); + int key = in.readInt(); + + switch (type) { + case MACRO_CHAT -> { + int lineCount = in.readInt(); + List lines = new ArrayList<>(lineCount); + for (int j = 0; j < lineCount; j++) lines.add(readString(in)); + macros.add(ClientConfig.MacroData.chat(name, key, lines)); + } + case MACRO_KEYBIND -> { + int keyCount = in.readInt(); + List keys = new ArrayList<>(keyCount); + for (int j = 0; j < keyCount; j++) keys.add(new ClientConfig.KeyData(in.readInt(), in.readInt())); + macros.add(ClientConfig.MacroData.keybind(name, key, keys)); + } + // no hay forma de saltarse una macro de un tipo que no conocemos (no se sabe + // cuánto ocupa), así que lo único seguro es fallar + default -> throw new IOException(I18nUtil.fmt("sputnik.config.error.invalidmacro", + "tipo de macro desconocido: %s", type)); + } + } + return macros; + } + + // v3 y v4: formato de antes de que hubiera tipos (nombre, tecla, líneas). eran todas de chat + private static List readLegacyMacros(DataInputStream in) throws IOException { int size = in.readInt(); List macros = new ArrayList<>(size); for (int i = 0; i < size; i++) { @@ -419,7 +487,7 @@ public class BinarySerializer { int lineCount = in.readInt(); List lines = new ArrayList<>(lineCount); for (int j = 0; j < lineCount; j++) lines.add(readString(in)); - macros.add(new ClientConfig.MacroData(name, key, lines)); + macros.add(ClientConfig.MacroData.chat(name, key, lines)); } return macros; } diff --git a/src/main/java/me/retucio/sputnik/config/ClientConfig.java b/src/main/java/me/retucio/sputnik/config/ClientConfig.java index f0a9b35..84d9c51 100644 --- a/src/main/java/me/retucio/sputnik/config/ClientConfig.java +++ b/src/main/java/me/retucio/sputnik/config/ClientConfig.java @@ -45,11 +45,15 @@ public class ClientConfig { // amigos: uuid -> FriendData (nombre, apodo, fecha) public Map friends = new HashMap<>(); + // macros, de cualquier tipo (ver MacroData) public List macros = new ArrayList<>(); // perfil cargado actualmente, vacío si es la config. suelta public String currentProfile = ""; + // Set only when loading a config written with GLFW keycodes (pre-26.3). + public transient boolean legacyKeyCodes; + public ClientConfig() { EVENT_BUS.subscribe(this); } @@ -183,7 +187,23 @@ public class ClientConfig { @Serial private static final long serialVersionUID = 1L; } - public record MacroData(String name, int key, List lines) implements Serializable { + public enum MacroType { CHAT, KEYBIND } + + public record KeyData(int key, int action) implements Serializable { @Serial private static final long serialVersionUID = 1L; } + + public record MacroData(MacroType type, String name, int key, + List lines, List keys + ) implements Serializable { + @Serial private static final long serialVersionUID = 2L; + + public static MacroData chat(String name, int key, List lines) { + return new MacroData(MacroType.CHAT, name, key, List.copyOf(lines), List.of()); + } + + public static MacroData keybind(String name, int key, List keys) { + return new MacroData(MacroType.KEYBIND, name, key, List.of(), List.copyOf(keys)); + } + } } diff --git a/src/main/java/me/retucio/sputnik/config/ConfigManager.java b/src/main/java/me/retucio/sputnik/config/ConfigManager.java index b5040af..f063132 100644 --- a/src/main/java/me/retucio/sputnik/config/ConfigManager.java +++ b/src/main/java/me/retucio/sputnik/config/ConfigManager.java @@ -21,6 +21,7 @@ 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.I18nUtil; +import me.retucio.sputnik.util.KeyUtil; import net.minecraft.network.chat.Component; import java.io.File; @@ -151,6 +152,7 @@ public class ConfigManager { try (FileReader reader = new FileReader(LEGACY_JSON_FILE)) { Gson gson = new GsonBuilder().setPrettyPrinting().create(); setConfig(gson.fromJson(reader, ClientConfig.class)); + config.legacyKeyCodes = true; Sputnik.LOGGER.info(I18nUtil.fmt("sputnik.config.info.json", "ajustes json cargados (migración)")); @@ -175,7 +177,9 @@ public class ConfigManager { if (!shouldApply()) return false; applying = true; + boolean migratedKeys = config.legacyKeyCodes; try { + migrateLegacyKeyCodes(); // los del mod primero: entre ellos está "teclas multimódulo", que decide si al // asignar una tecla se le quita a los demás módulos. aplicándolos los últimos, // las teclas de los módulos se cargaban con el valor por defecto de ese ajuste @@ -200,9 +204,32 @@ public class ConfigManager { loaded = true; } + if (migratedKeys) writeSnapshot(true); + return true; } + private void migrateLegacyKeyCodes() { + if (!config.legacyKeyCodes) return; + + ClientSettingsPanel.clientSettings.getSettings().forEach(this::migrateLegacyKeySetting); + ModuleManager.INSTANCE.getModules().forEach(module -> + module.getSettings().forEach(this::migrateLegacyKeySetting)); + BinarySerializer.migrateLegacyKeyCodes(config); + config.legacyKeyCodes = false; + } + + private void migrateLegacyKeySetting(Setting setting) { + if (!(setting instanceof KeySetting)) return; + String key = getSettingKey(setting); + Object value = config.settings.get(key); + if (value instanceof Integer code) { + config.settings.put(key, KeyUtil.fromLegacyGlfwKey(code)); + } else if (value instanceof Double code) { + config.settings.put(key, KeyUtil.fromLegacyGlfwKey(code.intValue())); + } + } + // true mientras se está cargando la config. sobre los ajustes. lo mira KeySetting para no // tratar las teclas guardadas como si el usuario las acabara de asignar, y ClientConfig // para no reescribir en la config. lo que se le está aplicando @@ -299,7 +326,7 @@ public class ConfigManager { public void setMacros(List macros) { ensureConfig(); config.macros = macros.stream() - .map(macro -> new ClientConfig.MacroData(macro.getName(), macro.getKey(), List.copyOf(macro.getLines()))) + .map(ConfigManager::toMacroData) .toList(); markDirty(); } @@ -323,12 +350,40 @@ public class ConfigManager { Sputnik.LOGGER.info(I18nUtil.fmt("sputnik.config.info.friends", "amigos aplicados")); } + public void applyMacros() { MacroManager.INSTANCE.setMacros(config.macros.stream() - .map(data -> new Macro(data.name(), data.key(), data.lines())) + .map(ConfigManager::fromMacroData) .toList()); } + private static ClientConfig.MacroData toMacroData(Macro macro) { + return switch (macro) { + case Macro.Chat chat -> ClientConfig.MacroData.chat( + chat.getName(), chat.getKey(), chat.getLines()); + + case Macro.Keybind keybind -> ClientConfig.MacroData.keybind( + keybind.getName(), keybind.getKey(), + keybind.getKeys().stream() + .map(k -> new ClientConfig.KeyData(k.key(), k.action())) + .toList()); + + default -> throw new IllegalArgumentException( + "tipo de macro sin serializar: " + macro.getClass().getName()); + }; + } + + private static Macro fromMacroData(ClientConfig.MacroData data) { + if (data.type() == ClientConfig.MacroType.KEYBIND) { + List keys = data.keys() == null ? List.of() : data.keys().stream() + .map(k -> new Macro.Keybind.Key(k.key(), k.action())) + .toList(); + return new Macro.Keybind(data.name(), data.key(), keys); + } + + return new Macro.Chat(data.name(), data.key(), data.lines() == null ? List.of() : data.lines()); + } + // el HudRenderer coloca sus elementos al construirse, pero al cambiar de perfil ya existen public void applyHudElements() { if (HudRenderer.INSTANCE == null) return; @@ -592,8 +647,6 @@ public class ConfigManager { ClientSettingsModule settings = ClientSettingsPanel.clientSettings; if (!settings.autosave.getValue()) return; - // desde el último guardado, no desde el último cambio: contando desde el cambio, - // tocando ajustes cada menos del intervalo no se autoguardaba nunca long intervalMs = (long) (settings.autosaveInterval.getValue() * 1000); if (System.currentTimeMillis() - lastSaveTime < intervalMs) return; @@ -602,4 +655,4 @@ public class ConfigManager { Component.translatable("sputnik.config.autosaving.desc").getString()); save(); } -} \ No newline at end of file +} diff --git a/src/main/java/me/retucio/sputnik/macro/Macro.java b/src/main/java/me/retucio/sputnik/macro/Macro.java index 218c44d..6d2ca15 100644 --- a/src/main/java/me/retucio/sputnik/macro/Macro.java +++ b/src/main/java/me/retucio/sputnik/macro/Macro.java @@ -1,38 +1,22 @@ package me.retucio.sputnik.macro; import me.retucio.sputnik.util.ChatUtil; +import me.retucio.sputnik.util.KeyUtil; import net.minecraft.client.Minecraft; -import org.lwjgl.glfw.GLFW; +import com.mojang.blaze3d.platform.InputConstants; import java.util.ArrayList; import java.util.List; -public class Macro { +public abstract class Macro { - private String name; - private int key; - private final List lines = new ArrayList<>(); + protected String name; + protected int key; - private boolean searchMatch = true; - - public Macro(String name) { - this(name, GLFW.GLFW_KEY_UNKNOWN, List.of()); - } - - public Macro(String name, int key, List lines) { + protected Macro(String name, int key) { this.name = name; this.key = key; - this.lines.addAll(lines); - } - - // cada línea se manda como si el usuario la hubiera escrito en el chat, así que valen - // comandos del mod, comandos del servidor y mensajes normales - public void run() { - if (Minecraft.getInstance().player == null) return; - for (String line : lines) { - if (!line.isBlank()) ChatUtil.simulateChatMessage(line); - } } public String getName() { return name; } @@ -41,13 +25,80 @@ public class Macro { public int getKey() { return key; } public void setKey(int key) { this.key = key; } - public List getLines() { return lines; } - - public void setLines(List lines) { - this.lines.clear(); - this.lines.addAll(lines); - } - + private boolean searchMatch = true; public boolean isSearchMatch() { return searchMatch; } public void setSearchMatch(boolean searchMatch) { this.searchMatch = searchMatch; } -} + + public abstract void run(); + + + // cada línea se manda como si el usuario la hubiera escrito en el chat, así que valen + // comandos del mod, comandos del servidor y mensajes normales + public static class Chat extends Macro { + + private final List lines = new ArrayList<>(); + + public Chat(String name) { + this(name, InputConstants.UNKNOWN.getValue(), List.of()); + } + + public Chat(String name, int key, List lines) { + super(name, key); + this.lines.addAll(lines); + } + + @Override + public void run() { + if (Minecraft.getInstance().player == null) return; + for (String line : lines) { + if (!line.isBlank()) ChatUtil.simulateChatMessage(line); + } + } + + public List getLines() { + return lines; + } + + public void setLines(List lines) { + this.lines.clear(); + this.lines.addAll(lines); + } + } + + + public static class Keybind extends Macro { + + private final List keys = new ArrayList<>(); + + public Keybind(String name) { + this(name, InputConstants.UNKNOWN.getValue(), List.of()); + } + + public Keybind(String name, int key, List keys) { + super(name, key); + this.keys.addAll(keys); + } + + @Override + public void run() { + for (Key k : keys) { + k.use(); + } + } + + public List getKeys() { + return keys; + } + + public void setKeys(List keys) { + this.keys.clear(); + this.keys.addAll(keys); + } + + public record Key(int key, int action) { + public void use() { + KeyUtil.pressKey(key, action); + } + } + } +} \ No newline at end of file diff --git a/src/main/java/me/retucio/sputnik/macro/MacroManager.java b/src/main/java/me/retucio/sputnik/macro/MacroManager.java index 0469dc7..1b49dd3 100644 --- a/src/main/java/me/retucio/sputnik/macro/MacroManager.java +++ b/src/main/java/me/retucio/sputnik/macro/MacroManager.java @@ -2,7 +2,7 @@ package me.retucio.sputnik.macro; import me.retucio.sputnik.config.ConfigManager; import net.minecraft.client.Minecraft; -import org.lwjgl.glfw.GLFW; +import com.mojang.blaze3d.platform.InputConstants; import java.util.ArrayList; import java.util.List; @@ -14,6 +14,9 @@ public class MacroManager { private final List macros = new ArrayList<>(); + // para evitar disparar un macro que presiona su propia tecla infinitamente + private boolean running = false; + public boolean add(Macro macro) { if (getByName(macro.getName()) != null) return false; macros.add(macro); @@ -34,15 +37,20 @@ public class MacroManager { } public boolean onKeyPress(int key) { - if (key == GLFW.GLFW_KEY_UNKNOWN || Minecraft.getInstance().gui.screen() != null) return false; + if (running || key == InputConstants.UNKNOWN.getValue() || Minecraft.getInstance().gui.screen() != null) return false; - boolean ran = false; - for (Macro macro : new ArrayList<>(macros)) { - if (macro.getKey() != key) continue; - macro.run(); - ran = true; + running = true; + try { + boolean ran = false; + for (Macro macro : new ArrayList<>(macros)) { + if (macro.getKey() != key) continue; + macro.run(); + ran = true; + } + return ran; + } finally { + running = false; } - return ran; } public void setMacros(List macros) { diff --git a/src/main/java/me/retucio/sputnik/mixin/accessors/LayerRenderStateAccessor.java b/src/main/java/me/retucio/sputnik/mixin/accessors/LayerRenderStateAccessor.java index 9717f41..420dedc 100644 --- a/src/main/java/me/retucio/sputnik/mixin/accessors/LayerRenderStateAccessor.java +++ b/src/main/java/me/retucio/sputnik/mixin/accessors/LayerRenderStateAccessor.java @@ -1,6 +1,7 @@ package me.retucio.sputnik.mixin.accessors; import net.minecraft.client.renderer.item.ItemStackRenderState; +import net.minecraft.client.resources.model.geometry.ItemQuads; import net.minecraft.client.resources.model.cuboid.ItemTransform; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Accessor; @@ -11,4 +12,7 @@ public interface LayerRenderStateAccessor { @Accessor("itemTransform") ItemTransform sputnik$getTransform(); -} \ No newline at end of file + + @Accessor("quads") + ItemQuads sputnik$getQuads(); +} diff --git a/src/main/java/me/retucio/sputnik/mixin/mixins/hud/HudMixin.java b/src/main/java/me/retucio/sputnik/mixin/mixins/hud/HudMixin.java index eeb2b71..8f745a8 100644 --- a/src/main/java/me/retucio/sputnik/mixin/mixins/hud/HudMixin.java +++ b/src/main/java/me/retucio/sputnik/mixin/mixins/hud/HudMixin.java @@ -1,7 +1,7 @@ package me.retucio.sputnik.mixin.mixins.hud; import com.llamalad7.mixinextras.injector.ModifyExpressionValue; -import com.mojang.blaze3d.pipeline.RenderPipeline; +import com.mojang.renderpearl.api.pipeline.RenderPipeline; import me.retucio.sputnik.Sputnik; import me.retucio.sputnik.event.render.Render2DEvent; import me.retucio.sputnik.module.ModuleManager; @@ -79,7 +79,7 @@ public abstract class HudMixin { 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)) + @Redirect(method = "extractCrosshair", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/GuiGraphicsExtractor;blitSprite(Lcom/mojang/renderpearl/api/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); diff --git a/src/main/java/me/retucio/sputnik/mixin/mixins/io/KeyboardHandlerMixin.java b/src/main/java/me/retucio/sputnik/mixin/mixins/io/KeyboardHandlerMixin.java index 0df5af1..cf5ca3f 100644 --- a/src/main/java/me/retucio/sputnik/mixin/mixins/io/KeyboardHandlerMixin.java +++ b/src/main/java/me/retucio/sputnik/mixin/mixins/io/KeyboardHandlerMixin.java @@ -2,6 +2,7 @@ package me.retucio.sputnik.mixin.mixins.io; import me.retucio.sputnik.Sputnik; import me.retucio.sputnik.event.input.KeyEvent; +import com.mojang.blaze3d.platform.InputConstants; import net.minecraft.client.KeyboardHandler; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; @@ -14,9 +15,9 @@ public abstract class KeyboardHandlerMixin { @Inject(method = "keyPress", at = @At("HEAD"), cancellable = true) private void onKeyPress(long handle, int action, net.minecraft.client.input.KeyEvent input, CallbackInfo ci) { - if (input.key() == -1) return; + if (input.key() == InputConstants.UNKNOWN.getValue() || input.key() == -1) return; Sputnik.INSTANCE.onInput(input.key(), action); - KeyEvent event = Sputnik.EVENT_BUS.post(new KeyEvent(input.key(), input.scancode(), action)); + KeyEvent event = Sputnik.EVENT_BUS.post(new KeyEvent(input.key(), input.keycode(), action)); if (event.isCancelled()) ci.cancel(); } } diff --git a/src/main/java/me/retucio/sputnik/mixin/mixins/io/MouseHandlerMixin.java b/src/main/java/me/retucio/sputnik/mixin/mixins/io/MouseHandlerMixin.java index 694c59f..17b5d68 100644 --- a/src/main/java/me/retucio/sputnik/mixin/mixins/io/MouseHandlerMixin.java +++ b/src/main/java/me/retucio/sputnik/mixin/mixins/io/MouseHandlerMixin.java @@ -16,7 +16,10 @@ public abstract class MouseHandlerMixin { @Inject(method = "onButton", at = @At("HEAD"), cancellable = true) private void onMouseButton(long handle, MouseButtonInfo input, int action, CallbackInfo ci) { - Sputnik.INSTANCE.onInput(input.button(), action); + if (Sputnik.INSTANCE.onMouseInput(input.button(), action)) { + ci.cancel(); + return; + } MouseClickEvent event = Sputnik.EVENT_BUS.post(new MouseClickEvent(action, input.button())); if (event.isCancelled()) ci.cancel(); } diff --git a/src/main/java/me/retucio/sputnik/mixin/mixins/network/ClientPacketListenerMixin.java b/src/main/java/me/retucio/sputnik/mixin/mixins/network/ClientPacketListenerMixin.java index b22c7bd..69a6596 100644 --- a/src/main/java/me/retucio/sputnik/mixin/mixins/network/ClientPacketListenerMixin.java +++ b/src/main/java/me/retucio/sputnik/mixin/mixins/network/ClientPacketListenerMixin.java @@ -3,18 +3,13 @@ package me.retucio.sputnik.mixin.mixins.network; import com.mojang.brigadier.exceptions.CommandSyntaxException; import me.retucio.sputnik.command.CommandManager; import me.retucio.sputnik.event.network.SendMessageEvent; -import me.retucio.sputnik.module.ModuleManager; -import me.retucio.sputnik.module.modules.render.NoRender; import me.retucio.sputnik.util.ChatUtil; import net.minecraft.client.multiplayer.ClientPacketListener; -import net.minecraft.client.renderer.GameRenderer; -import net.minecraft.world.item.ItemStack; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import static me.retucio.sputnik.Sputnik.*; @@ -51,11 +46,4 @@ public abstract class ClientPacketListenerMixin { mc.gui.hud.getChat().addRecentChat(content); ci.cancel(); } - - @Redirect(method = "handleEntityEvent", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/GameRenderer;displayItemActivation(Lnet/minecraft/world/item/ItemStack;)V")) - private void noRenderTotemPop(GameRenderer instance, ItemStack itemStack) { - NoRender noRender = ModuleManager.INSTANCE.getModuleByClass(NoRender.class); - if (!noRender.isEnabled() || noRender.totemPop.getValue()) - mc.gameRenderer.displayItemActivation(itemStack); - } } diff --git a/src/main/java/me/retucio/sputnik/mixin/mixins/network/YggdrasilUserApiServiceMixin.java b/src/main/java/me/retucio/sputnik/mixin/mixins/network/YggdrasilUserApiServiceMixin.java index 8361872..bd05373 100644 --- a/src/main/java/me/retucio/sputnik/mixin/mixins/network/YggdrasilUserApiServiceMixin.java +++ b/src/main/java/me/retucio/sputnik/mixin/mixins/network/YggdrasilUserApiServiceMixin.java @@ -1,17 +1,17 @@ package me.retucio.sputnik.mixin.mixins.network; -import com.mojang.authlib.yggdrasil.YggdrasilUserApiService; -import com.mojang.authlib.yggdrasil.response.UserAttributesResponse; +import com.mojang.authlib.services.MinecraftServicesUserApiService; +import com.mojang.authlib.services.response.UserAttributesResponse; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Redirect; // código robado de: https://github.com/kb-1000/no-telemetry -@Mixin(YggdrasilUserApiService.class) +@Mixin(MinecraftServicesUserApiService.class) public abstract class YggdrasilUserApiServiceMixin { - @Redirect(method = "fetchProperties", at = @At(value = "INVOKE", target = "Lcom/mojang/authlib/yggdrasil/response/UserAttributesResponse$Privileges;getTelemetry()Z", remap = false), remap = false, require = 0) + @Redirect(method = "fetchProperties", at = @At(value = "INVOKE", target = "Lcom/mojang/authlib/services/response/UserAttributesResponse$Privileges;getTelemetry()Z", remap = false), remap = false, require = 0) private boolean getTelemetry(UserAttributesResponse.Privileges instance) { return false; } diff --git a/src/main/java/me/retucio/sputnik/mixin/mixins/render/EquipmentLayerRendererMixin.java b/src/main/java/me/retucio/sputnik/mixin/mixins/render/EquipmentLayerRendererMixin.java index 3595e2d..de98963 100644 --- a/src/main/java/me/retucio/sputnik/mixin/mixins/render/EquipmentLayerRendererMixin.java +++ b/src/main/java/me/retucio/sputnik/mixin/mixins/render/EquipmentLayerRendererMixin.java @@ -4,6 +4,7 @@ import me.retucio.sputnik.module.ModuleManager; import me.retucio.sputnik.module.modules.render.GlintPlus; import net.minecraft.client.renderer.entity.layers.EquipmentLayerRenderer; import net.minecraft.client.renderer.rendertype.RenderType; +import net.minecraft.resources.Identifier; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.ModifyVariable; @@ -12,9 +13,9 @@ import org.spongepowered.asm.mixin.injection.Redirect; @Mixin(EquipmentLayerRenderer.class) public abstract class EquipmentLayerRendererMixin { - @Redirect(method = "renderLayers(Lnet/minecraft/client/resources/model/EquipmentClientInfo$LayerType;Lnet/minecraft/resources/ResourceKey;Lnet/minecraft/client/model/Model;Ljava/lang/Object;Lnet/minecraft/world/item/ItemStack;Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/SubmitNodeCollector;ILnet/minecraft/resources/Identifier;II)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/rendertype/RenderTypes;armorEntityGlint()Lnet/minecraft/client/renderer/rendertype/RenderType;")) - private RenderType redirectArmorEntityGlint() { + @Redirect(method = "renderLayers(Lnet/minecraft/client/resources/model/EquipmentClientInfo$LayerType;Lnet/minecraft/resources/ResourceKey;Lnet/minecraft/client/model/Model;Ljava/lang/Object;Lnet/minecraft/world/item/ItemStack;Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/SubmitNodeCollector;ILnet/minecraft/resources/Identifier;II)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/rendertype/RenderTypes;armorCutoutNoCullGlint(Lnet/minecraft/resources/Identifier;)Lnet/minecraft/client/renderer/rendertype/RenderType;")) + private RenderType redirectArmorEntityGlint(Identifier texture) { GlintPlus glintPlus = ModuleManager.INSTANCE.getModuleByClass(GlintPlus.class); - return glintPlus.getArmorEntityGlint(); + return glintPlus.getArmorEntityGlint(texture); } -} \ No newline at end of file +} diff --git a/src/main/java/me/retucio/sputnik/mixin/mixins/render/GameRendererMixin.java b/src/main/java/me/retucio/sputnik/mixin/mixins/render/GameRendererMixin.java index 4ad9356..96074e5 100644 --- a/src/main/java/me/retucio/sputnik/mixin/mixins/render/GameRendererMixin.java +++ b/src/main/java/me/retucio/sputnik/mixin/mixins/render/GameRendererMixin.java @@ -15,8 +15,11 @@ import com.mojang.blaze3d.resource.CrossFrameResourcePool; 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.FirstPersonHandsAndItemsRenderer; import net.minecraft.client.renderer.state.level.CameraRenderState; +import net.minecraft.client.renderer.state.level.PlayerRenderState; +import net.minecraft.client.renderer.item.ItemModelResolver; +import com.mojang.renderpearl.api.textures.GpuTextureView; import net.minecraft.client.resources.model.ModelManager; import org.joml.Matrix4fc; @@ -52,23 +55,20 @@ public abstract class GameRendererMixin { private CrossFrameResourcePool resourcePool; @Inject(method = "", at = @At("TAIL")) - private void getModules(Minecraft minecraft, ItemInHandRenderer itemInHandRenderer, ModelManager modelManager, CallbackInfo ci) { + private void getModules(Minecraft minecraft, FirstPersonHandsAndItemsRenderer itemInHandRenderer, ModelManager modelManager, ItemModelResolver itemModelResolver, CallbackInfo ci) { zoom = ModuleManager.INSTANCE.getModuleByClass(Zoom.class);; freecam = ModuleManager.INSTANCE.getModuleByClass(Freecam.class); noRender = ModuleManager.INSTANCE.getModuleByClass(NoRender.class); lsd = ModuleManager.INSTANCE.getModuleByClass(Lsd.class); } - // se aplica justo donde vanilla mete sus efectos de post (nausea, etc.): el mundo ya está - // en mainRenderTarget y el HUD todavía no, así que sólo distorsiona la escena 3D - @Inject(method = "render", at = @At(value = "INVOKE", shift = At.Shift.AFTER, - target = "Lnet/minecraft/client/renderer/LevelRenderer;doEntityOutline()V")) - private void applyLsd(DeltaTracker deltaTracker, boolean advanceGameTime, CallbackInfo ci) { + @Inject(method = "render", at = @At(value = "INVOKE", shift = At.Shift.AFTER, target = "Lnet/minecraft/client/renderer/LevelRenderer;blitEntityOutline()V")) + private void applyLsd(CallbackInfo ci) { if (lsd.isEnabled()) lsd.apply(mainRenderTarget, resourcePool); } @Inject(method = "render", at = @At("HEAD"), cancellable = true) - private void avoidRenderingUnfocusedCpu(DeltaTracker dt, boolean tick, CallbackInfo ci) { + private void avoidRenderingUnfocusedCpu(CallbackInfo ci) { if (ModuleManager.INSTANCE.getModuleByClass(UnfocusedCpu.class).isEnabled() && !mc.isWindowActive()) { ci.cancel(); } @@ -81,7 +81,7 @@ public abstract class GameRendererMixin { @Inject(method = "renderItemInHand", at = @At("HEAD"), cancellable = true) - private void renderHand(CameraRenderState cameraState, float deltaPartialTick, Matrix4fc modelViewMatrix, CallbackInfo ci) { + private void renderHand(CameraRenderState cameraState, PlayerRenderState playerRenderState, GpuTextureView texture, CallbackInfo ci) { if ((zoom.isEnabled() && !zoom.showHands.getValue()) || (freecam.isEnabled() && !freecam.renderHands.getValue())) ci.cancel(); diff --git a/src/main/java/me/retucio/sputnik/mixin/mixins/render/ItemFeatureRendererMixin.java b/src/main/java/me/retucio/sputnik/mixin/mixins/render/ItemFeatureRendererMixin.java index 0b844b6..5075654 100644 --- a/src/main/java/me/retucio/sputnik/mixin/mixins/render/ItemFeatureRendererMixin.java +++ b/src/main/java/me/retucio/sputnik/mixin/mixins/render/ItemFeatureRendererMixin.java @@ -3,11 +3,12 @@ package me.retucio.sputnik.mixin.mixins.render; import me.retucio.sputnik.module.ModuleManager; import me.retucio.sputnik.module.modules.render.GlintPlus; import net.minecraft.client.renderer.feature.ItemFeatureRenderer; +import net.minecraft.client.resources.model.geometry.BakedQuad; import net.minecraft.client.renderer.rendertype.RenderType; -import net.minecraft.client.renderer.rendertype.RenderTypes; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Redirect; +import com.llamalad7.mixinextras.injector.ModifyExpressionValue; +import com.llamalad7.mixinextras.sugar.Local; @Mixin(ItemFeatureRenderer.class) @@ -15,17 +16,15 @@ public abstract class ItemFeatureRendererMixin { // obtener módulo en cada redirect, ya que tiene un inicializador estático - @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() { + @ModifyExpressionValue(method = "prepareMainSubmit", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/resources/model/geometry/BakedQuad$MaterialInfo;itemGlintRenderType()Lnet/minecraft/client/renderer/rendertype/RenderType;")) + private RenderType sputnik$colorGlint(RenderType original, @Local BakedQuad.MaterialInfo materialInfo) { GlintPlus glintPlus = ModuleManager.INSTANCE.getModuleByClass(GlintPlus.class); - if (glintPlus == null) return RenderTypes.glint(); - return glintPlus.getGlint(); + return glintPlus == null ? original : glintPlus.getGlint(original, materialInfo); } - @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() { + @ModifyExpressionValue(method = "prepareMainSubmit", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/resources/model/geometry/BakedQuad$MaterialInfo;itemGlintSpecialRenderType()Lnet/minecraft/client/renderer/rendertype/RenderType;")) + private RenderType sputnik$colorSpecialGlint(RenderType original, @Local BakedQuad.MaterialInfo materialInfo) { GlintPlus glintPlus = ModuleManager.INSTANCE.getModuleByClass(GlintPlus.class); - if (glintPlus == null) return RenderTypes.glintTranslucent(); - return glintPlus.getGlintTranslucent(); + return glintPlus == null ? original : glintPlus.getGlint(original, materialInfo); } } diff --git a/src/main/java/me/retucio/sputnik/mixin/mixins/render/ItemInHandRendererMixin.java b/src/main/java/me/retucio/sputnik/mixin/mixins/render/ItemInHandRendererMixin.java index 9f461e8..1ec344f 100644 --- a/src/main/java/me/retucio/sputnik/mixin/mixins/render/ItemInHandRendererMixin.java +++ b/src/main/java/me/retucio/sputnik/mixin/mixins/render/ItemInHandRendererMixin.java @@ -7,7 +7,7 @@ import me.retucio.sputnik.event.render.RenderArmEvent; import me.retucio.sputnik.module.ModuleManager; import me.retucio.sputnik.module.modules.render.HandView; import net.minecraft.client.player.AbstractClientPlayer; -import net.minecraft.client.renderer.ItemInHandRenderer; +import net.minecraft.client.renderer.FirstPersonHandsAndItemsRenderer; import net.minecraft.client.renderer.SubmitNodeCollector; import net.minecraft.world.InteractionHand; import net.minecraft.world.entity.HumanoidArm; @@ -23,7 +23,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import static me.retucio.sputnik.Sputnik.*; -@Mixin(ItemInHandRenderer.class) +@Mixin(FirstPersonHandsAndItemsRenderer.class) public abstract class ItemInHandRendererMixin { @Unique @@ -49,12 +49,12 @@ public abstract class ItemInHandRendererMixin { handView = ModuleManager.INSTANCE.getModuleByClass(HandView.class); } - @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)) + @Inject(method = "submitArmWithItem", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/FirstPersonHandsAndItemsRenderer;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 = "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")) + @Inject(method = "submitArmWithItem", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/FirstPersonHandsAndItemsRenderer;renderPlayerArm(Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/SubmitNodeCollector;IFFLnet/minecraft/world/entity/HumanoidArm;)V")) private void onRenderArm(AbstractClientPlayer player, float frameInterp, float xRot, InteractionHand hand, float attack, ItemStack itemStack, float inverseArmHeight, PoseStack matrices, SubmitNodeCollector submitNodeCollector, int lightCoords, CallbackInfo ci) { EVENT_BUS.post(new RenderArmEvent(matrices, hand)); } diff --git a/src/main/java/me/retucio/sputnik/mixin/mixins/render/LevelRendererMixin.java b/src/main/java/me/retucio/sputnik/mixin/mixins/render/LevelRendererMixin.java index 8805631..1851c76 100644 --- a/src/main/java/me/retucio/sputnik/mixin/mixins/render/LevelRendererMixin.java +++ b/src/main/java/me/retucio/sputnik/mixin/mixins/render/LevelRendererMixin.java @@ -1,7 +1,6 @@ package me.retucio.sputnik.mixin.mixins.render; -import com.llamalad7.mixinextras.sugar.Local; -import com.mojang.blaze3d.buffers.GpuBufferSlice; +import com.mojang.renderpearl.api.buffers.GpuBufferSlice; import com.mojang.blaze3d.resource.GraphicsResourceAllocator; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.math.Axis; @@ -12,7 +11,6 @@ import me.retucio.sputnik.module.ModuleManager; import me.retucio.sputnik.module.modules.camera.Freecam; import me.retucio.sputnik.module.modules.render.BreakingProgress; import me.retucio.sputnik.util.render.SputnikBuffers; -import net.minecraft.client.DeltaTracker; import net.minecraft.client.renderer.GameRenderer; import net.minecraft.client.renderer.LevelRenderer; import net.minecraft.client.renderer.ShaderManager; @@ -25,6 +23,7 @@ import net.minecraft.client.renderer.texture.TextureManager; import net.minecraft.client.resources.model.ModelManager; import net.minecraft.client.resources.model.sprite.AtlasManager; import net.minecraft.util.profiling.ProfilerFiller; +import net.minecraft.util.profiling.Profiler; import org.joml.Matrix4fc; import org.joml.Vector4f; import org.spongepowered.asm.mixin.Mixin; @@ -49,17 +48,20 @@ public abstract class LevelRendererMixin { } @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) { + private void render(GraphicsResourceAllocator resourceAllocator, boolean renderOutline, + CameraRenderState cameraState, GpuBufferSlice terrainFog, Vector4f fogColor, + boolean shouldRenderSky, boolean shouldRenderWeather, CallbackInfo ci) { if (mc == null || mc.level == null) return; + ProfilerFiller profiler = Profiler.get(); PoseStack matrices = new PoseStack(); matrices.pushPose(); - matrices.mulPose(Axis.XP.rotationDegrees(cameraState.xRot)); - matrices.mulPose(Axis.YP.rotationDegrees(cameraState.yRot + 180f)); + matrices.rotate(Axis.XP.rotationDegrees(cameraState.xRot)); + matrices.rotate(Axis.YP.rotationDegrees(cameraState.yRot + 180f)); profiler.push(Sputnik.MOD_ID + "-3d"); - EVENT_BUS.post(new Render3DEvent(matrices, dt, cameraState)); + EVENT_BUS.post(new Render3DEvent(matrices, mc.getDeltaTracker(), cameraState)); SputnikBuffers.flush(); // antes de que empiece el hud profiler.pop(); @@ -90,4 +92,4 @@ public abstract class LevelRendererMixin { ci.cancel(); } } -} \ No newline at end of file +} diff --git a/src/main/java/me/retucio/sputnik/mixin/mixins/render/LightmapMixin.java b/src/main/java/me/retucio/sputnik/mixin/mixins/render/LightmapMixin.java index 2ba8cc9..d668a98 100644 --- a/src/main/java/me/retucio/sputnik/mixin/mixins/render/LightmapMixin.java +++ b/src/main/java/me/retucio/sputnik/mixin/mixins/render/LightmapMixin.java @@ -1,7 +1,7 @@ package me.retucio.sputnik.mixin.mixins.render; import com.mojang.blaze3d.systems.RenderSystem; -import com.mojang.blaze3d.textures.GpuTexture; +import com.mojang.renderpearl.api.textures.GpuTexture; import me.retucio.sputnik.module.ModuleManager; import me.retucio.sputnik.module.modules.camera.Fullbright; import net.minecraft.client.renderer.Lightmap; diff --git a/src/main/java/me/retucio/sputnik/mixin/mixins/render/ScreenEffectRendererMixin.java b/src/main/java/me/retucio/sputnik/mixin/mixins/render/ScreenEffectRendererMixin.java index 417509f..1575595 100644 --- a/src/main/java/me/retucio/sputnik/mixin/mixins/render/ScreenEffectRendererMixin.java +++ b/src/main/java/me/retucio/sputnik/mixin/mixins/render/ScreenEffectRendererMixin.java @@ -3,9 +3,9 @@ package me.retucio.sputnik.mixin.mixins.render; 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.ScreenEffectRenderer; import net.minecraft.client.renderer.SubmitNodeCollector; +import net.minecraft.client.renderer.state.level.PlayerRenderState; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; @@ -31,7 +31,7 @@ public abstract class ScreenEffectRendererMixin { } @Inject(method = "submitWater", at = @At("HEAD"), cancellable = true) - private static void noRenderUnderwaterOverlay(Minecraft minecraft, PoseStack matrices, SubmitNodeCollector collector, CallbackInfo ci) { + private static void noRenderUnderwaterOverlay(PlayerRenderState.WaterOverlay waterOverlay, PoseStack matrices, SubmitNodeCollector collector, CallbackInfo ci) { if (noRender.isEnabled() && !noRender.fluidOverlay.getValue()) ci.cancel(); } -} \ No newline at end of file +} diff --git a/src/main/java/me/retucio/sputnik/mixin/mixins/render/ShaderManagerMixin.java b/src/main/java/me/retucio/sputnik/mixin/mixins/render/ShaderManagerMixin.java index f089f23..1bebdeb 100644 --- a/src/main/java/me/retucio/sputnik/mixin/mixins/render/ShaderManagerMixin.java +++ b/src/main/java/me/retucio/sputnik/mixin/mixins/render/ShaderManagerMixin.java @@ -6,14 +6,23 @@ import net.minecraft.client.renderer.ShaderManager; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +import net.minecraft.server.packs.resources.PreparableReloadListener; + +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.Executor; @Mixin(ShaderManager.class) public abstract class ShaderManagerMixin { - @Inject(method = "apply(Lnet/minecraft/client/renderer/ShaderManager$Configs;Lnet/minecraft/server/packs/resources/ResourceManager;Lnet/minecraft/util/profiling/ProfilerFiller;)V", at = @At("TAIL")) - private void onReload(CallbackInfo ci) { - Pipelines.init(); - PostShaders.reload(); + @Inject(method = "reload", at = @At("RETURN")) + private void onReload(PreparableReloadListener.SharedState state, Executor preparationExecutor, + PreparableReloadListener.PreparationBarrier barrier, Executor applyExecutor, + CallbackInfoReturnable> cir) { + cir.getReturnValue().thenRun(() -> { + Pipelines.init(); + PostShaders.reload(); + }); } -} \ No newline at end of file +} diff --git a/src/main/java/me/retucio/sputnik/mixin/mixins/render/SkyRendererMixin.java b/src/main/java/me/retucio/sputnik/mixin/mixins/render/SkyRendererMixin.java index 0aea7f6..fdd8729 100644 --- a/src/main/java/me/retucio/sputnik/mixin/mixins/render/SkyRendererMixin.java +++ b/src/main/java/me/retucio/sputnik/mixin/mixins/render/SkyRendererMixin.java @@ -1,6 +1,7 @@ package me.retucio.sputnik.mixin.mixins.render; import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.renderpearl.api.commands.RenderPass; import me.retucio.sputnik.module.ModuleManager; import me.retucio.sputnik.module.modules.render.NoRender; import me.retucio.sputnik.module.modules.world.TimeChanger; @@ -26,17 +27,17 @@ public abstract class SkyRendererMixin { } @Inject(method = "renderSun", at = @At("HEAD"), cancellable = true) - private void onRenderSun(float rainBrightness, PoseStack poseStack, CallbackInfo ci) { + private void onRenderSun(RenderPass renderPass, float rainBrightness, PoseStack poseStack, CallbackInfo ci) { if (timeChanger.isEnabled() && !timeChanger.renderSun.getValue()) ci.cancel(); } @Inject(method = "renderMoon", at = @At("HEAD"), cancellable = true) - private void onRenderMoon(MoonPhase moonPhase, float rainBrightness, PoseStack poseStack, CallbackInfo ci) { + private void onRenderMoon(RenderPass renderPass, MoonPhase moonPhase, float rainBrightness, PoseStack poseStack, CallbackInfo ci) { if (!timeChanger.isEnabled()) return; if (!timeChanger.renderMoon.getValue()) ci.cancel(); } - @ModifyArg(method = "renderSunMoonAndStars", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/SkyRenderer;renderMoon(Lnet/minecraft/world/level/MoonPhase;FLcom/mojang/blaze3d/vertex/PoseStack;)V")) + @ModifyArg(method = "renderSunMoonAndStars", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/SkyRenderer;renderMoon(Lcom/mojang/renderpearl/api/commands/RenderPass;Lnet/minecraft/world/level/MoonPhase;FLcom/mojang/blaze3d/vertex/PoseStack;)V")) private MoonPhase timeChangerMoonPhase(MoonPhase original) { if (!timeChanger.isEnabled() || timeChanger.moonPhase.is(TimeChanger.MoonPhases.DEFAULT)) return original; int phase = timeChanger.moonPhase.getIndex(); @@ -45,12 +46,12 @@ public abstract class SkyRendererMixin { } @Inject(method = "renderStars", at = @At("HEAD"), cancellable = true) - private void onRenderStars(float starBrightness, PoseStack poseStack, CallbackInfo ci) { + private void onRenderStars(RenderPass renderPass, float starBrightness, PoseStack poseStack, CallbackInfo ci) { if (timeChanger.isEnabled() && !timeChanger.renderStars.getValue()) ci.cancel(); } @Inject(method = "renderEndFlash", at = @At("HEAD"), cancellable = true) - private void onEndFlash(PoseStack matrices, float intensity, float xAngle, float yAngle, CallbackInfo ci) { + private void onEndFlash(RenderPass renderPass, PoseStack poseStack, float intensity, float xAngle, float yAngle, CallbackInfo ci) { NoRender noRender = ModuleManager.INSTANCE.getModuleByClass(NoRender.class); if (noRender.isEnabled() && !noRender.endFlashes.getValue()) ci.cancel(); } diff --git a/src/main/java/me/retucio/sputnik/mixin/mixins/render/WeatherEffectRendererMixin.java b/src/main/java/me/retucio/sputnik/mixin/mixins/render/WeatherEffectRendererMixin.java index 1752626..be33be8 100644 --- a/src/main/java/me/retucio/sputnik/mixin/mixins/render/WeatherEffectRendererMixin.java +++ b/src/main/java/me/retucio/sputnik/mixin/mixins/render/WeatherEffectRendererMixin.java @@ -4,7 +4,7 @@ import me.retucio.sputnik.module.ModuleManager; import me.retucio.sputnik.module.modules.render.NoRender; import net.minecraft.client.renderer.WeatherEffectRenderer; import net.minecraft.client.renderer.state.level.WeatherRenderState; -import net.minecraft.world.phys.Vec3; +import com.mojang.renderpearl.api.commands.RenderPass; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; @@ -24,7 +24,7 @@ public abstract class WeatherEffectRendererMixin { } @Inject(method = "render", at = @At("HEAD")) - private void noRenderRainAndSnow(Vec3 cameraPos, WeatherRenderState renderState, CallbackInfo ci) { + private void noRenderRainAndSnow(WeatherRenderState renderState, RenderPass renderPass, CallbackInfo ci) { if (noRender.isEnabled()) { if (!noRender.rain.getValue()) renderState.rainColumns.clear(); if (!noRender.snow.getValue()) renderState.snowColumns.clear(); diff --git a/src/main/java/me/retucio/sputnik/module/Module.java b/src/main/java/me/retucio/sputnik/module/Module.java index cd5bc32..002a40c 100644 --- a/src/main/java/me/retucio/sputnik/module/Module.java +++ b/src/main/java/me/retucio/sputnik/module/Module.java @@ -1,6 +1,7 @@ package me.retucio.sputnik.module; import com.github.retucio.neutrino.EventListener; +import com.mojang.blaze3d.platform.InputConstants; import me.retucio.sputnik.Sputnik; import me.retucio.sputnik.config.ConfigManager; import me.retucio.sputnik.event.sputnik.ToggleModuleEvent; @@ -16,7 +17,6 @@ import me.retucio.sputnik.util.Colors; import me.retucio.sputnik.util.I18nUtil; import net.minecraft.client.Minecraft; import net.minecraft.network.chat.Component; -import org.lwjgl.glfw.GLFW; import java.awt.*; import java.lang.reflect.Method; @@ -41,7 +41,7 @@ public class Module { protected KeySetting bind = new KeySetting( "tecla", "tecla asignada al módulo, ESC para desactivar", - GLFW.GLFW_KEY_UNKNOWN + InputConstants.UNKNOWN.getValue() ).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 diff --git a/src/main/java/me/retucio/sputnik/module/modules/camera/CrosshairPlus.java b/src/main/java/me/retucio/sputnik/module/modules/camera/CrosshairPlus.java index dc664e6..c0f1c29 100644 --- a/src/main/java/me/retucio/sputnik/module/modules/camera/CrosshairPlus.java +++ b/src/main/java/me/retucio/sputnik/module/modules/camera/CrosshairPlus.java @@ -1,6 +1,6 @@ package me.retucio.sputnik.module.modules.camera; -import com.mojang.blaze3d.pipeline.RenderPipeline; +import com.mojang.renderpearl.api.pipeline.RenderPipeline; import me.retucio.sputnik.module.Category; import me.retucio.sputnik.module.Module; import me.retucio.sputnik.module.setting.settings.ColorSetting; diff --git a/src/main/java/me/retucio/sputnik/module/modules/camera/Freecam.java b/src/main/java/me/retucio/sputnik/module/modules/camera/Freecam.java index 4e095e3..28f4450 100644 --- a/src/main/java/me/retucio/sputnik/module/modules/camera/Freecam.java +++ b/src/main/java/me/retucio/sputnik/module/modules/camera/Freecam.java @@ -31,7 +31,7 @@ import net.minecraft.network.protocol.game.*; import net.minecraft.util.Mth; import net.minecraft.world.phys.Vec3; import org.joml.Vector3d; -import org.lwjgl.glfw.GLFW; +import com.mojang.blaze3d.platform.InputConstants; /** continúa en: * @see CameraMixin @@ -104,7 +104,7 @@ public class Freecam extends Module { private final KeySetting scrollKey = sgSpeed.add(new KeySetting( "tecla del scroll", "tecla a mantener pulsada para cambiar velocidad con el scroll", - GLFW.GLFW_KEY_LEFT_CONTROL + InputConstants.KEY_LCONTROL )); private final NumberSetting scrollSens = sgSpeed.add(new NumberSetting( @@ -128,7 +128,7 @@ public class Freecam extends Module { super("cámara libre", "permite a la cámara moverse independientemente del jugador. útil para explorar alrededores", Category.CAMERA, - GLFW.GLFW_KEY_V); + InputConstants.KEY_V); speedSetting.onUpdate(newSpeed -> speed = newSpeed); } @@ -262,37 +262,36 @@ public class Freecam extends Module { Packet packet = event.getPacket(); if (packet instanceof ServerboundPlayerActionPacket || packet instanceof ServerboundUseItemOnPacket - || packet instanceof ServerboundUseItemPacket - || packet instanceof ServerboundSwingPacket) { + || packet instanceof ServerboundUseItemPacket) { event.cancel(); } } @EventListener private void onKey(KeyEvent event) { - if (KeyUtil.isKeyDown(GLFW.GLFW_KEY_F3)) return; + if (KeyUtil.isKeyDown(InputConstants.KEY_F3)) return; if (mc.gui.screen() != null) return; net.minecraft.client.input.KeyEvent key = new net.minecraft.client.input.KeyEvent(event.getKey(), event.getScancode(), 0); boolean shouldCancel = true; if (mc.options.keyUp.matches(key)) { - forward = event.getAction() != GLFW.GLFW_RELEASE; + forward = event.getAction() != InputConstants.RELEASE; mc.options.keyUp.setDown(false); } else if (mc.options.keyDown.matches(key)) { - backward = event.getAction() != GLFW.GLFW_RELEASE; + backward = event.getAction() != InputConstants.RELEASE; mc.options.keyDown.setDown(false); } else if (mc.options.keyRight.matches(key)) { - right = event.getAction() != GLFW.GLFW_RELEASE; + right = event.getAction() != InputConstants.RELEASE; mc.options.keyRight.setDown(false); } else if (mc.options.keyLeft.matches(key)) { - left = event.getAction() != GLFW.GLFW_RELEASE; + left = event.getAction() != InputConstants.RELEASE; mc.options.keyLeft.setDown(false); } else if (mc.options.keyJump.matches(key)) { - up = event.getAction() != GLFW.GLFW_RELEASE; + up = event.getAction() != InputConstants.RELEASE; mc.options.keyJump.setDown(false); } else if (mc.options.keyShift.matches(key)) { - down = event.getAction() != GLFW.GLFW_RELEASE; + down = event.getAction() != InputConstants.RELEASE; mc.options.keyShift.setDown(false); } else { shouldCancel = false; @@ -303,29 +302,29 @@ 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 (KeyUtil.isKeyDown(InputConstants.KEY_F3)) return; if (mc.gui.screen() != null) return; MouseButtonEvent click = new MouseButtonEvent(0, 0, new MouseButtonInfo(event.getButton(), 0)); boolean shouldCancel = true; if (mc.options.keyUp.matchesMouse(click)) { - forward = event.getAction() != GLFW.GLFW_RELEASE; + forward = event.getAction() != InputConstants.RELEASE; mc.options.keyUp.setDown(false); } else if (mc.options.keyDown.matchesMouse(click)) { - backward = event.getAction() != GLFW.GLFW_RELEASE; + backward = event.getAction() != InputConstants.RELEASE; mc.options.keyDown.setDown(false); } else if (mc.options.keyRight.matchesMouse(click)) { - right = event.getAction() != GLFW.GLFW_RELEASE; + right = event.getAction() != InputConstants.RELEASE; mc.options.keyRight.setDown(false); } else if (mc.options.keyLeft.matchesMouse(click)) { - left = event.getAction() != GLFW.GLFW_RELEASE; + left = event.getAction() != InputConstants.RELEASE; mc.options.keyLeft.setDown(false); } else if (mc.options.keyJump.matchesMouse(click)) { - up = event.getAction() != GLFW.GLFW_RELEASE; + up = event.getAction() != InputConstants.RELEASE; mc.options.keyJump.setDown(false); } else if (mc.options.keyShift.matchesMouse(click)) { - down = event.getAction() != GLFW.GLFW_RELEASE; + down = event.getAction() != InputConstants.RELEASE; mc.options.keyShift.setDown(false); } else { shouldCancel = false; diff --git a/src/main/java/me/retucio/sputnik/module/modules/camera/Freelook.java b/src/main/java/me/retucio/sputnik/module/modules/camera/Freelook.java index 942c459..d7f81d2 100644 --- a/src/main/java/me/retucio/sputnik/module/modules/camera/Freelook.java +++ b/src/main/java/me/retucio/sputnik/module/modules/camera/Freelook.java @@ -9,7 +9,7 @@ import me.retucio.sputnik.module.setting.settings.NumberSetting; import me.retucio.sputnik.util.KeyUtil; import net.minecraft.client.CameraType; import net.minecraft.util.Mth; -import org.lwjgl.glfw.GLFW; +import com.mojang.blaze3d.platform.InputConstants; /** continúa en: * @see CameraMixin @@ -37,7 +37,7 @@ public class Freelook extends Module { super("perspectiva libre", "te permite mover la cámara de la perspectiva sin mover la del jugador, o vice versa", Category.CAMERA, - GLFW.GLFW_KEY_B); + InputConstants.KEY_B); keyMode.setDefaultValue(KeyMode.HOLD); keyMode.setValue(KeyMode.HOLD); @@ -75,18 +75,18 @@ public class Freelook extends Module { for (int i = 0; i < (arrowSens.getValue() * 2); i++) { switch (mode.getValue()) { case PLAYER -> { - if (KeyUtil.isKeyDown(GLFW.GLFW_KEY_LEFT)) yaw -= 0.5f; - if (KeyUtil.isKeyDown(GLFW.GLFW_KEY_RIGHT)) yaw += 0.5f; - if (KeyUtil.isKeyDown(GLFW.GLFW_KEY_UP)) pitch -= 0.5f; - if (KeyUtil.isKeyDown(GLFW.GLFW_KEY_DOWN)) pitch += 0.5f; + if (KeyUtil.isKeyDown(InputConstants.KEY_LEFT)) yaw -= 0.5f; + if (KeyUtil.isKeyDown(InputConstants.KEY_RIGHT)) yaw += 0.5f; + if (KeyUtil.isKeyDown(InputConstants.KEY_UP)) pitch -= 0.5f; + if (KeyUtil.isKeyDown(InputConstants.KEY_DOWN)) pitch += 0.5f; } case CAMERA -> { float yaw = mc.player.getYRot(); float pitch = mc.player.getXRot(); - if (KeyUtil.isKeyDown(GLFW.GLFW_KEY_LEFT)) yaw -= 0.5f; - if (KeyUtil.isKeyDown(GLFW.GLFW_KEY_RIGHT)) yaw += 0.5f; - if (KeyUtil.isKeyDown(GLFW.GLFW_KEY_UP)) pitch -= 0.5f; - if (KeyUtil.isKeyDown(GLFW.GLFW_KEY_DOWN)) pitch += 0.5f; + if (KeyUtil.isKeyDown(InputConstants.KEY_LEFT)) yaw -= 0.5f; + if (KeyUtil.isKeyDown(InputConstants.KEY_RIGHT)) yaw += 0.5f; + if (KeyUtil.isKeyDown(InputConstants.KEY_UP)) pitch -= 0.5f; + if (KeyUtil.isKeyDown(InputConstants.KEY_DOWN)) pitch += 0.5f; mc.player.setYRot(yaw); mc.player.setXRot(pitch); diff --git a/src/main/java/me/retucio/sputnik/module/modules/camera/Fullbright.java b/src/main/java/me/retucio/sputnik/module/modules/camera/Fullbright.java index 8ada6ca..42c6787 100644 --- a/src/main/java/me/retucio/sputnik/module/modules/camera/Fullbright.java +++ b/src/main/java/me/retucio/sputnik/module/modules/camera/Fullbright.java @@ -9,7 +9,7 @@ import me.retucio.sputnik.module.setting.settings.EnumSetting; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.world.effect.MobEffectInstance; import net.minecraft.world.effect.MobEffects; -import org.lwjgl.glfw.GLFW; +import com.mojang.blaze3d.platform.InputConstants; import java.awt.*; @@ -39,7 +39,7 @@ public class Fullbright extends Module { super("brilli brilli", "deshabilita la oscuridad (y aplica colores a los shaders)", Category.CAMERA, - GLFW.GLFW_KEY_K); + InputConstants.KEY_K); mode.onUpdate(mode -> { if (mode != Modes.POTION) disableNightVision(); }); } diff --git a/src/main/java/me/retucio/sputnik/module/modules/camera/PerspectivePlus.java b/src/main/java/me/retucio/sputnik/module/modules/camera/PerspectivePlus.java index e2dbc94..e90cb9b 100644 --- a/src/main/java/me/retucio/sputnik/module/modules/camera/PerspectivePlus.java +++ b/src/main/java/me/retucio/sputnik/module/modules/camera/PerspectivePlus.java @@ -10,7 +10,7 @@ import me.retucio.sputnik.module.setting.settings.BooleanSetting; import me.retucio.sputnik.module.setting.settings.KeySetting; import me.retucio.sputnik.module.setting.settings.NumberSetting; import net.minecraft.client.CameraType; -import org.lwjgl.glfw.GLFW; +import com.mojang.blaze3d.platform.InputConstants; /** continúa en: @@ -36,7 +36,7 @@ public class PerspectivePlus extends Module { 1, 0, 8, 0.1)); private final KeySetting scrollKey = sgScroll.add(new KeySetting("tecla del scroll", "qué tecla mantener para usar la rueda del ratón", - GLFW.GLFW_KEY_LEFT_ALT)); + InputConstants.KEY_LALT)); private double distance; diff --git a/src/main/java/me/retucio/sputnik/module/modules/camera/Zoom.java b/src/main/java/me/retucio/sputnik/module/modules/camera/Zoom.java index cdd2832..8edfbb8 100644 --- a/src/main/java/me/retucio/sputnik/module/modules/camera/Zoom.java +++ b/src/main/java/me/retucio/sputnik/module/modules/camera/Zoom.java @@ -9,7 +9,7 @@ import me.retucio.sputnik.module.setting.SettingGroup; import me.retucio.sputnik.module.setting.settings.BooleanSetting; import me.retucio.sputnik.module.setting.settings.KeySetting; import me.retucio.sputnik.module.setting.settings.NumberSetting; -import org.lwjgl.glfw.GLFW; +import com.mojang.blaze3d.platform.InputConstants; /** continúa en: @@ -33,7 +33,7 @@ public class Zoom extends Module { private final NumberSetting scrollSens = sgScroll.add(new NumberSetting("sensibilidad del scroll", "sensibilidad de la rueda del ratón (0 para desactivar)", 0.4, 0, 8, 0.1)); private final KeySetting scrollKey = sgScroll.add(new KeySetting("tecla del scroll", "qué tecla mantener para usar la rueda del ratón", - GLFW.GLFW_KEY_LEFT_CONTROL)); + InputConstants.KEY_LCONTROL)); private final NumberSetting mouseSensMultiplier = sgCam.add(new NumberSetting("sensibilidad", "multiplicador de la sensibilidad del ratón", 0.4, 0, 1, 0.05)); @@ -49,7 +49,7 @@ public class Zoom extends Module { super("zoom", "lupa", Category.CAMERA, - GLFW.GLFW_KEY_F); + InputConstants.KEY_F); keyMode.setDefaultValue(KeyMode.HOLD); keyMode.setValue(KeyMode.HOLD); @@ -103,7 +103,7 @@ public class Zoom extends Module { @EventListener private void onMouseScroll(MouseScrollEvent event) { - boolean key = scrollKey.getValue() == GLFW.GLFW_KEY_UNKNOWN || scrollKey.isDown(); + boolean key = scrollKey.getValue() == InputConstants.UNKNOWN.getValue() || scrollKey.isDown(); if (isEnabled() && scrollSens.getValue() > 0 && key) { value += event.getVertical() * 0.25 * (scrollSens.getValue() * value); if (value < 1) value = 1; diff --git a/src/main/java/me/retucio/sputnik/module/modules/client/ClientSettingsModule.java b/src/main/java/me/retucio/sputnik/module/modules/client/ClientSettingsModule.java index da717ed..d29d6b2 100644 --- a/src/main/java/me/retucio/sputnik/module/modules/client/ClientSettingsModule.java +++ b/src/main/java/me/retucio/sputnik/module/modules/client/ClientSettingsModule.java @@ -1,6 +1,7 @@ package me.retucio.sputnik.module.modules.client; import com.github.retucio.neutrino.EventListener; +import com.mojang.blaze3d.platform.InputConstants; import me.retucio.sputnik.Sputnik; import me.retucio.sputnik.command.CommandManager; import me.retucio.sputnik.event.TickEvent; @@ -17,7 +18,6 @@ import me.retucio.sputnik.module.setting.settings.NumberSetting; import me.retucio.sputnik.module.setting.settings.StringSetting; import me.retucio.sputnik.util.ChatUtil; import me.retucio.sputnik.util.Colors; -import org.lwjgl.glfw.GLFW; import java.awt.*; @@ -130,7 +130,7 @@ public class ClientSettingsModule extends Module { super("interfaz", "ajustes de la interfaz, y otros misceláneos", Category.CLIENT, - GLFW.GLFW_KEY_RIGHT_SHIFT); + InputConstants.KEY_RSHIFT); Sputnik.EVENT_BUS.subscribe(this); diff --git a/src/main/java/me/retucio/sputnik/module/modules/client/Friends.java b/src/main/java/me/retucio/sputnik/module/modules/client/Friends.java index 2c06064..edfffd8 100644 --- a/src/main/java/me/retucio/sputnik/module/modules/client/Friends.java +++ b/src/main/java/me/retucio/sputnik/module/modules/client/Friends.java @@ -11,7 +11,7 @@ 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; +import com.mojang.blaze3d.platform.InputConstants; public class Friends extends Module { @@ -34,8 +34,8 @@ public class Friends extends Module { @EventListener public void onMouseClick(MouseClickEvent event) { - if (event.getButton() == GLFW.GLFW_MOUSE_BUTTON_MIDDLE - && event.getAction() == GLFW.GLFW_PRESS + if (event.getButton() == InputConstants.MOUSE_BUTTON_MIDDLE + && event.getAction() == InputConstants.PRESS && middleClick.getValue()) { Entity target = mc.crosshairPickEntity; diff --git a/src/main/java/me/retucio/sputnik/module/modules/client/Hud.java b/src/main/java/me/retucio/sputnik/module/modules/client/Hud.java index 9234c98..82cdd53 100644 --- a/src/main/java/me/retucio/sputnik/module/modules/client/Hud.java +++ b/src/main/java/me/retucio/sputnik/module/modules/client/Hud.java @@ -9,7 +9,7 @@ import me.retucio.sputnik.ui.hud.HudRenderer; import me.retucio.sputnik.ui.hud.HudEditorScreen; import me.retucio.sputnik.ui.hud.elements.CustomImageElement; import me.retucio.sputnik.ui.hud.elements.DynoElement; -import org.lwjgl.glfw.GLFW; +import com.mojang.blaze3d.platform.InputConstants; import java.awt.*; @@ -32,7 +32,7 @@ public class Hud extends Module { public KeySetting editorKey = sgEditor.add(new KeySetting( "tecla del editor", "tecla asignada al editor de elementos del hud", - GLFW.GLFW_KEY_INSERT + InputConstants.KEY_INSERT )); public BooleanSetting axialMovement = sgEditor.add(new BooleanSetting( @@ -144,7 +144,7 @@ public class Hud extends Module { super("HUD", "superposición de la pantalla con info. adicional", Category.CLIENT, - GLFW.GLFW_KEY_F12 + InputConstants.KEY_F12 ); dyno.onUpdate(v -> { diff --git a/src/main/java/me/retucio/sputnik/module/modules/combat/KillAura.java b/src/main/java/me/retucio/sputnik/module/modules/combat/KillAura.java index 95d6353..849d9d0 100644 --- a/src/main/java/me/retucio/sputnik/module/modules/combat/KillAura.java +++ b/src/main/java/me/retucio/sputnik/module/modules/combat/KillAura.java @@ -93,7 +93,7 @@ public class KillAura extends Module { if (!mc.level.isTickingEntity(entity)) return; if (swingHand.getValue()) { - mc.player.swing(InteractionHand.MAIN_HAND); + mc.player.swing(InteractionHand.MAIN_HAND, net.minecraft.world.item.component.SwingAnimation.DEFAULT, false); } mc.gameMode.attack(mc.player, entity); diff --git a/src/main/java/me/retucio/sputnik/module/modules/inventory/Burglar.java b/src/main/java/me/retucio/sputnik/module/modules/inventory/Burglar.java index 757a7c8..ff473ed 100644 --- a/src/main/java/me/retucio/sputnik/module/modules/inventory/Burglar.java +++ b/src/main/java/me/retucio/sputnik/module/modules/inventory/Burglar.java @@ -15,7 +15,7 @@ import net.minecraft.world.Container; import net.minecraft.world.inventory.AbstractContainerMenu; import net.minecraft.world.item.ItemStack; import org.jspecify.annotations.NonNull; -import org.lwjgl.glfw.GLFW; +import com.mojang.blaze3d.platform.InputConstants; import java.util.List; @@ -31,19 +31,19 @@ public class Burglar extends Module { private final KeySetting triggerKey = sgKeys.add(new KeySetting( "tecla activadora", "tecla a mantener para que las otras teclas funcionen", - GLFW.GLFW_KEY_LEFT_CONTROL + InputConstants.KEY_LCONTROL )); private final KeySetting stealKey = sgKeys.add(new KeySetting( "robar", "tecla para robar todo", - GLFW.GLFW_KEY_S + InputConstants.KEY_S )); private final KeySetting dumpKey = sgKeys.add(new KeySetting( "dejar", "tecla para dejar todo", - GLFW.GLFW_KEY_D + InputConstants.KEY_D )); @@ -67,7 +67,7 @@ public class Burglar extends Module { @EventListener private void onKey(KeyEvent event) { - if (!triggerKey.isDown() || event.getAction() != GLFW.GLFW_PRESS + if (!triggerKey.isDown() || event.getAction() != InputConstants.PRESS || !(mc.gui.screen() instanceof AbstractContainerScreen container)) return; if (event.getKey() == stealKey.getValue()) steal(container); if (event.getKey() == dumpKey.getValue()) dump(container); diff --git a/src/main/java/me/retucio/sputnik/module/modules/inventory/InventoryPlus.java b/src/main/java/me/retucio/sputnik/module/modules/inventory/InventoryPlus.java index d286c03..4f0bbdc 100644 --- a/src/main/java/me/retucio/sputnik/module/modules/inventory/InventoryPlus.java +++ b/src/main/java/me/retucio/sputnik/module/modules/inventory/InventoryPlus.java @@ -12,7 +12,7 @@ import me.retucio.sputnik.util.InventoryUtil; import me.retucio.sputnik.util.KeyUtil; import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; import net.minecraft.world.inventory.Slot; -import org.lwjgl.glfw.GLFW; +import com.mojang.blaze3d.platform.InputConstants; /** @@ -21,9 +21,9 @@ import org.lwjgl.glfw.GLFW; public class InventoryPlus extends Module { - private final KeySetting row1key = sgGeneral.add(new KeySetting("fila 1", "tecla para mover items a la primera fila", GLFW.GLFW_KEY_A)); - private final KeySetting row2key = sgGeneral.add(new KeySetting("fila 2", "tecla para mover items a la segunda fila", GLFW.GLFW_KEY_S)); - private final KeySetting row3key = sgGeneral.add(new KeySetting("fila 3", "tecla para mover items a la tercera fila", GLFW.GLFW_KEY_D)); + private final KeySetting row1key = sgGeneral.add(new KeySetting("fila 1", "tecla para mover items a la primera fila", InputConstants.KEY_A)); + private final KeySetting row2key = sgGeneral.add(new KeySetting("fila 2", "tecla para mover items a la segunda fila", InputConstants.KEY_S)); + private final KeySetting row3key = sgGeneral.add(new KeySetting("fila 3", "tecla para mover items a la tercera fila", InputConstants.KEY_D)); public InventoryPlus() { super("inventario plus", @@ -33,13 +33,13 @@ public class InventoryPlus extends Module { @EventListener private void onKey(KeyEvent event) { - if (event.getAction() == GLFW.GLFW_RELEASE) return; + if (event.getAction() == InputConstants.RELEASE) return; processInput(event.getKey(), event); } @EventListener private void onMouseButton(MouseClickEvent event) { - if (event.getAction() == GLFW.GLFW_RELEASE) return; + if (event.getAction() == InputConstants.RELEASE) return; processInput(event.getButton(), event); } diff --git a/src/main/java/me/retucio/sputnik/module/modules/inventory/ShulkerPeek.java b/src/main/java/me/retucio/sputnik/module/modules/inventory/ShulkerPeek.java index 7013704..c040881 100644 --- a/src/main/java/me/retucio/sputnik/module/modules/inventory/ShulkerPeek.java +++ b/src/main/java/me/retucio/sputnik/module/modules/inventory/ShulkerPeek.java @@ -22,7 +22,7 @@ import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; import net.minecraft.world.item.component.ItemContainerContents; import net.minecraft.world.level.block.ShulkerBoxBlock; -import org.lwjgl.glfw.GLFW; +import com.mojang.blaze3d.platform.InputConstants; import java.awt.*; import java.util.HashMap; @@ -30,7 +30,7 @@ import java.util.HashMap; public class ShulkerPeek extends Module { - public final KeySetting previewKey = sgGeneral.add(new KeySetting("tecla de previsualización", "tecla a mantener para previsualizar", GLFW.GLFW_KEY_LEFT_ALT)); + public final KeySetting previewKey = sgGeneral.add(new KeySetting("tecla de previsualización", "tecla a mantener para previsualizar", InputConstants.KEY_LALT)); public final BooleanSetting showTooltips = sgGeneral.add(new BooleanSetting("mostrar tooltips", "añadir texto a los tooltips (cajas de texto) de los shulkers", true)); public static final HashMap SHULKER_COLORS = new HashMap<>(); @@ -65,12 +65,12 @@ public class ShulkerPeek extends Module { if (mc.player == null) return; if (event.getKey() != previewKey.getValue()) return; - if (event.getAction() == GLFW.GLFW_PRESS) { + if (event.getAction() == InputConstants.PRESS) { openPreviewScreen(); return; } - if (event.getAction() == GLFW.GLFW_REPEAT) { + if (event.getAction() == InputConstants.REPEAT) { if (mc.gui.screen() instanceof PreviewScreen preview) { if (preview.getType() != PreviewScreen.PreviewType.SHULKER) openPreviewScreen(); @@ -78,7 +78,7 @@ public class ShulkerPeek extends Module { return; } - if (event.getAction() == GLFW.GLFW_RELEASE) { + if (event.getAction() == InputConstants.RELEASE) { if (mc.gui.screen() instanceof PreviewScreen preview) preview.onClose(); } @@ -117,6 +117,6 @@ public class ShulkerPeek extends Module { if (container == null) return true; // .stream()? - return container.allItemsCopyStream().allMatch(ItemStack::isEmpty); + return container.nonEmptyItemCopyStream().allMatch(ItemStack::isEmpty); } } diff --git a/src/main/java/me/retucio/sputnik/module/modules/misc/FakePlayer.java b/src/main/java/me/retucio/sputnik/module/modules/misc/FakePlayer.java index faf0eec..97c97e4 100644 --- a/src/main/java/me/retucio/sputnik/module/modules/misc/FakePlayer.java +++ b/src/main/java/me/retucio/sputnik/module/modules/misc/FakePlayer.java @@ -14,8 +14,12 @@ import java.util.UUID; public class FakePlayer extends Module { - private final StringSetting name = sgGeneral.add(new StringSetting("nombre", "qué nombre asignarle al jugador", "apio boy", 22)); + private final StringSetting name = sgGeneral.add(new StringSetting( + "nombre", "qué nombre asignarle al jugador", + "apio boy", 22 + )); + private static int nextFakeId = -2; private RemotePlayer player = null; public FakePlayer() { @@ -27,7 +31,7 @@ public class FakePlayer extends Module { @Override public void onEnable() { if (mc.level == null) return; - addPlayer(mc.player, name.getValue()); + player = addPlayer(mc.player, name.getValue()); super.onEnable(); } @@ -40,20 +44,23 @@ public class FakePlayer extends Module { // intento miserable de hacer que no colisione con jugadores public RemotePlayer addPlayer(Player playerToCopy, String dummyName) { - player = new RemotePlayer(mc.level, new GameProfile(UUID.randomUUID(), dummyName)) { - @Override public void playerTouch(@NonNull Player player) {} + RemotePlayer fake = new RemotePlayer(mc.level, new GameProfile(UUID.randomUUID(), dummyName)) { + @Override public void playerTouch(@NonNull Player p) {} }; - player.restoreFrom(playerToCopy); - player.setCustomNameVisible(true); - player.noPhysics = true; - player.horizontalCollision = false; - player.verticalCollision = false; - mc.level.addEntity(player); - return player; + fake.restoreFrom(playerToCopy); + fake.setCustomNameVisible(true); + fake.noPhysics = true; + fake.horizontalCollision = false; + fake.verticalCollision = false; + + fake.setId(nextFakeId--); + mc.level.addEntity(fake); + return fake; } public void removePlayer() { + if (player == null) return; player.setRemoved(Entity.RemovalReason.KILLED); player.onClientRemoval(); player = null; diff --git a/src/main/java/me/retucio/sputnik/module/modules/network/LogoutSpots.java b/src/main/java/me/retucio/sputnik/module/modules/network/LogoutSpots.java index 8795b33..dc59143 100644 --- a/src/main/java/me/retucio/sputnik/module/modules/network/LogoutSpots.java +++ b/src/main/java/me/retucio/sputnik/module/modules/network/LogoutSpots.java @@ -257,12 +257,16 @@ public class LogoutSpots extends Module { if (outlines.getValue()) { RenderUtil.drawBlockFaceOutlines(matrices, BlockPos.containing(x + halfWidth, y, z + halfWidth), - Direction.UP, outlineColor.getValue(), lineWidth.getFloatValue(), true); + Direction.UP, outlineColor.getValue(), lineWidth.getFloatValue(), + true + ); } if (filling.getValue()) { RenderUtil.drawBlockFaceFilled(matrices, BlockPos.containing(x + halfWidth, y, z + halfWidth), - Direction.UP, fillingColor.getValue(), 0.001f, true); + Direction.UP, fillingColor.getValue(), 0.001f, + true + ); } } } diff --git a/src/main/java/me/retucio/sputnik/module/modules/player/AirPlace.java b/src/main/java/me/retucio/sputnik/module/modules/player/AirPlace.java index db23e70..3d0a1dc 100644 --- a/src/main/java/me/retucio/sputnik/module/modules/player/AirPlace.java +++ b/src/main/java/me/retucio/sputnik/module/modules/player/AirPlace.java @@ -20,7 +20,7 @@ import net.minecraft.world.item.BlockItem; import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.HitResult; import net.minecraft.world.phys.Vec3; -import org.lwjgl.glfw.GLFW; +import com.mojang.blaze3d.platform.InputConstants; public class AirPlace extends Module { @@ -52,7 +52,7 @@ public class AirPlace extends Module { private final KeySetting scrollKey = sgScroll.add(new KeySetting( "tecla del scroll", "tecla a mantener para que el scroll funcione", - GLFW.GLFW_KEY_LEFT_CONTROL + InputConstants.KEY_LCONTROL )); private final NumberSetting scrollSens = sgScroll.add(new NumberSetting( @@ -138,7 +138,7 @@ public class AirPlace extends Module { @EventListener private void onKey(KeyEvent event) { - if (event.getKey() == scrollKey.getValue() && event.getAction() == GLFW.GLFW_RELEASE) { + if (event.getKey() == scrollKey.getValue() && event.getAction() == InputConstants.RELEASE) { rangeValue = (int) Math.clamp(rangeValue, range.getMin(), range.getMax()); } } diff --git a/src/main/java/me/retucio/sputnik/module/modules/player/FastUse.java b/src/main/java/me/retucio/sputnik/module/modules/player/FastUse.java index 5f4a308..7313dbf 100644 --- a/src/main/java/me/retucio/sputnik/module/modules/player/FastUse.java +++ b/src/main/java/me/retucio/sputnik/module/modules/player/FastUse.java @@ -7,7 +7,7 @@ import me.retucio.sputnik.module.setting.settings.NumberSetting; import net.minecraft.world.item.BlockItem; import net.minecraft.world.item.ItemStack; -import org.lwjgl.glfw.GLFW; +import com.mojang.blaze3d.platform.InputConstants; public class FastUse extends Module { @@ -61,7 +61,7 @@ public class FastUse extends Module { super("precoz", "hace cosas como usar items o colocar bloques más rápido", Category.PLAYER, - GLFW.GLFW_KEY_F6); + InputConstants.KEY_F6); items.onUpdate(itemCooldown::visibility); blocks.onUpdate(blockCooldown::visibility); diff --git a/src/main/java/me/retucio/sputnik/module/modules/render/GlintPlus.java b/src/main/java/me/retucio/sputnik/module/modules/render/GlintPlus.java index b8dcef2..8923455 100644 --- a/src/main/java/me/retucio/sputnik/module/modules/render/GlintPlus.java +++ b/src/main/java/me/retucio/sputnik/module/modules/render/GlintPlus.java @@ -8,9 +8,11 @@ import me.retucio.sputnik.module.Module; import me.retucio.sputnik.module.setting.settings.BooleanSetting; import me.retucio.sputnik.module.setting.settings.EnumSetting; import me.retucio.sputnik.util.render.GlintRenderType; +import net.minecraft.client.resources.model.geometry.BakedQuad; import net.minecraft.client.renderer.rendertype.RenderType; import net.minecraft.client.renderer.rendertype.RenderTypes; import net.minecraft.world.item.DyeColor; +import net.minecraft.resources.Identifier; /** continúa en: * @see RenderBuffersMixin @@ -45,28 +47,22 @@ public class GlintPlus extends Module { Category.RENDER); } - public RenderType getGlint() { - int color = getGlintColor(); - if (!isEnabled() || !items.getValue()) return RenderTypes.glint(); - return GlintRenderType.glintColor.get(color); - } - - public RenderType getGlintTranslucent() { - int color = getGlintColor(); - if (!isEnabled() || !items.getValue()) return RenderTypes.glintTranslucent(); - return GlintRenderType.glintTranslucentColor.get(color); + public RenderType getGlint(RenderType vanilla, BakedQuad.MaterialInfo materialInfo) { + if (!isEnabled() || !items.getValue()) return vanilla; + return GlintRenderType.itemGlint(glintColor.getValue().getRealName(), vanilla, + materialInfo.sprite().atlasLocation()); } public RenderType getEntityGlint() { int color = getGlintColor(); - if (!isEnabled() || !items.getValue()) return RenderTypes.entityGlint(); + if (!isEnabled() || !items.getValue()) return RenderTypes.entitySolidGlint(net.minecraft.client.renderer.texture.TextureAtlas.LOCATION_BLOCKS); return GlintRenderType.entityGlintColor.get(color); } - public RenderType getArmorEntityGlint() { + public RenderType getArmorEntityGlint(Identifier armorTexture) { int color = getGlintColor(); - if (!isEnabled() || !armor.getValue()) return RenderTypes.armorEntityGlint(); - return GlintRenderType.armorEntityGlintColor.get(color); + if (!isEnabled() || !armor.getValue()) return RenderTypes.armorCutoutNoCullGlint(armorTexture); + return GlintRenderType.armorEntityGlint(glintColor.getValue().getRealName(), armorTexture); } public int getGlintColor() { diff --git a/src/main/java/me/retucio/sputnik/module/modules/render/HandView.java b/src/main/java/me/retucio/sputnik/module/modules/render/HandView.java index b5f9acb..ee41e37 100644 --- a/src/main/java/me/retucio/sputnik/module/modules/render/HandView.java +++ b/src/main/java/me/retucio/sputnik/module/modules/render/HandView.java @@ -128,9 +128,9 @@ public class HandView extends Module { } private void rotate(PoseStack matrix, Vec3 rotation) { - matrix.mulPose(Axis.XP.rotationDegrees((float) rotation.x)); - matrix.mulPose(Axis.YP.rotationDegrees((float) rotation.y)); - matrix.mulPose(Axis.ZP.rotationDegrees((float) rotation.z)); + matrix.rotate(Axis.XP.rotationDegrees((float) rotation.x)); + matrix.rotate(Axis.YP.rotationDegrees((float) rotation.y)); + matrix.rotate(Axis.ZP.rotationDegrees((float) rotation.z)); } private void scale(PoseStack matrix, Vec3 scale) { diff --git a/src/main/java/me/retucio/sputnik/module/modules/render/ItemPhysics.java b/src/main/java/me/retucio/sputnik/module/modules/render/ItemPhysics.java index 34cc6c5..0403a0a 100644 --- a/src/main/java/me/retucio/sputnik/module/modules/render/ItemPhysics.java +++ b/src/main/java/me/retucio/sputnik/module/modules/render/ItemPhysics.java @@ -50,7 +50,7 @@ public class ItemPhysics extends Module { var accessor = (ItemStackRenderStateAccessor) event.renderState.item; for (int i = 0; i < accessor.getActiveLayerCount(); i++) { ItemStackRenderState.LayerRenderState layer = accessor.getLayers()[i]; - ModelInfo info = getInfo(layer.prepareQuadList()); + ModelInfo info = getInfo(((LayerRenderStateAccessor) layer).sputnik$getQuads().all()); matrices.pushPose(); applyTransformation(matrices, ((LayerRenderStateAccessor) layer).sputnik$getTransform()); @@ -58,7 +58,7 @@ public class ItemPhysics extends Module { offsetInWater(matrices, event.itemEntity); if (info.flat) { - matrices.mulPose(Axis.XP.rotationDegrees(90)); + matrices.rotate(Axis.XP.rotationDegrees(90)); matrices.translate(0, 0, info.offsetZ); } @@ -73,7 +73,7 @@ public class ItemPhysics extends Module { float degrees = (random.nextFloat() * 2 - 1) * 90; matrices.translate(x, y, z); - matrices.mulPose(axis.rotationDegrees(degrees)); + matrices.rotate(axis.rotationDegrees(degrees)); matrices.translate(-x, -y, -z); } diff --git a/src/main/java/me/retucio/sputnik/module/modules/render/Lsd.java b/src/main/java/me/retucio/sputnik/module/modules/render/Lsd.java index 7ccdba3..f7cf80a 100644 --- a/src/main/java/me/retucio/sputnik/module/modules/render/Lsd.java +++ b/src/main/java/me/retucio/sputnik/module/modules/render/Lsd.java @@ -7,6 +7,7 @@ import com.mojang.blaze3d.resource.GraphicsResourceAllocator; import me.retucio.sputnik.Sputnik; import me.retucio.sputnik.module.Category; 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.render.PostShader; @@ -43,10 +44,11 @@ public class Lsd extends Module { 1, 0, 10, 0.1 )); - private final NumberSetting seed = sgGeneral.add(new NumberSetting( - "tono", - "desplazamiento de tono que se aplica sobre la imagen", - 0.3, 0, 1, 0.01 + private final EnumSetting color = sgGeneral.add(new EnumSetting<>( + "color", + "elige el color del efecto", + ColorMode.class, + ColorMode.RAINBOW )); private final NumberSetting speed = sgGeneral.add(new NumberSetting( @@ -71,7 +73,7 @@ public class Lsd extends Module { public void apply(RenderTarget target, GraphicsResourceAllocator pool) { SHADER.render(target, pool, b -> b .putFloat(strength.getFloatValue()) - .putFloat(seed.getFloatValue()) + .putFloat(color.getValue().hue) .putFloat(rotations.getFloatValue()) .putFloat(getTime())); } @@ -82,4 +84,28 @@ public class Lsd extends Module { double elapsed = (System.nanoTime() - startNanos) / 1_000_000_000.0; return (float) ((elapsed * speed.getValue()) % 100_000.0); } + + public enum ColorMode { + RAINBOW("gay", -1.0F), + RED("psoe", 0.0F), + ORANGE("ciudadanos", 0.08F), + YELLOW("d21", 0.16F), + GREEN("vox", 0.33F), + CYAN("eh bildu", 0.5F), + BLUE("pp", 0.66F), + PURPLE("podemos", 0.78F), + PINK("sumar", 0.92F); + + private final String name; + private final float hue; + + ColorMode(String name, float hue) { + this.name = name; this.hue = hue; + } + + @Override + public String toString() { + return name; + } + } } diff --git a/src/main/java/me/retucio/sputnik/module/modules/render/Stylish.java b/src/main/java/me/retucio/sputnik/module/modules/render/Stylish.java index bc9b7a7..0a3321f 100644 --- a/src/main/java/me/retucio/sputnik/module/modules/render/Stylish.java +++ b/src/main/java/me/retucio/sputnik/module/modules/render/Stylish.java @@ -12,7 +12,7 @@ import me.retucio.sputnik.module.setting.settings.KeySetting; import me.retucio.sputnik.module.setting.settings.NumberSetting; import net.minecraft.world.InteractionHand; import org.joml.Quaternionf; -import org.lwjgl.glfw.GLFW; +import com.mojang.blaze3d.platform.InputConstants; import java.util.ArrayList; import java.util.List; @@ -22,7 +22,7 @@ public class Stylish extends Module { private final KeySetting key = sgGeneral.add(new KeySetting( "tecla", "tecla a pulsar para hacer el truco", - GLFW.GLFW_KEY_Y + InputConstants.KEY_Y )); private final EnumSetting trick = sgGeneral.add(new EnumSetting<>( @@ -87,7 +87,7 @@ public class Stylish extends Module { @EventListener private void onKey(KeyEvent event) { if (event.getKey() != key.getValue()) return; - if (event.getAction() != GLFW.GLFW_PRESS) return; + if (event.getAction() != InputConstants.PRESS) return; if (spinning) return; long now = System.currentTimeMillis(); @@ -175,41 +175,41 @@ public class Stylish extends Module { float angleRad = (float) Math.toRadians(degrees * directionSign); switch (type) { - case SPIN -> matrices.mulPose(new Quaternionf().rotationZ(angleRad)); + case SPIN -> matrices.rotate(new Quaternionf().rotationZ(angleRad)); - case FLIP -> matrices.mulPose(new Quaternionf().rotationX(angleRad)); + case FLIP -> matrices.rotate(new Quaternionf().rotationX(angleRad)); - case ROLL -> matrices.mulPose(new Quaternionf().rotationY(angleRad)); + case ROLL -> matrices.rotate(new Quaternionf().rotationY(angleRad)); case TWIRL -> { // combina spin + flip para un giro más aparatoso - matrices.mulPose(new Quaternionf().rotationZ(angleRad)); - matrices.mulPose(new Quaternionf().rotationX(angleRad * 0.5f)); + matrices.rotate(new Quaternionf().rotationZ(angleRad)); + matrices.rotate(new Quaternionf().rotationX(angleRad * 0.5f)); } case WAVE -> { // bamboleo tipo saludo, sin vuelta completa float waveAngle = (float) Math.sin(fraction * Math.PI * spins.getIntValue()) * 25f; - matrices.mulPose(new Quaternionf().rotationZ((float) Math.toRadians(waveAngle * directionSign))); + matrices.rotate(new Quaternionf().rotationZ((float) Math.toRadians(waveAngle * directionSign))); } case POP -> { // pequeño pulso de escala, como si el ítem "respirara" float scalePulse = 1f + (float) Math.sin(fraction * Math.PI) * 0.25f; matrices.scale(scalePulse, scalePulse, scalePulse); - matrices.mulPose(new Quaternionf().rotationZ(angleRad * 0.3f)); + matrices.rotate(new Quaternionf().rotationZ(angleRad * 0.3f)); } case THROW_CATCH -> { // el ítem "sube", gira en el aire y "cae" de vuelta float height = (float) Math.sin(fraction * Math.PI) * 0.35f; matrices.translate(0f, height, 0f); - matrices.mulPose(new Quaternionf().rotationX(angleRad * 2f)); + matrices.rotate(new Quaternionf().rotationX(angleRad * 2f)); } case RANDOM -> { // no debería llegar aquí, resolveTrick lo reemplaza antes - matrices.mulPose(new Quaternionf().rotationZ(angleRad)); + matrices.rotate(new Quaternionf().rotationZ(angleRad)); } } } diff --git a/src/main/java/me/retucio/sputnik/module/modules/world/AutoMine.java b/src/main/java/me/retucio/sputnik/module/modules/world/AutoMine.java index 888e6a2..62be038 100644 --- a/src/main/java/me/retucio/sputnik/module/modules/world/AutoMine.java +++ b/src/main/java/me/retucio/sputnik/module/modules/world/AutoMine.java @@ -34,7 +34,7 @@ import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.HitResult; import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.shapes.VoxelShape; -import org.lwjgl.glfw.GLFW; +import com.mojang.blaze3d.platform.InputConstants; import java.awt.*; import java.util.ArrayDeque; @@ -204,8 +204,8 @@ public class AutoMine extends Module { private void onClick(MouseClickEvent event) { if (mc.gui.screen() != null) return; if (mc.level == null || mc.hitResult == null) return; - if (event.getAction() != GLFW.GLFW_PRESS) return; - if (event.getButton() != GLFW.GLFW_MOUSE_BUTTON_1) return; + if (event.getAction() != InputConstants.PRESS) return; + if (event.getButton() != InputConstants.MOUSE_BUTTON_LEFT) return; BlockHitResult bhr; if (mc.hitResult.getType() == HitResult.Type.BLOCK) { bhr = (BlockHitResult) mc.hitResult; diff --git a/src/main/java/me/retucio/sputnik/module/modules/world/AutoSign.java b/src/main/java/me/retucio/sputnik/module/modules/world/AutoSign.java index 32ac161..18f0fd1 100644 --- a/src/main/java/me/retucio/sputnik/module/modules/world/AutoSign.java +++ b/src/main/java/me/retucio/sputnik/module/modules/world/AutoSign.java @@ -12,6 +12,10 @@ 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; +import net.minecraft.world.level.block.entity.SignTextSlot; +import me.retucio.sputnik.util.NetworkUtil; + +import java.util.List; public class AutoSign extends Module { @@ -41,21 +45,24 @@ public class AutoSign extends Module { if (event.getScreen() instanceof AbstractSignEditScreen screen && text != null && mc != null && mc.player != null) { event.cancel(); SignBlockEntity sign = ((AbstractSignEditScreenAccessor) screen).getBlockEntity(); - fillText(sign.getBlockPos(), sign.isFacingFrontText(mc.player), text); + fillText(sign.getBlockPos(), sign.getSlotPlayerIsFacing(mc.player), text); } } @EventListener private void onSendPacket(PacketEvent.Send event) { if (event.getPacket() instanceof ServerboundSignUpdatePacket packet) { - if (text == null) text = packet.getLines().clone(); - else System.arraycopy(text, 0, packet.getLines(), 0, 4); + if (text == null) { + text = packet.lines().toArray(String[]::new); + } else { + event.cancel(); + NetworkUtil.sendPacketNoEvent(new ServerboundSignUpdatePacket( + packet.pos(), List.of(text), packet.slot())); + } } } - private void fillText(BlockPos blockPos, boolean front, String[] text) { - mc.getConnection().send(new ServerboundSignUpdatePacket( - blockPos, front, text[0], text[1], text[2], text[3] - )); + private void fillText(BlockPos blockPos, SignTextSlot slot, String[] text) { + mc.getConnection().send(new ServerboundSignUpdatePacket(blockPos, List.of(text), slot)); } -} \ No newline at end of file +} diff --git a/src/main/java/me/retucio/sputnik/module/modules/world/AutoTool.java b/src/main/java/me/retucio/sputnik/module/modules/world/AutoTool.java index 6a3fd49..c09fcfc 100644 --- a/src/main/java/me/retucio/sputnik/module/modules/world/AutoTool.java +++ b/src/main/java/me/retucio/sputnik/module/modules/world/AutoTool.java @@ -19,7 +19,7 @@ import net.minecraft.world.item.component.Tool; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.HitResult; -import org.lwjgl.glfw.GLFW; +import com.mojang.blaze3d.platform.InputConstants; import java.util.HashMap; import java.util.List; @@ -96,7 +96,7 @@ public class AutoTool extends Module { if (mc.gui.screen() != null) return; if (mode.is(AutoToolMode.ON_TICK) && mc.options.keyAttack.isDown()) { - handle(KeyUtil.getKey(mc.options.keyAttack), GLFW.GLFW_PRESS); + handle(KeyUtil.getKey(mc.options.keyAttack), InputConstants.PRESS); } if (startedMining && delaySetting.getIntValue() > 0) { @@ -132,9 +132,9 @@ public class AutoTool extends Module { if (mc.player == null) return; if (key != KeyUtil.getKey(mc.options.keyAttack)) return; - if (action == GLFW.GLFW_PRESS) { + if (action == InputConstants.PRESS) { onStartMining(); - } else if (action == GLFW.GLFW_RELEASE) { + } else if (action == InputConstants.RELEASE) { onFinishMining(); } } diff --git a/src/main/java/me/retucio/sputnik/module/modules/world/BlockInfo.java b/src/main/java/me/retucio/sputnik/module/modules/world/BlockInfo.java index 7f43478..023e288 100644 --- a/src/main/java/me/retucio/sputnik/module/modules/world/BlockInfo.java +++ b/src/main/java/me/retucio/sputnik/module/modules/world/BlockInfo.java @@ -20,7 +20,7 @@ import net.minecraft.world.level.block.state.properties.Property; import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.HitResult; import net.minecraft.world.phys.Vec3; -import org.lwjgl.glfw.GLFW; +import com.mojang.blaze3d.platform.InputConstants; import java.util.Collection; import java.util.LinkedHashMap; import java.util.Map; @@ -31,7 +31,7 @@ public class BlockInfo extends Module { private final KeySetting key = sgGeneral.add(new KeySetting( "tecla", "tecla a pulsar para obtener la info.", - GLFW.GLFW_KEY_CAPS_LOCK + InputConstants.KEY_CAPSLOCK )); private final EnumSetting copy = sgGeneral.add(new EnumSetting<>( @@ -56,7 +56,7 @@ public class BlockInfo extends Module { @EventListener private void onKey(KeyEvent event) { if (mc.player == null || mc.level == null) return; - if (event.getKey() != key.getValue() || event.getAction() != GLFW.GLFW_PRESS) return; + if (event.getKey() != key.getValue() || event.getAction() != InputConstants.PRESS) return; HitResult result = mc.player.pick( mc.player.blockInteractionRange(), diff --git a/src/main/java/me/retucio/sputnik/module/modules/world/ColoredSigns.java b/src/main/java/me/retucio/sputnik/module/modules/world/ColoredSigns.java index 5d201eb..10994c9 100644 --- a/src/main/java/me/retucio/sputnik/module/modules/world/ColoredSigns.java +++ b/src/main/java/me/retucio/sputnik/module/modules/world/ColoredSigns.java @@ -6,6 +6,9 @@ import me.retucio.sputnik.module.Category; import me.retucio.sputnik.module.Module; import me.retucio.sputnik.module.setting.settings.StringSetting; import net.minecraft.network.protocol.game.ServerboundSignUpdatePacket; +import me.retucio.sputnik.util.NetworkUtil; + +import java.util.ArrayList; public class ColoredSigns extends Module { @@ -26,9 +29,11 @@ public class ColoredSigns extends Module { @EventListener private void onSendPacket(PacketEvent.Send event) { if (event.getPacket() instanceof ServerboundSignUpdatePacket packet) { - for (int i = 0; i < 4; i++) { - packet.getLines()[i] = packet.getLines()[i].replace(symbol.getValue(), "\247" + "\247a"); - } + event.cancel(); + NetworkUtil.sendPacketNoEvent(new ServerboundSignUpdatePacket( + packet.pos(), packet.lines().stream() + .map(line -> line.replace(symbol.getValue(), "\247" + "\247a")) + .toList(), packet.slot())); } } } diff --git a/src/main/java/me/retucio/sputnik/module/modules/world/Racist.java b/src/main/java/me/retucio/sputnik/module/modules/world/Racist.java index 0c27567..320bcde 100644 --- a/src/main/java/me/retucio/sputnik/module/modules/world/Racist.java +++ b/src/main/java/me/retucio/sputnik/module/modules/world/Racist.java @@ -5,7 +5,7 @@ import me.retucio.sputnik.module.Module; import me.retucio.sputnik.util.EntityUtil; import me.retucio.sputnik.util.RotationUtil; import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.monster.EnderMan; +import net.minecraft.world.entity.monster.Enderman; import java.util.ArrayList; import java.util.List; @@ -14,7 +14,7 @@ import java.util.List; public class Racist extends Module { private int lookTimer; - private final List lookedEndermen = new ArrayList<>(); + private final List lookedEndermen = new ArrayList<>(); public Racist() { super("racismo", @@ -33,7 +33,7 @@ public class Racist extends Module { if (mc.level == null || mc.player == null) return; for (Entity entity : mc.level.getEntities().getAll()) { - if (!(entity instanceof EnderMan enderman)) continue; + if (!(entity instanceof Enderman enderman)) continue; if (shouldLookAt(enderman)) { lookAtEnderman(enderman); @@ -47,12 +47,12 @@ public class Racist extends Module { lookTimer++; } - private boolean shouldLookAt(EnderMan enderman) { + private boolean shouldLookAt(Enderman enderman) { return !(lookedEndermen.contains(enderman)) && lookTimer >= 10 && EntityUtil.hasLineOfSight(mc.player, enderman); } - private void lookAtEnderman(EnderMan enderman) { + private void lookAtEnderman(Enderman enderman) { RotationUtil.lookAt(RotationUtil.LOW, enderman, EntityUtil.Target.HEAD, 0, RotationUtil.Mode.CLIENT); } } diff --git a/src/main/java/me/retucio/sputnik/module/setting/settings/KeySetting.java b/src/main/java/me/retucio/sputnik/module/setting/settings/KeySetting.java index bd101ae..de6cb6e 100644 --- a/src/main/java/me/retucio/sputnik/module/setting/settings/KeySetting.java +++ b/src/main/java/me/retucio/sputnik/module/setting/settings/KeySetting.java @@ -1,5 +1,6 @@ package me.retucio.sputnik.module.setting.settings; +import com.mojang.blaze3d.platform.InputConstants; import me.retucio.sputnik.config.ConfigManager; import me.retucio.sputnik.module.Module; import me.retucio.sputnik.module.ModuleManager; @@ -8,7 +9,7 @@ import me.retucio.sputnik.ui.widgets.panels.settings.ClientSettingsPanel; import me.retucio.sputnik.util.ChatUtil; import me.retucio.sputnik.util.KeyUtil; import net.minecraft.network.chat.Component; -import org.lwjgl.glfw.GLFW; + public class KeySetting extends Setting { @@ -22,32 +23,19 @@ public class KeySetting extends Setting { public void setValue(Integer value) { if (this.value.equals(value)) return; - if (value == GLFW.GLFW_KEY_ESCAPE) { - this.value = GLFW.GLFW_KEY_UNKNOWN; // asignar la tecla ESC a deshabilitar la tecla + if (value == InputConstants.KEY_ESCAPE) { + this.value = InputConstants.UNKNOWN.getValue(); // asignar la tecla ESC a deshabilitar la tecla fireUpdateEvent(); - // 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; } - // 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. - // - // mientras se carga la config. no se toca nada: son las teclas que el usuario ya - // tenía, y quitárselas aquí se las machacaba (y encima guardaba el -1). - // - // clientSettings puede ser null: el módulo de ajustes se construye en el - // inicializador estático de ClientSettingsPanel, y su propia tecla por defecto pasa - // por aquí antes de que el campo esté asignado - if (ModuleManager.INSTANCE != null - && ClientSettingsPanel.clientSettings != null - && !ConfigManager.INSTANCE.isApplying() - && !ClientSettingsPanel.clientSettings.multipleKeybinds.getValue()) { + if (ModuleManager.INSTANCE != null && !ConfigManager.INSTANCE.isApplying() + && !ClientSettingsPanel.clientSettings.multipleKeybinds.getValue() + ) { for (Module module : ModuleManager.INSTANCE.getModules()) - if (module.getKey() == value && value != -1) { - module.setKey(-1); + if (module.getKey() == value && value != InputConstants.UNKNOWN.getValue()) { + module.setKey(InputConstants.UNKNOWN.getValue()); ChatUtil.info(Component.translatable("sputnik.setting.key.reset", module.getDisplayName())); } } diff --git a/src/main/java/me/retucio/sputnik/ui/hud/HudEditor.java b/src/main/java/me/retucio/sputnik/ui/hud/HudEditor.java index 14661f2..89f8839 100644 --- a/src/main/java/me/retucio/sputnik/ui/hud/HudEditor.java +++ b/src/main/java/me/retucio/sputnik/ui/hud/HudEditor.java @@ -9,7 +9,7 @@ import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiGraphicsExtractor; import net.minecraft.network.chat.Component; import org.jetbrains.annotations.Nullable; -import org.lwjgl.glfw.GLFW; +import com.mojang.blaze3d.platform.InputConstants; import java.util.ArrayList; import java.util.List; @@ -120,11 +120,11 @@ public class HudEditor { int offset = hud.arrowOffset.getIntValue(); switch (key) { - case GLFW.GLFW_KEY_UP -> selected.setY(Math.max(1, selected.getY() - offset)); - case GLFW.GLFW_KEY_DOWN -> selected.setY(Math.min( + case InputConstants.KEY_UP -> selected.setY(Math.max(1, selected.getY() - offset)); + case InputConstants.KEY_DOWN -> selected.setY(Math.min( mc.getWindow().getGuiScaledHeight() - selected.getH() + 1, selected.getY() + offset)); - case GLFW.GLFW_KEY_LEFT -> selected.setX(Math.max(1, selected.getX() - offset)); - case GLFW.GLFW_KEY_RIGHT -> selected.setX(Math.min( + case InputConstants.KEY_LEFT -> selected.setX(Math.max(1, selected.getX() - offset)); + case InputConstants.KEY_RIGHT -> selected.setX(Math.min( mc.getWindow().getGuiScaledWidth() - selected.getW() + 1, selected.getX() + offset)); } } diff --git a/src/main/java/me/retucio/sputnik/ui/hud/HudEditorScreen.java b/src/main/java/me/retucio/sputnik/ui/hud/HudEditorScreen.java index 7835456..8b6b41a 100644 --- a/src/main/java/me/retucio/sputnik/ui/hud/HudEditorScreen.java +++ b/src/main/java/me/retucio/sputnik/ui/hud/HudEditorScreen.java @@ -11,7 +11,7 @@ import net.minecraft.client.gui.screens.Screen; import net.minecraft.client.input.MouseButtonEvent; import net.minecraft.network.chat.Component; import org.jspecify.annotations.NonNull; -import org.lwjgl.glfw.GLFW; +import com.mojang.blaze3d.platform.InputConstants; public class HudEditorScreen extends Screen { @@ -61,10 +61,10 @@ public class HudEditorScreen extends Screen { @EventListener public void onKey(KeyEvent event) { if (mc.gui.screen() != INSTANCE) return; - if (event.getAction() == GLFW.GLFW_RELEASE) return; + if (event.getAction() == InputConstants.RELEASE) return; event.cancel(); - if (event.getKey() == GLFW.GLFW_KEY_ESCAPE) { + if (event.getKey() == InputConstants.KEY_ESCAPE) { HudEditor.INSTANCE.saveAll(); HudEditor.INSTANCE.unselect(); mc.gui.setScreen(null); diff --git a/src/main/java/me/retucio/sputnik/ui/screen/ClickGui.java b/src/main/java/me/retucio/sputnik/ui/screen/ClickGui.java index 6c96285..e0ed504 100644 --- a/src/main/java/me/retucio/sputnik/ui/screen/ClickGui.java +++ b/src/main/java/me/retucio/sputnik/ui/screen/ClickGui.java @@ -42,7 +42,7 @@ import net.minecraft.network.chat.Component; import org.jetbrains.annotations.Nullable; import org.jspecify.annotations.NonNull; -import org.lwjgl.glfw.GLFW; +import com.mojang.blaze3d.platform.InputConstants; import java.util.ArrayList; import java.util.List; @@ -94,6 +94,7 @@ public class ClickGui extends Screen { public void extractRenderState(@NonNull GuiGraphicsExtractor gui, int mouseX, int mouseY, float delta) { switch (tabBar.getSelected()) { case MODULES -> renderModules(gui, mouseX, mouseY, delta); + case CLIENT_SETTINGS -> renderClientSettings(gui, mouseX, mouseY, delta); case HUD -> renderHud(gui, mouseX, mouseY); case PROFILES -> profilesTab.render(gui, mouseX, mouseY, delta); case MACROS -> macrosTab.render(gui, mouseX, mouseY, delta); @@ -113,6 +114,11 @@ public class ClickGui extends Screen { HudEditor.INSTANCE.render(gui, mouseX, mouseY); } + private void renderClientSettings(GuiGraphicsExtractor gui, int mouseX, int mouseY, float delta) { + clientSettingsPanel.render(gui, mouseX, mouseY, delta); + clientSettingsPanel.drawTooltips(gui, mouseX, mouseY); + } + private void renderModules(@NonNull GuiGraphicsExtractor gui, int mouseX, int mouseY, float delta) { scrollBar.setWindowHeight(mc.getWindow().getGuiScaledHeight()); scrollBar.setContentHeight(calculateContentHeight()); @@ -149,9 +155,6 @@ public class ClickGui extends Screen { sp.drawTooltips(gui, mouseX, mouseY); } - clientSettingsPanel.render(gui, mouseX, mouseY, delta); - clientSettingsPanel.updatePosition(mouseX, mouseY); - filterSearchResults(); renderBottomGradient(gui, scrollOffset); @@ -188,10 +191,6 @@ public class ClickGui extends Screen { bottom = Math.max(bottom, sp.getY() + sp.getH() + sp.getTotalHeight()); } - int clientBottom = clientSettingsPanel.getY() + clientSettingsPanel.getH() - + (clientSettingsPanel.isExtended() ? clientSettingsPanel.getTotalHeight() : 0); - bottom = Math.max(bottom, clientBottom); - return bottom + 20; // padding } @@ -226,8 +225,7 @@ public class ClickGui extends Screen { if (rectsOverlap(x, y, w, h, sp.getX(), sp.getY(), sp.getW(), spHeight)) return true; } - int clientHeight = clientSettingsPanel.getH() + (clientSettingsPanel.isExtended() ? clientSettingsPanel.getTotalHeight() : 0); - return rectsOverlap(x, y, w, h, clientSettingsPanel.getX(), clientSettingsPanel.getY(), clientSettingsPanel.getW(), clientHeight); + return false; } private boolean rectsOverlap(int ax, int ay, int aw, int ah, int bx, int by, int bw, int bh) { @@ -239,24 +237,29 @@ public class ClickGui extends Screen { public boolean mouseClicked(MouseButtonEvent click, boolean doubled) { int x = (int) click.x(); int y = (int) click.y(); + int button = KeyUtil.toLegacyMouseButton(click.button()); - if (tabBar.handleClick(x, y, click.button())) return super.mouseClicked(click, doubled); + if (tabBar.handleClick(x, y, button)) return super.mouseClicked(click, doubled); switch (tabBar.getSelected()) { case MODULES -> { - miscWidgets.forEach(w -> w.mouseClicked(x, y, click.button())); - clientSettingsPanel.mouseClicked(x, y, click.button()); + miscWidgets.forEach(w -> w.mouseClicked(x, y, button)); for (ModulePanel mp : modulePanels.reversed()) { - mp.mouseClicked(x, y, click.button()); + mp.mouseClicked(x, y, button); } for (SettingsPanel sp : new ArrayList<>(settingsPanels)) { - sp.mouseClicked(x, y, click.button()); + sp.mouseClicked(x, y, button); } } - case HUD -> HudEditor.INSTANCE.mouseClicked(x, y, click.button()); - case PROFILES -> profilesTab.mouseClicked(x, y, click.button()); - case MACROS -> macrosTab.mouseClicked(x, y, click.button()); - case FRIENDS -> friendsTab.mouseClicked(x, y, click.button()); + case CLIENT_SETTINGS -> { + if (!clientSettingsPanel.mouseClickedGroupTab(x, y, button)) { + clientSettingsPanel.mouseClicked(x, y, button); + } + } + case HUD -> HudEditor.INSTANCE.mouseClicked(x, y, button); + case PROFILES -> profilesTab.mouseClicked(x, y, button); + case MACROS -> macrosTab.mouseClicked(x, y, button); + case FRIENDS -> friendsTab.mouseClicked(x, y, button); } return super.mouseClicked(click, doubled); @@ -266,24 +269,29 @@ public class ClickGui extends Screen { public boolean mouseReleased(MouseButtonEvent click) { int x = (int) click.x(); int y = (int) click.y(); + int button = KeyUtil.toLegacyMouseButton(click.button()); if (tabBar.getSelected() == Tab.HUD) { - HudEditor.INSTANCE.mouseReleased(click.button()); + HudEditor.INSTANCE.mouseReleased(button); + return super.mouseReleased(click); + } + + if (tabBar.getSelected() == Tab.CLIENT_SETTINGS) { + clientSettingsPanel.mouseReleased(x, y, button); return super.mouseReleased(click); } if (tabBar.getSelected() != Tab.MODULES) return super.mouseReleased(click); miscWidgets.forEach(w -> w.mouseReleased( - x, y, click.button())); + x, y, button)); // registrar cuándo se suelta el clic, en cada panel respectivamente - clientSettingsPanel.mouseReleased(x, y, click.button()); for (ModulePanel mp : modulePanels.reversed()) { - mp.mouseReleased(x, y, click.button()); + mp.mouseReleased(x, y, button); } for (SettingsPanel sp : new ArrayList<>(settingsPanels)) { - sp.mouseReleased(x, y, click.button()); + sp.mouseReleased(x, y, button); } return super.mouseReleased(click); @@ -291,8 +299,14 @@ public class ClickGui extends Screen { @Override public boolean mouseDragged(@NonNull MouseButtonEvent click, double deltaX, double deltaY) { + int button = KeyUtil.toLegacyMouseButton(click.button()); if (tabBar.getSelected() == Tab.HUD) { - HudEditor.INSTANCE.mouseDragged((int) click.x(), (int) click.y(), click.button()); + HudEditor.INSTANCE.mouseDragged((int) click.x(), (int) click.y(), button); + return super.mouseDragged(click, deltaX, deltaY); + } + + if (tabBar.getSelected() == Tab.CLIENT_SETTINGS) { + clientSettingsPanel.mouseDragged((int) click.x(), (int) click.y()); return super.mouseDragged(click, deltaX, deltaY); } @@ -316,8 +330,9 @@ public class ClickGui extends Screen { switch (tabBar.getSelected()) { case MODULES -> searchBar.onKey(event.getKey(), event.getAction()); + case CLIENT_SETTINGS -> clientSettingsPanel.onKey(event.getKey(), event.getAction()); case HUD -> { - if (event.getAction() != GLFW.GLFW_RELEASE) HudEditor.INSTANCE.onKey(event.getKey()); + if (event.getAction() != InputConstants.RELEASE) HudEditor.INSTANCE.onKey(event.getKey()); } case PROFILES -> profilesTab.onKey(event.getKey(), event.getAction()); case MACROS -> macrosTab.onKey(event.getKey(), event.getAction()); @@ -335,7 +350,7 @@ public class ClickGui extends Screen { @EventListener public void onMouseMiddleButton(MouseClickEvent event) { // mover todos los paneles a un punto visible al presionar shift + la rueda del ratón - if (Sputnik.mc.gui.screen() != this || event.getButton() != 2 || !KeyUtil.isKeyDown(GLFW.GLFW_KEY_LEFT_SHIFT)) return; + if (Sputnik.mc.gui.screen() != this || event.getButton() != 2 || !KeyUtil.isKeyDown(InputConstants.KEY_LSHIFT)) return; int h = Sputnik.mc.getWindow().getGuiScaledHeight(); int minY = Math.min(modulePanels.stream().mapToInt(Panel::getY).min().getAsInt(), settingsPanels.stream().mapToInt(Panel::getY).min().getAsInt()); diff --git a/src/main/java/me/retucio/sputnik/ui/screen/PreviewScreen.java b/src/main/java/me/retucio/sputnik/ui/screen/PreviewScreen.java index 456c726..78dea98 100644 --- a/src/main/java/me/retucio/sputnik/ui/screen/PreviewScreen.java +++ b/src/main/java/me/retucio/sputnik/ui/screen/PreviewScreen.java @@ -40,7 +40,7 @@ public class PreviewScreen extends Screen { super(Component.translatable("sputnik.ui.preview.shulker")); this.color = ShulkerPeek.SHULKER_COLORS.get(shulker.getItem()); this.title = shulker.getHoverName(); - this.inventory = shulker.get(DataComponents.CONTAINER).allItemsCopyStream().toList(); + this.inventory = shulker.get(DataComponents.CONTAINER).nonEmptyItemCopyStream().toList(); this.parent = parent; this.type = PreviewType.SHULKER; } diff --git a/src/main/java/me/retucio/sputnik/ui/screen/Tab.java b/src/main/java/me/retucio/sputnik/ui/screen/Tab.java index dfa78d3..997cde5 100644 --- a/src/main/java/me/retucio/sputnik/ui/screen/Tab.java +++ b/src/main/java/me/retucio/sputnik/ui/screen/Tab.java @@ -6,6 +6,7 @@ import me.retucio.sputnik.util.I18nUtil; public enum Tab { MODULES("módulos"), + CLIENT_SETTINGS("ajustes"), HUD("hud"), PROFILES("perfiles"), MACROS("macros"), diff --git a/src/main/java/me/retucio/sputnik/ui/screen/tabs/MacrosTab.java b/src/main/java/me/retucio/sputnik/ui/screen/tabs/MacrosTab.java index d8c3b80..a888a78 100644 --- a/src/main/java/me/retucio/sputnik/ui/screen/tabs/MacrosTab.java +++ b/src/main/java/me/retucio/sputnik/ui/screen/tabs/MacrosTab.java @@ -10,7 +10,7 @@ import net.minecraft.client.gui.GuiGraphicsExtractor; import net.minecraft.network.chat.Component; import net.minecraft.util.FormattedCharSequence; import org.jetbrains.annotations.Nullable; -import org.lwjgl.glfw.GLFW; +import com.mojang.blaze3d.platform.InputConstants; import java.util.ArrayList; import java.util.List; @@ -27,7 +27,7 @@ public class MacrosTab { private static final int TOP = 46; private final TextFieldWidget nameField = new TextFieldWidget( - () -> "sputnik.ui.macros.nameplaceholder", 0, 0, LIST_WIDTH - 24, ROW_HEIGHT) + () -> "sputnik.ui.macros.nameplaceholder", 0, 0, LIST_WIDTH - 44, ROW_HEIGHT) .maxLength(32) .onSubmit(this::create); @@ -52,10 +52,8 @@ public class MacrosTab { nameField.setY(TOP); nameField.render(gui, mouseX, mouseY, delta); - int addX = listX + LIST_WIDTH - 20; - gui.fill(addX, TOP, addX + 20, TOP + ROW_HEIGHT, - isAddHovered(mouseX, mouseY) ? Colors.buttonColor.brighter().getRGB() : Colors.buttonColor.getRGB()); - gui.text(mc.font, "+", addX + 8, TOP + ROW_HEIGHT / 2 - mc.font.lineHeight / 2, -1, true); + drawAddButton(gui, listX + LIST_WIDTH - 40, "C", isAddChatHovered(mouseX, mouseY)); + drawAddButton(gui, listX + LIST_WIDTH - 20, "K", isAddKeybindHovered(mouseX, mouseY)); drawHint(gui, Component.translatable("sputnik.ui.macros.instructions"), listX, LIST_WIDTH); @@ -85,12 +83,13 @@ public class MacrosTab { renderLines(gui, mouseX, mouseY, delta); } + // el panel de líneas solo aplica a macros de chat; las Keybind no tienen líneas que editar private void renderLines(GuiGraphicsExtractor gui, int mouseX, int mouseY, float delta) { - if (selected == null) return; + if (!(selected instanceof Macro.Chat chat)) return; int x = linesX(); - gui.text(mc.font, selected.getName(), x, TOP - 14, Colors.mainColor.getRGB(), true); + gui.text(mc.font, chat.getName(), x, TOP - 14, Colors.mainColor.getRGB(), true); lineField.setX(x); lineField.setY(TOP); @@ -104,7 +103,7 @@ public class MacrosTab { drawHint(gui, Component.translatable("sputnik.ui.macros.lineinstructions"), x, LINES_WIDTH); int rowY = listTop(); - for (String line : selected.getLines()) { + for (String line : chat.getLines()) { boolean hovered = isHovered(x, rowY, LINES_WIDTH, mouseX, mouseY); gui.fill(x, rowY, x + LINES_WIDTH, rowY + ROW_HEIGHT, hovered ? Colors.buttonColor.brighter().getRGB() : Colors.buttonColor.getRGB()); @@ -124,7 +123,13 @@ public class MacrosTab { return; } - if (button == 0 && selected != null && isAddLineHovered(mouseX, mouseY)) { + if (button == 0 && isAddKeybindHovered(mouseX, mouseY)) { + createKeybind(nameField.getText().trim()); + nameField.clear(); + return; + } + + if (button == 0 && selected instanceof Macro.Chat && isAddLineHovered(mouseX, mouseY)) { addLine(lineField.getText().trim()); lineField.clear(); return; @@ -139,13 +144,13 @@ public class MacrosTab { rowY += ROW_HEIGHT + 2; } - if (selected == null) return; + if (!(selected instanceof Macro.Chat chat)) return; rowY = listTop(); - for (String line : new ArrayList<>(selected.getLines())) { + for (String line : new ArrayList<>(chat.getLines())) { if (isHovered(linesX(), rowY, LINES_WIDTH, mouseX, mouseY)) { if (button == 1 && KeyUtil.isShiftDown()) { - selected.getLines().remove(line); + chat.getLines().remove(line); MacroManager.INSTANCE.save(); } return; @@ -172,19 +177,25 @@ public class MacrosTab { private void create(String name) { if (name.isEmpty()) return; - Macro macro = new Macro(name); + Macro macro = new Macro.Chat(name); + if (MacroManager.INSTANCE.add(macro)) selected = macro; + } + + private void createKeybind(String name) { + if (name.isEmpty()) return; + Macro macro = new Macro.Keybind(name); if (MacroManager.INSTANCE.add(macro)) selected = macro; } private void addLine(String line) { - if (selected == null || line.isEmpty()) return; - selected.getLines().add(line); + if (!(selected instanceof Macro.Chat chat) || line.isEmpty()) return; + chat.getLines().add(line); MacroManager.INSTANCE.save(); } public void onKey(int key, int action) { - if (listening != null && action != GLFW.GLFW_RELEASE) { - listening.setKey(key == GLFW.GLFW_KEY_ESCAPE ? GLFW.GLFW_KEY_UNKNOWN : key); + if (listening != null && action != InputConstants.RELEASE) { + listening.setKey(key == InputConstants.KEY_ESCAPE ? InputConstants.UNKNOWN.getValue() : key); listening = null; MacroManager.INSTANCE.save(); return; @@ -236,10 +247,26 @@ public class MacrosTab { } private static boolean isAddHovered(int mouseX, int mouseY) { + return isAddChatHovered(mouseX, mouseY); + } + + private static boolean isAddChatHovered(int mouseX, int mouseY) { + int addX = listX() + LIST_WIDTH - 40; + return mouseX >= addX && mouseX < addX + 20 && mouseY >= TOP && mouseY < TOP + ROW_HEIGHT; + } + + private static boolean isAddKeybindHovered(int mouseX, int mouseY) { int addX = listX() + LIST_WIDTH - 20; return mouseX >= addX && mouseX < addX + 20 && mouseY >= TOP && mouseY < TOP + ROW_HEIGHT; } + private static void drawAddButton(GuiGraphicsExtractor gui, int x, String label, boolean hovered) { + gui.fill(x, TOP, x + 20, TOP + ROW_HEIGHT, + hovered ? Colors.buttonColor.brighter().getRGB() : Colors.buttonColor.getRGB()); + gui.text(mc.font, label, x + (20 - mc.font.width(label)) / 2, + TOP + ROW_HEIGHT / 2 - mc.font.lineHeight / 2, -1, true); + } + private static boolean isAddLineHovered(int mouseX, int mouseY) { int addX = linesX() + LINES_WIDTH - 20; return mouseX >= addX && mouseX < addX + 20 && mouseY >= TOP && mouseY < TOP + ROW_HEIGHT; diff --git a/src/main/java/me/retucio/sputnik/ui/widgets/buttons/settings/BindButton.java b/src/main/java/me/retucio/sputnik/ui/widgets/buttons/settings/BindButton.java index 606bf51..d2a9988 100644 --- a/src/main/java/me/retucio/sputnik/ui/widgets/buttons/settings/BindButton.java +++ b/src/main/java/me/retucio/sputnik/ui/widgets/buttons/settings/BindButton.java @@ -12,9 +12,11 @@ import net.minecraft.ChatFormatting; import net.minecraft.client.KeyMapping; import net.minecraft.client.gui.GuiGraphicsExtractor; import net.minecraft.client.input.KeyEvent; +import net.minecraft.client.input.MouseButtonEvent; +import net.minecraft.client.input.MouseButtonInfo; import net.minecraft.client.resources.language.I18n; import net.minecraft.network.chat.Component; -import org.lwjgl.glfw.GLFW; +import com.mojang.blaze3d.platform.InputConstants; import java.util.ArrayList; import java.util.List; @@ -49,12 +51,13 @@ public class BindButton extends SettingButton { if (hovered && ClickGui.INSTANCE.trySelect(this)) { if (listening) { + int key = KeyUtil.fromLegacyGlfwKey(button); List keys = new ArrayList<>(List.of(mc.options.keyMappings)); keys.removeAll(List.of(mc.options.debugKeys)); boolean allowMultiple = ClientSettingsPanel.clientSettings.multipleKeybinds.getValue(); for (KeyMapping bind : keys) { - if (bind.matches(new KeyEvent(button, 0, 0))) { + if (bind.matches(new KeyEvent(key, 0, 0))) { if (!allowMultiple) { ChatUtil.warn(Component.translatable("sputnik.commands.bind.keytaken", ChatFormatting.GREEN + "\"" + I18n.get(bind.getName()) + "\"")); @@ -64,7 +67,7 @@ public class BindButton extends SettingButton { } } - setting.setValue(button); + setting.setValue(key); listening = false; } else { if (button == 0) { @@ -81,10 +84,10 @@ public class BindButton extends SettingButton { } public void onKey(int key, int action) { - if (!listening || action != GLFW.GLFW_PRESS) return; + if (!listening || action != InputConstants.PRESS) return; - if (key == GLFW.GLFW_KEY_ESCAPE) { - setting.setValue(GLFW.GLFW_KEY_UNKNOWN); + if (key == InputConstants.KEY_ESCAPE) { + setting.setValue(InputConstants.UNKNOWN.getValue()); } else { List keys = new ArrayList<>(List.of(mc.options.keyMappings)); keys.removeAll(List.of(mc.options.debugKeys)); @@ -106,7 +109,28 @@ public class BindButton extends SettingButton { listening = false; } + public void onMouse(int button, int action) { + if (!listening || action != InputConstants.PRESS) return; + + List keys = new ArrayList<>(List.of(mc.options.keyMappings)); + keys.removeAll(List.of(mc.options.debugKeys)); + boolean allowMultiple = ClientSettingsPanel.clientSettings.multipleKeybinds.getValue(); + MouseButtonEvent mouseEvent = new MouseButtonEvent(0, 0, new MouseButtonInfo(button, 0)); + + for (KeyMapping bind : keys) { + if (bind.matchesMouse(mouseEvent) && !allowMultiple) { + ChatUtil.warn(Component.translatable("sputnik.commands.bind.keytaken", + ChatFormatting.GREEN + "\"" + I18n.get(bind.getName()) + "\"")); + listening = false; + return; + } + } + + setting.setValue(KeyUtil.encodeMouseButton(button)); + listening = false; + } + public boolean isFocused() { return listening; } -} \ No newline at end of file +} diff --git a/src/main/java/me/retucio/sputnik/ui/widgets/buttons/settings/FileButton.java b/src/main/java/me/retucio/sputnik/ui/widgets/buttons/settings/FileButton.java index 4672147..6832133 100644 --- a/src/main/java/me/retucio/sputnik/ui/widgets/buttons/settings/FileButton.java +++ b/src/main/java/me/retucio/sputnik/ui/widgets/buttons/settings/FileButton.java @@ -13,8 +13,9 @@ import net.minecraft.client.resources.language.I18n; import org.jetbrains.annotations.Nullable; -import org.lwjgl.glfw.GLFW; -import org.lwjgl.util.tinyfd.TinyFileDialogs; +import com.mojang.blaze3d.platform.InputConstants; +import java.awt.FileDialog; +import java.awt.Frame; import java.awt.*; import java.nio.file.Path; @@ -75,23 +76,23 @@ public class FileButton extends SettingButton { @Override public void onKey(int key, int action) { - if (!typing || action == GLFW.GLFW_RELEASE) return; + if (!typing || action == InputConstants.RELEASE) return; // pegar con ctrl + v - if (key == GLFW.GLFW_KEY_V && KeyUtil.isKeyDown(GLFW.GLFW_KEY_LEFT_CONTROL)) { + if (key == InputConstants.KEY_V && KeyUtil.isKeyDown(InputConstants.KEY_LCONTROL)) { paste(); return; } switch (key) { // casos para teclas especiales como enter, escape o borrar - case GLFW.GLFW_KEY_ENTER -> { + case InputConstants.KEY_RETURN -> { setting.setValue(buffer.toString()); typing = false; - } case GLFW.GLFW_KEY_BACKSPACE -> { + } case InputConstants.KEY_BACKSPACE -> { onBackspace(); - } case GLFW.GLFW_KEY_ESCAPE -> { + } case InputConstants.KEY_ESCAPE -> { typing = false; - } case GLFW.GLFW_KEY_SPACE -> { + } case InputConstants.KEY_SPACE -> { charTyped(' '); } default -> { String c = KeyUtil.getKeyName(key); @@ -139,14 +140,14 @@ public class FileButton extends SettingButton { @Nullable public Path pickFile() { - String result = TinyFileDialogs.tinyfd_openFileDialog( - I18n.get("sputnik.filesetting.choose"), - setting.isDirectory() - ? setting.getValue() - : setting.getPath().getParent().toString(), - null, - I18n.get("sputnik.filesetting.supportedfiles"), - false); - return result == null ? null : Path.of(result); + FileDialog dialog = new FileDialog((Frame) null, + I18n.get("sputnik.filesetting.choose"), FileDialog.LOAD); + String initial = setting.isDirectory() + ? setting.getValue() + : setting.getPath().getParent().toString(); + dialog.setDirectory(initial); + dialog.setVisible(true); + String file = dialog.getFile(); + return file == null ? null : Path.of(dialog.getDirectory(), file); } } diff --git a/src/main/java/me/retucio/sputnik/ui/widgets/buttons/settings/SliderButton.java b/src/main/java/me/retucio/sputnik/ui/widgets/buttons/settings/SliderButton.java index 84c777c..628ad53 100644 --- a/src/main/java/me/retucio/sputnik/ui/widgets/buttons/settings/SliderButton.java +++ b/src/main/java/me/retucio/sputnik/ui/widgets/buttons/settings/SliderButton.java @@ -8,7 +8,7 @@ import me.retucio.sputnik.ui.widgets.panels.settings.ClientSettingsPanel; import me.retucio.sputnik.util.Colors; import me.retucio.sputnik.util.KeyUtil; import net.minecraft.client.gui.GuiGraphicsExtractor; -import org.lwjgl.glfw.GLFW; +import com.mojang.blaze3d.platform.InputConstants; import java.awt.*; import java.text.DecimalFormat; @@ -60,7 +60,7 @@ public class SliderButton extends SettingButton { public void onKey(int key, int action) { // de no ser de esto, si se cierra la interfaz sin haber soltado el ratón mientras se arrastraba el valor, // al reabrir la interfaz se seguía arrastrando, aun habiendo soltado ya el clic - if (key == GLFW.GLFW_KEY_ESCAPE + if (key == InputConstants.KEY_ESCAPE || key == ClientSettingsPanel.clientSettings.getKey()) dragging = false; } diff --git a/src/main/java/me/retucio/sputnik/ui/widgets/buttons/settings/TextButton.java b/src/main/java/me/retucio/sputnik/ui/widgets/buttons/settings/TextButton.java index 8a8efb5..b162946 100644 --- a/src/main/java/me/retucio/sputnik/ui/widgets/buttons/settings/TextButton.java +++ b/src/main/java/me/retucio/sputnik/ui/widgets/buttons/settings/TextButton.java @@ -8,7 +8,7 @@ import me.retucio.sputnik.util.Colors; import me.retucio.sputnik.util.KeyUtil; import me.retucio.sputnik.util.MiscUtil; import net.minecraft.client.gui.GuiGraphicsExtractor; -import org.lwjgl.glfw.GLFW; +import com.mojang.blaze3d.platform.InputConstants; // botón para los ajustes que requieran introducir texto @@ -55,23 +55,23 @@ public class TextButton extends SettingButton { @Override public void onKey(int key, int action) { - if (!typing || action == GLFW.GLFW_RELEASE) return; + if (!typing || action == InputConstants.RELEASE) return; // pegar con ctrl + v - if (key == GLFW.GLFW_KEY_V && KeyUtil.isKeyDown(GLFW.GLFW_KEY_LEFT_CONTROL)) { + if (key == InputConstants.KEY_V && KeyUtil.isKeyDown(InputConstants.KEY_LCONTROL)) { paste(); return; } switch (key) { // casos para teclas especiales como enter, escape o borrar - case GLFW.GLFW_KEY_ENTER -> { + case InputConstants.KEY_RETURN -> { setting.setValue(buffer.toString()); typing = false; - } case GLFW.GLFW_KEY_BACKSPACE -> { + } case InputConstants.KEY_BACKSPACE -> { onBackspace(); - } case GLFW.GLFW_KEY_ESCAPE -> { + } case InputConstants.KEY_ESCAPE -> { typing = false; - } case GLFW.GLFW_KEY_SPACE -> { + } case InputConstants.KEY_SPACE -> { charTyped(' '); } default -> { String c = KeyUtil.getKeyName(key); diff --git a/src/main/java/me/retucio/sputnik/ui/widgets/misc/SearchBarWidget.java b/src/main/java/me/retucio/sputnik/ui/widgets/misc/SearchBarWidget.java index 612b339..a702e1a 100644 --- a/src/main/java/me/retucio/sputnik/ui/widgets/misc/SearchBarWidget.java +++ b/src/main/java/me/retucio/sputnik/ui/widgets/misc/SearchBarWidget.java @@ -17,7 +17,7 @@ import net.minecraft.ChatFormatting; import net.minecraft.client.gui.GuiGraphicsExtractor; import net.minecraft.client.renderer.RenderPipelines; import net.minecraft.network.chat.Component; -import org.lwjgl.glfw.GLFW; +import com.mojang.blaze3d.platform.InputConstants; import java.awt.Color; import java.util.List; @@ -99,25 +99,25 @@ public class SearchBarWidget extends Widget { @Override public void onKey(int key, int action) { if (!ClientSettingsPanel.clientSettings.searchBar.getValue()) return; - if (!focused || action == GLFW.GLFW_RELEASE) return; + if (!focused || action == InputConstants.RELEASE) return; - if (key == GLFW.GLFW_KEY_V && KeyUtil.isKeyDown(GLFW.GLFW_KEY_LEFT_CONTROL)) { + if (key == InputConstants.KEY_V && KeyUtil.isKeyDown(InputConstants.KEY_LCONTROL)) { paste(); return; } switch (key) { - case GLFW.GLFW_KEY_ENTER -> focused = false; - case GLFW.GLFW_KEY_ESCAPE -> { + case InputConstants.KEY_RETURN -> focused = false; + case InputConstants.KEY_ESCAPE -> { buffer.setLength(0); focused = false; } - case GLFW.GLFW_KEY_SPACE -> charTyped(' '); - case GLFW.GLFW_KEY_BACKSPACE -> onBackspace(); + case InputConstants.KEY_SPACE -> charTyped(' '); + case InputConstants.KEY_BACKSPACE -> onBackspace(); default -> { String c = KeyUtil.getKeyName(key); if (c.length() == 1) { - if (KeyUtil.isKeyDown(GLFW.GLFW_KEY_LEFT_SHIFT) || KeyUtil.isKeyDown(GLFW.GLFW_KEY_RIGHT_SHIFT)) + if (KeyUtil.isKeyDown(InputConstants.KEY_LSHIFT) || KeyUtil.isKeyDown(InputConstants.KEY_RSHIFT)) charTyped(KeyUtil.shiftKey(c).charAt(0)); else charTyped(c.toLowerCase().charAt(0)); diff --git a/src/main/java/me/retucio/sputnik/ui/widgets/misc/TextFieldWidget.java b/src/main/java/me/retucio/sputnik/ui/widgets/misc/TextFieldWidget.java index 6055b96..c7dc4ee 100644 --- a/src/main/java/me/retucio/sputnik/ui/widgets/misc/TextFieldWidget.java +++ b/src/main/java/me/retucio/sputnik/ui/widgets/misc/TextFieldWidget.java @@ -7,7 +7,7 @@ import me.retucio.sputnik.util.MiscUtil; import net.minecraft.ChatFormatting; import net.minecraft.client.gui.GuiGraphicsExtractor; import net.minecraft.network.chat.Component; -import org.lwjgl.glfw.GLFW; +import com.mojang.blaze3d.platform.InputConstants; import java.awt.Color; import java.util.function.Consumer; @@ -69,21 +69,21 @@ public class TextFieldWidget extends Widget { @Override public void onKey(int key, int action) { - if (!focused || action == GLFW.GLFW_RELEASE) return; + if (!focused || action == InputConstants.RELEASE) return; - if (key == GLFW.GLFW_KEY_V && KeyUtil.isKeyDown(GLFW.GLFW_KEY_LEFT_CONTROL)) { + if (key == InputConstants.KEY_V && KeyUtil.isKeyDown(InputConstants.KEY_LCONTROL)) { buffer.append(MiscUtil.getPasteContent(maxLength - buffer.length())); return; } switch (key) { - case GLFW.GLFW_KEY_ENTER -> submit(); - case GLFW.GLFW_KEY_ESCAPE -> { + case InputConstants.KEY_RETURN -> submit(); + case InputConstants.KEY_ESCAPE -> { buffer.setLength(0); focused = false; } - case GLFW.GLFW_KEY_BACKSPACE -> MiscUtil.backspace(buffer); - case GLFW.GLFW_KEY_SPACE -> charTyped(' '); + case InputConstants.KEY_BACKSPACE -> MiscUtil.backspace(buffer); + case InputConstants.KEY_SPACE -> charTyped(' '); default -> { String c = KeyUtil.getKeyName(key); if (c.length() == 1) diff --git a/src/main/java/me/retucio/sputnik/ui/widgets/panels/settings/ClientSettingsPanel.java b/src/main/java/me/retucio/sputnik/ui/widgets/panels/settings/ClientSettingsPanel.java index 4143d39..96b8a29 100644 --- a/src/main/java/me/retucio/sputnik/ui/widgets/panels/settings/ClientSettingsPanel.java +++ b/src/main/java/me/retucio/sputnik/ui/widgets/panels/settings/ClientSettingsPanel.java @@ -1,107 +1,128 @@ package me.retucio.sputnik.ui.widgets.panels.settings; -import me.retucio.sputnik.Sputnik; -import me.retucio.sputnik.event.sputnik.ClientSettingsPanelEvent; import me.retucio.sputnik.module.modules.client.ClientSettingsModule; -import me.retucio.sputnik.ui.screen.ClickGui; import me.retucio.sputnik.ui.widgets.panels.SettingsPanel; +import me.retucio.sputnik.ui.widgets.buttons.SettingButton; import me.retucio.sputnik.util.Colors; import me.retucio.sputnik.util.I18nUtil; +import me.retucio.sputnik.module.setting.SettingGroup; import net.minecraft.client.gui.GuiGraphicsExtractor; +import java.util.List; + public class ClientSettingsPanel extends SettingsPanel { public static final ClientSettingsModule clientSettings = new ClientSettingsModule(); - private boolean extended = false; + private final List allGroups; + private SettingGroup selectedGroup; + private static final int SIDEBAR_WIDTH = 190; + private static final int CONTENT_TOP = 62; + private static final int GROUP_HEIGHT = 28; public ClientSettingsPanel(int x, int y, int w, int h) { - super(clientSettings, x, y, w, h); + super(clientSettings, SIDEBAR_WIDTH, 28, 0, 24); + allGroups = clientSettings.getSgs().stream().filter(group -> !group.getSettings().isEmpty()).toList(); + selectedGroup = allGroups.getFirst(); + setSettingGroups(List.of(selectedGroup)); + selectedGroup.setExtended(true); setTitle(() -> I18nUtil.orElse("sputnik.ui.clientsettings.title", "ajustes del mod")); - this.drawHeader = false; // disable the original header + this.drawHeader = false; } @Override public void render(GuiGraphicsExtractor gui, int mouseX, int mouseY, float delta) { - updateWidth(); + int screenWidth = mc.getWindow().getGuiScaledWidth(); + int screenHeight = mc.getWindow().getGuiScaledHeight(); + x = SIDEBAR_WIDTH; + y = 28; + renderY = y; + w = screenWidth - SIDEBAR_WIDTH; + h = 24; - // Draw our own custom header (no close button, with +/- - gui.fill(x, renderY, x + w, renderY + h, Colors.mainColor.getRGB()); - gui.text(mc.font, getTitle(), - x + 8, - renderY + (h / 2) - (mc.font.lineHeight / 2), - -1, true); + gui.fill(0, 20, screenWidth, screenHeight, Colors.panelBgColor.getRGB()); + gui.fill(0, 20, SIDEBAR_WIDTH, screenHeight, Colors.buttonColor.getRGB()); + gui.text(mc.font, getTitle(), 14, 28, Colors.mainColor.getRGB(), true); - String symbol = extended ? "-" : "+"; - int textWidth = mc.font.width(symbol); - gui.text(mc.font, symbol, - x + w - textWidth - 8, - renderY + (h / 2) - (mc.font.lineHeight / 2), - -1, true); - - // Only draw the rest of the panel (content) if extended - if (extended) { - // Call super.render() – but since drawHeader=false, it will only draw the content - super.render(gui, mouseX, mouseY, delta); + int tabY = 52; + for (SettingGroup group : allGroups) { + boolean hovered = mouseX >= 8 && mouseX < SIDEBAR_WIDTH - 8 + && mouseY >= tabY && mouseY < tabY + GROUP_HEIGHT; + int color = group == selectedGroup ? Colors.mainColor.getRGB() + : hovered ? Colors.buttonColor.brighter().getRGB() : Colors.buttonColor.getRGB(); + gui.fill(8, tabY, SIDEBAR_WIDTH - 8, tabY + GROUP_HEIGHT, color); + gui.text(mc.font, group.getName(), 18, + tabY + (GROUP_HEIGHT - mc.font.lineHeight) / 2, -1, true); + tabY += GROUP_HEIGHT + 4; } + + gui.text(mc.font, selectedGroup.getName(), x + 12, y, + Colors.mainColor.getRGB(), true); + visibleButtons = buttons.stream() + .filter(button -> button.getSetting().getSg() == selectedGroup + && button.getSetting().isVisible() && button.getSetting().isSearchMatch()) + .toList(); + + int settingY = CONTENT_TOP; + for (SettingButton button : visibleButtons) { + button.setX(x + 12); + button.setY(settingY); + button.setW(w - 24); + button.setH(24); + button.render(gui, mouseX, mouseY, delta); + settingY += 30; + } + } + + public boolean mouseClickedGroupTab(int mouseX, int mouseY, int button) { + if (button != 0) return false; + int tabY = 52; + for (SettingGroup group : allGroups) { + if (mouseX >= 8 && mouseX < SIDEBAR_WIDTH - 8 + && mouseY >= tabY && mouseY < tabY + GROUP_HEIGHT) { + selectedGroup = group; + setSettingGroups(List.of(group)); + group.setExtended(true); + updateVisibleButtonsForGroup(group); + return true; + } + tabY += GROUP_HEIGHT + 4; + } + return false; } @Override public void mouseClicked(int mouseX, int mouseY, int button) { - if (isHovered(mouseX, mouseY) && ClickGui.INSTANCE.trySelect(this)) { - if (button == 0) { - dragging = true; - dragX = mouseX - x; - dragY = mouseY - y; - } else if (button == 1) { - extended = !extended; - Sputnik.EVENT_BUS.post(new ClientSettingsPanelEvent.Extend()); - return; - } - } - - if (extended) { - super.mouseClicked(mouseX, mouseY, button); - } + for (SettingButton settingButton : visibleButtons) + settingButton.mouseClicked(mouseX, mouseY, button); } @Override public void mouseReleased(int mouseX, int mouseY, int button) { - ClickGui.INSTANCE.unselect(this); - if (button == 0 && dragging) { - dragging = false; - Sputnik.EVENT_BUS.post(new ClientSettingsPanelEvent.Move()); - } - if (extended) { - super.mouseReleased(mouseX, mouseY, button); - } + for (SettingButton settingButton : visibleButtons) + settingButton.mouseReleased(mouseX, mouseY, button); } @Override public void mouseDragged(int mouseX, int mouseY) { - if (extended) { - super.mouseDragged(mouseX, mouseY); - } + for (SettingButton settingButton : visibleButtons) + settingButton.mouseDragged(mouseX, mouseY); } @Override public void mouseScrolled(double amount) { - if (extended) { - super.mouseScrolled(amount); - } + super.mouseScrolled(amount); } @Override public void onKey(int key, int action) { - if (extended) { - super.onKey(key, action); - } + super.onKey(key, action); } public boolean isExtended() { - return extended; + return true; } public void setExtended(boolean extended) { - this.extended = extended; + // La pestaña siempre muestra sus ajustes. } -} \ No newline at end of file +} diff --git a/src/main/java/me/retucio/sputnik/util/KeyUtil.java b/src/main/java/me/retucio/sputnik/util/KeyUtil.java index 8cfd9f0..6299cbf 100644 --- a/src/main/java/me/retucio/sputnik/util/KeyUtil.java +++ b/src/main/java/me/retucio/sputnik/util/KeyUtil.java @@ -3,10 +3,12 @@ package me.retucio.sputnik.util; import me.retucio.sputnik.mixin.accessors.KeyBindingAccessor; import net.minecraft.client.KeyMapping; import net.minecraft.client.input.KeyEvent; -import org.lwjgl.glfw.GLFW; +import com.mojang.blaze3d.platform.InputConstants; import java.awt.*; import java.awt.im.InputContext; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; import java.util.Locale; import static me.retucio.sputnik.Sputnik.mc; @@ -14,8 +16,103 @@ import static me.retucio.sputnik.Sputnik.mc; // cosas útiles relacionadas con las teclas public class KeyUtil { + private static final int MOUSE_BIND_BASE = -1000; + private static final Set PRESSED_MOUSE_BUTTONS = ConcurrentHashMap.newKeySet(); + + public static int encodeMouseButton(int button) { + return MOUSE_BIND_BASE - button; + } + + public static boolean isMouseBinding(int key) { + return key < MOUSE_BIND_BASE; + } + + private static int decodeMouseButton(int key) { + return MOUSE_BIND_BASE - key; + } + + public static void setMouseButtonDown(int button, boolean down) { + if (down) PRESSED_MOUSE_BUTTONS.add(button); + else PRESSED_MOUSE_BUTTONS.remove(button); + } + + /** Converts a pre-26.3 GLFW key or mouse button code to the SDL scancode used by 26.3. */ + public static int fromLegacyGlfwKey(int key) { + if (key >= 65 && key <= 90) return key - 61; // A-Z -> SDL scancodes 4-29 + if (key >= 48 && key <= 57) return key - 18; // 0-9 -> SDL scancodes 30-39 + if (key >= 290 && key <= 301) return key - 232; // F1-F12 -> 58-69 + if (key >= 302 && key <= 313) return key - 198; // F13-F24 -> 104-115 + if (key == 320) return InputConstants.KEY_NUMPAD0; + if (key >= 321 && key <= 329) return key - 232; // keypad 1-9 + if (key >= 3 && key <= 7) return encodeMouseButton(key + 1); // GLFW mouse 3-7 -> SDL 4-8 + + return switch (key) { + case 0 -> encodeMouseButton(InputConstants.MOUSE_BUTTON_LEFT); + case 1 -> encodeMouseButton(InputConstants.MOUSE_BUTTON_RIGHT); + case 2 -> encodeMouseButton(InputConstants.MOUSE_BUTTON_MIDDLE); + case 32 -> InputConstants.KEY_SPACE; + case 39 -> InputConstants.KEY_APOSTROPHE; + case 44 -> InputConstants.KEY_COMMA; + case 45 -> InputConstants.KEY_MINUS; + case 46 -> InputConstants.KEY_PERIOD; + case 47 -> InputConstants.KEY_SLASH; + case 59 -> InputConstants.KEY_SEMICOLON; + case 61 -> InputConstants.KEY_EQUALS; + case 91 -> InputConstants.KEY_LBRACKET; + case 92 -> InputConstants.KEY_BACKSLASH; + case 93 -> InputConstants.KEY_RBRACKET; + case 96 -> InputConstants.KEY_GRAVE; + case 256 -> InputConstants.KEY_ESCAPE; + case 257, 335 -> key == 257 ? InputConstants.KEY_RETURN : InputConstants.KEY_NUMPADENTER; + case 258 -> InputConstants.KEY_TAB; + case 259 -> InputConstants.KEY_BACKSPACE; + case 260 -> InputConstants.KEY_INSERT; + case 261 -> InputConstants.KEY_DELETE; + case 262 -> InputConstants.KEY_RIGHT; + case 263 -> InputConstants.KEY_LEFT; + case 264 -> InputConstants.KEY_DOWN; + case 265 -> InputConstants.KEY_UP; + case 266 -> InputConstants.KEY_PAGEUP; + case 267 -> InputConstants.KEY_PAGEDOWN; + case 268 -> InputConstants.KEY_HOME; + case 269 -> InputConstants.KEY_END; + case 280 -> InputConstants.KEY_CAPSLOCK; + case 281 -> InputConstants.KEY_SCROLLLOCK; + case 282 -> InputConstants.KEY_NUMLOCK; + case 283 -> InputConstants.KEY_PRINTSCREEN; + case 284 -> InputConstants.KEY_PAUSE; + case 330 -> 99; // SDL_NUMPAD_DECIMAL + case 331 -> 84; // SDL_NUMPAD_DIVIDE + case 332 -> InputConstants.KEY_MULTIPLY; + case 333 -> 86; // SDL_NUMPAD_SUBTRACT + case 334 -> InputConstants.KEY_ADD; + case 336 -> InputConstants.KEY_NUMPADEQUALS; + case 340 -> InputConstants.KEY_LSHIFT; + case 341 -> InputConstants.KEY_LCONTROL; + case 342 -> InputConstants.KEY_LALT; + case 343 -> InputConstants.KEY_LGUI; + case 344 -> InputConstants.KEY_RSHIFT; + case 345 -> InputConstants.KEY_RCONTROL; + case 346 -> InputConstants.KEY_RALT; + case -1 -> InputConstants.UNKNOWN.getValue(); + default -> key; + }; + } + + /** Converts 26.3 SDL mouse button numbers to the 0-based values used by our UI widgets. */ + public static int toLegacyMouseButton(int button) { + return switch (button) { + case InputConstants.MOUSE_BUTTON_LEFT -> 0; + case InputConstants.MOUSE_BUTTON_RIGHT -> 1; + case InputConstants.MOUSE_BUTTON_MIDDLE -> 2; + default -> button >= InputConstants.MOUSE_BUTTON_4 && button <= InputConstants.MOUSE_BUTTON_8 + ? button - 1 : button; + }; + } + + public static int getKeyAction(int key) { - return GLFW.glfwGetKey(mc.getWindow().handle(), key); + return InputConstants.isKeyDown(key) ? InputConstants.PRESS : InputConstants.RELEASE; } public static boolean isKeyDown(KeyMapping key) { @@ -23,14 +120,13 @@ public class KeyUtil { } public static boolean isKeyDown(int key) { - return GLFW.glfwGetKey( - mc.getWindow().handle(), - key) != GLFW.GLFW_RELEASE; + if (isMouseBinding(key)) return PRESSED_MOUSE_BUTTONS.contains(decodeMouseButton(key)); + return InputConstants.isKeyDown(key); } public static boolean isShiftDown() { - return isKeyDown(GLFW.GLFW_KEY_LEFT_SHIFT) - || isKeyDown(GLFW.GLFW_KEY_RIGHT_SHIFT); + return isKeyDown(InputConstants.KEY_LSHIFT) + || isKeyDown(InputConstants.KEY_RSHIFT); } public static int getKey(KeyMapping kb) { @@ -58,39 +154,48 @@ public class KeyUtil { } public static String getKeyName(int key) { - if (key == GLFW.GLFW_KEY_UNKNOWN) return I18nUtil.orElse("sputnik.key.none", "ninguna"); + if (key == InputConstants.UNKNOWN.getValue()) return I18nUtil.orElse("sputnik.key.none", "ninguna"); + if (isMouseBinding(key)) { + int button = decodeMouseButton(key); + return switch (button) { + case InputConstants.MOUSE_BUTTON_LEFT -> I18nUtil.orElse("sputnik.key.leftclick", "clic izquierdo"); + case InputConstants.MOUSE_BUTTON_RIGHT -> I18nUtil.orElse("sputnik.key.rightclick", "clic derecho"); + case InputConstants.MOUSE_BUTTON_MIDDLE -> I18nUtil.orElse("sputnik.key.middleclick", "ruedita"); + default -> I18nUtil.orElse("sputnik.key.mousebutton", "botón del ratón " + button, button); + }; + } - String name = GLFW.glfwGetKeyName(key, 0); + String name = InputConstants.getKey(new net.minecraft.client.input.KeyEvent(key, 0, 0)).getDisplayName().getString(); if (name != null) return name.toUpperCase(); // para teclas especiales return switch (key) { - case GLFW.GLFW_MOUSE_BUTTON_1 -> I18nUtil.orElse("sputnik.key.leftclick", "clic izquierdo"); - case GLFW.GLFW_MOUSE_BUTTON_2 -> I18nUtil.orElse("sputnik.key.rightclick", "clic derecho"); - case GLFW.GLFW_MOUSE_BUTTON_3 -> I18nUtil.orElse("sputnik.key.middleclick", "ruedita"); - case GLFW.GLFW_KEY_SPACE -> I18nUtil.orElse("sputnik.key.space", "espacio"); - case GLFW.GLFW_KEY_LEFT_SHIFT -> I18nUtil.orElse("sputnik.key.leftshift", "shift izquierdo"); - case GLFW.GLFW_KEY_RIGHT_SHIFT -> I18nUtil.orElse("sputnik.key.rightshift", "shift derecho"); - case GLFW.GLFW_KEY_LEFT_CONTROL -> I18nUtil.orElse("sputnik.key.leftctrl", "ctrl izquierdo"); - case GLFW.GLFW_KEY_RIGHT_CONTROL -> I18nUtil.orElse("sputnik.key.rightctrl", "ctrl derecho"); - case GLFW.GLFW_KEY_LEFT_ALT -> I18nUtil.orElse("sputnik.key.leftalt", "alt izquierdo"); - case GLFW.GLFW_KEY_RIGHT_ALT -> I18nUtil.orElse("sputnik.key.altgr", "alt gr"); - case GLFW.GLFW_KEY_TAB -> I18nUtil.orElse("sputnik.key.tab", "tab"); - case GLFW.GLFW_KEY_ENTER -> I18nUtil.orElse("sputnik.key.enter", "enter"); - case GLFW.GLFW_KEY_BACKSPACE -> I18nUtil.orElse("sputnik.key.backspace", "borrar"); - case GLFW.GLFW_KEY_DELETE -> I18nUtil.orElse("sputnik.key.delete", "suprimir"); - case GLFW.GLFW_KEY_UP -> I18nUtil.orElse("sputnik.key.up", "arriba"); - case GLFW.GLFW_KEY_DOWN -> I18nUtil.orElse("sputnik.key.down", "abajo"); - case GLFW.GLFW_KEY_LEFT -> I18nUtil.orElse("sputnik.key.left", "izquierda"); - case GLFW.GLFW_KEY_RIGHT -> I18nUtil.orElse("sputnik.key.right", "derecha"); - case GLFW.GLFW_KEY_PAGE_UP -> I18nUtil.orElse("sputnik.key.pageup", "pág. arriba"); - case GLFW.GLFW_KEY_PAGE_DOWN -> I18nUtil.orElse("sputnik.key.pagedown", "pág. abajo"); - case GLFW.GLFW_KEY_CAPS_LOCK -> I18nUtil.orElse("sputnik.key.capslock", "bloq. mayús."); - case GLFW.GLFW_KEY_INSERT -> I18nUtil.orElse("sputnik.key.insert", "insertar"); + case InputConstants.MOUSE_BUTTON_LEFT -> I18nUtil.orElse("sputnik.key.leftclick", "clic izquierdo"); + case InputConstants.MOUSE_BUTTON_RIGHT -> I18nUtil.orElse("sputnik.key.rightclick", "clic derecho"); + case InputConstants.MOUSE_BUTTON_MIDDLE -> I18nUtil.orElse("sputnik.key.middleclick", "ruedita"); + case InputConstants.KEY_SPACE -> I18nUtil.orElse("sputnik.key.space", "espacio"); + case InputConstants.KEY_LSHIFT -> I18nUtil.orElse("sputnik.key.leftshift", "shift izquierdo"); + case InputConstants.KEY_RSHIFT -> I18nUtil.orElse("sputnik.key.rightshift", "shift derecho"); + case InputConstants.KEY_LCONTROL -> I18nUtil.orElse("sputnik.key.leftctrl", "ctrl izquierdo"); + case InputConstants.KEY_RCONTROL -> I18nUtil.orElse("sputnik.key.rightctrl", "ctrl derecho"); + case InputConstants.KEY_LALT -> I18nUtil.orElse("sputnik.key.leftalt", "alt izquierdo"); + case InputConstants.KEY_RALT -> I18nUtil.orElse("sputnik.key.altgr", "alt gr"); + case InputConstants.KEY_TAB -> I18nUtil.orElse("sputnik.key.tab", "tab"); + case InputConstants.KEY_RETURN -> I18nUtil.orElse("sputnik.key.enter", "enter"); + case InputConstants.KEY_BACKSPACE -> I18nUtil.orElse("sputnik.key.backspace", "borrar"); + case InputConstants.KEY_DELETE -> I18nUtil.orElse("sputnik.key.delete", "suprimir"); + case InputConstants.KEY_UP -> I18nUtil.orElse("sputnik.key.up", "arriba"); + case InputConstants.KEY_DOWN -> I18nUtil.orElse("sputnik.key.down", "abajo"); + case InputConstants.KEY_LEFT -> I18nUtil.orElse("sputnik.key.left", "izquierda"); + case InputConstants.KEY_RIGHT -> I18nUtil.orElse("sputnik.key.right", "derecha"); + case InputConstants.KEY_PAGEUP -> I18nUtil.orElse("sputnik.key.pageup", "pág. arriba"); + case InputConstants.KEY_PAGEDOWN -> I18nUtil.orElse("sputnik.key.pagedown", "pág. abajo"); + case InputConstants.KEY_CAPSLOCK -> I18nUtil.orElse("sputnik.key.capslock", "bloq. mayús."); + case InputConstants.KEY_INSERT -> I18nUtil.orElse("sputnik.key.insert", "insertar"); default -> { - if (key >= GLFW.GLFW_KEY_F1 && key <= GLFW.GLFW_KEY_F25) { - yield "F" + (key - GLFW.GLFW_KEY_F1 + 1); // F1–F25 - } else if (key >= GLFW.GLFW_MOUSE_BUTTON_4 && key <= GLFW.GLFW_MOUSE_BUTTON_8) { + if (key >= InputConstants.KEY_F1 && key <= InputConstants.KEY_F24) { + yield "F" + (key - InputConstants.KEY_F1 + 1); // F1–F25 + } else if (key >= InputConstants.MOUSE_BUTTON_4 && key <= InputConstants.MOUSE_BUTTON_8) { // botones del ratón yield I18nUtil.orElse("sputnik.key.mousebutton", "botón del ratón " + (key + 1), key + 1); diff --git a/src/main/java/me/retucio/sputnik/util/MiscUtil.java b/src/main/java/me/retucio/sputnik/util/MiscUtil.java index 23c69b5..daf41d4 100644 --- a/src/main/java/me/retucio/sputnik/util/MiscUtil.java +++ b/src/main/java/me/retucio/sputnik/util/MiscUtil.java @@ -12,7 +12,7 @@ import net.minecraft.world.phys.Vec3; import org.apache.commons.io.IOUtils; import org.joml.Vector3d; import org.joml.Vector3f; -import org.lwjgl.glfw.GLFW; +import com.mojang.blaze3d.platform.InputConstants; import java.io.*; import java.time.Instant; @@ -100,7 +100,7 @@ public class MiscUtil { } public static void backspace(StringBuilder buffer) { - if (KeyUtil.isKeyDown(GLFW.GLFW_KEY_LEFT_CONTROL)) { + if (KeyUtil.isKeyDown(InputConstants.KEY_LCONTROL)) { for (int i = buffer.length() - 1; i >= 0; i--) { char c = buffer.charAt(i); buffer.deleteCharAt(i); diff --git a/src/main/java/me/retucio/sputnik/util/NetworkUtil.java b/src/main/java/me/retucio/sputnik/util/NetworkUtil.java index 58f019f..92970ff 100644 --- a/src/main/java/me/retucio/sputnik/util/NetworkUtil.java +++ b/src/main/java/me/retucio/sputnik/util/NetworkUtil.java @@ -11,18 +11,17 @@ import net.minecraft.network.PacketListener; import net.minecraft.network.protocol.Packet; import net.minecraft.network.protocol.game.ClientboundSetTimePacket; import net.minecraft.network.protocol.game.ServerboundSetCarriedItemPacket; -import net.minecraft.network.protocol.game.ServerboundSwingPacket; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; import net.minecraft.world.item.BlockItem; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.component.SwingAnimation; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.*; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.shapes.CollisionContext; -import net.minecraft.world.phys.shapes.VoxelShape; import java.util.ArrayList; import java.util.List; @@ -100,8 +99,7 @@ public class NetworkUtil { InteractionResult result = mc.gameMode.useItemOn(mc.player, hand, blockHitResult); if (result.consumesAction()) { - if (swing) mc.player.swing(hand); - else mc.getConnection().send(new ServerboundSwingPacket(hand)); + mc.player.swing(hand, SwingAnimation.DEFAULT, false); } mc.player.setShiftKeyDown(wasSneaking); diff --git a/src/main/java/me/retucio/sputnik/util/render/GlintRenderType.java b/src/main/java/me/retucio/sputnik/util/render/GlintRenderType.java index d3f83ad..de767d2 100644 --- a/src/main/java/me/retucio/sputnik/util/render/GlintRenderType.java +++ b/src/main/java/me/retucio/sputnik/util/render/GlintRenderType.java @@ -4,12 +4,15 @@ import me.retucio.sputnik.Sputnik; import me.retucio.sputnik.module.modules.render.GlintPlus; import net.minecraft.client.renderer.RenderPipelines; import net.minecraft.client.renderer.rendertype.*; +import net.minecraft.client.renderer.oit.OitPipelineSet; import net.minecraft.resources.Identifier; import net.minecraft.world.item.DyeColor; import java.util.ArrayList; import java.util.List; import java.util.function.Function; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; /** utilidad para crear RenderTypes de glint con color personalizado @@ -22,7 +25,6 @@ public class GlintRenderType { public static final List glintColor = newRenderList(GlintRenderType::buildGlintRenderType); public static final List entityGlintColor = newRenderList(GlintRenderType::buildEntityGlintRenderType); - public static final List armorEntityGlintColor = newRenderList(GlintRenderType::buildArmorEntityGlintRenderType); public static final List glintTranslucentColor = newRenderList(GlintRenderType::buildGlintTranslucentRenderType); private static List newRenderList(Function func) { @@ -55,7 +57,6 @@ public class GlintRenderType { RenderSetup.builder(RenderPipelines.GLINT) .withTexture("Sampler0", res) .setTextureTransform(TextureTransform.GLINT_TEXTURING) - .setOutputTarget(OutputTarget.ITEM_ENTITY_TARGET) .createRenderSetup() ); } @@ -71,15 +72,57 @@ public class GlintRenderType { ); } - private static RenderType buildArmorEntityGlintRenderType(String name) { + private static final Map ARMOR_GLINT_TYPES = new ConcurrentHashMap<>(); + private static final Map ITEM_GLINT_TYPES = new ConcurrentHashMap<>(); + + public static RenderType itemGlint(String name, RenderType original, Identifier itemAtlas) { + return ITEM_GLINT_TYPES.computeIfAbsent(new ItemGlintKey(name, original.pipeline(), itemAtlas), key -> { + Identifier glintTexture = Identifier.fromNamespaceAndPath( + Sputnik.MOD_ID, "textures/misc/glint_" + name.toLowerCase() + ".png"); + RenderSetup.RenderSetupBuilder setup = RenderSetup.builder(original.pipeline()) + .withTexture("Sampler0", itemAtlas) + .withTexture("GlintSampler", glintTexture) + .setTextureTransform(TextureTransform.GLINT_TEXTURING) + .useLightmap() + .useOverlay() + .affectsCrumbling() + .setOutline(RenderSetup.OutlineProperty.AFFECTS_OUTLINE); + + if (original.pipeline() == RenderPipelines.ITEM_TRANSLUCENT_GLINT + || original.pipeline() == RenderPipelines.ITEM_TRANSLUCENT_GLINT_SPECIAL) { + OitPipelineSet oit = original.pipeline() == RenderPipelines.ITEM_TRANSLUCENT_GLINT_SPECIAL + ? RenderPipelines.OIT_ITEM_GLINT_SPECIAL : RenderPipelines.OIT_ITEM_GLINT; + setup.setOitPipelines(oit).sortOnUpload(); + } else if (original.pipeline() == RenderPipelines.ITEM_CUTOUT_GLINT_SPECIAL) { + setup.setOitPipelines(RenderPipelines.OIT_ITEM_GLINT_SPECIAL); + } + + return RenderType.create("sputnik_item_glint_" + name, setup.createRenderSetup()); + }); + } + + private record ItemGlintKey(String color, com.mojang.renderpearl.api.pipeline.RenderPipeline pipeline, + Identifier atlas) { } + + public static RenderType armorEntityGlint(String name, Identifier armorTexture) { + return ARMOR_GLINT_TYPES.computeIfAbsent(name + ":" + armorTexture, key -> + buildArmorEntityGlintRenderType(name, armorTexture)); + } + + private static RenderType buildArmorEntityGlintRenderType(String name, Identifier armorTexture) { final Identifier res = Identifier.fromNamespaceAndPath(Sputnik.MOD_ID, "textures/misc/glint_" + name.toLowerCase() + ".png"); return RenderType.create( "armor_glint_" + name, - RenderSetup.builder(RenderPipelines.GLINT) - .withTexture("Sampler0", res) + RenderSetup.builder(RenderPipelines.ARMOR_CUTOUT_NO_CULL_GLINT) + .withTexture("Sampler0", armorTexture) + .withTexture("GlintSampler", res) .setTextureTransform(TextureTransform.ARMOR_ENTITY_GLINT_TEXTURING) + .useLightmap() + .useOverlay() .setLayeringTransform(LayeringTransform.VIEW_OFFSET_Z_LAYERING) + .affectsCrumbling() + .setOutline(RenderSetup.OutlineProperty.AFFECTS_OUTLINE) .createRenderSetup() ); } -} \ No newline at end of file +} diff --git a/src/main/java/me/retucio/sputnik/util/render/Pipelines.java b/src/main/java/me/retucio/sputnik/util/render/Pipelines.java index 2d6acf5..6338547 100644 --- a/src/main/java/me/retucio/sputnik/util/render/Pipelines.java +++ b/src/main/java/me/retucio/sputnik/util/render/Pipelines.java @@ -1,13 +1,14 @@ package me.retucio.sputnik.util.render; -import com.mojang.blaze3d.PrimitiveTopology; -import com.mojang.blaze3d.pipeline.DepthStencilState; -import com.mojang.blaze3d.pipeline.RenderPipeline; -import com.mojang.blaze3d.platform.CompareOp; -import com.mojang.blaze3d.systems.GpuDevice; +import com.mojang.renderpearl.api.pipeline.PrimitiveTopology; +import com.mojang.renderpearl.api.pipeline.DepthStencilState; +import com.mojang.renderpearl.api.pipeline.RenderPipeline; +import com.mojang.renderpearl.api.pipeline.CompareOp; +import com.mojang.renderpearl.api.pipeline.ShaderType; +import com.mojang.renderpearl.api.device.GpuDevice; import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.vertex.DefaultVertexFormat; -import com.mojang.blaze3d.vertex.VertexFormat; +import com.mojang.renderpearl.api.vertex.VertexFormat; import me.retucio.sputnik.Sputnik; @@ -34,56 +35,46 @@ public class Pipelines { private static final DepthStencilState NO_DEPTH = new DepthStencilState(CompareOp.ALWAYS_PASS, false); private static final DepthStencilState DEPTH = new DepthStencilState(CompareOp.GREATER_THAN_OR_EQUAL, false); - static final RenderPipeline LINES_PIPELINE = add(RenderPipeline.builder(RenderPipelines.LINES_SNIPPET) + static final RenderPipeline LINES_PIPELINE = add(copy(RenderPipelines.LINES) .withLocation(Identifier.fromNamespaceAndPath(Sputnik.MOD_ID, "pipeline/lines")) .withVertexBinding(0, DefaultVertexFormat.POSITION_COLOR_NORMAL_LINE_WIDTH) .withPrimitiveTopology(PrimitiveTopology.LINES) .withDepthStencilState(NO_DEPTH) - .withCull(false) - .build()); + .withCull(false).build()); - static final RenderPipeline LINES_CULL_PIPELINE = add(RenderPipeline.builder(RenderPipelines.LINES_SNIPPET) + static final RenderPipeline LINES_CULL_PIPELINE = add(copy(RenderPipelines.LINES) .withLocation(Identifier.fromNamespaceAndPath(Sputnik.MOD_ID, "pipeline/lines_cull")) .withVertexBinding(0, DefaultVertexFormat.POSITION_COLOR_NORMAL_LINE_WIDTH) .withPrimitiveTopology(PrimitiveTopology.LINES) .withDepthStencilState(DEPTH) - .withCull(true) - .build()); + .withCull(true).build()); - static final RenderPipeline QUADS_PIPELINE = add(RenderPipeline.builder(RenderPipelines.DEBUG_FILLED_SNIPPET) + static final RenderPipeline QUADS_PIPELINE = add(copy(RenderPipelines.DEBUG_QUADS) .withLocation(Identifier.fromNamespaceAndPath(Sputnik.MOD_ID, "pipeline/quads")) .withVertexBinding(0, DefaultVertexFormat.POSITION_COLOR) .withPrimitiveTopology(PrimitiveTopology.QUADS) .withDepthStencilState(NO_DEPTH) - .withCull(false) - .build()); + .withCull(false).build()); - static final RenderPipeline QUADS_CULL_PIPELINE = add(RenderPipeline.builder(RenderPipelines.DEBUG_FILLED_SNIPPET) + static final RenderPipeline QUADS_CULL_PIPELINE = add(copy(RenderPipelines.DEBUG_QUADS) .withLocation(Identifier.fromNamespaceAndPath(Sputnik.MOD_ID, "pipeline/quads_cull")) .withVertexBinding(0, DefaultVertexFormat.POSITION_COLOR) .withPrimitiveTopology(PrimitiveTopology.QUADS) .withDepthStencilState(DEPTH) - .withCull(false) - .build()); + .withCull(false).build()); - static final RenderPipeline TEXT_PIPELINE = add(RenderPipeline.builder(RenderPipelines.GUI_TEXTURED_SNIPPET) + static final RenderPipeline TEXT_PIPELINE = add(copy(RenderPipelines.GUI_TEXTURED) .withLocation(Identifier.fromNamespaceAndPath(Sputnik.MOD_ID, "pipeline/text")) .withVertexBinding(0, DefaultVertexFormat.POSITION_TEX_COLOR) .withPrimitiveTopology(PrimitiveTopology.TRIANGLES) .withVertexShader(Identifier.fromNamespaceAndPath(Sputnik.MOD_ID, "shaders/text.vert")) .withFragmentShader(Identifier.fromNamespaceAndPath(Sputnik.MOD_ID, "shaders/text.frag")) - // 26.2 cambió los samplers por bind groups; ojo: los shaders de text.vert/frag - // siguen usando uniforms con nombre (u_Texture, u_ProjectionMatrix) y seguramente - // haya que reescribirlos para que casen con las convenciones nuevas .withBindGroupLayout(BindGroupLayouts.SAMPLER0) .withDepthStencilState(NO_DEPTH) - .withCull(false) - .build()); + .withCull(false).build()); public static void init() { - for (RenderPipeline pipeline : PIPELINES) { - precompile(pipeline); - } + for (RenderPipeline pipeline : PIPELINES) precompile(pipeline); } private static RenderPipeline add(RenderPipeline pipeline) { @@ -92,17 +83,25 @@ public class Pipelines { } public static void precompile(RenderPipeline pipeline) { - GpuDevice device = RenderSystem.getDevice(); - ResourceManager resources = Minecraft.getInstance().getResourceManager(); - - device.precompilePipeline(pipeline, (identifier, shaderType) -> { - Resource resource = resources.getResource(identifier).get(); - - try (InputStream is = resource.open()) { - return IOUtils.toString(is, StandardCharsets.UTF_8); - } catch (IOException e) { - throw new RuntimeException(e); - } - }); + // Pipeline compilation is lazy in 26.3; RenderPass resolves it from its RenderPipeline. } -} \ No newline at end of file + + private static RenderPipeline.Builder copy(RenderPipeline base) { + RenderPipeline.Builder builder = RenderPipeline.builder() + .withLocation(base.getLocation()) + .withCull(base.isCull()) + .withPrimitiveTopology(base.getPrimitiveTopology()) + .withPolygonMode(base.getPolygonMode()); + base.getShaders().forEach((type, shader) -> { + if (type == ShaderType.VERTEX) builder.withVertexShader(shader); + else if (type == ShaderType.FRAGMENT) builder.withFragmentShader(shader); + }); + base.getBindGroupLayouts().forEach(builder::withBindGroupLayout); + for (int i = 0; i < base.getVertexFormatBindings().size(); i++) + builder.withVertexBinding(i, base.getVertexFormatBinding(i)); + for (int i = 0; i < base.getColorTargetStates().size(); i++) + builder.withColorTargetState(i, base.getColorTargetStates().get(i)); + builder.withDepthStencilState(java.util.Optional.ofNullable(base.getDepthStencilState())); + return builder; + } +} diff --git a/src/main/java/me/retucio/sputnik/util/render/PostShader.java b/src/main/java/me/retucio/sputnik/util/render/PostShader.java index 371a0f8..ad22086 100644 --- a/src/main/java/me/retucio/sputnik/util/render/PostShader.java +++ b/src/main/java/me/retucio/sputnik/util/render/PostShader.java @@ -1,27 +1,33 @@ package me.retucio.sputnik.util.render; -import com.mojang.blaze3d.GpuFormat; -import com.mojang.blaze3d.buffers.GpuBuffer; -import com.mojang.blaze3d.buffers.GpuBufferSlice; +import com.mojang.renderpearl.api.GpuFormat; +import com.mojang.renderpearl.api.buffers.GpuBuffer; +import com.mojang.renderpearl.api.buffers.GpuBufferSlice; import com.mojang.blaze3d.buffers.Std140Builder; import com.mojang.blaze3d.framegraph.FrameGraphBuilder; import com.mojang.blaze3d.framegraph.FramePass; -import com.mojang.blaze3d.pipeline.BindGroupLayout; -import com.mojang.blaze3d.pipeline.RenderPipeline; +import com.mojang.renderpearl.api.pipeline.BindGroupLayout; +import com.mojang.renderpearl.api.pipeline.ColorTargetState; +import com.mojang.renderpearl.api.pipeline.CompiledRenderPipeline; +import com.mojang.renderpearl.api.pipeline.ShaderSource; +import com.mojang.renderpearl.api.pipeline.ShaderType; +import com.mojang.renderpearl.api.pipeline.RenderPipeline; import com.mojang.blaze3d.pipeline.RenderTarget; import com.mojang.blaze3d.resource.GraphicsResourceAllocator; import com.mojang.blaze3d.resource.RenderTargetDescriptor; import com.mojang.blaze3d.resource.ResourceHandle; -import com.mojang.blaze3d.shaders.UniformType; -import com.mojang.blaze3d.systems.CommandEncoder; -import com.mojang.blaze3d.systems.RenderPass; +import com.mojang.renderpearl.api.pipeline.UniformType; +import com.mojang.renderpearl.api.commands.CommandEncoder; +import com.mojang.renderpearl.api.commands.RenderPass; import com.mojang.blaze3d.systems.RenderSystem; -import com.mojang.blaze3d.textures.FilterMode; -import com.mojang.blaze3d.textures.GpuSampler; +import com.mojang.renderpearl.api.textures.FilterMode; +import com.mojang.renderpearl.api.textures.GpuSampler; import me.retucio.sputnik.Sputnik; import net.minecraft.client.renderer.MappableRingBuffer; +import net.minecraft.client.renderer.BindGroupLayouts; +import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.RenderPipelines; import net.minecraft.resources.Identifier; @@ -30,6 +36,8 @@ import org.joml.Vector4f; import java.util.Optional; import java.util.OptionalDouble; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; import java.util.function.Consumer; @@ -51,7 +59,8 @@ public class PostShader { .withLocation(Identifier.fromNamespaceAndPath(Sputnik.MOD_ID, "pipeline/post/blit")) .withVertexShader(SCREENQUAD) .withFragmentShader(Identifier.fromNamespaceAndPath(Sputnik.MOD_ID, "post/blit")) - .withBindGroupLayout(BindGroupLayout.builder().withSampler(INPUT_SAMPLER).build()) + .withBindGroupLayout(BindGroupLayouts.IN_SAMPLER) + .withColorTargetState(ColorTargetState.DEFAULT) .build(); private final String name; @@ -64,6 +73,7 @@ public class PostShader { // 0 sin intentar, 1 ok, -1 falló al compilar (shader roto: no reintentar hasta recarga) private int state = 0; + private static final Map COMPILED = new ConcurrentHashMap<>(); private PostShader(String name, RenderPipeline pipeline, FilterMode filter, @Nullable String uniformBlock, int uniformSize) { @@ -86,14 +96,20 @@ public class PostShader { private boolean ensureReady() { if (state != 0) return state == 1; - boolean ok = RenderSystem.getDevice().precompilePipeline(pipeline).isValid() - && RenderSystem.getDevice().precompilePipeline(BLIT_PIPELINE).isValid(); + boolean ok; + try { + compile(pipeline); + compile(BLIT_PIPELINE); + ok = true; + } catch (RuntimeException e) { + Sputnik.LOGGER.error("Failed to compile post shader '{}'", name, e); + ok = false; + } if (ok && uniformBlock != null && uniformUbo == null) { // 130 = USAGE_UNIFORM (128) | USAGE_MAP_WRITE (2): se reescribe cada frame uniformUbo = new MappableRingBuffer(() -> "sputnik post " + name, 130, uniformSize); } state = ok ? 1 : -1; - if (!ok) Sputnik.LOGGER.error("no se pudo compilar el shader de post '{}'", name); return ok; } @@ -109,8 +125,9 @@ public class PostShader { FrameGraphBuilder frame = new FrameGraphBuilder(); ResourceHandle mainHandle = frame.importExternal(name + "_main", target); - RenderTargetDescriptor swapDesc = new RenderTargetDescriptor( - target.width, target.height, true, NO_CLEAR, GpuFormat.RGBA8_UNORM); + RenderTargetDescriptor swapDesc = new RenderTargetDescriptor(target.width, target.height, + new RenderTargetDescriptor.TextureProperties(NO_CLEAR, GpuFormat.RGBA8_UNORM), + RenderTargetDescriptor.TextureProperties.DEFAULT_DEPTH); ResourceHandle swapHandle = frame.createInternal(name + "_swap", swapDesc); // pasada del efecto: main -> swap @@ -145,16 +162,44 @@ public class PostShader { () -> "sputnik post " + name, out.getColorTextureView(), Optional.empty(), - out.useDepth ? out.getDepthTextureView() : null, + out.hasDepth() ? out.getDepthTextureView() : null, OptionalDouble.empty())) { - pass.setPipeline(pipeline); + pass.setPipeline(compile(pipeline)); RenderSystem.bindDefaultUniforms(pass); if (uniform != null && uniformBlock != null) pass.setUniform(uniformBlock, uniform); - pass.bindTexture(INPUT_SAMPLER, in.getColorTextureView(), sampler); + pass.setUniform(INPUT_SAMPLER, in.getColorTextureView(), sampler); pass.draw(3, 1, 0, 0); } } + private static CompiledRenderPipeline compile(RenderPipeline pipeline) { + return COMPILED.computeIfAbsent(pipeline, key -> { + ShaderSource source = new ShaderSource() { + @Override + public String getShader(Identifier id, ShaderType type) { + Identifier location = type.idConverter().idToFile(id); + try (var stream = Minecraft.getInstance().getResourceManager().getResourceOrThrow(location).open()) { + return new String(stream.readAllBytes(), java.nio.charset.StandardCharsets.UTF_8); + } catch (java.io.IOException e) { + throw new RuntimeException("Failed to load shader " + location, e); + } + } + + @Override + public ShaderSource.CachedIncludeSource getInclude(Identifier id) { + return ShaderSource.CachedIncludeSource.create(id, getShader(id, ShaderType.VERTEX)); + } + + @Override public void close() { } + }; + var pending = RenderSystem.getDevice().compilePipeline(key, source, Runnable::run).join(); + if (pending == CompiledRenderPipeline.Pending.NULL) { + throw new IllegalStateException("Shader pipeline compilation failed: " + key.getLocation()); + } + return pending.finishCompile(); + }); + } + public static class Builder { @@ -183,15 +228,17 @@ public class PostShader { } public PostShader build() { - BindGroupLayout.Builder layout = BindGroupLayout.builder().withSampler(INPUT_SAMPLER); - if (uniformBlock != null) layout.withUniform(uniformBlock, UniformType.UNIFORM_BUFFER); - - RenderPipeline pipeline = RenderPipeline.builder(RenderPipelines.POST_PROCESSING_SNIPPET) + RenderPipeline.Builder pipelineBuilder = RenderPipeline.builder(RenderPipelines.POST_PROCESSING_SNIPPET) .withLocation(Identifier.fromNamespaceAndPath(Sputnik.MOD_ID, "pipeline/post/" + name)) .withVertexShader(SCREENQUAD) .withFragmentShader(fragmentShader) - .withBindGroupLayout(layout.build()) - .build(); + .withBindGroupLayout(BindGroupLayouts.IN_SAMPLER) + .withColorTargetState(ColorTargetState.DEFAULT); + if (uniformBlock != null) { + pipelineBuilder.withBindGroupLayout( + BindGroupLayout.builder().withUniform(uniformBlock, UniformType.UNIFORM_BUFFER).build()); + } + RenderPipeline pipeline = pipelineBuilder.build(); return PostShaders.register(new PostShader(name, pipeline, filter, uniformBlock, uniformSize)); } diff --git a/src/main/java/me/retucio/sputnik/util/render/RenderUtil.java b/src/main/java/me/retucio/sputnik/util/render/RenderUtil.java index 9485d1a..2d7331a 100644 --- a/src/main/java/me/retucio/sputnik/util/render/RenderUtil.java +++ b/src/main/java/me/retucio/sputnik/util/render/RenderUtil.java @@ -1,6 +1,6 @@ package me.retucio.sputnik.util.render; -import com.mojang.blaze3d.PrimitiveTopology; +import com.mojang.renderpearl.api.pipeline.PrimitiveTopology; import com.mojang.blaze3d.vertex.*; import com.mojang.math.Axis; import net.minecraft.client.Camera; @@ -453,8 +453,8 @@ public class RenderUtil { Camera camera = mc.gameRenderer.mainCamera(); Vec3 camPos = camera.position(); - matrices.mulPose(Axis.XP.rotationDegrees(camera.yRot())); - matrices.mulPose(Axis.YP.rotationDegrees(camera.xRot() + 180.0f)); + matrices.rotate(Axis.XP.rotationDegrees(camera.yRot())); + matrices.rotate(Axis.YP.rotationDegrees(camera.xRot() + 180.0f)); matrices.translate( pos.x() - camPos.x(), diff --git a/src/main/java/me/retucio/sputnik/util/render/SputnikBuffers.java b/src/main/java/me/retucio/sputnik/util/render/SputnikBuffers.java index ad4ce79..fc20015 100644 --- a/src/main/java/me/retucio/sputnik/util/render/SputnikBuffers.java +++ b/src/main/java/me/retucio/sputnik/util/render/SputnikBuffers.java @@ -1,8 +1,12 @@ package me.retucio.sputnik.util.render; -import com.mojang.blaze3d.PrimitiveTopology; +import com.mojang.renderpearl.api.pipeline.PrimitiveTopology; import com.mojang.blaze3d.vertex.VertexConsumer; -import com.mojang.blaze3d.vertex.VertexFormat; +import com.mojang.renderpearl.api.vertex.VertexFormat; +import com.mojang.renderpearl.api.commands.CommandEncoder; +import com.mojang.renderpearl.api.commands.RenderPass; +import com.mojang.blaze3d.systems.RenderSystem; +import net.minecraft.client.Minecraft; import me.retucio.sputnik.Sputnik; import net.minecraft.client.renderer.StagedVertexBuffer; import net.minecraft.client.renderer.rendertype.PreparedRenderType; @@ -60,10 +64,18 @@ public class SputnikBuffers { buffer.upload(); - for (QueuedDraw queued : queue) { - StagedVertexBuffer.ExecuteInfo info = buffer.getExecuteInfo(queued.draw()); - if (info != null) queued.type().drawFromBuffer(info); + CommandEncoder encoder = RenderSystem.getDevice().createCommandEncoder(); + try (RenderPass pass = encoder.createRenderPass(() -> "sputnik buffers", + Minecraft.getInstance().gameRenderer.mainRenderTarget().getColorTextureView(), + java.util.Optional.empty(), + Minecraft.getInstance().gameRenderer.mainRenderTarget().getDepthTextureView(), + java.util.OptionalDouble.empty())) { + for (QueuedDraw queued : queue) { + StagedVertexBuffer.ExecuteInfo info = buffer.getExecuteInfo(queued.draw()); + if (info != null) queued.type().drawFromBuffer(info, pass); + } } + encoder.submit(); queue.clear(); buffer.endDraw(); diff --git a/src/main/resources/assets/sputnik/lang/en_us.json b/src/main/resources/assets/sputnik/lang/en_us.json index c2ba409..b3a9906 100644 --- a/src/main/resources/assets/sputnik/lang/en_us.json +++ b/src/main/resources/assets/sputnik/lang/en_us.json @@ -1632,7 +1632,7 @@ "sputnik.ui.friends.title": "friends", "sputnik.ui.list.tooltip": "%s (%s of %s)", "sputnik.ui.macros.empty": "no macros yet", - "sputnik.ui.macros.instructions": "left click: select / right click: bind / shift + right click: delete", + "sputnik.ui.macros.instructions": "C: chat macro / K: keybind macro / left click: select / right click: bind / shift + right click: delete", "sputnik.ui.macros.lineinstructions": "shift + right click on a line to remove it", "sputnik.ui.macros.lineplaceholder": "command or message...", "sputnik.ui.macros.nameplaceholder": "macro name...", @@ -1651,6 +1651,7 @@ "sputnik.ui.searchbar.placeholder": "search...", "sputnik.ui.settingsof": "%s settings", "sputnik.ui.tab.hud": "hud", + "sputnik.ui.tab.client_settings": "client settings", "sputnik.ui.tab.macros": "macros", "sputnik.ui.tab.modules": "modules", "sputnik.ui.tab.profiles": "profiles", diff --git a/src/main/resources/assets/sputnik/lang/es_es.json b/src/main/resources/assets/sputnik/lang/es_es.json index 4e400b8..f8bfc84 100644 --- a/src/main/resources/assets/sputnik/lang/es_es.json +++ b/src/main/resources/assets/sputnik/lang/es_es.json @@ -1632,7 +1632,7 @@ "sputnik.ui.friends.title": "amigos", "sputnik.ui.list.tooltip": "%s (%s de %s)", "sputnik.ui.macros.empty": "todavía no hay macros", - "sputnik.ui.macros.instructions": "clic izq.: seleccionar / clic der.: asignar tecla / shift + clic der.: borrar", + "sputnik.ui.macros.instructions": "C: macro de chat / K: macro de teclas / clic izq.: seleccionar / clic der.: asignar tecla / shift + clic der.: borrar", "sputnik.ui.macros.lineinstructions": "shift + clic der. sobre una línea para quitarla", "sputnik.ui.macros.lineplaceholder": "comando o mensaje...", "sputnik.ui.macros.nameplaceholder": "nombre de la macro...", @@ -1651,6 +1651,7 @@ "sputnik.ui.searchbar.placeholder": "buscar...", "sputnik.ui.settingsof": "ajustes de %s", "sputnik.ui.tab.hud": "hud", + "sputnik.ui.tab.client_settings": "ajustes", "sputnik.ui.tab.macros": "macros", "sputnik.ui.tab.modules": "módulos", "sputnik.ui.tab.profiles": "perfiles", @@ -1671,4 +1672,4 @@ "sputnik.ui.friends.removed": "%s ya no es tu amigo", "sputnik.ui.friends.empty": "no tienes amigos jajsjsjs", "sputnik.ui.friends.uuid": "UUID: %s" -} \ No newline at end of file +} diff --git a/src/main/resources/assets/sputnik/shaders/post/blit.fsh b/src/main/resources/assets/sputnik/shaders/post/blit.fsh index 8a0b2ad..4314bc8 100644 --- a/src/main/resources/assets/sputnik/shaders/post/blit.fsh +++ b/src/main/resources/assets/sputnik/shaders/post/blit.fsh @@ -1,11 +1,12 @@ #version 330 +#extension GL_ARB_separate_shader_objects : require // copia el resultado de la pasada lsd (un objetivo intermedio) de vuelta al objetivo // principal: una pasada de post no puede leer y escribir la misma textura a la vez uniform sampler2D InSampler; -in vec2 texCoord; -out vec4 fragColor; +layout(location = 0) in vec2 texCoord; +layout(location = 0) out vec4 fragColor; void main() { fragColor = texture(InSampler, texCoord); diff --git a/src/main/resources/assets/sputnik/shaders/post/lsd.fsh b/src/main/resources/assets/sputnik/shaders/post/lsd.fsh index b8cae94..6733d24 100644 --- a/src/main/resources/assets/sputnik/shaders/post/lsd.fsh +++ b/src/main/resources/assets/sputnik/shaders/post/lsd.fsh @@ -1,11 +1,10 @@ #version 330 - -#define M_PI 3.1415926535897932384626433832795 +#extension GL_ARB_separate_shader_objects : require uniform sampler2D InSampler; -in vec2 texCoord; -out vec4 fragColor; +layout(location = 0) in vec2 texCoord; +layout(location = 0) out vec4 fragColor; layout(std140) uniform LsdConfig { float strength; @@ -87,32 +86,19 @@ float cnoise(vec3 P){ } -vec3 hueShift(vec3 color, float hueAdjust){ - const vec3 kRGBToYPrime = vec3(0.299, 0.587, 0.114); - const vec3 kRGBToI = vec3(0.596, -0.275, -0.321); - const vec3 kRGBToQ = vec3(0.212, -0.523, 0.311); - - const vec3 kYIQToR = vec3 (1.0, 0.956, 0.621); - const vec3 kYIQToG = vec3 (1.0, -0.272, -0.647); - const vec3 kYIQToB = vec3 (1.0, -1.107, 1.704); - - float YPrime = dot(color, kRGBToYPrime); - float I = dot(color, kRGBToI); - float Q = dot(color, kRGBToQ); - float hue = atan(Q, I); - float chroma = sqrt(I * I + Q * Q); - - hue += hueAdjust; - - Q = chroma * sin(hue); - I = chroma * cos(hue); - - vec3 yIQ = vec3(YPrime, I, Q); - - return vec3(dot(yIQ, kYIQToR), dot(yIQ, kYIQToG), dot(yIQ, kYIQToB)); - +vec3 rgbToHsv(vec3 color) { + vec4 k = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0); + vec4 p = mix(vec4(color.bg, k.wz), vec4(color.gb, k.xy), step(color.b, color.g)); + vec4 q = mix(vec4(p.xyw, color.r), vec4(color.r, p.yzx), step(p.x, color.r)); + float d = q.x - min(q.w, q.y); + float e = 1.0e-10; + return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x); } +vec3 hsvToRgb(vec3 color) { + vec3 p = abs(fract(color.xxx + vec3(0.0, 2.0 / 3.0, 1.0 / 3.0)) * 6.0 - 3.0); + return color.z * mix(vec3(1.0), clamp(p - 1.0, 0.0, 1.0), color.y); +} void main() { vec2 oneTexel = vec2(1.0) / vec2(textureSize(InSampler, 0)); @@ -122,5 +108,9 @@ void main() { float c = cos(ang); vec2 offset = vec2(s, c) * perlin; vec4 tex = texture(InSampler, texCoord + (offset * strength * 30.0) * oneTexel); - fragColor = mix(tex, vec4(hueShift(tex.rgb, seed * 2.0 * M_PI), 1.0), strength); + float hue = seed < 0.0 ? fract(texCoord.x + time * 0.08 + perlin * 0.08) : seed; + vec3 hsv = rgbToHsv(tex.rgb); + hsv.x = hue; + hsv.y = max(hsv.y, 0.65); + fragColor = vec4(mix(tex.rgb, hsvToRgb(hsv), strength), tex.a); } diff --git a/src/main/resources/sputnik.accesswidener b/src/main/resources/sputnik.accesswidener index 76ff8ba..18fa127 100644 --- a/src/main/resources/sputnik.accesswidener +++ b/src/main/resources/sputnik.accesswidener @@ -34,9 +34,6 @@ accessible field net/minecraft/client/particle/Particle hasPhysics Z # renderizado 3d accessible method net/minecraft/client/renderer/rendertype/RenderType (Ljava/lang/String;Lnet/minecraft/client/renderer/rendertype/RenderSetup;)V accessible method net/minecraft/client/renderer/rendertype/RenderType create (Ljava/lang/String;Lnet/minecraft/client/renderer/rendertype/RenderSetup;)Lnet/minecraft/client/renderer/rendertype/RenderType; -accessible field net/minecraft/client/renderer/RenderPipelines LINES_SNIPPET Lcom/mojang/blaze3d/pipeline/RenderPipeline$Snippet; -accessible field net/minecraft/client/renderer/RenderPipelines DEBUG_FILLED_SNIPPET Lcom/mojang/blaze3d/pipeline/RenderPipeline$Snippet; -accessible field net/minecraft/client/renderer/RenderPipelines GUI_TEXTURED_SNIPPET Lcom/mojang/blaze3d/pipeline/RenderPipeline$Snippet; # pantallas accessible field net/minecraft/client/gui/screens/inventory/AbstractContainerScreen imageWidth I diff --git a/src/main/resources/sputnik.mixins.json b/src/main/resources/sputnik.mixins.json index 1978773..c083146 100644 --- a/src/main/resources/sputnik.mixins.json +++ b/src/main/resources/sputnik.mixins.json @@ -81,11 +81,10 @@ "mixins.render.EntityRenderDispatcherMixin", "mixins.render.EntityRenderStateMixin", "mixins.render.EquipmentLayerRendererMixin", + "mixins.render.ItemFeatureRendererMixin", "mixins.render.FogRendererMixin", "mixins.render.FontMixin", "mixins.render.GameRendererMixin", - "mixins.render.ItemFeatureRendererMixin", - "mixins.render.ItemInHandRendererMixin", "mixins.render.LevelRendererMixin", "mixins.render.LightmapMixin", "mixins.render.LightmapRenderStateExtractorMixin", @@ -115,4 +114,4 @@ "mixins.world.TrackingEmitterMixin", "mixins.world.VisGraphMixin" ] -} \ No newline at end of file +}