Compare commits

...
2 Commits
Author SHA1 Message Date
retucio 4307b0a479 v6.7
build / build (push) Waiting to run
2026-11-01 17:57:33 +01:00
retucio ab191a9016 v6.6 2026-10-11 11:56:22 +02:00
90 changed files with 1197 additions and 620 deletions

No files matched your search

+4 -4
View File
@@ -5,23 +5,23 @@
# jenny's mod 2 (100% real) # 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 ## installation
### for normal people: ### for normal people:
1. go to [releases](https://codeberg.org/retucio/sputnik/releases) 1. go to [releases](https://git.retucio.me/retucio/sputnik/releases)
2. choose the most recent version 2. choose the most recent version
3. download the .jar file 3. download the .jar file
4. move it to your mods dir (prolly `%appdata%/.minecraft/mods`) 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 issues could arise when using it with other mods, especially other clients, since they could conflict
### for nerds ### for nerds
1. clone the repo (`git clone https://codeberg.org/retucio/sputnik`) 1. clone the repo (`git clone https://git.retucio.me/retucio/sputnik`)
2. enter the repo dir (`cd sputnik`) 2. enter the repo dir (`cd sputnik`)
3. `gradlew build` for Windows (ew) or `chmod +x gradlew` + `./gradlew build` for Unix-likes (Linux & Mac) 3. `gradlew build` for Windows (ew) or `chmod +x gradlew` + `./gradlew build` for Unix-likes (Linux & Mac)
4. the built .jar will be found in `/build/libs/sputnik-X.X.jar` 4. the built .jar will be found in `/build/libs/sputnik-X.X.jar`
+5 -5
View File
@@ -5,21 +5,21 @@
# jenny's mod 2 100% real # 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 ## instalación
### para gente normal: ### para gente normal:
1. ir a [lanzamientos](https://codeberg.org/retucio/sputnik/releases) 1. ir a [lanzamientos](https://git.retucio.me/retucio/sputnik/releases)
2. selecionar la versión más reciente 2. seleccionar la versión más reciente
3. descargar el .jar 3. descargar el .jar
4. moverlo a tu directorio de mods (probablemente `%appdata%/.minecraft/mods`) 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. 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 ### para frikis de 200 de iq
1. clona el respositorio (`git clone https://codeberg.org/retucio/sputnik`) 1. clona el respositorio (`git clone https://git.retucio.me/retucio/sputnik`)
2. entra al directorio del repositorio (`cd sputnik`) 2. entra al directorio del repositorio (`cd sputnik`)
3. `gradlew build` para Windows (ew) o `chmod +x gradlew` + `./gradlew build` para Unix-likes (Linux & Mac) 3. `gradlew build` para Windows (ew) o `chmod +x gradlew` + `./gradlew build` para Unix-likes (Linux & Mac)
4. el resultado estará en `/build/libs/sputnik-X.X.jar` 4. el resultado estará en `/build/libs/sputnik-X.X.jar`
+5 -4
View File
@@ -1,16 +1,17 @@
# v6.5 # v6.7
## novedades ## novedades
- SIC SEBEN
- migrado de Codeberg a mi propia instancia de Gitea
### adiciones ### adiciones
### arreglos / mejoras ### 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
## problemas reconocidos ## problemas reconocidos
- `reponer` no funciona - `reponer` no funciona
- `copiar` tras sacar una captura con `capturas` no funciona correctamente - `copiar` tras sacar una captura con `capturas` no funciona correctamente
- `manos` no funciona del todo
- \+ lo de siempre. - \+ lo de siempre.
+5 -5
View File
@@ -1,15 +1,15 @@
org.gradle.jvmargs=-Xmx2G org.gradle.jvmargs=-Xmx2G
org.gradle.parallel=true org.gradle.parallel=true
minecraft_version=26.2 minecraft_version=26.3
loader_version=0.19.3 loader_version=0.19.5
loom_version=1.17-SNAPSHOT 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 discord_rpc_version=1.0.3
neutrino_version=1.1.0 neutrino_version=1.1.0
jdk_version=25 jdk_version=25
mod_version=6.5 mod_version=6.7
maven_group=me.retucio maven_group=me.retucio
archives_base_name=sputnik archives_base_name=sputnik
+1 -1
View File
@@ -1,6 +1,6 @@
#Sat Aug 29 22:10:52 CEST 2026 #Sat Aug 29 22:10:52 CEST 2026
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists 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 zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists
+43 -11
View File
@@ -2,6 +2,7 @@ package me.retucio.sputnik;
import com.github.retucio.neutrino.EventBus; import com.github.retucio.neutrino.EventBus;
import com.github.retucio.neutrino.EventListener; import com.github.retucio.neutrino.EventListener;
import com.mojang.blaze3d.platform.InputConstants;
import me.retucio.sputnik.cape.CapeManager; import me.retucio.sputnik.cape.CapeManager;
import me.retucio.sputnik.command.CommandManager; import me.retucio.sputnik.command.CommandManager;
import me.retucio.sputnik.command.commands.BindCommand; 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.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.lwjgl.glfw.GLFW;
public class Sputnik implements ClientModInitializer { public class Sputnik implements ClientModInitializer {
@@ -157,32 +156,64 @@ public class Sputnik implements ClientModInitializer {
// se ejecuta cada vez que se presiona una tecla // se ejecuta cada vez que se presiona una tecla
public void onInput(int key, int action) { 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 // prevenir interrumpir combos de F3
if (key == GLFW.GLFW_KEY_F3) return; if (key == InputConstants.KEY_F3) return;
boolean anyFocused = isAnySettingButtonFocused() || ClickGui.INSTANCE.isCapturingInput(); boolean anyFocused = isAnySettingButtonFocused() || ClickGui.INSTANCE.isCapturingInput();
ClickGui.INSTANCE.setAnyFocused(anyFocused); 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 (BindCommand.onKeyPress(key)) return;
if (action == GLFW.GLFW_PRESS && MacroManager.INSTANCE.onKeyPress(key)) return; if (action == InputConstants.PRESS && MacroManager.INSTANCE.onKeyPress(key)) return;
if (action == GLFW.GLFW_PRESS) { if (action == InputConstants.PRESS) {
handleModuleToggle(key, anyFocused); handleModuleToggle(key, anyFocused);
handleClickGuiKey(key, anyFocused); handleClickGuiKey(key, anyFocused);
handleHudEditorKey(key, anyFocused); handleHudEditorKey(key, anyFocused);
} }
// solo reenviar teclas del teclado
if (key >= 32) {
handleSettingButtonsKey(key, action);
}
} else if (!anyFocused) { } else if (!anyFocused) {
handleModuleRelease(key); 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 // verifica si algún botón de ajustes está escuchando
private boolean isAnySettingButtonFocused() { private boolean isAnySettingButtonFocused() {
if (ClickGui.INSTANCE == null) return false; 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 (SettingsPanel sf : ClickGui.INSTANCE.getSettingsPanels())
for (Button sb : sf.getButtons()) for (Button sb : sf.getButtons())
if ((sb instanceof BindButton b && b.isFocused()) if ((sb instanceof BindButton b && b.isFocused())
@@ -200,7 +231,7 @@ public class Sputnik implements ClientModInitializer {
for (Module module : ModuleManager.INSTANCE.getModules()) { for (Module module : ModuleManager.INSTANCE.getModules()) {
// evitar interrumpir combinaciones de teclas del F3 // evitar interrumpir combinaciones de teclas del F3
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()) if (module.shouldToggleOnBindRelease() && !module.isEnabled())
module.setEnabled(true); 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 // se ocupa de hacer los botones de ajustes que lo necesiten escuchar teclas
private void handleSettingButtonsKey(int key, int action) { private void handleSettingButtonsKey(int key, int action) {
ClickGui.INSTANCE.getClientSettingsPanel().onKey(key, action);
for (SettingsPanel sf : ClickGui.INSTANCE.getSettingsPanels()) { for (SettingsPanel sf : ClickGui.INSTANCE.getSettingsPanels()) {
for (SettingButton<?> sb : sf.getButtons()) { for (SettingButton<?> sb : sf.getButtons()) {
if (sb instanceof BindButton bb) bb.onKey(key, action); if (sb instanceof BindButton bb) bb.onKey(key, action);
@@ -16,7 +16,7 @@ import java.util.List;
public abstract class Command { public abstract class Command {
// utilizar los "registries" ya existentes de Brigadier para el autocompletado // 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 int SUCCESS = com.mojang.brigadier.Command.SINGLE_SUCCESS;
protected static final Minecraft mc = Minecraft.getInstance(); protected static final Minecraft mc = Minecraft.getInstance();
@@ -36,11 +36,12 @@ public class MacroCommand extends Command {
list(); list();
return SUCCESS; return SUCCESS;
})) }))
// por ahora "add" solo crea macros de chat
.then(literal("add") .then(literal("add")
.then(argument("nombre", StringArgumentType.word()).executes(ctx -> { .then(argument("nombre", StringArgumentType.word()).executes(ctx -> {
String name = ctx.getArgument("nombre", String.class); 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", ChatUtil.info(Component.translatable("sputnik.commands.macro.added",
ChatFormatting.AQUA + name)); ChatFormatting.AQUA + name));
else else
@@ -60,7 +61,7 @@ public class MacroCommand extends Command {
.then(literal("line") .then(literal("line")
.then(argument("nombre", StringArgumentType.word()).suggests(MACROS) .then(argument("nombre", StringArgumentType.word()).suggests(MACROS)
.then(argument("línea", StringArgumentType.greedyString()).executes(ctx -> { .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; if (macro == null) return SUCCESS;
String line = ctx.getArgument("línea", String.class); String line = ctx.getArgument("línea", String.class);
@@ -73,7 +74,7 @@ public class MacroCommand extends Command {
})))) }))))
.then(literal("clear") .then(literal("clear")
.then(argument("nombre", StringArgumentType.word()).suggests(MACROS).executes(ctx -> { .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; if (macro == null) return SUCCESS;
macro.getLines().clear(); macro.getLines().clear();
@@ -97,6 +98,19 @@ public class MacroCommand extends Command {
return macro; 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() { private static void list() {
List<Macro> macros = MacroManager.INSTANCE.getMacros(); List<Macro> macros = MacroManager.INSTANCE.getMacros();
@@ -106,9 +120,17 @@ public class MacroCommand extends Command {
} }
ChatUtil.info(Component.translatable("sputnik.commands.macro.list", macros.size())); 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() ChatUtil.addMessage(ChatFormatting.GRAY + " - " + macro.getName()
+ ChatFormatting.DARK_GRAY + " [" + KeyUtil.getKeyName(macro.getKey()) + "] " + ChatFormatting.DARK_GRAY + " [" + KeyUtil.getKeyName(macro.getKey()) + "] "
+ macro.getLines().size()); + count);
}
} }
} }
@@ -50,7 +50,7 @@ public class SendCommand extends Command {
message, message,
instant, instant,
salt, salt,
messageSignature, java.util.Optional.ofNullable(messageSignature),
lastSeenMessages.update() lastSeenMessages.update()
)); ));
} }
@@ -8,7 +8,7 @@ import me.retucio.sputnik.event.input.KeyEvent;
import me.retucio.sputnik.util.EntityUtil; import me.retucio.sputnik.util.EntityUtil;
import net.minecraft.commands.SharedSuggestionProvider; import net.minecraft.commands.SharedSuggestionProvider;
import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Entity;
import org.lwjgl.glfw.GLFW; import com.mojang.blaze3d.platform.InputConstants;
import java.awt.*; import java.awt.*;
@@ -43,7 +43,7 @@ public class SpectateCommand extends Command {
@EventListener @EventListener
public void onKey(KeyEvent event) { public void onKey(KeyEvent event) {
if (mc.getCameraEntity() != mc.player && mc.gui.screen() == null 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(); event.cancel();
mc.setCameraEntity(mc.player); mc.setCameraEntity(mc.player);
} }
@@ -1,6 +1,7 @@
package me.retucio.sputnik.config; package me.retucio.sputnik.config;
import me.retucio.sputnik.util.I18nUtil; import me.retucio.sputnik.util.I18nUtil;
import me.retucio.sputnik.util.KeyUtil;
import java.io.*; import java.io.*;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
@@ -14,7 +15,7 @@ import java.util.Map;
public class BinarySerializer { public class BinarySerializer {
private static final int MAGIC_NUMBER = 0x53505554; // "SPUT" 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 int MIN_VERSION = 2;
private static final byte TYPE_NULL = 0; 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_INT_ARRAY = 6;
private static final byte TYPE_FRAME_DATA = 7; 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 { public static void writeConfig(ClientConfig config, File file) throws IOException {
byte[] bytes = toBytes(config); byte[] bytes = toBytes(config);
writeBytes(bytes, file); writeBytes(bytes, file);
@@ -127,7 +131,12 @@ public class BinarySerializer {
? readFriendsMap(in) ? readFriendsMap(in)
: migrateFriendsMap(readStringStringMap(in)); : migrateFriendsMap(readStringStringMap(in));
List<ClientConfig.MacroData> macros = version >= 3 ? readMacros(in) : new ArrayList<>(); // v3 y v4: macros sin tipo (todas eran de chat). v5+: con tipo
List<ClientConfig.MacroData> macros;
if (version >= 5) macros = readMacros(in);
else if (version >= 3) macros = readLegacyMacros(in);
else macros = new ArrayList<>();
String currentProfile = version >= 3 ? readString(in) : ""; String currentProfile = version >= 3 ? readString(in) : "";
// leer pos. de la barra de búsqueda // leer pos. de la barra de búsqueda
@@ -147,11 +156,22 @@ public class BinarySerializer {
config.macros = macros; config.macros = macros;
config.currentProfile = currentProfile == null ? "" : currentProfile; config.currentProfile = currentProfile == null ? "" : currentProfile;
if (searchBarPosition != null) config.searchBarPosition = searchBarPosition; if (searchBarPosition != null) config.searchBarPosition = searchBarPosition;
config.legacyKeyCodes = version < 6;
return config; return config;
} }
} }
public static void migrateLegacyKeyCodes(ClientConfig config) {
config.macros = config.macros.stream().map(macro -> {
int key = KeyUtil.fromLegacyGlfwKey(macro.key());
List<ClientConfig.KeyData> 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<String, Boolean> map) private static void writeStringBooleanMap(DataOutputStream out, Map<String, Boolean> map)
throws IOException { throws IOException {
if (map == null) { if (map == null) {
@@ -395,6 +415,9 @@ public class BinarySerializer {
return map; 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<ClientConfig.MacroData> macros) private static void writeMacros(DataOutputStream out, List<ClientConfig.MacroData> macros)
throws IOException { throws IOException {
if (macros == null) { if (macros == null) {
@@ -403,14 +426,59 @@ public class BinarySerializer {
} }
out.writeInt(macros.size()); out.writeInt(macros.size());
for (ClientConfig.MacroData macro : macros) { for (ClientConfig.MacroData macro : macros) {
boolean keybind = macro.type() == ClientConfig.MacroType.KEYBIND;
out.writeByte(keybind ? MACRO_KEYBIND : MACRO_CHAT);
writeString(out, macro.name()); writeString(out, macro.name());
out.writeInt(macro.key()); out.writeInt(macro.key());
out.writeInt(macro.lines().size());
for (String line : macro.lines()) writeString(out, line); if (keybind) {
List<ClientConfig.KeyData> 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<String> lines = macro.lines() == null ? List.of() : macro.lines();
out.writeInt(lines.size());
for (String line : lines) writeString(out, line);
}
} }
} }
private static List<ClientConfig.MacroData> readMacros(DataInputStream in) throws IOException { private static List<ClientConfig.MacroData> readMacros(DataInputStream in) throws IOException {
int size = in.readInt();
List<ClientConfig.MacroData> 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<String> 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<ClientConfig.KeyData> 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<ClientConfig.MacroData> readLegacyMacros(DataInputStream in) throws IOException {
int size = in.readInt(); int size = in.readInt();
List<ClientConfig.MacroData> macros = new ArrayList<>(size); List<ClientConfig.MacroData> macros = new ArrayList<>(size);
for (int i = 0; i < size; i++) { for (int i = 0; i < size; i++) {
@@ -419,7 +487,7 @@ public class BinarySerializer {
int lineCount = in.readInt(); int lineCount = in.readInt();
List<String> lines = new ArrayList<>(lineCount); List<String> lines = new ArrayList<>(lineCount);
for (int j = 0; j < lineCount; j++) lines.add(readString(in)); 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; return macros;
} }
@@ -45,11 +45,15 @@ public class ClientConfig {
// amigos: uuid -> FriendData (nombre, apodo, fecha) // amigos: uuid -> FriendData (nombre, apodo, fecha)
public Map<String, FriendData> friends = new HashMap<>(); public Map<String, FriendData> friends = new HashMap<>();
// macros, de cualquier tipo (ver MacroData)
public List<MacroData> macros = new ArrayList<>(); public List<MacroData> macros = new ArrayList<>();
// perfil cargado actualmente, vacío si es la config. suelta // perfil cargado actualmente, vacío si es la config. suelta
public String currentProfile = ""; public String currentProfile = "";
// Set only when loading a config written with GLFW keycodes (pre-26.3).
public transient boolean legacyKeyCodes;
public ClientConfig() { public ClientConfig() {
EVENT_BUS.subscribe(this); EVENT_BUS.subscribe(this);
} }
@@ -183,7 +187,23 @@ public class ClientConfig {
@Serial private static final long serialVersionUID = 1L; @Serial private static final long serialVersionUID = 1L;
} }
public record MacroData(String name, int key, List<String> lines) implements Serializable { public enum MacroType { CHAT, KEYBIND }
public record KeyData(int key, int action) implements Serializable {
@Serial private static final long serialVersionUID = 1L; @Serial private static final long serialVersionUID = 1L;
} }
public record MacroData(MacroType type, String name, int key,
List<String> lines, List<KeyData> keys
) implements Serializable {
@Serial private static final long serialVersionUID = 2L;
public static MacroData chat(String name, int key, List<String> lines) {
return new MacroData(MacroType.CHAT, name, key, List.copyOf(lines), List.of());
}
public static MacroData keybind(String name, int key, List<KeyData> keys) {
return new MacroData(MacroType.KEYBIND, name, key, List.of(), List.copyOf(keys));
}
}
} }
@@ -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.settings.ClientSettingsPanel;
import me.retucio.sputnik.ui.widgets.panels.SettingsPanel; import me.retucio.sputnik.ui.widgets.panels.SettingsPanel;
import me.retucio.sputnik.util.I18nUtil; import me.retucio.sputnik.util.I18nUtil;
import me.retucio.sputnik.util.KeyUtil;
import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Component;
import java.io.File; import java.io.File;
@@ -151,6 +152,7 @@ public class ConfigManager {
try (FileReader reader = new FileReader(LEGACY_JSON_FILE)) { try (FileReader reader = new FileReader(LEGACY_JSON_FILE)) {
Gson gson = new GsonBuilder().setPrettyPrinting().create(); Gson gson = new GsonBuilder().setPrettyPrinting().create();
setConfig(gson.fromJson(reader, ClientConfig.class)); setConfig(gson.fromJson(reader, ClientConfig.class));
config.legacyKeyCodes = true;
Sputnik.LOGGER.info(I18nUtil.fmt("sputnik.config.info.json", Sputnik.LOGGER.info(I18nUtil.fmt("sputnik.config.info.json",
"ajustes json cargados (migración)")); "ajustes json cargados (migración)"));
@@ -175,7 +177,9 @@ public class ConfigManager {
if (!shouldApply()) return false; if (!shouldApply()) return false;
applying = true; applying = true;
boolean migratedKeys = config.legacyKeyCodes;
try { try {
migrateLegacyKeyCodes();
// los del mod primero: entre ellos está "teclas multimódulo", que decide si al // 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, // 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 // 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; loaded = true;
} }
if (migratedKeys) writeSnapshot(true);
return 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 // 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 // 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 // para no reescribir en la config. lo que se le está aplicando
@@ -299,7 +326,7 @@ public class ConfigManager {
public void setMacros(List<Macro> macros) { public void setMacros(List<Macro> macros) {
ensureConfig(); ensureConfig();
config.macros = macros.stream() config.macros = macros.stream()
.map(macro -> new ClientConfig.MacroData(macro.getName(), macro.getKey(), List.copyOf(macro.getLines()))) .map(ConfigManager::toMacroData)
.toList(); .toList();
markDirty(); markDirty();
} }
@@ -323,12 +350,40 @@ public class ConfigManager {
Sputnik.LOGGER.info(I18nUtil.fmt("sputnik.config.info.friends", Sputnik.LOGGER.info(I18nUtil.fmt("sputnik.config.info.friends",
"amigos aplicados")); "amigos aplicados"));
} }
public void applyMacros() { public void applyMacros() {
MacroManager.INSTANCE.setMacros(config.macros.stream() MacroManager.INSTANCE.setMacros(config.macros.stream()
.map(data -> new Macro(data.name(), data.key(), data.lines())) .map(ConfigManager::fromMacroData)
.toList()); .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<Macro.Keybind.Key> 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 // el HudRenderer coloca sus elementos al construirse, pero al cambiar de perfil ya existen
public void applyHudElements() { public void applyHudElements() {
if (HudRenderer.INSTANCE == null) return; if (HudRenderer.INSTANCE == null) return;
@@ -592,8 +647,6 @@ public class ConfigManager {
ClientSettingsModule settings = ClientSettingsPanel.clientSettings; ClientSettingsModule settings = ClientSettingsPanel.clientSettings;
if (!settings.autosave.getValue()) return; 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); long intervalMs = (long) (settings.autosaveInterval.getValue() * 1000);
if (System.currentTimeMillis() - lastSaveTime < intervalMs) return; if (System.currentTimeMillis() - lastSaveTime < intervalMs) return;
@@ -1,38 +1,22 @@
package me.retucio.sputnik.macro; package me.retucio.sputnik.macro;
import me.retucio.sputnik.util.ChatUtil; import me.retucio.sputnik.util.ChatUtil;
import me.retucio.sputnik.util.KeyUtil;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import org.lwjgl.glfw.GLFW; import com.mojang.blaze3d.platform.InputConstants;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
public class Macro { public abstract class Macro {
private String name; protected String name;
private int key; protected int key;
private final List<String> lines = new ArrayList<>();
private boolean searchMatch = true; protected Macro(String name, int key) {
public Macro(String name) {
this(name, GLFW.GLFW_KEY_UNKNOWN, List.of());
}
public Macro(String name, int key, List<String> lines) {
this.name = name; this.name = name;
this.key = key; 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; } public String getName() { return name; }
@@ -41,13 +25,80 @@ public class Macro {
public int getKey() { return key; } public int getKey() { return key; }
public void setKey(int key) { this.key = key; } public void setKey(int key) { this.key = key; }
public List<String> getLines() { return 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<String> lines = new ArrayList<>();
public Chat(String name) {
this(name, InputConstants.UNKNOWN.getValue(), List.of());
}
public Chat(String name, int key, List<String> 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<String> getLines() {
return lines;
}
public void setLines(List<String> lines) { public void setLines(List<String> lines) {
this.lines.clear(); this.lines.clear();
this.lines.addAll(lines); this.lines.addAll(lines);
} }
}
public boolean isSearchMatch() { return searchMatch; }
public void setSearchMatch(boolean searchMatch) { this.searchMatch = searchMatch; } public static class Keybind extends Macro {
private final List<Key> keys = new ArrayList<>();
public Keybind(String name) {
this(name, InputConstants.UNKNOWN.getValue(), List.of());
}
public Keybind(String name, int key, List<Key> keys) {
super(name, key);
this.keys.addAll(keys);
}
@Override
public void run() {
for (Key k : keys) {
k.use();
}
}
public List<Key> getKeys() {
return keys;
}
public void setKeys(List<Key> keys) {
this.keys.clear();
this.keys.addAll(keys);
}
public record Key(int key, int action) {
public void use() {
KeyUtil.pressKey(key, action);
}
}
}
} }
@@ -2,7 +2,7 @@ package me.retucio.sputnik.macro;
import me.retucio.sputnik.config.ConfigManager; import me.retucio.sputnik.config.ConfigManager;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import org.lwjgl.glfw.GLFW; import com.mojang.blaze3d.platform.InputConstants;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@@ -14,6 +14,9 @@ public class MacroManager {
private final List<Macro> macros = new ArrayList<>(); private final List<Macro> macros = new ArrayList<>();
// para evitar disparar un macro que presiona su propia tecla infinitamente
private boolean running = false;
public boolean add(Macro macro) { public boolean add(Macro macro) {
if (getByName(macro.getName()) != null) return false; if (getByName(macro.getName()) != null) return false;
macros.add(macro); macros.add(macro);
@@ -34,8 +37,10 @@ public class MacroManager {
} }
public boolean onKeyPress(int key) { 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;
running = true;
try {
boolean ran = false; boolean ran = false;
for (Macro macro : new ArrayList<>(macros)) { for (Macro macro : new ArrayList<>(macros)) {
if (macro.getKey() != key) continue; if (macro.getKey() != key) continue;
@@ -43,6 +48,9 @@ public class MacroManager {
ran = true; ran = true;
} }
return ran; return ran;
} finally {
running = false;
}
} }
public void setMacros(List<Macro> macros) { public void setMacros(List<Macro> macros) {
@@ -1,6 +1,7 @@
package me.retucio.sputnik.mixin.accessors; package me.retucio.sputnik.mixin.accessors;
import net.minecraft.client.renderer.item.ItemStackRenderState; import net.minecraft.client.renderer.item.ItemStackRenderState;
import net.minecraft.client.resources.model.geometry.ItemQuads;
import net.minecraft.client.resources.model.cuboid.ItemTransform; import net.minecraft.client.resources.model.cuboid.ItemTransform;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor; import org.spongepowered.asm.mixin.gen.Accessor;
@@ -11,4 +12,7 @@ public interface LayerRenderStateAccessor {
@Accessor("itemTransform") @Accessor("itemTransform")
ItemTransform sputnik$getTransform(); ItemTransform sputnik$getTransform();
@Accessor("quads")
ItemQuads sputnik$getQuads();
} }
@@ -1,7 +1,7 @@
package me.retucio.sputnik.mixin.mixins.hud; package me.retucio.sputnik.mixin.mixins.hud;
import com.llamalad7.mixinextras.injector.ModifyExpressionValue; 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.Sputnik;
import me.retucio.sputnik.event.render.Render2DEvent; import me.retucio.sputnik.event.render.Render2DEvent;
import me.retucio.sputnik.module.ModuleManager; import me.retucio.sputnik.module.ModuleManager;
@@ -79,7 +79,7 @@ public abstract class HudMixin {
HudRenderer.INSTANCE.render(gui, dt); 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) { private void onRenderCrosshair(GuiGraphicsExtractor gui, RenderPipeline pipeline, Identifier id, int x, int y, int width, int height) {
// dangerous abbreviation // dangerous abbreviation
CrosshairPlus cp = ModuleManager.INSTANCE.getModuleByClass(CrosshairPlus.class); CrosshairPlus cp = ModuleManager.INSTANCE.getModuleByClass(CrosshairPlus.class);
@@ -2,6 +2,7 @@ package me.retucio.sputnik.mixin.mixins.io;
import me.retucio.sputnik.Sputnik; import me.retucio.sputnik.Sputnik;
import me.retucio.sputnik.event.input.KeyEvent; import me.retucio.sputnik.event.input.KeyEvent;
import com.mojang.blaze3d.platform.InputConstants;
import net.minecraft.client.KeyboardHandler; import net.minecraft.client.KeyboardHandler;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
@@ -14,9 +15,9 @@ public abstract class KeyboardHandlerMixin {
@Inject(method = "keyPress", at = @At("HEAD"), cancellable = true) @Inject(method = "keyPress", at = @At("HEAD"), cancellable = true)
private void onKeyPress(long handle, int action, net.minecraft.client.input.KeyEvent input, CallbackInfo ci) { 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); 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(); if (event.isCancelled()) ci.cancel();
} }
} }
@@ -16,7 +16,10 @@ public abstract class MouseHandlerMixin {
@Inject(method = "onButton", at = @At("HEAD"), cancellable = true) @Inject(method = "onButton", at = @At("HEAD"), cancellable = true)
private void onMouseButton(long handle, MouseButtonInfo input, int action, CallbackInfo ci) { 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())); MouseClickEvent event = Sputnik.EVENT_BUS.post(new MouseClickEvent(action, input.button()));
if (event.isCancelled()) ci.cancel(); if (event.isCancelled()) ci.cancel();
} }
@@ -3,18 +3,13 @@ package me.retucio.sputnik.mixin.mixins.network;
import com.mojang.brigadier.exceptions.CommandSyntaxException; import com.mojang.brigadier.exceptions.CommandSyntaxException;
import me.retucio.sputnik.command.CommandManager; import me.retucio.sputnik.command.CommandManager;
import me.retucio.sputnik.event.network.SendMessageEvent; 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 me.retucio.sputnik.util.ChatUtil;
import net.minecraft.client.multiplayer.ClientPacketListener; 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.Mixin;
import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import static me.retucio.sputnik.Sputnik.*; import static me.retucio.sputnik.Sputnik.*;
@@ -51,11 +46,4 @@ public abstract class ClientPacketListenerMixin {
mc.gui.hud.getChat().addRecentChat(content); mc.gui.hud.getChat().addRecentChat(content);
ci.cancel(); 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);
}
} }
@@ -1,17 +1,17 @@
package me.retucio.sputnik.mixin.mixins.network; package me.retucio.sputnik.mixin.mixins.network;
import com.mojang.authlib.yggdrasil.YggdrasilUserApiService; import com.mojang.authlib.services.MinecraftServicesUserApiService;
import com.mojang.authlib.yggdrasil.response.UserAttributesResponse; import com.mojang.authlib.services.response.UserAttributesResponse;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.Redirect;
// código robado de: https://github.com/kb-1000/no-telemetry // código robado de: https://github.com/kb-1000/no-telemetry
@Mixin(YggdrasilUserApiService.class) @Mixin(MinecraftServicesUserApiService.class)
public abstract class YggdrasilUserApiServiceMixin { 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) { private boolean getTelemetry(UserAttributesResponse.Privileges instance) {
return false; return false;
} }
@@ -4,6 +4,7 @@ import me.retucio.sputnik.module.ModuleManager;
import me.retucio.sputnik.module.modules.render.GlintPlus; import me.retucio.sputnik.module.modules.render.GlintPlus;
import net.minecraft.client.renderer.entity.layers.EquipmentLayerRenderer; import net.minecraft.client.renderer.entity.layers.EquipmentLayerRenderer;
import net.minecraft.client.renderer.rendertype.RenderType; import net.minecraft.client.renderer.rendertype.RenderType;
import net.minecraft.resources.Identifier;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.ModifyVariable; import org.spongepowered.asm.mixin.injection.ModifyVariable;
@@ -12,9 +13,9 @@ import org.spongepowered.asm.mixin.injection.Redirect;
@Mixin(EquipmentLayerRenderer.class) @Mixin(EquipmentLayerRenderer.class)
public abstract class EquipmentLayerRendererMixin { 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;")) @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() { private RenderType redirectArmorEntityGlint(Identifier texture) {
GlintPlus glintPlus = ModuleManager.INSTANCE.getModuleByClass(GlintPlus.class); GlintPlus glintPlus = ModuleManager.INSTANCE.getModuleByClass(GlintPlus.class);
return glintPlus.getArmorEntityGlint(); return glintPlus.getArmorEntityGlint(texture);
} }
} }
@@ -15,8 +15,11 @@ import com.mojang.blaze3d.resource.CrossFrameResourcePool;
import net.minecraft.client.DeltaTracker; import net.minecraft.client.DeltaTracker;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.GameRenderer; import net.minecraft.client.renderer.GameRenderer;
import net.minecraft.client.renderer.ItemInHandRenderer; import net.minecraft.client.renderer.FirstPersonHandsAndItemsRenderer;
import net.minecraft.client.renderer.state.level.CameraRenderState; 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 net.minecraft.client.resources.model.ModelManager;
import org.joml.Matrix4fc; import org.joml.Matrix4fc;
@@ -52,23 +55,20 @@ public abstract class GameRendererMixin {
private CrossFrameResourcePool resourcePool; private CrossFrameResourcePool resourcePool;
@Inject(method = "<init>", at = @At("TAIL")) @Inject(method = "<init>", 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);; zoom = ModuleManager.INSTANCE.getModuleByClass(Zoom.class);;
freecam = ModuleManager.INSTANCE.getModuleByClass(Freecam.class); freecam = ModuleManager.INSTANCE.getModuleByClass(Freecam.class);
noRender = ModuleManager.INSTANCE.getModuleByClass(NoRender.class); noRender = ModuleManager.INSTANCE.getModuleByClass(NoRender.class);
lsd = ModuleManager.INSTANCE.getModuleByClass(Lsd.class); lsd = ModuleManager.INSTANCE.getModuleByClass(Lsd.class);
} }
// se aplica justo donde vanilla mete sus efectos de post (nausea, etc.): el mundo ya está @Inject(method = "render", at = @At(value = "INVOKE", shift = At.Shift.AFTER, target = "Lnet/minecraft/client/renderer/LevelRenderer;blitEntityOutline()V"))
// en mainRenderTarget y el HUD todavía no, así que sólo distorsiona la escena 3D private void applyLsd(CallbackInfo ci) {
@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) {
if (lsd.isEnabled()) lsd.apply(mainRenderTarget, resourcePool); if (lsd.isEnabled()) lsd.apply(mainRenderTarget, resourcePool);
} }
@Inject(method = "render", at = @At("HEAD"), cancellable = true) @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()) { if (ModuleManager.INSTANCE.getModuleByClass(UnfocusedCpu.class).isEnabled() && !mc.isWindowActive()) {
ci.cancel(); ci.cancel();
} }
@@ -81,7 +81,7 @@ public abstract class GameRendererMixin {
@Inject(method = "renderItemInHand", at = @At("HEAD"), cancellable = true) @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()) if ((zoom.isEnabled() && !zoom.showHands.getValue())
|| (freecam.isEnabled() && !freecam.renderHands.getValue())) || (freecam.isEnabled() && !freecam.renderHands.getValue()))
ci.cancel(); ci.cancel();
@@ -3,11 +3,12 @@ package me.retucio.sputnik.mixin.mixins.render;
import me.retucio.sputnik.module.ModuleManager; import me.retucio.sputnik.module.ModuleManager;
import me.retucio.sputnik.module.modules.render.GlintPlus; import me.retucio.sputnik.module.modules.render.GlintPlus;
import net.minecraft.client.renderer.feature.ItemFeatureRenderer; 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.RenderType;
import net.minecraft.client.renderer.rendertype.RenderTypes;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect; import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
import com.llamalad7.mixinextras.sugar.Local;
@Mixin(ItemFeatureRenderer.class) @Mixin(ItemFeatureRenderer.class)
@@ -15,17 +16,15 @@ public abstract class ItemFeatureRendererMixin {
// obtener módulo en cada redirect, ya que tiene un inicializador estático // obtener módulo en cada redirect, ya que tiene un inicializador estático
@Redirect(method = "getFoilBuffer", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/rendertype/RenderTypes;glint()Lnet/minecraft/client/renderer/rendertype/RenderType;")) @ModifyExpressionValue(method = "prepareMainSubmit", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/resources/model/geometry/BakedQuad$MaterialInfo;itemGlintRenderType()Lnet/minecraft/client/renderer/rendertype/RenderType;"))
private static RenderType redirectGlint() { private RenderType sputnik$colorGlint(RenderType original, @Local BakedQuad.MaterialInfo materialInfo) {
GlintPlus glintPlus = ModuleManager.INSTANCE.getModuleByClass(GlintPlus.class); GlintPlus glintPlus = ModuleManager.INSTANCE.getModuleByClass(GlintPlus.class);
if (glintPlus == null) return RenderTypes.glint(); return glintPlus == null ? original : glintPlus.getGlint(original, materialInfo);
return glintPlus.getGlint();
} }
@Redirect(method = "getFoilBuffer", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/rendertype/RenderTypes;glintTranslucent()Lnet/minecraft/client/renderer/rendertype/RenderType;")) @ModifyExpressionValue(method = "prepareMainSubmit", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/resources/model/geometry/BakedQuad$MaterialInfo;itemGlintSpecialRenderType()Lnet/minecraft/client/renderer/rendertype/RenderType;"))
private static RenderType redirectGlintTranslucent() { private RenderType sputnik$colorSpecialGlint(RenderType original, @Local BakedQuad.MaterialInfo materialInfo) {
GlintPlus glintPlus = ModuleManager.INSTANCE.getModuleByClass(GlintPlus.class); GlintPlus glintPlus = ModuleManager.INSTANCE.getModuleByClass(GlintPlus.class);
if (glintPlus == null) return RenderTypes.glintTranslucent(); return glintPlus == null ? original : glintPlus.getGlint(original, materialInfo);
return glintPlus.getGlintTranslucent();
} }
} }
@@ -7,7 +7,7 @@ import me.retucio.sputnik.event.render.RenderArmEvent;
import me.retucio.sputnik.module.ModuleManager; import me.retucio.sputnik.module.ModuleManager;
import me.retucio.sputnik.module.modules.render.HandView; import me.retucio.sputnik.module.modules.render.HandView;
import net.minecraft.client.player.AbstractClientPlayer; 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.client.renderer.SubmitNodeCollector;
import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionHand;
import net.minecraft.world.entity.HumanoidArm; import net.minecraft.world.entity.HumanoidArm;
@@ -23,7 +23,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import static me.retucio.sputnik.Sputnik.*; import static me.retucio.sputnik.Sputnik.*;
@Mixin(ItemInHandRenderer.class) @Mixin(FirstPersonHandsAndItemsRenderer.class)
public abstract class ItemInHandRendererMixin { public abstract class ItemInHandRendererMixin {
@Unique @Unique
@@ -49,12 +49,12 @@ public abstract class ItemInHandRendererMixin {
handView = ModuleManager.INSTANCE.getModuleByClass(HandView.class); 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) { private void onRenderItem(AbstractClientPlayer player, float frameInterp, float xRot, InteractionHand hand, float attack, ItemStack itemStack, float inverseArmHeight, PoseStack matrices, SubmitNodeCollector submitNodeCollector, int lightCoords, CallbackInfo ci) {
EVENT_BUS.post(new RenderHeldItemEvent(matrices, hand)); EVENT_BUS.post(new RenderHeldItemEvent(matrices, hand));
} }
@Inject(method = "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) { private void onRenderArm(AbstractClientPlayer player, float frameInterp, float xRot, InteractionHand hand, float attack, ItemStack itemStack, float inverseArmHeight, PoseStack matrices, SubmitNodeCollector submitNodeCollector, int lightCoords, CallbackInfo ci) {
EVENT_BUS.post(new RenderArmEvent(matrices, hand)); EVENT_BUS.post(new RenderArmEvent(matrices, hand));
} }
@@ -1,7 +1,6 @@
package me.retucio.sputnik.mixin.mixins.render; package me.retucio.sputnik.mixin.mixins.render;
import com.llamalad7.mixinextras.sugar.Local; import com.mojang.renderpearl.api.buffers.GpuBufferSlice;
import com.mojang.blaze3d.buffers.GpuBufferSlice;
import com.mojang.blaze3d.resource.GraphicsResourceAllocator; import com.mojang.blaze3d.resource.GraphicsResourceAllocator;
import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.math.Axis; 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.camera.Freecam;
import me.retucio.sputnik.module.modules.render.BreakingProgress; import me.retucio.sputnik.module.modules.render.BreakingProgress;
import me.retucio.sputnik.util.render.SputnikBuffers; import me.retucio.sputnik.util.render.SputnikBuffers;
import net.minecraft.client.DeltaTracker;
import net.minecraft.client.renderer.GameRenderer; import net.minecraft.client.renderer.GameRenderer;
import net.minecraft.client.renderer.LevelRenderer; import net.minecraft.client.renderer.LevelRenderer;
import net.minecraft.client.renderer.ShaderManager; 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.ModelManager;
import net.minecraft.client.resources.model.sprite.AtlasManager; import net.minecraft.client.resources.model.sprite.AtlasManager;
import net.minecraft.util.profiling.ProfilerFiller; import net.minecraft.util.profiling.ProfilerFiller;
import net.minecraft.util.profiling.Profiler;
import org.joml.Matrix4fc; import org.joml.Matrix4fc;
import org.joml.Vector4f; import org.joml.Vector4f;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
@@ -49,17 +48,20 @@ public abstract class LevelRendererMixin {
} }
@Inject(method = "render", at = @At("RETURN")) @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; if (mc == null || mc.level == null) return;
ProfilerFiller profiler = Profiler.get();
PoseStack matrices = new PoseStack(); PoseStack matrices = new PoseStack();
matrices.pushPose(); matrices.pushPose();
matrices.mulPose(Axis.XP.rotationDegrees(cameraState.xRot)); matrices.rotate(Axis.XP.rotationDegrees(cameraState.xRot));
matrices.mulPose(Axis.YP.rotationDegrees(cameraState.yRot + 180f)); matrices.rotate(Axis.YP.rotationDegrees(cameraState.yRot + 180f));
profiler.push(Sputnik.MOD_ID + "-3d"); 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 SputnikBuffers.flush(); // antes de que empiece el hud
profiler.pop(); profiler.pop();
@@ -1,7 +1,7 @@
package me.retucio.sputnik.mixin.mixins.render; package me.retucio.sputnik.mixin.mixins.render;
import com.mojang.blaze3d.systems.RenderSystem; 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.ModuleManager;
import me.retucio.sputnik.module.modules.camera.Fullbright; import me.retucio.sputnik.module.modules.camera.Fullbright;
import net.minecraft.client.renderer.Lightmap; import net.minecraft.client.renderer.Lightmap;
@@ -3,9 +3,9 @@ package me.retucio.sputnik.mixin.mixins.render;
import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.PoseStack;
import me.retucio.sputnik.module.ModuleManager; import me.retucio.sputnik.module.ModuleManager;
import me.retucio.sputnik.module.modules.render.NoRender; import me.retucio.sputnik.module.modules.render.NoRender;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.ScreenEffectRenderer; import net.minecraft.client.renderer.ScreenEffectRenderer;
import net.minecraft.client.renderer.SubmitNodeCollector; import net.minecraft.client.renderer.SubmitNodeCollector;
import net.minecraft.client.renderer.state.level.PlayerRenderState;
import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.Unique;
@@ -31,7 +31,7 @@ public abstract class ScreenEffectRendererMixin {
} }
@Inject(method = "submitWater", at = @At("HEAD"), cancellable = true) @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(); if (noRender.isEnabled() && !noRender.fluidOverlay.getValue()) ci.cancel();
} }
} }
@@ -6,14 +6,23 @@ import net.minecraft.client.renderer.ShaderManager;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject; 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) @Mixin(ShaderManager.class)
public abstract class ShaderManagerMixin { 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")) @Inject(method = "reload", at = @At("RETURN"))
private void onReload(CallbackInfo ci) { private void onReload(PreparableReloadListener.SharedState state, Executor preparationExecutor,
PreparableReloadListener.PreparationBarrier barrier, Executor applyExecutor,
CallbackInfoReturnable<CompletableFuture<Void>> cir) {
cir.getReturnValue().thenRun(() -> {
Pipelines.init(); Pipelines.init();
PostShaders.reload(); PostShaders.reload();
});
} }
} }
@@ -1,6 +1,7 @@
package me.retucio.sputnik.mixin.mixins.render; package me.retucio.sputnik.mixin.mixins.render;
import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.renderpearl.api.commands.RenderPass;
import me.retucio.sputnik.module.ModuleManager; import me.retucio.sputnik.module.ModuleManager;
import me.retucio.sputnik.module.modules.render.NoRender; import me.retucio.sputnik.module.modules.render.NoRender;
import me.retucio.sputnik.module.modules.world.TimeChanger; import me.retucio.sputnik.module.modules.world.TimeChanger;
@@ -26,17 +27,17 @@ public abstract class SkyRendererMixin {
} }
@Inject(method = "renderSun", at = @At("HEAD"), cancellable = true) @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(); if (timeChanger.isEnabled() && !timeChanger.renderSun.getValue()) ci.cancel();
} }
@Inject(method = "renderMoon", at = @At("HEAD"), cancellable = true) @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.isEnabled()) return;
if (!timeChanger.renderMoon.getValue()) ci.cancel(); 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) { private MoonPhase timeChangerMoonPhase(MoonPhase original) {
if (!timeChanger.isEnabled() || timeChanger.moonPhase.is(TimeChanger.MoonPhases.DEFAULT)) return original; if (!timeChanger.isEnabled() || timeChanger.moonPhase.is(TimeChanger.MoonPhases.DEFAULT)) return original;
int phase = timeChanger.moonPhase.getIndex(); int phase = timeChanger.moonPhase.getIndex();
@@ -45,12 +46,12 @@ public abstract class SkyRendererMixin {
} }
@Inject(method = "renderStars", at = @At("HEAD"), cancellable = true) @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(); if (timeChanger.isEnabled() && !timeChanger.renderStars.getValue()) ci.cancel();
} }
@Inject(method = "renderEndFlash", at = @At("HEAD"), cancellable = true) @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); NoRender noRender = ModuleManager.INSTANCE.getModuleByClass(NoRender.class);
if (noRender.isEnabled() && !noRender.endFlashes.getValue()) ci.cancel(); if (noRender.isEnabled() && !noRender.endFlashes.getValue()) ci.cancel();
} }
@@ -4,7 +4,7 @@ import me.retucio.sputnik.module.ModuleManager;
import me.retucio.sputnik.module.modules.render.NoRender; import me.retucio.sputnik.module.modules.render.NoRender;
import net.minecraft.client.renderer.WeatherEffectRenderer; import net.minecraft.client.renderer.WeatherEffectRenderer;
import net.minecraft.client.renderer.state.level.WeatherRenderState; import net.minecraft.client.renderer.state.level.WeatherRenderState;
import net.minecraft.world.phys.Vec3; import com.mojang.renderpearl.api.commands.RenderPass;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
@@ -24,7 +24,7 @@ public abstract class WeatherEffectRendererMixin {
} }
@Inject(method = "render", at = @At("HEAD")) @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.isEnabled()) {
if (!noRender.rain.getValue()) renderState.rainColumns.clear(); if (!noRender.rain.getValue()) renderState.rainColumns.clear();
if (!noRender.snow.getValue()) renderState.snowColumns.clear(); if (!noRender.snow.getValue()) renderState.snowColumns.clear();
@@ -1,6 +1,7 @@
package me.retucio.sputnik.module; package me.retucio.sputnik.module;
import com.github.retucio.neutrino.EventListener; import com.github.retucio.neutrino.EventListener;
import com.mojang.blaze3d.platform.InputConstants;
import me.retucio.sputnik.Sputnik; import me.retucio.sputnik.Sputnik;
import me.retucio.sputnik.config.ConfigManager; import me.retucio.sputnik.config.ConfigManager;
import me.retucio.sputnik.event.sputnik.ToggleModuleEvent; import me.retucio.sputnik.event.sputnik.ToggleModuleEvent;
@@ -16,7 +17,6 @@ import me.retucio.sputnik.util.Colors;
import me.retucio.sputnik.util.I18nUtil; import me.retucio.sputnik.util.I18nUtil;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Component;
import org.lwjgl.glfw.GLFW;
import java.awt.*; import java.awt.*;
import java.lang.reflect.Method; import java.lang.reflect.Method;
@@ -41,7 +41,7 @@ public class Module {
protected KeySetting bind = new KeySetting( protected KeySetting bind = new KeySetting(
"tecla", "tecla",
"tecla asignada al módulo, ESC para desactivar", "tecla asignada al módulo, ESC para desactivar",
GLFW.GLFW_KEY_UNKNOWN InputConstants.UNKNOWN.getValue()
).translationKey("sputnik.setting.common.bind"); ).translationKey("sputnik.setting.common.bind");
// dejar al usuario elegir si el módulo debería apagarse tras soltar su tecla asignada, o si la tecla debería alternar su estado // dejar al usuario elegir si el módulo debería apagarse tras soltar su tecla asignada, o si la tecla debería alternar su estado
@@ -1,6 +1,6 @@
package me.retucio.sputnik.module.modules.camera; 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.Category;
import me.retucio.sputnik.module.Module; import me.retucio.sputnik.module.Module;
import me.retucio.sputnik.module.setting.settings.ColorSetting; import me.retucio.sputnik.module.setting.settings.ColorSetting;
@@ -31,7 +31,7 @@ import net.minecraft.network.protocol.game.*;
import net.minecraft.util.Mth; import net.minecraft.util.Mth;
import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.Vec3;
import org.joml.Vector3d; import org.joml.Vector3d;
import org.lwjgl.glfw.GLFW; import com.mojang.blaze3d.platform.InputConstants;
/** continúa en: /** continúa en:
* @see CameraMixin * @see CameraMixin
@@ -104,7 +104,7 @@ public class Freecam extends Module {
private final KeySetting scrollKey = sgSpeed.add(new KeySetting( private final KeySetting scrollKey = sgSpeed.add(new KeySetting(
"tecla del scroll", "tecla del scroll",
"tecla a mantener pulsada para cambiar velocidad con el 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( private final NumberSetting scrollSens = sgSpeed.add(new NumberSetting(
@@ -128,7 +128,7 @@ public class Freecam extends Module {
super("cámara libre", super("cámara libre",
"permite a la cámara moverse independientemente del jugador. útil para explorar alrededores", "permite a la cámara moverse independientemente del jugador. útil para explorar alrededores",
Category.CAMERA, Category.CAMERA,
GLFW.GLFW_KEY_V); InputConstants.KEY_V);
speedSetting.onUpdate(newSpeed -> speed = newSpeed); speedSetting.onUpdate(newSpeed -> speed = newSpeed);
} }
@@ -262,37 +262,36 @@ public class Freecam extends Module {
Packet<?> packet = event.getPacket(); Packet<?> packet = event.getPacket();
if (packet instanceof ServerboundPlayerActionPacket if (packet instanceof ServerboundPlayerActionPacket
|| packet instanceof ServerboundUseItemOnPacket || packet instanceof ServerboundUseItemOnPacket
|| packet instanceof ServerboundUseItemPacket || packet instanceof ServerboundUseItemPacket) {
|| packet instanceof ServerboundSwingPacket) {
event.cancel(); event.cancel();
} }
} }
@EventListener @EventListener
private void onKey(KeyEvent event) { 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; if (mc.gui.screen() != null) return;
net.minecraft.client.input.KeyEvent key = new net.minecraft.client.input.KeyEvent(event.getKey(), event.getScancode(), 0); net.minecraft.client.input.KeyEvent key = new net.minecraft.client.input.KeyEvent(event.getKey(), event.getScancode(), 0);
boolean shouldCancel = true; boolean shouldCancel = true;
if (mc.options.keyUp.matches(key)) { if (mc.options.keyUp.matches(key)) {
forward = event.getAction() != GLFW.GLFW_RELEASE; forward = event.getAction() != InputConstants.RELEASE;
mc.options.keyUp.setDown(false); mc.options.keyUp.setDown(false);
} else if (mc.options.keyDown.matches(key)) { } else if (mc.options.keyDown.matches(key)) {
backward = event.getAction() != GLFW.GLFW_RELEASE; backward = event.getAction() != InputConstants.RELEASE;
mc.options.keyDown.setDown(false); mc.options.keyDown.setDown(false);
} else if (mc.options.keyRight.matches(key)) { } else if (mc.options.keyRight.matches(key)) {
right = event.getAction() != GLFW.GLFW_RELEASE; right = event.getAction() != InputConstants.RELEASE;
mc.options.keyRight.setDown(false); mc.options.keyRight.setDown(false);
} else if (mc.options.keyLeft.matches(key)) { } else if (mc.options.keyLeft.matches(key)) {
left = event.getAction() != GLFW.GLFW_RELEASE; left = event.getAction() != InputConstants.RELEASE;
mc.options.keyLeft.setDown(false); mc.options.keyLeft.setDown(false);
} else if (mc.options.keyJump.matches(key)) { } else if (mc.options.keyJump.matches(key)) {
up = event.getAction() != GLFW.GLFW_RELEASE; up = event.getAction() != InputConstants.RELEASE;
mc.options.keyJump.setDown(false); mc.options.keyJump.setDown(false);
} else if (mc.options.keyShift.matches(key)) { } else if (mc.options.keyShift.matches(key)) {
down = event.getAction() != GLFW.GLFW_RELEASE; down = event.getAction() != InputConstants.RELEASE;
mc.options.keyShift.setDown(false); mc.options.keyShift.setDown(false);
} else { } else {
shouldCancel = false; shouldCancel = false;
@@ -303,29 +302,29 @@ public class Freecam extends Module {
@EventListener @EventListener
private void onMouseClick(MouseClickEvent event) { // por si el restrasado del usuario usa el ratón para moverse private void onMouseClick(MouseClickEvent event) { // por si el restrasado del usuario usa el ratón para moverse
if (KeyUtil.isKeyDown(GLFW.GLFW_KEY_F3)) return; if (KeyUtil.isKeyDown(InputConstants.KEY_F3)) return;
if (mc.gui.screen() != null) return; if (mc.gui.screen() != null) return;
MouseButtonEvent click = new MouseButtonEvent(0, 0, new MouseButtonInfo(event.getButton(), 0)); MouseButtonEvent click = new MouseButtonEvent(0, 0, new MouseButtonInfo(event.getButton(), 0));
boolean shouldCancel = true; boolean shouldCancel = true;
if (mc.options.keyUp.matchesMouse(click)) { if (mc.options.keyUp.matchesMouse(click)) {
forward = event.getAction() != GLFW.GLFW_RELEASE; forward = event.getAction() != InputConstants.RELEASE;
mc.options.keyUp.setDown(false); mc.options.keyUp.setDown(false);
} else if (mc.options.keyDown.matchesMouse(click)) { } else if (mc.options.keyDown.matchesMouse(click)) {
backward = event.getAction() != GLFW.GLFW_RELEASE; backward = event.getAction() != InputConstants.RELEASE;
mc.options.keyDown.setDown(false); mc.options.keyDown.setDown(false);
} else if (mc.options.keyRight.matchesMouse(click)) { } else if (mc.options.keyRight.matchesMouse(click)) {
right = event.getAction() != GLFW.GLFW_RELEASE; right = event.getAction() != InputConstants.RELEASE;
mc.options.keyRight.setDown(false); mc.options.keyRight.setDown(false);
} else if (mc.options.keyLeft.matchesMouse(click)) { } else if (mc.options.keyLeft.matchesMouse(click)) {
left = event.getAction() != GLFW.GLFW_RELEASE; left = event.getAction() != InputConstants.RELEASE;
mc.options.keyLeft.setDown(false); mc.options.keyLeft.setDown(false);
} else if (mc.options.keyJump.matchesMouse(click)) { } else if (mc.options.keyJump.matchesMouse(click)) {
up = event.getAction() != GLFW.GLFW_RELEASE; up = event.getAction() != InputConstants.RELEASE;
mc.options.keyJump.setDown(false); mc.options.keyJump.setDown(false);
} else if (mc.options.keyShift.matchesMouse(click)) { } else if (mc.options.keyShift.matchesMouse(click)) {
down = event.getAction() != GLFW.GLFW_RELEASE; down = event.getAction() != InputConstants.RELEASE;
mc.options.keyShift.setDown(false); mc.options.keyShift.setDown(false);
} else { } else {
shouldCancel = false; shouldCancel = false;
@@ -9,7 +9,7 @@ import me.retucio.sputnik.module.setting.settings.NumberSetting;
import me.retucio.sputnik.util.KeyUtil; import me.retucio.sputnik.util.KeyUtil;
import net.minecraft.client.CameraType; import net.minecraft.client.CameraType;
import net.minecraft.util.Mth; import net.minecraft.util.Mth;
import org.lwjgl.glfw.GLFW; import com.mojang.blaze3d.platform.InputConstants;
/** continúa en: /** continúa en:
* @see CameraMixin * @see CameraMixin
@@ -37,7 +37,7 @@ public class Freelook extends Module {
super("perspectiva libre", super("perspectiva libre",
"te permite mover la cámara de la perspectiva sin mover la del jugador, o vice versa", "te permite mover la cámara de la perspectiva sin mover la del jugador, o vice versa",
Category.CAMERA, Category.CAMERA,
GLFW.GLFW_KEY_B); InputConstants.KEY_B);
keyMode.setDefaultValue(KeyMode.HOLD); keyMode.setDefaultValue(KeyMode.HOLD);
keyMode.setValue(KeyMode.HOLD); keyMode.setValue(KeyMode.HOLD);
@@ -75,18 +75,18 @@ public class Freelook extends Module {
for (int i = 0; i < (arrowSens.getValue() * 2); i++) { for (int i = 0; i < (arrowSens.getValue() * 2); i++) {
switch (mode.getValue()) { switch (mode.getValue()) {
case PLAYER -> { case PLAYER -> {
if (KeyUtil.isKeyDown(GLFW.GLFW_KEY_LEFT)) yaw -= 0.5f; if (KeyUtil.isKeyDown(InputConstants.KEY_LEFT)) yaw -= 0.5f;
if (KeyUtil.isKeyDown(GLFW.GLFW_KEY_RIGHT)) yaw += 0.5f; if (KeyUtil.isKeyDown(InputConstants.KEY_RIGHT)) yaw += 0.5f;
if (KeyUtil.isKeyDown(GLFW.GLFW_KEY_UP)) pitch -= 0.5f; if (KeyUtil.isKeyDown(InputConstants.KEY_UP)) pitch -= 0.5f;
if (KeyUtil.isKeyDown(GLFW.GLFW_KEY_DOWN)) pitch += 0.5f; if (KeyUtil.isKeyDown(InputConstants.KEY_DOWN)) pitch += 0.5f;
} case CAMERA -> { } case CAMERA -> {
float yaw = mc.player.getYRot(); float yaw = mc.player.getYRot();
float pitch = mc.player.getXRot(); float pitch = mc.player.getXRot();
if (KeyUtil.isKeyDown(GLFW.GLFW_KEY_LEFT)) yaw -= 0.5f; if (KeyUtil.isKeyDown(InputConstants.KEY_LEFT)) yaw -= 0.5f;
if (KeyUtil.isKeyDown(GLFW.GLFW_KEY_RIGHT)) yaw += 0.5f; if (KeyUtil.isKeyDown(InputConstants.KEY_RIGHT)) yaw += 0.5f;
if (KeyUtil.isKeyDown(GLFW.GLFW_KEY_UP)) pitch -= 0.5f; if (KeyUtil.isKeyDown(InputConstants.KEY_UP)) pitch -= 0.5f;
if (KeyUtil.isKeyDown(GLFW.GLFW_KEY_DOWN)) pitch += 0.5f; if (KeyUtil.isKeyDown(InputConstants.KEY_DOWN)) pitch += 0.5f;
mc.player.setYRot(yaw); mc.player.setYRot(yaw);
mc.player.setXRot(pitch); mc.player.setXRot(pitch);
@@ -9,7 +9,7 @@ import me.retucio.sputnik.module.setting.settings.EnumSetting;
import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.world.effect.MobEffectInstance; import net.minecraft.world.effect.MobEffectInstance;
import net.minecraft.world.effect.MobEffects; import net.minecraft.world.effect.MobEffects;
import org.lwjgl.glfw.GLFW; import com.mojang.blaze3d.platform.InputConstants;
import java.awt.*; import java.awt.*;
@@ -39,7 +39,7 @@ public class Fullbright extends Module {
super("brilli brilli", super("brilli brilli",
"deshabilita la oscuridad (y aplica colores a los shaders)", "deshabilita la oscuridad (y aplica colores a los shaders)",
Category.CAMERA, Category.CAMERA,
GLFW.GLFW_KEY_K); InputConstants.KEY_K);
mode.onUpdate(mode -> { if (mode != Modes.POTION) disableNightVision(); }); mode.onUpdate(mode -> { if (mode != Modes.POTION) disableNightVision(); });
} }
@@ -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.KeySetting;
import me.retucio.sputnik.module.setting.settings.NumberSetting; import me.retucio.sputnik.module.setting.settings.NumberSetting;
import net.minecraft.client.CameraType; import net.minecraft.client.CameraType;
import org.lwjgl.glfw.GLFW; import com.mojang.blaze3d.platform.InputConstants;
/** continúa en: /** continúa en:
@@ -36,7 +36,7 @@ public class PerspectivePlus extends Module {
1, 0, 8, 0.1)); 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", 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; private double distance;
@@ -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.BooleanSetting;
import me.retucio.sputnik.module.setting.settings.KeySetting; import me.retucio.sputnik.module.setting.settings.KeySetting;
import me.retucio.sputnik.module.setting.settings.NumberSetting; import me.retucio.sputnik.module.setting.settings.NumberSetting;
import org.lwjgl.glfw.GLFW; import com.mojang.blaze3d.platform.InputConstants;
/** continúa en: /** 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)", 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)); 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", 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", private final NumberSetting mouseSensMultiplier = sgCam.add(new NumberSetting("sensibilidad", "multiplicador de la sensibilidad del ratón",
0.4, 0, 1, 0.05)); 0.4, 0, 1, 0.05));
@@ -49,7 +49,7 @@ public class Zoom extends Module {
super("zoom", super("zoom",
"lupa", "lupa",
Category.CAMERA, Category.CAMERA,
GLFW.GLFW_KEY_F); InputConstants.KEY_F);
keyMode.setDefaultValue(KeyMode.HOLD); keyMode.setDefaultValue(KeyMode.HOLD);
keyMode.setValue(KeyMode.HOLD); keyMode.setValue(KeyMode.HOLD);
@@ -103,7 +103,7 @@ public class Zoom extends Module {
@EventListener @EventListener
private void onMouseScroll(MouseScrollEvent event) { 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) { if (isEnabled() && scrollSens.getValue() > 0 && key) {
value += event.getVertical() * 0.25 * (scrollSens.getValue() * value); value += event.getVertical() * 0.25 * (scrollSens.getValue() * value);
if (value < 1) value = 1; if (value < 1) value = 1;
@@ -1,6 +1,7 @@
package me.retucio.sputnik.module.modules.client; package me.retucio.sputnik.module.modules.client;
import com.github.retucio.neutrino.EventListener; import com.github.retucio.neutrino.EventListener;
import com.mojang.blaze3d.platform.InputConstants;
import me.retucio.sputnik.Sputnik; import me.retucio.sputnik.Sputnik;
import me.retucio.sputnik.command.CommandManager; import me.retucio.sputnik.command.CommandManager;
import me.retucio.sputnik.event.TickEvent; 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.module.setting.settings.StringSetting;
import me.retucio.sputnik.util.ChatUtil; import me.retucio.sputnik.util.ChatUtil;
import me.retucio.sputnik.util.Colors; import me.retucio.sputnik.util.Colors;
import org.lwjgl.glfw.GLFW;
import java.awt.*; import java.awt.*;
@@ -130,7 +130,7 @@ public class ClientSettingsModule extends Module {
super("interfaz", super("interfaz",
"ajustes de la interfaz, y otros misceláneos", "ajustes de la interfaz, y otros misceláneos",
Category.CLIENT, Category.CLIENT,
GLFW.GLFW_KEY_RIGHT_SHIFT); InputConstants.KEY_RSHIFT);
Sputnik.EVENT_BUS.subscribe(this); Sputnik.EVENT_BUS.subscribe(this);
@@ -11,7 +11,7 @@ import me.retucio.sputnik.util.ChatUtil;
import net.minecraft.ChatFormatting; import net.minecraft.ChatFormatting;
import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Component;
import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Entity;
import org.lwjgl.glfw.GLFW; import com.mojang.blaze3d.platform.InputConstants;
public class Friends extends Module { public class Friends extends Module {
@@ -34,8 +34,8 @@ public class Friends extends Module {
@EventListener @EventListener
public void onMouseClick(MouseClickEvent event) { public void onMouseClick(MouseClickEvent event) {
if (event.getButton() == GLFW.GLFW_MOUSE_BUTTON_MIDDLE if (event.getButton() == InputConstants.MOUSE_BUTTON_MIDDLE
&& event.getAction() == GLFW.GLFW_PRESS && event.getAction() == InputConstants.PRESS
&& middleClick.getValue()) && middleClick.getValue())
{ {
Entity target = mc.crosshairPickEntity; Entity target = mc.crosshairPickEntity;
@@ -9,7 +9,7 @@ import me.retucio.sputnik.ui.hud.HudRenderer;
import me.retucio.sputnik.ui.hud.HudEditorScreen; import me.retucio.sputnik.ui.hud.HudEditorScreen;
import me.retucio.sputnik.ui.hud.elements.CustomImageElement; import me.retucio.sputnik.ui.hud.elements.CustomImageElement;
import me.retucio.sputnik.ui.hud.elements.DynoElement; import me.retucio.sputnik.ui.hud.elements.DynoElement;
import org.lwjgl.glfw.GLFW; import com.mojang.blaze3d.platform.InputConstants;
import java.awt.*; import java.awt.*;
@@ -32,7 +32,7 @@ public class Hud extends Module {
public KeySetting editorKey = sgEditor.add(new KeySetting( public KeySetting editorKey = sgEditor.add(new KeySetting(
"tecla del editor", "tecla del editor",
"tecla asignada al editor de elementos del hud", "tecla asignada al editor de elementos del hud",
GLFW.GLFW_KEY_INSERT InputConstants.KEY_INSERT
)); ));
public BooleanSetting axialMovement = sgEditor.add(new BooleanSetting( public BooleanSetting axialMovement = sgEditor.add(new BooleanSetting(
@@ -144,7 +144,7 @@ public class Hud extends Module {
super("HUD", super("HUD",
"superposición de la pantalla con info. adicional", "superposición de la pantalla con info. adicional",
Category.CLIENT, Category.CLIENT,
GLFW.GLFW_KEY_F12 InputConstants.KEY_F12
); );
dyno.onUpdate(v -> { dyno.onUpdate(v -> {
@@ -93,7 +93,7 @@ public class KillAura extends Module {
if (!mc.level.isTickingEntity(entity)) return; if (!mc.level.isTickingEntity(entity)) return;
if (swingHand.getValue()) { 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); mc.gameMode.attack(mc.player, entity);
@@ -15,7 +15,7 @@ import net.minecraft.world.Container;
import net.minecraft.world.inventory.AbstractContainerMenu; import net.minecraft.world.inventory.AbstractContainerMenu;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import org.jspecify.annotations.NonNull; import org.jspecify.annotations.NonNull;
import org.lwjgl.glfw.GLFW; import com.mojang.blaze3d.platform.InputConstants;
import java.util.List; import java.util.List;
@@ -31,19 +31,19 @@ public class Burglar extends Module {
private final KeySetting triggerKey = sgKeys.add(new KeySetting( private final KeySetting triggerKey = sgKeys.add(new KeySetting(
"tecla activadora", "tecla activadora",
"tecla a mantener para que las otras teclas funcionen", "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( private final KeySetting stealKey = sgKeys.add(new KeySetting(
"robar", "robar",
"tecla para robar todo", "tecla para robar todo",
GLFW.GLFW_KEY_S InputConstants.KEY_S
)); ));
private final KeySetting dumpKey = sgKeys.add(new KeySetting( private final KeySetting dumpKey = sgKeys.add(new KeySetting(
"dejar", "dejar",
"tecla para dejar todo", "tecla para dejar todo",
GLFW.GLFW_KEY_D InputConstants.KEY_D
)); ));
@@ -67,7 +67,7 @@ public class Burglar extends Module {
@EventListener @EventListener
private void onKey(KeyEvent event) { private void onKey(KeyEvent event) {
if (!triggerKey.isDown() || event.getAction() != GLFW.GLFW_PRESS if (!triggerKey.isDown() || event.getAction() != InputConstants.PRESS
|| !(mc.gui.screen() instanceof AbstractContainerScreen<?> container)) return; || !(mc.gui.screen() instanceof AbstractContainerScreen<?> container)) return;
if (event.getKey() == stealKey.getValue()) steal(container); if (event.getKey() == stealKey.getValue()) steal(container);
if (event.getKey() == dumpKey.getValue()) dump(container); if (event.getKey() == dumpKey.getValue()) dump(container);
@@ -12,7 +12,7 @@ import me.retucio.sputnik.util.InventoryUtil;
import me.retucio.sputnik.util.KeyUtil; import me.retucio.sputnik.util.KeyUtil;
import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen;
import net.minecraft.world.inventory.Slot; 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 { 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 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", GLFW.GLFW_KEY_S)); 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", GLFW.GLFW_KEY_D)); private final KeySetting row3key = sgGeneral.add(new KeySetting("fila 3", "tecla para mover items a la tercera fila", InputConstants.KEY_D));
public InventoryPlus() { public InventoryPlus() {
super("inventario plus", super("inventario plus",
@@ -33,13 +33,13 @@ public class InventoryPlus extends Module {
@EventListener @EventListener
private void onKey(KeyEvent event) { private void onKey(KeyEvent event) {
if (event.getAction() == GLFW.GLFW_RELEASE) return; if (event.getAction() == InputConstants.RELEASE) return;
processInput(event.getKey(), event); processInput(event.getKey(), event);
} }
@EventListener @EventListener
private void onMouseButton(MouseClickEvent event) { private void onMouseButton(MouseClickEvent event) {
if (event.getAction() == GLFW.GLFW_RELEASE) return; if (event.getAction() == InputConstants.RELEASE) return;
processInput(event.getButton(), event); processInput(event.getButton(), event);
} }
@@ -22,7 +22,7 @@ import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items; import net.minecraft.world.item.Items;
import net.minecraft.world.item.component.ItemContainerContents; import net.minecraft.world.item.component.ItemContainerContents;
import net.minecraft.world.level.block.ShulkerBoxBlock; import net.minecraft.world.level.block.ShulkerBoxBlock;
import org.lwjgl.glfw.GLFW; import com.mojang.blaze3d.platform.InputConstants;
import java.awt.*; import java.awt.*;
import java.util.HashMap; import java.util.HashMap;
@@ -30,7 +30,7 @@ import java.util.HashMap;
public class ShulkerPeek extends Module { 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 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<Item, Color> SHULKER_COLORS = new HashMap<>(); public static final HashMap<Item, Color> SHULKER_COLORS = new HashMap<>();
@@ -65,12 +65,12 @@ public class ShulkerPeek extends Module {
if (mc.player == null) return; if (mc.player == null) return;
if (event.getKey() != previewKey.getValue()) return; if (event.getKey() != previewKey.getValue()) return;
if (event.getAction() == GLFW.GLFW_PRESS) { if (event.getAction() == InputConstants.PRESS) {
openPreviewScreen(); openPreviewScreen();
return; return;
} }
if (event.getAction() == GLFW.GLFW_REPEAT) { if (event.getAction() == InputConstants.REPEAT) {
if (mc.gui.screen() instanceof PreviewScreen preview) { if (mc.gui.screen() instanceof PreviewScreen preview) {
if (preview.getType() != PreviewScreen.PreviewType.SHULKER) if (preview.getType() != PreviewScreen.PreviewType.SHULKER)
openPreviewScreen(); openPreviewScreen();
@@ -78,7 +78,7 @@ public class ShulkerPeek extends Module {
return; return;
} }
if (event.getAction() == GLFW.GLFW_RELEASE) { if (event.getAction() == InputConstants.RELEASE) {
if (mc.gui.screen() instanceof PreviewScreen preview) if (mc.gui.screen() instanceof PreviewScreen preview)
preview.onClose(); preview.onClose();
} }
@@ -117,6 +117,6 @@ public class ShulkerPeek extends Module {
if (container == null) return true; if (container == null) return true;
// .stream()? // .stream()?
return container.allItemsCopyStream().allMatch(ItemStack::isEmpty); return container.nonEmptyItemCopyStream().allMatch(ItemStack::isEmpty);
} }
} }
@@ -14,8 +14,12 @@ import java.util.UUID;
public class FakePlayer extends Module { 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; private RemotePlayer player = null;
public FakePlayer() { public FakePlayer() {
@@ -27,7 +31,7 @@ public class FakePlayer extends Module {
@Override @Override
public void onEnable() { public void onEnable() {
if (mc.level == null) return; if (mc.level == null) return;
addPlayer(mc.player, name.getValue()); player = addPlayer(mc.player, name.getValue());
super.onEnable(); super.onEnable();
} }
@@ -40,20 +44,23 @@ public class FakePlayer extends Module {
// intento miserable de hacer que no colisione con jugadores // intento miserable de hacer que no colisione con jugadores
public RemotePlayer addPlayer(Player playerToCopy, String dummyName) { public RemotePlayer addPlayer(Player playerToCopy, String dummyName) {
player = new RemotePlayer(mc.level, new GameProfile(UUID.randomUUID(), dummyName)) { RemotePlayer fake = new RemotePlayer(mc.level, new GameProfile(UUID.randomUUID(), dummyName)) {
@Override public void playerTouch(@NonNull Player player) {} @Override public void playerTouch(@NonNull Player p) {}
}; };
player.restoreFrom(playerToCopy); fake.restoreFrom(playerToCopy);
player.setCustomNameVisible(true); fake.setCustomNameVisible(true);
player.noPhysics = true; fake.noPhysics = true;
player.horizontalCollision = false; fake.horizontalCollision = false;
player.verticalCollision = false; fake.verticalCollision = false;
mc.level.addEntity(player);
return player; fake.setId(nextFakeId--);
mc.level.addEntity(fake);
return fake;
} }
public void removePlayer() { public void removePlayer() {
if (player == null) return;
player.setRemoved(Entity.RemovalReason.KILLED); player.setRemoved(Entity.RemovalReason.KILLED);
player.onClientRemoval(); player.onClientRemoval();
player = null; player = null;
@@ -257,12 +257,16 @@ public class LogoutSpots extends Module {
if (outlines.getValue()) { if (outlines.getValue()) {
RenderUtil.drawBlockFaceOutlines(matrices, RenderUtil.drawBlockFaceOutlines(matrices,
BlockPos.containing(x + halfWidth, y, z + halfWidth), BlockPos.containing(x + halfWidth, y, z + halfWidth),
Direction.UP, outlineColor.getValue(), lineWidth.getFloatValue(), true); Direction.UP, outlineColor.getValue(), lineWidth.getFloatValue(),
true
);
} }
if (filling.getValue()) { if (filling.getValue()) {
RenderUtil.drawBlockFaceFilled(matrices, RenderUtil.drawBlockFaceFilled(matrices,
BlockPos.containing(x + halfWidth, y, z + halfWidth), BlockPos.containing(x + halfWidth, y, z + halfWidth),
Direction.UP, fillingColor.getValue(), 0.001f, true); Direction.UP, fillingColor.getValue(), 0.001f,
true
);
} }
} }
} }
@@ -20,7 +20,7 @@ import net.minecraft.world.item.BlockItem;
import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.HitResult; import net.minecraft.world.phys.HitResult;
import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.Vec3;
import org.lwjgl.glfw.GLFW; import com.mojang.blaze3d.platform.InputConstants;
public class AirPlace extends Module { public class AirPlace extends Module {
@@ -52,7 +52,7 @@ public class AirPlace extends Module {
private final KeySetting scrollKey = sgScroll.add(new KeySetting( private final KeySetting scrollKey = sgScroll.add(new KeySetting(
"tecla del scroll", "tecla del scroll",
"tecla a mantener para que el scroll funcione", "tecla a mantener para que el scroll funcione",
GLFW.GLFW_KEY_LEFT_CONTROL InputConstants.KEY_LCONTROL
)); ));
private final NumberSetting scrollSens = sgScroll.add(new NumberSetting( private final NumberSetting scrollSens = sgScroll.add(new NumberSetting(
@@ -138,7 +138,7 @@ public class AirPlace extends Module {
@EventListener @EventListener
private void onKey(KeyEvent event) { 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()); rangeValue = (int) Math.clamp(rangeValue, range.getMin(), range.getMax());
} }
} }
@@ -7,7 +7,7 @@ import me.retucio.sputnik.module.setting.settings.NumberSetting;
import net.minecraft.world.item.BlockItem; import net.minecraft.world.item.BlockItem;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import org.lwjgl.glfw.GLFW; import com.mojang.blaze3d.platform.InputConstants;
public class FastUse extends Module { public class FastUse extends Module {
@@ -61,7 +61,7 @@ public class FastUse extends Module {
super("precoz", super("precoz",
"hace cosas como usar items o colocar bloques más rápido", "hace cosas como usar items o colocar bloques más rápido",
Category.PLAYER, Category.PLAYER,
GLFW.GLFW_KEY_F6); InputConstants.KEY_F6);
items.onUpdate(itemCooldown::visibility); items.onUpdate(itemCooldown::visibility);
blocks.onUpdate(blockCooldown::visibility); blocks.onUpdate(blockCooldown::visibility);
@@ -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.BooleanSetting;
import me.retucio.sputnik.module.setting.settings.EnumSetting; import me.retucio.sputnik.module.setting.settings.EnumSetting;
import me.retucio.sputnik.util.render.GlintRenderType; 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.RenderType;
import net.minecraft.client.renderer.rendertype.RenderTypes; import net.minecraft.client.renderer.rendertype.RenderTypes;
import net.minecraft.world.item.DyeColor; import net.minecraft.world.item.DyeColor;
import net.minecraft.resources.Identifier;
/** continúa en: /** continúa en:
* @see RenderBuffersMixin * @see RenderBuffersMixin
@@ -45,28 +47,22 @@ public class GlintPlus extends Module {
Category.RENDER); Category.RENDER);
} }
public RenderType getGlint() { public RenderType getGlint(RenderType vanilla, BakedQuad.MaterialInfo materialInfo) {
int color = getGlintColor(); if (!isEnabled() || !items.getValue()) return vanilla;
if (!isEnabled() || !items.getValue()) return RenderTypes.glint(); return GlintRenderType.itemGlint(glintColor.getValue().getRealName(), vanilla,
return GlintRenderType.glintColor.get(color); materialInfo.sprite().atlasLocation());
}
public RenderType getGlintTranslucent() {
int color = getGlintColor();
if (!isEnabled() || !items.getValue()) return RenderTypes.glintTranslucent();
return GlintRenderType.glintTranslucentColor.get(color);
} }
public RenderType getEntityGlint() { public RenderType getEntityGlint() {
int color = getGlintColor(); 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); return GlintRenderType.entityGlintColor.get(color);
} }
public RenderType getArmorEntityGlint() { public RenderType getArmorEntityGlint(Identifier armorTexture) {
int color = getGlintColor(); int color = getGlintColor();
if (!isEnabled() || !armor.getValue()) return RenderTypes.armorEntityGlint(); if (!isEnabled() || !armor.getValue()) return RenderTypes.armorCutoutNoCullGlint(armorTexture);
return GlintRenderType.armorEntityGlintColor.get(color); return GlintRenderType.armorEntityGlint(glintColor.getValue().getRealName(), armorTexture);
} }
public int getGlintColor() { public int getGlintColor() {
@@ -128,9 +128,9 @@ public class HandView extends Module {
} }
private void rotate(PoseStack matrix, Vec3 rotation) { private void rotate(PoseStack matrix, Vec3 rotation) {
matrix.mulPose(Axis.XP.rotationDegrees((float) rotation.x)); matrix.rotate(Axis.XP.rotationDegrees((float) rotation.x));
matrix.mulPose(Axis.YP.rotationDegrees((float) rotation.y)); matrix.rotate(Axis.YP.rotationDegrees((float) rotation.y));
matrix.mulPose(Axis.ZP.rotationDegrees((float) rotation.z)); matrix.rotate(Axis.ZP.rotationDegrees((float) rotation.z));
} }
private void scale(PoseStack matrix, Vec3 scale) { private void scale(PoseStack matrix, Vec3 scale) {
@@ -50,7 +50,7 @@ public class ItemPhysics extends Module {
var accessor = (ItemStackRenderStateAccessor) event.renderState.item; var accessor = (ItemStackRenderStateAccessor) event.renderState.item;
for (int i = 0; i < accessor.getActiveLayerCount(); i++) { for (int i = 0; i < accessor.getActiveLayerCount(); i++) {
ItemStackRenderState.LayerRenderState layer = accessor.getLayers()[i]; ItemStackRenderState.LayerRenderState layer = accessor.getLayers()[i];
ModelInfo info = getInfo(layer.prepareQuadList()); ModelInfo info = getInfo(((LayerRenderStateAccessor) layer).sputnik$getQuads().all());
matrices.pushPose(); matrices.pushPose();
applyTransformation(matrices, ((LayerRenderStateAccessor) layer).sputnik$getTransform()); applyTransformation(matrices, ((LayerRenderStateAccessor) layer).sputnik$getTransform());
@@ -58,7 +58,7 @@ public class ItemPhysics extends Module {
offsetInWater(matrices, event.itemEntity); offsetInWater(matrices, event.itemEntity);
if (info.flat) { if (info.flat) {
matrices.mulPose(Axis.XP.rotationDegrees(90)); matrices.rotate(Axis.XP.rotationDegrees(90));
matrices.translate(0, 0, info.offsetZ); matrices.translate(0, 0, info.offsetZ);
} }
@@ -73,7 +73,7 @@ public class ItemPhysics extends Module {
float degrees = (random.nextFloat() * 2 - 1) * 90; float degrees = (random.nextFloat() * 2 - 1) * 90;
matrices.translate(x, y, z); matrices.translate(x, y, z);
matrices.mulPose(axis.rotationDegrees(degrees)); matrices.rotate(axis.rotationDegrees(degrees));
matrices.translate(-x, -y, -z); matrices.translate(-x, -y, -z);
} }
@@ -7,6 +7,7 @@ import com.mojang.blaze3d.resource.GraphicsResourceAllocator;
import me.retucio.sputnik.Sputnik; import me.retucio.sputnik.Sputnik;
import me.retucio.sputnik.module.Category; import me.retucio.sputnik.module.Category;
import me.retucio.sputnik.module.Module; import me.retucio.sputnik.module.Module;
import me.retucio.sputnik.module.setting.settings.EnumSetting;
import me.retucio.sputnik.module.setting.settings.NumberSetting; import me.retucio.sputnik.module.setting.settings.NumberSetting;
import me.retucio.sputnik.util.render.PostShader; import me.retucio.sputnik.util.render.PostShader;
@@ -43,10 +44,11 @@ public class Lsd extends Module {
1, 0, 10, 0.1 1, 0, 10, 0.1
)); ));
private final NumberSetting seed = sgGeneral.add(new NumberSetting( private final EnumSetting<ColorMode> color = sgGeneral.add(new EnumSetting<>(
"tono", "color",
"desplazamiento de tono que se aplica sobre la imagen", "elige el color del efecto",
0.3, 0, 1, 0.01 ColorMode.class,
ColorMode.RAINBOW
)); ));
private final NumberSetting speed = sgGeneral.add(new NumberSetting( private final NumberSetting speed = sgGeneral.add(new NumberSetting(
@@ -71,7 +73,7 @@ public class Lsd extends Module {
public void apply(RenderTarget target, GraphicsResourceAllocator pool) { public void apply(RenderTarget target, GraphicsResourceAllocator pool) {
SHADER.render(target, pool, b -> b SHADER.render(target, pool, b -> b
.putFloat(strength.getFloatValue()) .putFloat(strength.getFloatValue())
.putFloat(seed.getFloatValue()) .putFloat(color.getValue().hue)
.putFloat(rotations.getFloatValue()) .putFloat(rotations.getFloatValue())
.putFloat(getTime())); .putFloat(getTime()));
} }
@@ -82,4 +84,28 @@ public class Lsd extends Module {
double elapsed = (System.nanoTime() - startNanos) / 1_000_000_000.0; double elapsed = (System.nanoTime() - startNanos) / 1_000_000_000.0;
return (float) ((elapsed * speed.getValue()) % 100_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;
}
}
} }
@@ -12,7 +12,7 @@ import me.retucio.sputnik.module.setting.settings.KeySetting;
import me.retucio.sputnik.module.setting.settings.NumberSetting; import me.retucio.sputnik.module.setting.settings.NumberSetting;
import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionHand;
import org.joml.Quaternionf; import org.joml.Quaternionf;
import org.lwjgl.glfw.GLFW; import com.mojang.blaze3d.platform.InputConstants;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@@ -22,7 +22,7 @@ public class Stylish extends Module {
private final KeySetting key = sgGeneral.add(new KeySetting( private final KeySetting key = sgGeneral.add(new KeySetting(
"tecla", "tecla a pulsar para hacer el truco", "tecla", "tecla a pulsar para hacer el truco",
GLFW.GLFW_KEY_Y InputConstants.KEY_Y
)); ));
private final EnumSetting<TrickType> trick = sgGeneral.add(new EnumSetting<>( private final EnumSetting<TrickType> trick = sgGeneral.add(new EnumSetting<>(
@@ -87,7 +87,7 @@ public class Stylish extends Module {
@EventListener @EventListener
private void onKey(KeyEvent event) { private void onKey(KeyEvent event) {
if (event.getKey() != key.getValue()) return; if (event.getKey() != key.getValue()) return;
if (event.getAction() != GLFW.GLFW_PRESS) return; if (event.getAction() != InputConstants.PRESS) return;
if (spinning) return; if (spinning) return;
long now = System.currentTimeMillis(); long now = System.currentTimeMillis();
@@ -175,41 +175,41 @@ public class Stylish extends Module {
float angleRad = (float) Math.toRadians(degrees * directionSign); float angleRad = (float) Math.toRadians(degrees * directionSign);
switch (type) { 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 -> { case TWIRL -> {
// combina spin + flip para un giro más aparatoso // combina spin + flip para un giro más aparatoso
matrices.mulPose(new Quaternionf().rotationZ(angleRad)); matrices.rotate(new Quaternionf().rotationZ(angleRad));
matrices.mulPose(new Quaternionf().rotationX(angleRad * 0.5f)); matrices.rotate(new Quaternionf().rotationX(angleRad * 0.5f));
} }
case WAVE -> { case WAVE -> {
// bamboleo tipo saludo, sin vuelta completa // bamboleo tipo saludo, sin vuelta completa
float waveAngle = (float) Math.sin(fraction * Math.PI * spins.getIntValue()) * 25f; 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 -> { case POP -> {
// pequeño pulso de escala, como si el ítem "respirara" // pequeño pulso de escala, como si el ítem "respirara"
float scalePulse = 1f + (float) Math.sin(fraction * Math.PI) * 0.25f; float scalePulse = 1f + (float) Math.sin(fraction * Math.PI) * 0.25f;
matrices.scale(scalePulse, scalePulse, scalePulse); matrices.scale(scalePulse, scalePulse, scalePulse);
matrices.mulPose(new Quaternionf().rotationZ(angleRad * 0.3f)); matrices.rotate(new Quaternionf().rotationZ(angleRad * 0.3f));
} }
case THROW_CATCH -> { case THROW_CATCH -> {
// el ítem "sube", gira en el aire y "cae" de vuelta // el ítem "sube", gira en el aire y "cae" de vuelta
float height = (float) Math.sin(fraction * Math.PI) * 0.35f; float height = (float) Math.sin(fraction * Math.PI) * 0.35f;
matrices.translate(0f, height, 0f); matrices.translate(0f, height, 0f);
matrices.mulPose(new Quaternionf().rotationX(angleRad * 2f)); matrices.rotate(new Quaternionf().rotationX(angleRad * 2f));
} }
case RANDOM -> { case RANDOM -> {
// no debería llegar aquí, resolveTrick lo reemplaza antes // no debería llegar aquí, resolveTrick lo reemplaza antes
matrices.mulPose(new Quaternionf().rotationZ(angleRad)); matrices.rotate(new Quaternionf().rotationZ(angleRad));
} }
} }
} }
@@ -34,7 +34,7 @@ import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.HitResult; import net.minecraft.world.phys.HitResult;
import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.Vec3;
import net.minecraft.world.phys.shapes.VoxelShape; import net.minecraft.world.phys.shapes.VoxelShape;
import org.lwjgl.glfw.GLFW; import com.mojang.blaze3d.platform.InputConstants;
import java.awt.*; import java.awt.*;
import java.util.ArrayDeque; import java.util.ArrayDeque;
@@ -204,8 +204,8 @@ public class AutoMine extends Module {
private void onClick(MouseClickEvent event) { private void onClick(MouseClickEvent event) {
if (mc.gui.screen() != null) return; if (mc.gui.screen() != null) return;
if (mc.level == null || mc.hitResult == null) return; if (mc.level == null || mc.hitResult == null) return;
if (event.getAction() != GLFW.GLFW_PRESS) return; if (event.getAction() != InputConstants.PRESS) return;
if (event.getButton() != GLFW.GLFW_MOUSE_BUTTON_1) return; if (event.getButton() != InputConstants.MOUSE_BUTTON_LEFT) return;
BlockHitResult bhr; BlockHitResult bhr;
if (mc.hitResult.getType() == HitResult.Type.BLOCK) { if (mc.hitResult.getType() == HitResult.Type.BLOCK) {
bhr = (BlockHitResult) mc.hitResult; bhr = (BlockHitResult) mc.hitResult;
@@ -12,6 +12,10 @@ import net.minecraft.core.BlockPos;
import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Component;
import net.minecraft.network.protocol.game.ServerboundSignUpdatePacket; import net.minecraft.network.protocol.game.ServerboundSignUpdatePacket;
import net.minecraft.world.level.block.entity.SignBlockEntity; import net.minecraft.world.level.block.entity.SignBlockEntity;
import net.minecraft.world.level.block.entity.SignTextSlot;
import me.retucio.sputnik.util.NetworkUtil;
import java.util.List;
public class AutoSign extends Module { 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) { if (event.getScreen() instanceof AbstractSignEditScreen screen && text != null && mc != null && mc.player != null) {
event.cancel(); event.cancel();
SignBlockEntity sign = ((AbstractSignEditScreenAccessor) screen).getBlockEntity(); SignBlockEntity sign = ((AbstractSignEditScreenAccessor) screen).getBlockEntity();
fillText(sign.getBlockPos(), sign.isFacingFrontText(mc.player), text); fillText(sign.getBlockPos(), sign.getSlotPlayerIsFacing(mc.player), text);
} }
} }
@EventListener @EventListener
private void onSendPacket(PacketEvent.Send event) { private void onSendPacket(PacketEvent.Send event) {
if (event.getPacket() instanceof ServerboundSignUpdatePacket packet) { if (event.getPacket() instanceof ServerboundSignUpdatePacket packet) {
if (text == null) text = packet.getLines().clone(); if (text == null) {
else System.arraycopy(text, 0, packet.getLines(), 0, 4); 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) { private void fillText(BlockPos blockPos, SignTextSlot slot, String[] text) {
mc.getConnection().send(new ServerboundSignUpdatePacket( mc.getConnection().send(new ServerboundSignUpdatePacket(blockPos, List.of(text), slot));
blockPos, front, text[0], text[1], text[2], text[3]
));
} }
} }
@@ -19,7 +19,7 @@ import net.minecraft.world.item.component.Tool;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.HitResult; import net.minecraft.world.phys.HitResult;
import org.lwjgl.glfw.GLFW; import com.mojang.blaze3d.platform.InputConstants;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
@@ -96,7 +96,7 @@ public class AutoTool extends Module {
if (mc.gui.screen() != null) return; if (mc.gui.screen() != null) return;
if (mode.is(AutoToolMode.ON_TICK) && mc.options.keyAttack.isDown()) { 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) { if (startedMining && delaySetting.getIntValue() > 0) {
@@ -132,9 +132,9 @@ public class AutoTool extends Module {
if (mc.player == null) return; if (mc.player == null) return;
if (key != KeyUtil.getKey(mc.options.keyAttack)) return; if (key != KeyUtil.getKey(mc.options.keyAttack)) return;
if (action == GLFW.GLFW_PRESS) { if (action == InputConstants.PRESS) {
onStartMining(); onStartMining();
} else if (action == GLFW.GLFW_RELEASE) { } else if (action == InputConstants.RELEASE) {
onFinishMining(); onFinishMining();
} }
} }
@@ -20,7 +20,7 @@ import net.minecraft.world.level.block.state.properties.Property;
import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.HitResult; import net.minecraft.world.phys.HitResult;
import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.Vec3;
import org.lwjgl.glfw.GLFW; import com.mojang.blaze3d.platform.InputConstants;
import java.util.Collection; import java.util.Collection;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.Map; import java.util.Map;
@@ -31,7 +31,7 @@ public class BlockInfo extends Module {
private final KeySetting key = sgGeneral.add(new KeySetting( private final KeySetting key = sgGeneral.add(new KeySetting(
"tecla", "tecla",
"tecla a pulsar para obtener la info.", "tecla a pulsar para obtener la info.",
GLFW.GLFW_KEY_CAPS_LOCK InputConstants.KEY_CAPSLOCK
)); ));
private final EnumSetting<CopyMode> copy = sgGeneral.add(new EnumSetting<>( private final EnumSetting<CopyMode> copy = sgGeneral.add(new EnumSetting<>(
@@ -56,7 +56,7 @@ public class BlockInfo extends Module {
@EventListener @EventListener
private void onKey(KeyEvent event) { private void onKey(KeyEvent event) {
if (mc.player == null || mc.level == null) return; 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( HitResult result = mc.player.pick(
mc.player.blockInteractionRange(), mc.player.blockInteractionRange(),
@@ -6,6 +6,9 @@ import me.retucio.sputnik.module.Category;
import me.retucio.sputnik.module.Module; import me.retucio.sputnik.module.Module;
import me.retucio.sputnik.module.setting.settings.StringSetting; import me.retucio.sputnik.module.setting.settings.StringSetting;
import net.minecraft.network.protocol.game.ServerboundSignUpdatePacket; import net.minecraft.network.protocol.game.ServerboundSignUpdatePacket;
import me.retucio.sputnik.util.NetworkUtil;
import java.util.ArrayList;
public class ColoredSigns extends Module { public class ColoredSigns extends Module {
@@ -26,9 +29,11 @@ public class ColoredSigns extends Module {
@EventListener @EventListener
private void onSendPacket(PacketEvent.Send event) { private void onSendPacket(PacketEvent.Send event) {
if (event.getPacket() instanceof ServerboundSignUpdatePacket packet) { if (event.getPacket() instanceof ServerboundSignUpdatePacket packet) {
for (int i = 0; i < 4; i++) { event.cancel();
packet.getLines()[i] = packet.getLines()[i].replace(symbol.getValue(), "\247" + "\247a"); NetworkUtil.sendPacketNoEvent(new ServerboundSignUpdatePacket(
} packet.pos(), packet.lines().stream()
.map(line -> line.replace(symbol.getValue(), "\247" + "\247a"))
.toList(), packet.slot()));
} }
} }
} }
@@ -5,7 +5,7 @@ import me.retucio.sputnik.module.Module;
import me.retucio.sputnik.util.EntityUtil; import me.retucio.sputnik.util.EntityUtil;
import me.retucio.sputnik.util.RotationUtil; import me.retucio.sputnik.util.RotationUtil;
import net.minecraft.world.entity.Entity; 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.ArrayList;
import java.util.List; import java.util.List;
@@ -14,7 +14,7 @@ import java.util.List;
public class Racist extends Module { public class Racist extends Module {
private int lookTimer; private int lookTimer;
private final List<EnderMan> lookedEndermen = new ArrayList<>(); private final List<Enderman> lookedEndermen = new ArrayList<>();
public Racist() { public Racist() {
super("racismo", super("racismo",
@@ -33,7 +33,7 @@ public class Racist extends Module {
if (mc.level == null || mc.player == null) return; if (mc.level == null || mc.player == null) return;
for (Entity entity : mc.level.getEntities().getAll()) { for (Entity entity : mc.level.getEntities().getAll()) {
if (!(entity instanceof EnderMan enderman)) continue; if (!(entity instanceof Enderman enderman)) continue;
if (shouldLookAt(enderman)) { if (shouldLookAt(enderman)) {
lookAtEnderman(enderman); lookAtEnderman(enderman);
@@ -47,12 +47,12 @@ public class Racist extends Module {
lookTimer++; lookTimer++;
} }
private boolean shouldLookAt(EnderMan enderman) { private boolean shouldLookAt(Enderman enderman) {
return !(lookedEndermen.contains(enderman)) && lookTimer >= 10 return !(lookedEndermen.contains(enderman)) && lookTimer >= 10
&& EntityUtil.hasLineOfSight(mc.player, enderman); && 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); RotationUtil.lookAt(RotationUtil.LOW, enderman, EntityUtil.Target.HEAD, 0, RotationUtil.Mode.CLIENT);
} }
} }
@@ -1,5 +1,6 @@
package me.retucio.sputnik.module.setting.settings; package me.retucio.sputnik.module.setting.settings;
import com.mojang.blaze3d.platform.InputConstants;
import me.retucio.sputnik.config.ConfigManager; import me.retucio.sputnik.config.ConfigManager;
import me.retucio.sputnik.module.Module; import me.retucio.sputnik.module.Module;
import me.retucio.sputnik.module.ModuleManager; 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.ChatUtil;
import me.retucio.sputnik.util.KeyUtil; import me.retucio.sputnik.util.KeyUtil;
import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Component;
import org.lwjgl.glfw.GLFW;
public class KeySetting extends Setting<Integer> { public class KeySetting extends Setting<Integer> {
@@ -22,32 +23,19 @@ public class KeySetting extends Setting<Integer> {
public void setValue(Integer value) { public void setValue(Integer value) {
if (this.value.equals(value)) return; if (this.value.equals(value)) return;
if (value == GLFW.GLFW_KEY_ESCAPE) { if (value == InputConstants.KEY_ESCAPE) {
this.value = GLFW.GLFW_KEY_UNKNOWN; // asignar la tecla ESC a deshabilitar la tecla this.value = InputConstants.UNKNOWN.getValue(); // asignar la tecla ESC a deshabilitar la tecla
fireUpdateEvent(); 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); if (updateListener != null) updateListener.accept(this.value);
return; return;
} }
// con "teclas multimódulo" puesto se permite repetir tecla, que es justo lo que if (ModuleManager.INSTANCE != null && !ConfigManager.INSTANCE.isApplying()
// dice el ajuste. antes se le quitaba la tecla al otro módulo igualmente, así que && !ClientSettingsPanel.clientSettings.multipleKeybinds.getValue()
// 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()) {
for (Module module : ModuleManager.INSTANCE.getModules()) for (Module module : ModuleManager.INSTANCE.getModules())
if (module.getKey() == value && value != -1) { if (module.getKey() == value && value != InputConstants.UNKNOWN.getValue()) {
module.setKey(-1); module.setKey(InputConstants.UNKNOWN.getValue());
ChatUtil.info(Component.translatable("sputnik.setting.key.reset", module.getDisplayName())); ChatUtil.info(Component.translatable("sputnik.setting.key.reset", module.getDisplayName()));
} }
} }
@@ -9,7 +9,7 @@ import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiGraphicsExtractor; import net.minecraft.client.gui.GuiGraphicsExtractor;
import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Component;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.lwjgl.glfw.GLFW; import com.mojang.blaze3d.platform.InputConstants;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@@ -120,11 +120,11 @@ public class HudEditor {
int offset = hud.arrowOffset.getIntValue(); int offset = hud.arrowOffset.getIntValue();
switch (key) { switch (key) {
case GLFW.GLFW_KEY_UP -> selected.setY(Math.max(1, selected.getY() - offset)); case InputConstants.KEY_UP -> selected.setY(Math.max(1, selected.getY() - offset));
case GLFW.GLFW_KEY_DOWN -> selected.setY(Math.min( case InputConstants.KEY_DOWN -> selected.setY(Math.min(
mc.getWindow().getGuiScaledHeight() - selected.getH() + 1, selected.getY() + offset)); mc.getWindow().getGuiScaledHeight() - selected.getH() + 1, selected.getY() + offset));
case GLFW.GLFW_KEY_LEFT -> selected.setX(Math.max(1, selected.getX() - offset)); case InputConstants.KEY_LEFT -> selected.setX(Math.max(1, selected.getX() - offset));
case GLFW.GLFW_KEY_RIGHT -> selected.setX(Math.min( case InputConstants.KEY_RIGHT -> selected.setX(Math.min(
mc.getWindow().getGuiScaledWidth() - selected.getW() + 1, selected.getX() + offset)); mc.getWindow().getGuiScaledWidth() - selected.getW() + 1, selected.getX() + offset));
} }
} }
@@ -11,7 +11,7 @@ import net.minecraft.client.gui.screens.Screen;
import net.minecraft.client.input.MouseButtonEvent; import net.minecraft.client.input.MouseButtonEvent;
import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Component;
import org.jspecify.annotations.NonNull; import org.jspecify.annotations.NonNull;
import org.lwjgl.glfw.GLFW; import com.mojang.blaze3d.platform.InputConstants;
public class HudEditorScreen extends Screen { public class HudEditorScreen extends Screen {
@@ -61,10 +61,10 @@ public class HudEditorScreen extends Screen {
@EventListener @EventListener
public void onKey(KeyEvent event) { public void onKey(KeyEvent event) {
if (mc.gui.screen() != INSTANCE) return; if (mc.gui.screen() != INSTANCE) return;
if (event.getAction() == GLFW.GLFW_RELEASE) return; if (event.getAction() == InputConstants.RELEASE) return;
event.cancel(); event.cancel();
if (event.getKey() == GLFW.GLFW_KEY_ESCAPE) { if (event.getKey() == InputConstants.KEY_ESCAPE) {
HudEditor.INSTANCE.saveAll(); HudEditor.INSTANCE.saveAll();
HudEditor.INSTANCE.unselect(); HudEditor.INSTANCE.unselect();
mc.gui.setScreen(null); mc.gui.setScreen(null);
@@ -42,7 +42,7 @@ import net.minecraft.network.chat.Component;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jspecify.annotations.NonNull; import org.jspecify.annotations.NonNull;
import org.lwjgl.glfw.GLFW; import com.mojang.blaze3d.platform.InputConstants;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; 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) { public void extractRenderState(@NonNull GuiGraphicsExtractor gui, int mouseX, int mouseY, float delta) {
switch (tabBar.getSelected()) { switch (tabBar.getSelected()) {
case MODULES -> renderModules(gui, mouseX, mouseY, delta); case MODULES -> renderModules(gui, mouseX, mouseY, delta);
case CLIENT_SETTINGS -> renderClientSettings(gui, mouseX, mouseY, delta);
case HUD -> renderHud(gui, mouseX, mouseY); case HUD -> renderHud(gui, mouseX, mouseY);
case PROFILES -> profilesTab.render(gui, mouseX, mouseY, delta); case PROFILES -> profilesTab.render(gui, mouseX, mouseY, delta);
case MACROS -> macrosTab.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); 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) { private void renderModules(@NonNull GuiGraphicsExtractor gui, int mouseX, int mouseY, float delta) {
scrollBar.setWindowHeight(mc.getWindow().getGuiScaledHeight()); scrollBar.setWindowHeight(mc.getWindow().getGuiScaledHeight());
scrollBar.setContentHeight(calculateContentHeight()); scrollBar.setContentHeight(calculateContentHeight());
@@ -149,9 +155,6 @@ public class ClickGui extends Screen {
sp.drawTooltips(gui, mouseX, mouseY); sp.drawTooltips(gui, mouseX, mouseY);
} }
clientSettingsPanel.render(gui, mouseX, mouseY, delta);
clientSettingsPanel.updatePosition(mouseX, mouseY);
filterSearchResults(); filterSearchResults();
renderBottomGradient(gui, scrollOffset); renderBottomGradient(gui, scrollOffset);
@@ -188,10 +191,6 @@ public class ClickGui extends Screen {
bottom = Math.max(bottom, sp.getY() + sp.getH() + sp.getTotalHeight()); 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 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; 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 false;
return rectsOverlap(x, y, w, h, clientSettingsPanel.getX(), clientSettingsPanel.getY(), clientSettingsPanel.getW(), clientHeight);
} }
private boolean rectsOverlap(int ax, int ay, int aw, int ah, int bx, int by, int bw, int bh) { 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) { public boolean mouseClicked(MouseButtonEvent click, boolean doubled) {
int x = (int) click.x(); int x = (int) click.x();
int y = (int) click.y(); 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()) { switch (tabBar.getSelected()) {
case MODULES -> { case MODULES -> {
miscWidgets.forEach(w -> w.mouseClicked(x, y, click.button())); miscWidgets.forEach(w -> w.mouseClicked(x, y, button));
clientSettingsPanel.mouseClicked(x, y, click.button());
for (ModulePanel mp : modulePanels.reversed()) { for (ModulePanel mp : modulePanels.reversed()) {
mp.mouseClicked(x, y, click.button()); mp.mouseClicked(x, y, button);
} }
for (SettingsPanel sp : new ArrayList<>(settingsPanels)) { 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 CLIENT_SETTINGS -> {
case PROFILES -> profilesTab.mouseClicked(x, y, click.button()); if (!clientSettingsPanel.mouseClickedGroupTab(x, y, button)) {
case MACROS -> macrosTab.mouseClicked(x, y, click.button()); clientSettingsPanel.mouseClicked(x, y, button);
case FRIENDS -> friendsTab.mouseClicked(x, y, click.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); return super.mouseClicked(click, doubled);
@@ -266,24 +269,29 @@ public class ClickGui extends Screen {
public boolean mouseReleased(MouseButtonEvent click) { public boolean mouseReleased(MouseButtonEvent click) {
int x = (int) click.x(); int x = (int) click.x();
int y = (int) click.y(); int y = (int) click.y();
int button = KeyUtil.toLegacyMouseButton(click.button());
if (tabBar.getSelected() == Tab.HUD) { 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); return super.mouseReleased(click);
} }
if (tabBar.getSelected() != Tab.MODULES) return super.mouseReleased(click); if (tabBar.getSelected() != Tab.MODULES) return super.mouseReleased(click);
miscWidgets.forEach(w -> w.mouseReleased( miscWidgets.forEach(w -> w.mouseReleased(
x, y, click.button())); x, y, button));
// registrar cuándo se suelta el clic, en cada panel respectivamente // registrar cuándo se suelta el clic, en cada panel respectivamente
clientSettingsPanel.mouseReleased(x, y, click.button());
for (ModulePanel mp : modulePanels.reversed()) { for (ModulePanel mp : modulePanels.reversed()) {
mp.mouseReleased(x, y, click.button()); mp.mouseReleased(x, y, button);
} }
for (SettingsPanel sp : new ArrayList<>(settingsPanels)) { for (SettingsPanel sp : new ArrayList<>(settingsPanels)) {
sp.mouseReleased(x, y, click.button()); sp.mouseReleased(x, y, button);
} }
return super.mouseReleased(click); return super.mouseReleased(click);
@@ -291,8 +299,14 @@ public class ClickGui extends Screen {
@Override @Override
public boolean mouseDragged(@NonNull MouseButtonEvent click, double deltaX, double deltaY) { public boolean mouseDragged(@NonNull MouseButtonEvent click, double deltaX, double deltaY) {
int button = KeyUtil.toLegacyMouseButton(click.button());
if (tabBar.getSelected() == Tab.HUD) { 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); return super.mouseDragged(click, deltaX, deltaY);
} }
@@ -316,8 +330,9 @@ public class ClickGui extends Screen {
switch (tabBar.getSelected()) { switch (tabBar.getSelected()) {
case MODULES -> searchBar.onKey(event.getKey(), event.getAction()); case MODULES -> searchBar.onKey(event.getKey(), event.getAction());
case CLIENT_SETTINGS -> clientSettingsPanel.onKey(event.getKey(), event.getAction());
case HUD -> { 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 PROFILES -> profilesTab.onKey(event.getKey(), event.getAction());
case MACROS -> macrosTab.onKey(event.getKey(), event.getAction()); case MACROS -> macrosTab.onKey(event.getKey(), event.getAction());
@@ -335,7 +350,7 @@ public class ClickGui extends Screen {
@EventListener @EventListener
public void onMouseMiddleButton(MouseClickEvent event) { public void onMouseMiddleButton(MouseClickEvent event) {
// mover todos los paneles a un punto visible al presionar shift + la rueda del ratón // 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 h = Sputnik.mc.getWindow().getGuiScaledHeight();
int minY = Math.min(modulePanels.stream().mapToInt(Panel::getY).min().getAsInt(), settingsPanels.stream().mapToInt(Panel::getY).min().getAsInt()); int minY = Math.min(modulePanels.stream().mapToInt(Panel::getY).min().getAsInt(), settingsPanels.stream().mapToInt(Panel::getY).min().getAsInt());
@@ -40,7 +40,7 @@ public class PreviewScreen extends Screen {
super(Component.translatable("sputnik.ui.preview.shulker")); super(Component.translatable("sputnik.ui.preview.shulker"));
this.color = ShulkerPeek.SHULKER_COLORS.get(shulker.getItem()); this.color = ShulkerPeek.SHULKER_COLORS.get(shulker.getItem());
this.title = shulker.getHoverName(); this.title = shulker.getHoverName();
this.inventory = shulker.get(DataComponents.CONTAINER).allItemsCopyStream().toList(); this.inventory = shulker.get(DataComponents.CONTAINER).nonEmptyItemCopyStream().toList();
this.parent = parent; this.parent = parent;
this.type = PreviewType.SHULKER; this.type = PreviewType.SHULKER;
} }
@@ -6,6 +6,7 @@ import me.retucio.sputnik.util.I18nUtil;
public enum Tab { public enum Tab {
MODULES("módulos"), MODULES("módulos"),
CLIENT_SETTINGS("ajustes"),
HUD("hud"), HUD("hud"),
PROFILES("perfiles"), PROFILES("perfiles"),
MACROS("macros"), MACROS("macros"),
@@ -10,7 +10,7 @@ import net.minecraft.client.gui.GuiGraphicsExtractor;
import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Component;
import net.minecraft.util.FormattedCharSequence; import net.minecraft.util.FormattedCharSequence;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.lwjgl.glfw.GLFW; import com.mojang.blaze3d.platform.InputConstants;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@@ -27,7 +27,7 @@ public class MacrosTab {
private static final int TOP = 46; private static final int TOP = 46;
private final TextFieldWidget nameField = new TextFieldWidget( 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) .maxLength(32)
.onSubmit(this::create); .onSubmit(this::create);
@@ -52,10 +52,8 @@ public class MacrosTab {
nameField.setY(TOP); nameField.setY(TOP);
nameField.render(gui, mouseX, mouseY, delta); nameField.render(gui, mouseX, mouseY, delta);
int addX = listX + LIST_WIDTH - 20; drawAddButton(gui, listX + LIST_WIDTH - 40, "C", isAddChatHovered(mouseX, mouseY));
gui.fill(addX, TOP, addX + 20, TOP + ROW_HEIGHT, drawAddButton(gui, listX + LIST_WIDTH - 20, "K", isAddKeybindHovered(mouseX, mouseY));
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);
drawHint(gui, Component.translatable("sputnik.ui.macros.instructions"), listX, LIST_WIDTH); drawHint(gui, Component.translatable("sputnik.ui.macros.instructions"), listX, LIST_WIDTH);
@@ -85,12 +83,13 @@ public class MacrosTab {
renderLines(gui, mouseX, mouseY, delta); 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) { 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(); 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.setX(x);
lineField.setY(TOP); lineField.setY(TOP);
@@ -104,7 +103,7 @@ public class MacrosTab {
drawHint(gui, Component.translatable("sputnik.ui.macros.lineinstructions"), x, LINES_WIDTH); drawHint(gui, Component.translatable("sputnik.ui.macros.lineinstructions"), x, LINES_WIDTH);
int rowY = listTop(); int rowY = listTop();
for (String line : selected.getLines()) { for (String line : chat.getLines()) {
boolean hovered = isHovered(x, rowY, LINES_WIDTH, mouseX, mouseY); boolean hovered = isHovered(x, rowY, LINES_WIDTH, mouseX, mouseY);
gui.fill(x, rowY, x + LINES_WIDTH, rowY + ROW_HEIGHT, gui.fill(x, rowY, x + LINES_WIDTH, rowY + ROW_HEIGHT,
hovered ? Colors.buttonColor.brighter().getRGB() : Colors.buttonColor.getRGB()); hovered ? Colors.buttonColor.brighter().getRGB() : Colors.buttonColor.getRGB());
@@ -124,7 +123,13 @@ public class MacrosTab {
return; 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()); addLine(lineField.getText().trim());
lineField.clear(); lineField.clear();
return; return;
@@ -139,13 +144,13 @@ public class MacrosTab {
rowY += ROW_HEIGHT + 2; rowY += ROW_HEIGHT + 2;
} }
if (selected == null) return; if (!(selected instanceof Macro.Chat chat)) return;
rowY = listTop(); 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 (isHovered(linesX(), rowY, LINES_WIDTH, mouseX, mouseY)) {
if (button == 1 && KeyUtil.isShiftDown()) { if (button == 1 && KeyUtil.isShiftDown()) {
selected.getLines().remove(line); chat.getLines().remove(line);
MacroManager.INSTANCE.save(); MacroManager.INSTANCE.save();
} }
return; return;
@@ -172,19 +177,25 @@ public class MacrosTab {
private void create(String name) { private void create(String name) {
if (name.isEmpty()) return; 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; if (MacroManager.INSTANCE.add(macro)) selected = macro;
} }
private void addLine(String line) { private void addLine(String line) {
if (selected == null || line.isEmpty()) return; if (!(selected instanceof Macro.Chat chat) || line.isEmpty()) return;
selected.getLines().add(line); chat.getLines().add(line);
MacroManager.INSTANCE.save(); MacroManager.INSTANCE.save();
} }
public void onKey(int key, int action) { public void onKey(int key, int action) {
if (listening != null && action != GLFW.GLFW_RELEASE) { if (listening != null && action != InputConstants.RELEASE) {
listening.setKey(key == GLFW.GLFW_KEY_ESCAPE ? GLFW.GLFW_KEY_UNKNOWN : key); listening.setKey(key == InputConstants.KEY_ESCAPE ? InputConstants.UNKNOWN.getValue() : key);
listening = null; listening = null;
MacroManager.INSTANCE.save(); MacroManager.INSTANCE.save();
return; return;
@@ -236,10 +247,26 @@ public class MacrosTab {
} }
private static boolean isAddHovered(int mouseX, int mouseY) { 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; int addX = listX() + LIST_WIDTH - 20;
return mouseX >= addX && mouseX < addX + 20 && mouseY >= TOP && mouseY < TOP + ROW_HEIGHT; 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) { private static boolean isAddLineHovered(int mouseX, int mouseY) {
int addX = linesX() + LINES_WIDTH - 20; int addX = linesX() + LINES_WIDTH - 20;
return mouseX >= addX && mouseX < addX + 20 && mouseY >= TOP && mouseY < TOP + ROW_HEIGHT; return mouseX >= addX && mouseX < addX + 20 && mouseY >= TOP && mouseY < TOP + ROW_HEIGHT;
@@ -12,9 +12,11 @@ import net.minecraft.ChatFormatting;
import net.minecraft.client.KeyMapping; import net.minecraft.client.KeyMapping;
import net.minecraft.client.gui.GuiGraphicsExtractor; import net.minecraft.client.gui.GuiGraphicsExtractor;
import net.minecraft.client.input.KeyEvent; 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.client.resources.language.I18n;
import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Component;
import org.lwjgl.glfw.GLFW; import com.mojang.blaze3d.platform.InputConstants;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@@ -49,12 +51,13 @@ public class BindButton extends SettingButton<KeySetting> {
if (hovered && ClickGui.INSTANCE.trySelect(this)) { if (hovered && ClickGui.INSTANCE.trySelect(this)) {
if (listening) { if (listening) {
int key = KeyUtil.fromLegacyGlfwKey(button);
List<KeyMapping> keys = new ArrayList<>(List.of(mc.options.keyMappings)); List<KeyMapping> keys = new ArrayList<>(List.of(mc.options.keyMappings));
keys.removeAll(List.of(mc.options.debugKeys)); keys.removeAll(List.of(mc.options.debugKeys));
boolean allowMultiple = ClientSettingsPanel.clientSettings.multipleKeybinds.getValue(); boolean allowMultiple = ClientSettingsPanel.clientSettings.multipleKeybinds.getValue();
for (KeyMapping bind : keys) { for (KeyMapping bind : keys) {
if (bind.matches(new KeyEvent(button, 0, 0))) { if (bind.matches(new KeyEvent(key, 0, 0))) {
if (!allowMultiple) { if (!allowMultiple) {
ChatUtil.warn(Component.translatable("sputnik.commands.bind.keytaken", ChatUtil.warn(Component.translatable("sputnik.commands.bind.keytaken",
ChatFormatting.GREEN + "\"" + I18n.get(bind.getName()) + "\"")); ChatFormatting.GREEN + "\"" + I18n.get(bind.getName()) + "\""));
@@ -64,7 +67,7 @@ public class BindButton extends SettingButton<KeySetting> {
} }
} }
setting.setValue(button); setting.setValue(key);
listening = false; listening = false;
} else { } else {
if (button == 0) { if (button == 0) {
@@ -81,10 +84,10 @@ public class BindButton extends SettingButton<KeySetting> {
} }
public void onKey(int key, int action) { 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) { if (key == InputConstants.KEY_ESCAPE) {
setting.setValue(GLFW.GLFW_KEY_UNKNOWN); setting.setValue(InputConstants.UNKNOWN.getValue());
} else { } else {
List<KeyMapping> keys = new ArrayList<>(List.of(mc.options.keyMappings)); List<KeyMapping> keys = new ArrayList<>(List.of(mc.options.keyMappings));
keys.removeAll(List.of(mc.options.debugKeys)); keys.removeAll(List.of(mc.options.debugKeys));
@@ -106,6 +109,27 @@ public class BindButton extends SettingButton<KeySetting> {
listening = false; listening = false;
} }
public void onMouse(int button, int action) {
if (!listening || action != InputConstants.PRESS) return;
List<KeyMapping> 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() { public boolean isFocused() {
return listening; return listening;
} }
@@ -13,8 +13,9 @@ import net.minecraft.client.resources.language.I18n;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.lwjgl.glfw.GLFW; import com.mojang.blaze3d.platform.InputConstants;
import org.lwjgl.util.tinyfd.TinyFileDialogs; import java.awt.FileDialog;
import java.awt.Frame;
import java.awt.*; import java.awt.*;
import java.nio.file.Path; import java.nio.file.Path;
@@ -75,23 +76,23 @@ public class FileButton extends SettingButton<FileSetting> {
@Override @Override
public void onKey(int key, int action) { public void onKey(int key, int action) {
if (!typing || action == GLFW.GLFW_RELEASE) return; if (!typing || action == InputConstants.RELEASE) return;
// pegar con ctrl + v // 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(); paste();
return; return;
} }
switch (key) { // casos para teclas especiales como enter, escape o borrar switch (key) { // casos para teclas especiales como enter, escape o borrar
case GLFW.GLFW_KEY_ENTER -> { case InputConstants.KEY_RETURN -> {
setting.setValue(buffer.toString()); setting.setValue(buffer.toString());
typing = false; typing = false;
} case GLFW.GLFW_KEY_BACKSPACE -> { } case InputConstants.KEY_BACKSPACE -> {
onBackspace(); onBackspace();
} case GLFW.GLFW_KEY_ESCAPE -> { } case InputConstants.KEY_ESCAPE -> {
typing = false; typing = false;
} case GLFW.GLFW_KEY_SPACE -> { } case InputConstants.KEY_SPACE -> {
charTyped(' '); charTyped(' ');
} default -> { } default -> {
String c = KeyUtil.getKeyName(key); String c = KeyUtil.getKeyName(key);
@@ -139,14 +140,14 @@ public class FileButton extends SettingButton<FileSetting> {
@Nullable @Nullable
public Path pickFile() { public Path pickFile() {
String result = TinyFileDialogs.tinyfd_openFileDialog( FileDialog dialog = new FileDialog((Frame) null,
I18n.get("sputnik.filesetting.choose"), I18n.get("sputnik.filesetting.choose"), FileDialog.LOAD);
setting.isDirectory() String initial = setting.isDirectory()
? setting.getValue() ? setting.getValue()
: setting.getPath().getParent().toString(), : setting.getPath().getParent().toString();
null, dialog.setDirectory(initial);
I18n.get("sputnik.filesetting.supportedfiles"), dialog.setVisible(true);
false); String file = dialog.getFile();
return result == null ? null : Path.of(result); return file == null ? null : Path.of(dialog.getDirectory(), file);
} }
} }
@@ -8,7 +8,7 @@ import me.retucio.sputnik.ui.widgets.panels.settings.ClientSettingsPanel;
import me.retucio.sputnik.util.Colors; import me.retucio.sputnik.util.Colors;
import me.retucio.sputnik.util.KeyUtil; import me.retucio.sputnik.util.KeyUtil;
import net.minecraft.client.gui.GuiGraphicsExtractor; import net.minecraft.client.gui.GuiGraphicsExtractor;
import org.lwjgl.glfw.GLFW; import com.mojang.blaze3d.platform.InputConstants;
import java.awt.*; import java.awt.*;
import java.text.DecimalFormat; import java.text.DecimalFormat;
@@ -60,7 +60,7 @@ public class SliderButton extends SettingButton<NumberSetting> {
public void onKey(int key, int action) { 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, // 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 // 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()) || key == ClientSettingsPanel.clientSettings.getKey())
dragging = false; dragging = false;
} }
@@ -8,7 +8,7 @@ import me.retucio.sputnik.util.Colors;
import me.retucio.sputnik.util.KeyUtil; import me.retucio.sputnik.util.KeyUtil;
import me.retucio.sputnik.util.MiscUtil; import me.retucio.sputnik.util.MiscUtil;
import net.minecraft.client.gui.GuiGraphicsExtractor; 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 // botón para los ajustes que requieran introducir texto
@@ -55,23 +55,23 @@ public class TextButton extends SettingButton<StringSetting> {
@Override @Override
public void onKey(int key, int action) { public void onKey(int key, int action) {
if (!typing || action == GLFW.GLFW_RELEASE) return; if (!typing || action == InputConstants.RELEASE) return;
// pegar con ctrl + v // 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(); paste();
return; return;
} }
switch (key) { // casos para teclas especiales como enter, escape o borrar switch (key) { // casos para teclas especiales como enter, escape o borrar
case GLFW.GLFW_KEY_ENTER -> { case InputConstants.KEY_RETURN -> {
setting.setValue(buffer.toString()); setting.setValue(buffer.toString());
typing = false; typing = false;
} case GLFW.GLFW_KEY_BACKSPACE -> { } case InputConstants.KEY_BACKSPACE -> {
onBackspace(); onBackspace();
} case GLFW.GLFW_KEY_ESCAPE -> { } case InputConstants.KEY_ESCAPE -> {
typing = false; typing = false;
} case GLFW.GLFW_KEY_SPACE -> { } case InputConstants.KEY_SPACE -> {
charTyped(' '); charTyped(' ');
} default -> { } default -> {
String c = KeyUtil.getKeyName(key); String c = KeyUtil.getKeyName(key);
@@ -17,7 +17,7 @@ import net.minecraft.ChatFormatting;
import net.minecraft.client.gui.GuiGraphicsExtractor; import net.minecraft.client.gui.GuiGraphicsExtractor;
import net.minecraft.client.renderer.RenderPipelines; import net.minecraft.client.renderer.RenderPipelines;
import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Component;
import org.lwjgl.glfw.GLFW; import com.mojang.blaze3d.platform.InputConstants;
import java.awt.Color; import java.awt.Color;
import java.util.List; import java.util.List;
@@ -99,25 +99,25 @@ public class SearchBarWidget extends Widget {
@Override @Override
public void onKey(int key, int action) { public void onKey(int key, int action) {
if (!ClientSettingsPanel.clientSettings.searchBar.getValue()) return; 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(); paste();
return; return;
} }
switch (key) { switch (key) {
case GLFW.GLFW_KEY_ENTER -> focused = false; case InputConstants.KEY_RETURN -> focused = false;
case GLFW.GLFW_KEY_ESCAPE -> { case InputConstants.KEY_ESCAPE -> {
buffer.setLength(0); buffer.setLength(0);
focused = false; focused = false;
} }
case GLFW.GLFW_KEY_SPACE -> charTyped(' '); case InputConstants.KEY_SPACE -> charTyped(' ');
case GLFW.GLFW_KEY_BACKSPACE -> onBackspace(); case InputConstants.KEY_BACKSPACE -> onBackspace();
default -> { default -> {
String c = KeyUtil.getKeyName(key); String c = KeyUtil.getKeyName(key);
if (c.length() == 1) { 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)); charTyped(KeyUtil.shiftKey(c).charAt(0));
else else
charTyped(c.toLowerCase().charAt(0)); charTyped(c.toLowerCase().charAt(0));
@@ -7,7 +7,7 @@ import me.retucio.sputnik.util.MiscUtil;
import net.minecraft.ChatFormatting; import net.minecraft.ChatFormatting;
import net.minecraft.client.gui.GuiGraphicsExtractor; import net.minecraft.client.gui.GuiGraphicsExtractor;
import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Component;
import org.lwjgl.glfw.GLFW; import com.mojang.blaze3d.platform.InputConstants;
import java.awt.Color; import java.awt.Color;
import java.util.function.Consumer; import java.util.function.Consumer;
@@ -69,21 +69,21 @@ public class TextFieldWidget extends Widget {
@Override @Override
public void onKey(int key, int action) { 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())); buffer.append(MiscUtil.getPasteContent(maxLength - buffer.length()));
return; return;
} }
switch (key) { switch (key) {
case GLFW.GLFW_KEY_ENTER -> submit(); case InputConstants.KEY_RETURN -> submit();
case GLFW.GLFW_KEY_ESCAPE -> { case InputConstants.KEY_ESCAPE -> {
buffer.setLength(0); buffer.setLength(0);
focused = false; focused = false;
} }
case GLFW.GLFW_KEY_BACKSPACE -> MiscUtil.backspace(buffer); case InputConstants.KEY_BACKSPACE -> MiscUtil.backspace(buffer);
case GLFW.GLFW_KEY_SPACE -> charTyped(' '); case InputConstants.KEY_SPACE -> charTyped(' ');
default -> { default -> {
String c = KeyUtil.getKeyName(key); String c = KeyUtil.getKeyName(key);
if (c.length() == 1) if (c.length() == 1)
@@ -1,107 +1,128 @@
package me.retucio.sputnik.ui.widgets.panels.settings; 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.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.panels.SettingsPanel;
import me.retucio.sputnik.ui.widgets.buttons.SettingButton;
import me.retucio.sputnik.util.Colors; import me.retucio.sputnik.util.Colors;
import me.retucio.sputnik.util.I18nUtil; import me.retucio.sputnik.util.I18nUtil;
import me.retucio.sputnik.module.setting.SettingGroup;
import net.minecraft.client.gui.GuiGraphicsExtractor; import net.minecraft.client.gui.GuiGraphicsExtractor;
import java.util.List;
public class ClientSettingsPanel extends SettingsPanel { public class ClientSettingsPanel extends SettingsPanel {
public static final ClientSettingsModule clientSettings = new ClientSettingsModule(); public static final ClientSettingsModule clientSettings = new ClientSettingsModule();
private boolean extended = false; private final List<SettingGroup> 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) { 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")); setTitle(() -> I18nUtil.orElse("sputnik.ui.clientsettings.title", "ajustes del mod"));
this.drawHeader = false; // disable the original header this.drawHeader = false;
} }
@Override @Override
public void render(GuiGraphicsExtractor gui, int mouseX, int mouseY, float delta) { 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(0, 20, screenWidth, screenHeight, Colors.panelBgColor.getRGB());
gui.fill(x, renderY, x + w, renderY + h, Colors.mainColor.getRGB()); gui.fill(0, 20, SIDEBAR_WIDTH, screenHeight, Colors.buttonColor.getRGB());
gui.text(mc.font, getTitle(), gui.text(mc.font, getTitle(), 14, 28, Colors.mainColor.getRGB(), true);
x + 8,
renderY + (h / 2) - (mc.font.lineHeight / 2),
-1, true);
String symbol = extended ? "-" : "+"; int tabY = 52;
int textWidth = mc.font.width(symbol); for (SettingGroup group : allGroups) {
gui.text(mc.font, symbol, boolean hovered = mouseX >= 8 && mouseX < SIDEBAR_WIDTH - 8
x + w - textWidth - 8, && mouseY >= tabY && mouseY < tabY + GROUP_HEIGHT;
renderY + (h / 2) - (mc.font.lineHeight / 2), int color = group == selectedGroup ? Colors.mainColor.getRGB()
-1, true); : hovered ? Colors.buttonColor.brighter().getRGB() : Colors.buttonColor.getRGB();
gui.fill(8, tabY, SIDEBAR_WIDTH - 8, tabY + GROUP_HEIGHT, color);
// Only draw the rest of the panel (content) if extended gui.text(mc.font, group.getName(), 18,
if (extended) { tabY + (GROUP_HEIGHT - mc.font.lineHeight) / 2, -1, true);
// Call super.render() – but since drawHeader=false, it will only draw the content tabY += GROUP_HEIGHT + 4;
super.render(gui, mouseX, mouseY, delta);
} }
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 @Override
public void mouseClicked(int mouseX, int mouseY, int button) { public void mouseClicked(int mouseX, int mouseY, int button) {
if (isHovered(mouseX, mouseY) && ClickGui.INSTANCE.trySelect(this)) { for (SettingButton<?> settingButton : visibleButtons)
if (button == 0) { settingButton.mouseClicked(mouseX, mouseY, button);
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);
}
} }
@Override @Override
public void mouseReleased(int mouseX, int mouseY, int button) { public void mouseReleased(int mouseX, int mouseY, int button) {
ClickGui.INSTANCE.unselect(this); for (SettingButton<?> settingButton : visibleButtons)
if (button == 0 && dragging) { settingButton.mouseReleased(mouseX, mouseY, button);
dragging = false;
Sputnik.EVENT_BUS.post(new ClientSettingsPanelEvent.Move());
}
if (extended) {
super.mouseReleased(mouseX, mouseY, button);
}
} }
@Override @Override
public void mouseDragged(int mouseX, int mouseY) { public void mouseDragged(int mouseX, int mouseY) {
if (extended) { for (SettingButton<?> settingButton : visibleButtons)
super.mouseDragged(mouseX, mouseY); settingButton.mouseDragged(mouseX, mouseY);
}
} }
@Override @Override
public void mouseScrolled(double amount) { public void mouseScrolled(double amount) {
if (extended) {
super.mouseScrolled(amount); super.mouseScrolled(amount);
} }
}
@Override @Override
public void onKey(int key, int action) { public void onKey(int key, int action) {
if (extended) {
super.onKey(key, action); super.onKey(key, action);
} }
}
public boolean isExtended() { public boolean isExtended() {
return extended; return true;
} }
public void setExtended(boolean extended) { public void setExtended(boolean extended) {
this.extended = extended; // La pestaña siempre muestra sus ajustes.
} }
} }
@@ -3,10 +3,12 @@ package me.retucio.sputnik.util;
import me.retucio.sputnik.mixin.accessors.KeyBindingAccessor; import me.retucio.sputnik.mixin.accessors.KeyBindingAccessor;
import net.minecraft.client.KeyMapping; import net.minecraft.client.KeyMapping;
import net.minecraft.client.input.KeyEvent; import net.minecraft.client.input.KeyEvent;
import org.lwjgl.glfw.GLFW; import com.mojang.blaze3d.platform.InputConstants;
import java.awt.*; import java.awt.*;
import java.awt.im.InputContext; import java.awt.im.InputContext;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.Locale; import java.util.Locale;
import static me.retucio.sputnik.Sputnik.mc; import static me.retucio.sputnik.Sputnik.mc;
@@ -14,8 +16,103 @@ import static me.retucio.sputnik.Sputnik.mc;
// cosas útiles relacionadas con las teclas // cosas útiles relacionadas con las teclas
public class KeyUtil { public class KeyUtil {
private static final int MOUSE_BIND_BASE = -1000;
private static final Set<Integer> 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) { 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) { public static boolean isKeyDown(KeyMapping key) {
@@ -23,14 +120,13 @@ public class KeyUtil {
} }
public static boolean isKeyDown(int key) { public static boolean isKeyDown(int key) {
return GLFW.glfwGetKey( if (isMouseBinding(key)) return PRESSED_MOUSE_BUTTONS.contains(decodeMouseButton(key));
mc.getWindow().handle(), return InputConstants.isKeyDown(key);
key) != GLFW.GLFW_RELEASE;
} }
public static boolean isShiftDown() { public static boolean isShiftDown() {
return isKeyDown(GLFW.GLFW_KEY_LEFT_SHIFT) return isKeyDown(InputConstants.KEY_LSHIFT)
|| isKeyDown(GLFW.GLFW_KEY_RIGHT_SHIFT); || isKeyDown(InputConstants.KEY_RSHIFT);
} }
public static int getKey(KeyMapping kb) { public static int getKey(KeyMapping kb) {
@@ -58,39 +154,48 @@ public class KeyUtil {
} }
public static String getKeyName(int key) { 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(); if (name != null) return name.toUpperCase();
// para teclas especiales // para teclas especiales
return switch (key) { return switch (key) {
case GLFW.GLFW_MOUSE_BUTTON_1 -> I18nUtil.orElse("sputnik.key.leftclick", "clic izquierdo"); case InputConstants.MOUSE_BUTTON_LEFT -> I18nUtil.orElse("sputnik.key.leftclick", "clic izquierdo");
case GLFW.GLFW_MOUSE_BUTTON_2 -> I18nUtil.orElse("sputnik.key.rightclick", "clic derecho"); case InputConstants.MOUSE_BUTTON_RIGHT -> I18nUtil.orElse("sputnik.key.rightclick", "clic derecho");
case GLFW.GLFW_MOUSE_BUTTON_3 -> I18nUtil.orElse("sputnik.key.middleclick", "ruedita"); case InputConstants.MOUSE_BUTTON_MIDDLE -> I18nUtil.orElse("sputnik.key.middleclick", "ruedita");
case GLFW.GLFW_KEY_SPACE -> I18nUtil.orElse("sputnik.key.space", "espacio"); case InputConstants.KEY_SPACE -> I18nUtil.orElse("sputnik.key.space", "espacio");
case GLFW.GLFW_KEY_LEFT_SHIFT -> I18nUtil.orElse("sputnik.key.leftshift", "shift izquierdo"); case InputConstants.KEY_LSHIFT -> I18nUtil.orElse("sputnik.key.leftshift", "shift izquierdo");
case GLFW.GLFW_KEY_RIGHT_SHIFT -> I18nUtil.orElse("sputnik.key.rightshift", "shift derecho"); case InputConstants.KEY_RSHIFT -> I18nUtil.orElse("sputnik.key.rightshift", "shift derecho");
case GLFW.GLFW_KEY_LEFT_CONTROL -> I18nUtil.orElse("sputnik.key.leftctrl", "ctrl izquierdo"); case InputConstants.KEY_LCONTROL -> I18nUtil.orElse("sputnik.key.leftctrl", "ctrl izquierdo");
case GLFW.GLFW_KEY_RIGHT_CONTROL -> I18nUtil.orElse("sputnik.key.rightctrl", "ctrl derecho"); case InputConstants.KEY_RCONTROL -> I18nUtil.orElse("sputnik.key.rightctrl", "ctrl derecho");
case GLFW.GLFW_KEY_LEFT_ALT -> I18nUtil.orElse("sputnik.key.leftalt", "alt izquierdo"); case InputConstants.KEY_LALT -> I18nUtil.orElse("sputnik.key.leftalt", "alt izquierdo");
case GLFW.GLFW_KEY_RIGHT_ALT -> I18nUtil.orElse("sputnik.key.altgr", "alt gr"); case InputConstants.KEY_RALT -> I18nUtil.orElse("sputnik.key.altgr", "alt gr");
case GLFW.GLFW_KEY_TAB -> I18nUtil.orElse("sputnik.key.tab", "tab"); case InputConstants.KEY_TAB -> I18nUtil.orElse("sputnik.key.tab", "tab");
case GLFW.GLFW_KEY_ENTER -> I18nUtil.orElse("sputnik.key.enter", "enter"); case InputConstants.KEY_RETURN -> I18nUtil.orElse("sputnik.key.enter", "enter");
case GLFW.GLFW_KEY_BACKSPACE -> I18nUtil.orElse("sputnik.key.backspace", "borrar"); case InputConstants.KEY_BACKSPACE -> I18nUtil.orElse("sputnik.key.backspace", "borrar");
case GLFW.GLFW_KEY_DELETE -> I18nUtil.orElse("sputnik.key.delete", "suprimir"); case InputConstants.KEY_DELETE -> I18nUtil.orElse("sputnik.key.delete", "suprimir");
case GLFW.GLFW_KEY_UP -> I18nUtil.orElse("sputnik.key.up", "arriba"); case InputConstants.KEY_UP -> I18nUtil.orElse("sputnik.key.up", "arriba");
case GLFW.GLFW_KEY_DOWN -> I18nUtil.orElse("sputnik.key.down", "abajo"); case InputConstants.KEY_DOWN -> I18nUtil.orElse("sputnik.key.down", "abajo");
case GLFW.GLFW_KEY_LEFT -> I18nUtil.orElse("sputnik.key.left", "izquierda"); case InputConstants.KEY_LEFT -> I18nUtil.orElse("sputnik.key.left", "izquierda");
case GLFW.GLFW_KEY_RIGHT -> I18nUtil.orElse("sputnik.key.right", "derecha"); case InputConstants.KEY_RIGHT -> I18nUtil.orElse("sputnik.key.right", "derecha");
case GLFW.GLFW_KEY_PAGE_UP -> I18nUtil.orElse("sputnik.key.pageup", "pág. arriba"); case InputConstants.KEY_PAGEUP -> I18nUtil.orElse("sputnik.key.pageup", "pág. arriba");
case GLFW.GLFW_KEY_PAGE_DOWN -> I18nUtil.orElse("sputnik.key.pagedown", "pág. abajo"); case InputConstants.KEY_PAGEDOWN -> I18nUtil.orElse("sputnik.key.pagedown", "pág. abajo");
case GLFW.GLFW_KEY_CAPS_LOCK -> I18nUtil.orElse("sputnik.key.capslock", "bloq. mayús."); case InputConstants.KEY_CAPSLOCK -> I18nUtil.orElse("sputnik.key.capslock", "bloq. mayús.");
case GLFW.GLFW_KEY_INSERT -> I18nUtil.orElse("sputnik.key.insert", "insertar"); case InputConstants.KEY_INSERT -> I18nUtil.orElse("sputnik.key.insert", "insertar");
default -> { default -> {
if (key >= GLFW.GLFW_KEY_F1 && key <= GLFW.GLFW_KEY_F25) { if (key >= InputConstants.KEY_F1 && key <= InputConstants.KEY_F24) {
yield "F" + (key - GLFW.GLFW_KEY_F1 + 1); // F1–F25 yield "F" + (key - InputConstants.KEY_F1 + 1); // F1–F25
} else if (key >= GLFW.GLFW_MOUSE_BUTTON_4 && key <= GLFW.GLFW_MOUSE_BUTTON_8) { } else if (key >= InputConstants.MOUSE_BUTTON_4 && key <= InputConstants.MOUSE_BUTTON_8) {
// botones del ratón // botones del ratón
yield I18nUtil.orElse("sputnik.key.mousebutton", yield I18nUtil.orElse("sputnik.key.mousebutton",
"botón del ratón " + (key + 1), key + 1); "botón del ratón " + (key + 1), key + 1);
@@ -12,7 +12,7 @@ import net.minecraft.world.phys.Vec3;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import org.joml.Vector3d; import org.joml.Vector3d;
import org.joml.Vector3f; import org.joml.Vector3f;
import org.lwjgl.glfw.GLFW; import com.mojang.blaze3d.platform.InputConstants;
import java.io.*; import java.io.*;
import java.time.Instant; import java.time.Instant;
@@ -100,7 +100,7 @@ public class MiscUtil {
} }
public static void backspace(StringBuilder buffer) { 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--) { for (int i = buffer.length() - 1; i >= 0; i--) {
char c = buffer.charAt(i); char c = buffer.charAt(i);
buffer.deleteCharAt(i); buffer.deleteCharAt(i);
@@ -11,18 +11,17 @@ import net.minecraft.network.PacketListener;
import net.minecraft.network.protocol.Packet; import net.minecraft.network.protocol.Packet;
import net.minecraft.network.protocol.game.ClientboundSetTimePacket; import net.minecraft.network.protocol.game.ClientboundSetTimePacket;
import net.minecraft.network.protocol.game.ServerboundSetCarriedItemPacket; import net.minecraft.network.protocol.game.ServerboundSetCarriedItemPacket;
import net.minecraft.network.protocol.game.ServerboundSwingPacket;
import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult; import net.minecraft.world.InteractionResult;
import net.minecraft.world.item.BlockItem; import net.minecraft.world.item.BlockItem;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.component.SwingAnimation;
import net.minecraft.world.level.Level; import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.*; import net.minecraft.world.level.block.*;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.Vec3;
import net.minecraft.world.phys.shapes.CollisionContext; import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.VoxelShape;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@@ -100,8 +99,7 @@ public class NetworkUtil {
InteractionResult result = mc.gameMode.useItemOn(mc.player, hand, blockHitResult); InteractionResult result = mc.gameMode.useItemOn(mc.player, hand, blockHitResult);
if (result.consumesAction()) { if (result.consumesAction()) {
if (swing) mc.player.swing(hand); mc.player.swing(hand, SwingAnimation.DEFAULT, false);
else mc.getConnection().send(new ServerboundSwingPacket(hand));
} }
mc.player.setShiftKeyDown(wasSneaking); mc.player.setShiftKeyDown(wasSneaking);
@@ -126,8 +126,8 @@ public class VersionChecker {
.get("sources") .get("sources")
.orElse(null); .orElse(null);
if (sources != null && sources.contains("codeberg.org")) { if (sources != null && sources.contains("retucio.me")) {
// codeberg (forgejo) sirve los archivos crudos en /raw/branch/<rama>/<archivo> // gitea sirve los archivos crudos en /raw/branch/<rama>/<archivo>
String rawUrl = sources.replaceAll("/+$", "") String rawUrl = sources.replaceAll("/+$", "")
+ "/raw/branch/master/gradle.properties"; + "/raw/branch/master/gradle.properties";
return URI.create(rawUrl); return URI.create(rawUrl);
@@ -4,12 +4,15 @@ import me.retucio.sputnik.Sputnik;
import me.retucio.sputnik.module.modules.render.GlintPlus; import me.retucio.sputnik.module.modules.render.GlintPlus;
import net.minecraft.client.renderer.RenderPipelines; import net.minecraft.client.renderer.RenderPipelines;
import net.minecraft.client.renderer.rendertype.*; import net.minecraft.client.renderer.rendertype.*;
import net.minecraft.client.renderer.oit.OitPipelineSet;
import net.minecraft.resources.Identifier; import net.minecraft.resources.Identifier;
import net.minecraft.world.item.DyeColor; import net.minecraft.world.item.DyeColor;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.function.Function; import java.util.function.Function;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/** utilidad para crear RenderTypes de glint con color personalizado /** utilidad para crear RenderTypes de glint con color personalizado
@@ -22,7 +25,6 @@ public class GlintRenderType {
public static final List<RenderType> glintColor = newRenderList(GlintRenderType::buildGlintRenderType); public static final List<RenderType> glintColor = newRenderList(GlintRenderType::buildGlintRenderType);
public static final List<RenderType> entityGlintColor = newRenderList(GlintRenderType::buildEntityGlintRenderType); public static final List<RenderType> entityGlintColor = newRenderList(GlintRenderType::buildEntityGlintRenderType);
public static final List<RenderType> armorEntityGlintColor = newRenderList(GlintRenderType::buildArmorEntityGlintRenderType);
public static final List<RenderType> glintTranslucentColor = newRenderList(GlintRenderType::buildGlintTranslucentRenderType); public static final List<RenderType> glintTranslucentColor = newRenderList(GlintRenderType::buildGlintTranslucentRenderType);
private static List<RenderType> newRenderList(Function<String, RenderType> func) { private static List<RenderType> newRenderList(Function<String, RenderType> func) {
@@ -55,7 +57,6 @@ public class GlintRenderType {
RenderSetup.builder(RenderPipelines.GLINT) RenderSetup.builder(RenderPipelines.GLINT)
.withTexture("Sampler0", res) .withTexture("Sampler0", res)
.setTextureTransform(TextureTransform.GLINT_TEXTURING) .setTextureTransform(TextureTransform.GLINT_TEXTURING)
.setOutputTarget(OutputTarget.ITEM_ENTITY_TARGET)
.createRenderSetup() .createRenderSetup()
); );
} }
@@ -71,14 +72,56 @@ public class GlintRenderType {
); );
} }
private static RenderType buildArmorEntityGlintRenderType(String name) { private static final Map<String, RenderType> ARMOR_GLINT_TYPES = new ConcurrentHashMap<>();
private static final Map<ItemGlintKey, RenderType> 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"); final Identifier res = Identifier.fromNamespaceAndPath(Sputnik.MOD_ID, "textures/misc/glint_" + name.toLowerCase() + ".png");
return RenderType.create( return RenderType.create(
"armor_glint_" + name, "armor_glint_" + name,
RenderSetup.builder(RenderPipelines.GLINT) RenderSetup.builder(RenderPipelines.ARMOR_CUTOUT_NO_CULL_GLINT)
.withTexture("Sampler0", res) .withTexture("Sampler0", armorTexture)
.withTexture("GlintSampler", res)
.setTextureTransform(TextureTransform.ARMOR_ENTITY_GLINT_TEXTURING) .setTextureTransform(TextureTransform.ARMOR_ENTITY_GLINT_TEXTURING)
.useLightmap()
.useOverlay()
.setLayeringTransform(LayeringTransform.VIEW_OFFSET_Z_LAYERING) .setLayeringTransform(LayeringTransform.VIEW_OFFSET_Z_LAYERING)
.affectsCrumbling()
.setOutline(RenderSetup.OutlineProperty.AFFECTS_OUTLINE)
.createRenderSetup() .createRenderSetup()
); );
} }
@@ -1,13 +1,14 @@
package me.retucio.sputnik.util.render; package me.retucio.sputnik.util.render;
import com.mojang.blaze3d.PrimitiveTopology; import com.mojang.renderpearl.api.pipeline.PrimitiveTopology;
import com.mojang.blaze3d.pipeline.DepthStencilState; import com.mojang.renderpearl.api.pipeline.DepthStencilState;
import com.mojang.blaze3d.pipeline.RenderPipeline; import com.mojang.renderpearl.api.pipeline.RenderPipeline;
import com.mojang.blaze3d.platform.CompareOp; import com.mojang.renderpearl.api.pipeline.CompareOp;
import com.mojang.blaze3d.systems.GpuDevice; import com.mojang.renderpearl.api.pipeline.ShaderType;
import com.mojang.renderpearl.api.device.GpuDevice;
import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.vertex.DefaultVertexFormat; import com.mojang.blaze3d.vertex.DefaultVertexFormat;
import com.mojang.blaze3d.vertex.VertexFormat; import com.mojang.renderpearl.api.vertex.VertexFormat;
import me.retucio.sputnik.Sputnik; 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 NO_DEPTH = new DepthStencilState(CompareOp.ALWAYS_PASS, false);
private static final DepthStencilState DEPTH = new DepthStencilState(CompareOp.GREATER_THAN_OR_EQUAL, 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")) .withLocation(Identifier.fromNamespaceAndPath(Sputnik.MOD_ID, "pipeline/lines"))
.withVertexBinding(0, DefaultVertexFormat.POSITION_COLOR_NORMAL_LINE_WIDTH) .withVertexBinding(0, DefaultVertexFormat.POSITION_COLOR_NORMAL_LINE_WIDTH)
.withPrimitiveTopology(PrimitiveTopology.LINES) .withPrimitiveTopology(PrimitiveTopology.LINES)
.withDepthStencilState(NO_DEPTH) .withDepthStencilState(NO_DEPTH)
.withCull(false) .withCull(false).build());
.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")) .withLocation(Identifier.fromNamespaceAndPath(Sputnik.MOD_ID, "pipeline/lines_cull"))
.withVertexBinding(0, DefaultVertexFormat.POSITION_COLOR_NORMAL_LINE_WIDTH) .withVertexBinding(0, DefaultVertexFormat.POSITION_COLOR_NORMAL_LINE_WIDTH)
.withPrimitiveTopology(PrimitiveTopology.LINES) .withPrimitiveTopology(PrimitiveTopology.LINES)
.withDepthStencilState(DEPTH) .withDepthStencilState(DEPTH)
.withCull(true) .withCull(true).build());
.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")) .withLocation(Identifier.fromNamespaceAndPath(Sputnik.MOD_ID, "pipeline/quads"))
.withVertexBinding(0, DefaultVertexFormat.POSITION_COLOR) .withVertexBinding(0, DefaultVertexFormat.POSITION_COLOR)
.withPrimitiveTopology(PrimitiveTopology.QUADS) .withPrimitiveTopology(PrimitiveTopology.QUADS)
.withDepthStencilState(NO_DEPTH) .withDepthStencilState(NO_DEPTH)
.withCull(false) .withCull(false).build());
.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")) .withLocation(Identifier.fromNamespaceAndPath(Sputnik.MOD_ID, "pipeline/quads_cull"))
.withVertexBinding(0, DefaultVertexFormat.POSITION_COLOR) .withVertexBinding(0, DefaultVertexFormat.POSITION_COLOR)
.withPrimitiveTopology(PrimitiveTopology.QUADS) .withPrimitiveTopology(PrimitiveTopology.QUADS)
.withDepthStencilState(DEPTH) .withDepthStencilState(DEPTH)
.withCull(false) .withCull(false).build());
.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")) .withLocation(Identifier.fromNamespaceAndPath(Sputnik.MOD_ID, "pipeline/text"))
.withVertexBinding(0, DefaultVertexFormat.POSITION_TEX_COLOR) .withVertexBinding(0, DefaultVertexFormat.POSITION_TEX_COLOR)
.withPrimitiveTopology(PrimitiveTopology.TRIANGLES) .withPrimitiveTopology(PrimitiveTopology.TRIANGLES)
.withVertexShader(Identifier.fromNamespaceAndPath(Sputnik.MOD_ID, "shaders/text.vert")) .withVertexShader(Identifier.fromNamespaceAndPath(Sputnik.MOD_ID, "shaders/text.vert"))
.withFragmentShader(Identifier.fromNamespaceAndPath(Sputnik.MOD_ID, "shaders/text.frag")) .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) .withBindGroupLayout(BindGroupLayouts.SAMPLER0)
.withDepthStencilState(NO_DEPTH) .withDepthStencilState(NO_DEPTH)
.withCull(false) .withCull(false).build());
.build());
public static void init() { public static void init() {
for (RenderPipeline pipeline : PIPELINES) { for (RenderPipeline pipeline : PIPELINES) precompile(pipeline);
precompile(pipeline);
}
} }
private static RenderPipeline add(RenderPipeline pipeline) { private static RenderPipeline add(RenderPipeline pipeline) {
@@ -92,17 +83,25 @@ public class Pipelines {
} }
public static void precompile(RenderPipeline pipeline) { public static void precompile(RenderPipeline pipeline) {
GpuDevice device = RenderSystem.getDevice(); // Pipeline compilation is lazy in 26.3; RenderPass resolves it from its RenderPipeline.
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);
} }
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;
} }
} }
@@ -1,27 +1,33 @@
package me.retucio.sputnik.util.render; package me.retucio.sputnik.util.render;
import com.mojang.blaze3d.GpuFormat; import com.mojang.renderpearl.api.GpuFormat;
import com.mojang.blaze3d.buffers.GpuBuffer; import com.mojang.renderpearl.api.buffers.GpuBuffer;
import com.mojang.blaze3d.buffers.GpuBufferSlice; import com.mojang.renderpearl.api.buffers.GpuBufferSlice;
import com.mojang.blaze3d.buffers.Std140Builder; import com.mojang.blaze3d.buffers.Std140Builder;
import com.mojang.blaze3d.framegraph.FrameGraphBuilder; import com.mojang.blaze3d.framegraph.FrameGraphBuilder;
import com.mojang.blaze3d.framegraph.FramePass; import com.mojang.blaze3d.framegraph.FramePass;
import com.mojang.blaze3d.pipeline.BindGroupLayout; import com.mojang.renderpearl.api.pipeline.BindGroupLayout;
import com.mojang.blaze3d.pipeline.RenderPipeline; 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.pipeline.RenderTarget;
import com.mojang.blaze3d.resource.GraphicsResourceAllocator; import com.mojang.blaze3d.resource.GraphicsResourceAllocator;
import com.mojang.blaze3d.resource.RenderTargetDescriptor; import com.mojang.blaze3d.resource.RenderTargetDescriptor;
import com.mojang.blaze3d.resource.ResourceHandle; import com.mojang.blaze3d.resource.ResourceHandle;
import com.mojang.blaze3d.shaders.UniformType; import com.mojang.renderpearl.api.pipeline.UniformType;
import com.mojang.blaze3d.systems.CommandEncoder; import com.mojang.renderpearl.api.commands.CommandEncoder;
import com.mojang.blaze3d.systems.RenderPass; import com.mojang.renderpearl.api.commands.RenderPass;
import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.textures.FilterMode; import com.mojang.renderpearl.api.textures.FilterMode;
import com.mojang.blaze3d.textures.GpuSampler; import com.mojang.renderpearl.api.textures.GpuSampler;
import me.retucio.sputnik.Sputnik; import me.retucio.sputnik.Sputnik;
import net.minecraft.client.renderer.MappableRingBuffer; 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.client.renderer.RenderPipelines;
import net.minecraft.resources.Identifier; import net.minecraft.resources.Identifier;
@@ -30,6 +36,8 @@ import org.joml.Vector4f;
import java.util.Optional; import java.util.Optional;
import java.util.OptionalDouble; import java.util.OptionalDouble;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Consumer; import java.util.function.Consumer;
@@ -51,7 +59,8 @@ public class PostShader {
.withLocation(Identifier.fromNamespaceAndPath(Sputnik.MOD_ID, "pipeline/post/blit")) .withLocation(Identifier.fromNamespaceAndPath(Sputnik.MOD_ID, "pipeline/post/blit"))
.withVertexShader(SCREENQUAD) .withVertexShader(SCREENQUAD)
.withFragmentShader(Identifier.fromNamespaceAndPath(Sputnik.MOD_ID, "post/blit")) .withFragmentShader(Identifier.fromNamespaceAndPath(Sputnik.MOD_ID, "post/blit"))
.withBindGroupLayout(BindGroupLayout.builder().withSampler(INPUT_SAMPLER).build()) .withBindGroupLayout(BindGroupLayouts.IN_SAMPLER)
.withColorTargetState(ColorTargetState.DEFAULT)
.build(); .build();
private final String name; 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) // 0 sin intentar, 1 ok, -1 falló al compilar (shader roto: no reintentar hasta recarga)
private int state = 0; private int state = 0;
private static final Map<RenderPipeline, CompiledRenderPipeline> COMPILED = new ConcurrentHashMap<>();
private PostShader(String name, RenderPipeline pipeline, FilterMode filter, private PostShader(String name, RenderPipeline pipeline, FilterMode filter,
@Nullable String uniformBlock, int uniformSize) { @Nullable String uniformBlock, int uniformSize) {
@@ -86,14 +96,20 @@ public class PostShader {
private boolean ensureReady() { private boolean ensureReady() {
if (state != 0) return state == 1; if (state != 0) return state == 1;
boolean ok = RenderSystem.getDevice().precompilePipeline(pipeline).isValid() boolean ok;
&& RenderSystem.getDevice().precompilePipeline(BLIT_PIPELINE).isValid(); 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) { if (ok && uniformBlock != null && uniformUbo == null) {
// 130 = USAGE_UNIFORM (128) | USAGE_MAP_WRITE (2): se reescribe cada frame // 130 = USAGE_UNIFORM (128) | USAGE_MAP_WRITE (2): se reescribe cada frame
uniformUbo = new MappableRingBuffer(() -> "sputnik post " + name, 130, uniformSize); uniformUbo = new MappableRingBuffer(() -> "sputnik post " + name, 130, uniformSize);
} }
state = ok ? 1 : -1; state = ok ? 1 : -1;
if (!ok) Sputnik.LOGGER.error("no se pudo compilar el shader de post '{}'", name);
return ok; return ok;
} }
@@ -109,8 +125,9 @@ public class PostShader {
FrameGraphBuilder frame = new FrameGraphBuilder(); FrameGraphBuilder frame = new FrameGraphBuilder();
ResourceHandle<RenderTarget> mainHandle = frame.importExternal(name + "_main", target); ResourceHandle<RenderTarget> mainHandle = frame.importExternal(name + "_main", target);
RenderTargetDescriptor swapDesc = new RenderTargetDescriptor( RenderTargetDescriptor swapDesc = new RenderTargetDescriptor(target.width, target.height,
target.width, target.height, true, NO_CLEAR, GpuFormat.RGBA8_UNORM); new RenderTargetDescriptor.TextureProperties(NO_CLEAR, GpuFormat.RGBA8_UNORM),
RenderTargetDescriptor.TextureProperties.DEFAULT_DEPTH);
ResourceHandle<RenderTarget> swapHandle = frame.createInternal(name + "_swap", swapDesc); ResourceHandle<RenderTarget> swapHandle = frame.createInternal(name + "_swap", swapDesc);
// pasada del efecto: main -> swap // pasada del efecto: main -> swap
@@ -145,16 +162,44 @@ public class PostShader {
() -> "sputnik post " + name, () -> "sputnik post " + name,
out.getColorTextureView(), out.getColorTextureView(),
Optional.empty(), Optional.empty(),
out.useDepth ? out.getDepthTextureView() : null, out.hasDepth() ? out.getDepthTextureView() : null,
OptionalDouble.empty())) { OptionalDouble.empty())) {
pass.setPipeline(pipeline); pass.setPipeline(compile(pipeline));
RenderSystem.bindDefaultUniforms(pass); RenderSystem.bindDefaultUniforms(pass);
if (uniform != null && uniformBlock != null) pass.setUniform(uniformBlock, uniform); 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); 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 { public static class Builder {
@@ -183,15 +228,17 @@ public class PostShader {
} }
public PostShader build() { public PostShader build() {
BindGroupLayout.Builder layout = BindGroupLayout.builder().withSampler(INPUT_SAMPLER); RenderPipeline.Builder pipelineBuilder = RenderPipeline.builder(RenderPipelines.POST_PROCESSING_SNIPPET)
if (uniformBlock != null) layout.withUniform(uniformBlock, UniformType.UNIFORM_BUFFER);
RenderPipeline pipeline = RenderPipeline.builder(RenderPipelines.POST_PROCESSING_SNIPPET)
.withLocation(Identifier.fromNamespaceAndPath(Sputnik.MOD_ID, "pipeline/post/" + name)) .withLocation(Identifier.fromNamespaceAndPath(Sputnik.MOD_ID, "pipeline/post/" + name))
.withVertexShader(SCREENQUAD) .withVertexShader(SCREENQUAD)
.withFragmentShader(fragmentShader) .withFragmentShader(fragmentShader)
.withBindGroupLayout(layout.build()) .withBindGroupLayout(BindGroupLayouts.IN_SAMPLER)
.build(); .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)); return PostShaders.register(new PostShader(name, pipeline, filter, uniformBlock, uniformSize));
} }
@@ -1,6 +1,6 @@
package me.retucio.sputnik.util.render; 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.blaze3d.vertex.*;
import com.mojang.math.Axis; import com.mojang.math.Axis;
import net.minecraft.client.Camera; import net.minecraft.client.Camera;
@@ -453,8 +453,8 @@ public class RenderUtil {
Camera camera = mc.gameRenderer.mainCamera(); Camera camera = mc.gameRenderer.mainCamera();
Vec3 camPos = camera.position(); Vec3 camPos = camera.position();
matrices.mulPose(Axis.XP.rotationDegrees(camera.yRot())); matrices.rotate(Axis.XP.rotationDegrees(camera.yRot()));
matrices.mulPose(Axis.YP.rotationDegrees(camera.xRot() + 180.0f)); matrices.rotate(Axis.YP.rotationDegrees(camera.xRot() + 180.0f));
matrices.translate( matrices.translate(
pos.x() - camPos.x(), pos.x() - camPos.x(),
@@ -1,8 +1,12 @@
package me.retucio.sputnik.util.render; 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.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 me.retucio.sputnik.Sputnik;
import net.minecraft.client.renderer.StagedVertexBuffer; import net.minecraft.client.renderer.StagedVertexBuffer;
import net.minecraft.client.renderer.rendertype.PreparedRenderType; import net.minecraft.client.renderer.rendertype.PreparedRenderType;
@@ -60,10 +64,18 @@ public class SputnikBuffers {
buffer.upload(); buffer.upload();
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) { for (QueuedDraw queued : queue) {
StagedVertexBuffer.ExecuteInfo info = buffer.getExecuteInfo(queued.draw()); StagedVertexBuffer.ExecuteInfo info = buffer.getExecuteInfo(queued.draw());
if (info != null) queued.type().drawFromBuffer(info); if (info != null) queued.type().drawFromBuffer(info, pass);
} }
}
encoder.submit();
queue.clear(); queue.clear();
buffer.endDraw(); buffer.endDraw();
@@ -1632,7 +1632,7 @@
"sputnik.ui.friends.title": "friends", "sputnik.ui.friends.title": "friends",
"sputnik.ui.list.tooltip": "%s (%s of %s)", "sputnik.ui.list.tooltip": "%s (%s of %s)",
"sputnik.ui.macros.empty": "no macros yet", "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.lineinstructions": "shift + right click on a line to remove it",
"sputnik.ui.macros.lineplaceholder": "command or message...", "sputnik.ui.macros.lineplaceholder": "command or message...",
"sputnik.ui.macros.nameplaceholder": "macro name...", "sputnik.ui.macros.nameplaceholder": "macro name...",
@@ -1651,6 +1651,7 @@
"sputnik.ui.searchbar.placeholder": "search...", "sputnik.ui.searchbar.placeholder": "search...",
"sputnik.ui.settingsof": "%s settings", "sputnik.ui.settingsof": "%s settings",
"sputnik.ui.tab.hud": "hud", "sputnik.ui.tab.hud": "hud",
"sputnik.ui.tab.client_settings": "client settings",
"sputnik.ui.tab.macros": "macros", "sputnik.ui.tab.macros": "macros",
"sputnik.ui.tab.modules": "modules", "sputnik.ui.tab.modules": "modules",
"sputnik.ui.tab.profiles": "profiles", "sputnik.ui.tab.profiles": "profiles",
@@ -1632,7 +1632,7 @@
"sputnik.ui.friends.title": "amigos", "sputnik.ui.friends.title": "amigos",
"sputnik.ui.list.tooltip": "%s (%s de %s)", "sputnik.ui.list.tooltip": "%s (%s de %s)",
"sputnik.ui.macros.empty": "todavía no hay macros", "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.lineinstructions": "shift + clic der. sobre una línea para quitarla",
"sputnik.ui.macros.lineplaceholder": "comando o mensaje...", "sputnik.ui.macros.lineplaceholder": "comando o mensaje...",
"sputnik.ui.macros.nameplaceholder": "nombre de la macro...", "sputnik.ui.macros.nameplaceholder": "nombre de la macro...",
@@ -1651,6 +1651,7 @@
"sputnik.ui.searchbar.placeholder": "buscar...", "sputnik.ui.searchbar.placeholder": "buscar...",
"sputnik.ui.settingsof": "ajustes de %s", "sputnik.ui.settingsof": "ajustes de %s",
"sputnik.ui.tab.hud": "hud", "sputnik.ui.tab.hud": "hud",
"sputnik.ui.tab.client_settings": "ajustes",
"sputnik.ui.tab.macros": "macros", "sputnik.ui.tab.macros": "macros",
"sputnik.ui.tab.modules": "módulos", "sputnik.ui.tab.modules": "módulos",
"sputnik.ui.tab.profiles": "perfiles", "sputnik.ui.tab.profiles": "perfiles",
@@ -1,11 +1,12 @@
#version 330 #version 330
#extension GL_ARB_separate_shader_objects : require
// copia el resultado de la pasada lsd (un objetivo intermedio) de vuelta al objetivo // 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 // principal: una pasada de post no puede leer y escribir la misma textura a la vez
uniform sampler2D InSampler; uniform sampler2D InSampler;
in vec2 texCoord; layout(location = 0) in vec2 texCoord;
out vec4 fragColor; layout(location = 0) out vec4 fragColor;
void main() { void main() {
fragColor = texture(InSampler, texCoord); fragColor = texture(InSampler, texCoord);
@@ -1,11 +1,10 @@
#version 330 #version 330
#extension GL_ARB_separate_shader_objects : require
#define M_PI 3.1415926535897932384626433832795
uniform sampler2D InSampler; uniform sampler2D InSampler;
in vec2 texCoord; layout(location = 0) in vec2 texCoord;
out vec4 fragColor; layout(location = 0) out vec4 fragColor;
layout(std140) uniform LsdConfig { layout(std140) uniform LsdConfig {
float strength; float strength;
@@ -87,32 +86,19 @@ float cnoise(vec3 P){
} }
vec3 hueShift(vec3 color, float hueAdjust){ vec3 rgbToHsv(vec3 color) {
const vec3 kRGBToYPrime = vec3(0.299, 0.587, 0.114); vec4 k = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
const vec3 kRGBToI = vec3(0.596, -0.275, -0.321); vec4 p = mix(vec4(color.bg, k.wz), vec4(color.gb, k.xy), step(color.b, color.g));
const vec3 kRGBToQ = vec3(0.212, -0.523, 0.311); 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);
const vec3 kYIQToR = vec3 (1.0, 0.956, 0.621); float e = 1.0e-10;
const vec3 kYIQToG = vec3 (1.0, -0.272, -0.647); return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);
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 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() { void main() {
vec2 oneTexel = vec2(1.0) / vec2(textureSize(InSampler, 0)); vec2 oneTexel = vec2(1.0) / vec2(textureSize(InSampler, 0));
@@ -122,5 +108,9 @@ void main() {
float c = cos(ang); float c = cos(ang);
vec2 offset = vec2(s, c) * perlin; vec2 offset = vec2(s, c) * perlin;
vec4 tex = texture(InSampler, texCoord + (offset * strength * 30.0) * oneTexel); 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);
} }
+1 -1
View File
@@ -9,7 +9,7 @@
], ],
"contact": { "contact": {
"homepage": "https://retucio.me/projects/sputnik.html", "homepage": "https://retucio.me/projects/sputnik.html",
"sources": "https://codeberg.org/retucio/sputnik" "sources": "https://git.retucio.me/retucio/sputnik"
}, },
"license": "CC0-1.0", "license": "CC0-1.0",
"icon": "assets/sputnik/icon.png", "icon": "assets/sputnik/icon.png",
-3
View File
@@ -34,9 +34,6 @@ accessible field net/minecraft/client/particle/Particle hasPhysics Z
# renderizado 3d # renderizado 3d
accessible method net/minecraft/client/renderer/rendertype/RenderType <init> (Ljava/lang/String;Lnet/minecraft/client/renderer/rendertype/RenderSetup;)V accessible method net/minecraft/client/renderer/rendertype/RenderType <init> (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 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 # pantallas
accessible field net/minecraft/client/gui/screens/inventory/AbstractContainerScreen imageWidth I accessible field net/minecraft/client/gui/screens/inventory/AbstractContainerScreen imageWidth I
+1 -2
View File
@@ -81,11 +81,10 @@
"mixins.render.EntityRenderDispatcherMixin", "mixins.render.EntityRenderDispatcherMixin",
"mixins.render.EntityRenderStateMixin", "mixins.render.EntityRenderStateMixin",
"mixins.render.EquipmentLayerRendererMixin", "mixins.render.EquipmentLayerRendererMixin",
"mixins.render.ItemFeatureRendererMixin",
"mixins.render.FogRendererMixin", "mixins.render.FogRendererMixin",
"mixins.render.FontMixin", "mixins.render.FontMixin",
"mixins.render.GameRendererMixin", "mixins.render.GameRendererMixin",
"mixins.render.ItemFeatureRendererMixin",
"mixins.render.ItemInHandRendererMixin",
"mixins.render.LevelRendererMixin", "mixins.render.LevelRendererMixin",
"mixins.render.LightmapMixin", "mixins.render.LightmapMixin",
"mixins.render.LightmapRenderStateExtractorMixin", "mixins.render.LightmapRenderStateExtractorMixin",