v5.6
This commit is contained in:
1 parent
81fc25c33d
commit
e0f8523809
29 files changed
+502
-181
No files matched your search
+14
-3
@@ -6,13 +6,24 @@
|
|||||||
|
|
||||||
#### módulos nuevos:
|
#### módulos nuevos:
|
||||||
|
|
||||||
#### comandos nuevos:
|
- autoataque: mantén el botón de ataque pulsado para atacar automáticamente
|
||||||
|
|
||||||
- `$panorama`: construye un pack de texturas con una panorámica basada en tu posición actual.
|
#### comandos nuevos:
|
||||||
|
|
||||||
### arreglos / mejoras
|
### arreglos / mejoras
|
||||||
|
|
||||||
- arreglado ScreenshotMixin, es decir, que ya no crasheará al tomar capturas
|
- arreglado el guardado al cerrar el juego: petaba antes de escribir nada, así que se perdía
|
||||||
|
todo lo cambiado desde el último autoguardado y al volver a entrar salían los ajustes por defecto
|
||||||
|
- el autoguardado cuenta desde el último guardado y no desde el último cambio, que tocando
|
||||||
|
ajustes seguido no llegaba a guardar nunca
|
||||||
|
- guardando dos veces seguidas ya no se descarta la segunda (era la más reciente)
|
||||||
|
- las teclas de los módulos ya no se pisan entre ellas al cargar la config.
|
||||||
|
- si algo falla al aplicar los ajustes ya no se queda el mod entero sin guardar
|
||||||
|
- las listas (entidades, ítems, bloques...) se traducen al idioma del juego en vez de salir
|
||||||
|
siempre en inglés, y se guardan por nombre interno para que no dependan del idioma
|
||||||
|
- traducidos los títulos de los marcos, las descripciones de los módulos y los mensajes del
|
||||||
|
arranque, que salían en español o directamente como la clave de traducción
|
||||||
|
- añadidas las traducciones que faltaban del autoataque
|
||||||
|
|
||||||
## problemas reconocidos
|
## problemas reconocidos
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -10,6 +10,6 @@ discord_rpc_version=1.0.3
|
|||||||
neutrino_version=1.1.0
|
neutrino_version=1.1.0
|
||||||
jdk_version=25
|
jdk_version=25
|
||||||
|
|
||||||
mod_version=5.5
|
mod_version=5.6
|
||||||
maven_group=me.retucio
|
maven_group=me.retucio
|
||||||
archives_base_name=sputnik
|
archives_base_name=sputnik
|
||||||
@@ -135,11 +135,8 @@ public class Sputnik implements ClientModInitializer {
|
|||||||
|
|
||||||
// se ejecuta cada tick, es decir, 20 veces por segundo
|
// se ejecuta cada tick, es decir, 20 veces por segundo
|
||||||
public void onTick() {
|
public void onTick() {
|
||||||
if (!settingsApplied
|
if (!settingsApplied && !ConfigManager.INSTANCE.hasLoaded()) {
|
||||||
&& ConfigManager.INSTANCE.getConfig() != null
|
settingsApplied = ConfigManager.INSTANCE.applyConfig();
|
||||||
&& !ConfigManager.INSTANCE.hasLoaded()) {
|
|
||||||
ConfigManager.INSTANCE.applyConfig();
|
|
||||||
settingsApplied = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ModuleManager.INSTANCE.getEnabledModules().forEach(Module::onTick);
|
ModuleManager.INSTANCE.getEnabledModules().forEach(Module::onTick);
|
||||||
@@ -161,7 +158,7 @@ public class Sputnik implements ClientModInitializer {
|
|||||||
if (BindCommand.onKeyPress(key)) return;
|
if (BindCommand.onKeyPress(key)) return;
|
||||||
if (action == GLFW.GLFW_PRESS) {
|
if (action == GLFW.GLFW_PRESS) {
|
||||||
handleModuleToggle(key, anyFocused);
|
handleModuleToggle(key, anyFocused);
|
||||||
handleClickGUIKey(key, anyFocused);
|
handleClickGuiKey(key, anyFocused);
|
||||||
handleHudEditorKey(key, anyFocused);
|
handleHudEditorKey(key, anyFocused);
|
||||||
}
|
}
|
||||||
// solo reenviar teclas del teclado
|
// solo reenviar teclas del teclado
|
||||||
@@ -208,7 +205,7 @@ public class Sputnik implements ClientModInitializer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// maneja la lógica de apertura de la interfaz
|
// maneja la lógica de apertura de la interfaz
|
||||||
private void handleClickGUIKey(int key, boolean anyFocused) {
|
private void handleClickGuiKey(int key, boolean anyFocused) {
|
||||||
if (key != ClientSettingsPanel.clientSettings.getKey() || anyFocused || isOnTypingScreen())
|
if (key != ClientSettingsPanel.clientSettings.getKey() || anyFocused || isOnTypingScreen())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -221,7 +218,7 @@ public class Sputnik implements ClientModInitializer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// manejar la lógica de apertura del editor de elementos del hud, con la misma lógica que handleClickGUIKey()
|
// manejar la lógica de apertura del editor de elementos del hud, con la misma lógica que handleClickGuiKey()
|
||||||
private void handleHudEditorKey(int key, boolean anyFocused) {
|
private void handleHudEditorKey(int key, boolean anyFocused) {
|
||||||
Hud hud = ModuleManager.INSTANCE.getModuleByClass(Hud.class);
|
Hud hud = ModuleManager.INSTANCE.getModuleByClass(Hud.class);
|
||||||
if (key != hud.editorKey.getValue() || anyFocused || isOnTypingScreen()) return;
|
if (key != hud.editorKey.getValue() || anyFocused || isOnTypingScreen()) return;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
package me.retucio.sputnik.config;
|
package me.retucio.sputnik.config;
|
||||||
|
|
||||||
import net.minecraft.network.chat.Component;
|
import me.retucio.sputnik.util.I18nUtil;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
@@ -85,44 +85,59 @@ public class BinarySerializer {
|
|||||||
public static ClientConfig readConfig(File file)
|
public static ClientConfig readConfig(File file)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
if (!file.exists() || file.length() == 0) {
|
if (!file.exists() || file.length() == 0) {
|
||||||
throw new IOException(Component.translatable("sputnik.config.error.empty").getString());
|
throw new IOException(I18nUtil.fmt("sputnik.config.error.empty",
|
||||||
|
"archivo de config. vacío o inexistente"));
|
||||||
}
|
}
|
||||||
|
|
||||||
try (DataInputStream in = new DataInputStream(
|
try (DataInputStream in = new DataInputStream(
|
||||||
new BufferedInputStream(new FileInputStream(file)))) {
|
new BufferedInputStream(new FileInputStream(file)))) {
|
||||||
|
|
||||||
if (file.length() < 8) {
|
if (file.length() < 8) {
|
||||||
throw new IOException(Component.translatable("sputnik.config.error.toosmall").getString());
|
throw new IOException(I18nUtil.fmt("sputnik.config.error.toosmall",
|
||||||
|
"archivo demasiado pequeño para ser válido"));
|
||||||
}
|
}
|
||||||
|
|
||||||
// verificar cabezal
|
// verificar cabezal
|
||||||
int magic = in.readInt();
|
int magic = in.readInt();
|
||||||
if (magic != MAGIC_NUMBER) {
|
if (magic != MAGIC_NUMBER) {
|
||||||
throw new IOException(Component.translatable("sputnik.config.error.invalidformat", magic).getString());
|
throw new IOException(I18nUtil.fmt("sputnik.config.error.invalidformat",
|
||||||
|
"formato de archivo inválido: %s", magic));
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo: sustituir por lógica de migración en vez de simplemente no aceptarlo
|
// todo: sustituir por lógica de migración en vez de simplemente no aceptarlo
|
||||||
int version = in.readInt();
|
int version = in.readInt();
|
||||||
if (version != VERSION) {
|
if (version != VERSION) {
|
||||||
throw new IOException(Component.translatable("sputnik.config.error.invalidversion", version).getString());
|
throw new IOException(I18nUtil.fmt("sputnik.config.error.invalidversion",
|
||||||
|
"versión inválida: %s", version));
|
||||||
}
|
}
|
||||||
|
|
||||||
ClientConfig config = new ClientConfig();
|
// leer mapas. se leen a locales y la ClientConfig se construye al final: su
|
||||||
|
// constructor la suscribe al bus de eventos, así que crearla antes de terminar
|
||||||
// leer mapas
|
// de leer dejaba una config. huérfana escuchando si el archivo estaba corrupto
|
||||||
config.moduleStates = readStringBooleanMap(in);
|
Map<String, Boolean> moduleStates = readStringBooleanMap(in);
|
||||||
config.settings = readSettingsMap(in);
|
Map<String, Object> settings = readSettingsMap(in);
|
||||||
config.settingsPanels = readStringIntArrayMap(in);
|
Map<String, int[]> settingsPanels = readStringIntArrayMap(in);
|
||||||
config.extendablePanels = readExtendablePanels(in);
|
Map<String, ClientConfig.PanelData> extendablePanels = readExtendablePanels(in);
|
||||||
config.hudPositions = readStringIntArrayMap(in);
|
Map<String, int[]> hudPositions = readStringIntArrayMap(in);
|
||||||
config.hudVisibilities = readStringBooleanMap(in);
|
Map<String, Boolean> hudVisibilities = readStringBooleanMap(in);
|
||||||
config.hudImagePaths = readStringStringMap(in);
|
Map<String, String> hudImagePaths = readStringStringMap(in);
|
||||||
config.friends = readStringStringMap(in);
|
Map<String, String> friends = readStringStringMap(in);
|
||||||
|
|
||||||
// leer pos. de la barra de búsqueda
|
// leer pos. de la barra de búsqueda
|
||||||
if (in.readBoolean()) {
|
int[] searchBarPosition = in.readBoolean()
|
||||||
config.searchBarPosition = new int[]{in.readInt(), in.readInt()};
|
? new int[]{in.readInt(), in.readInt()}
|
||||||
}
|
: null;
|
||||||
|
|
||||||
|
ClientConfig config = new ClientConfig();
|
||||||
|
config.moduleStates = moduleStates;
|
||||||
|
config.settings = settings;
|
||||||
|
config.settingsPanels = settingsPanels;
|
||||||
|
config.extendablePanels = extendablePanels;
|
||||||
|
config.hudPositions = hudPositions;
|
||||||
|
config.hudVisibilities = hudVisibilities;
|
||||||
|
config.hudImagePaths = hudImagePaths;
|
||||||
|
config.friends = friends;
|
||||||
|
if (searchBarPosition != null) config.searchBarPosition = searchBarPosition;
|
||||||
|
|
||||||
return config;
|
return config;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ public class ClientConfig {
|
|||||||
case StringSetting s: value = s.getValue(); break;
|
case StringSetting s: value = s.getValue(); break;
|
||||||
case ListSetting l: value = l.getConfigValues(); break;
|
case ListSetting l: value = l.getConfigValues(); break;
|
||||||
case ColorSetting c: value = c.getConfigValue(); break;
|
case ColorSetting c: value = c.getConfigValue(); break;
|
||||||
case OptionSetting o: value = o.getDisplayName(); break;
|
case OptionSetting o: value = o.getConfigName(); break;
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,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.ChatUtil;
|
import me.retucio.sputnik.util.ChatUtil;
|
||||||
|
import me.retucio.sputnik.util.I18nUtil;
|
||||||
import net.minecraft.network.chat.Component;
|
import net.minecraft.network.chat.Component;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
@@ -30,7 +31,7 @@ import java.util.UUID;
|
|||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
// se ocupa de guardar, cargar y aplicar ajustes
|
// se ocupa de guardar, cargar y aplicar ajustes
|
||||||
@@ -42,8 +43,9 @@ public class ConfigManager {
|
|||||||
public static ConfigManager INSTANCE;
|
public static ConfigManager INSTANCE;
|
||||||
|
|
||||||
private boolean loaded = false;
|
private boolean loaded = false;
|
||||||
|
private boolean applying = false;
|
||||||
private boolean dirty = false;
|
private boolean dirty = false;
|
||||||
private long lastDirtyTime = 0L;
|
private long lastSaveTime = System.currentTimeMillis();
|
||||||
private ClientConfig config = null;
|
private ClientConfig config = null;
|
||||||
|
|
||||||
private final ExecutorService saveExecutor = Executors.newSingleThreadExecutor(r -> {
|
private final ExecutorService saveExecutor = Executors.newSingleThreadExecutor(r -> {
|
||||||
@@ -52,7 +54,10 @@ public class ConfigManager {
|
|||||||
return t;
|
return t;
|
||||||
});
|
});
|
||||||
|
|
||||||
private final AtomicBoolean saveQueued = new AtomicBoolean(false);
|
// instantánea pendiente de escribir. si llega otra antes de que el hilo de fondo escriba,
|
||||||
|
// sustituye a la anterior en vez de descartarse (que era lo que pasaba con un simple
|
||||||
|
// "ya hay uno en cola": se tiraba justo la más reciente y se perdían esos cambios)
|
||||||
|
private final AtomicReference<byte[]> pending = new AtomicReference<>();
|
||||||
|
|
||||||
|
|
||||||
// ------------------ MÉTODOS PRINCIPALES ------------------
|
// ------------------ MÉTODOS PRINCIPALES ------------------
|
||||||
@@ -60,58 +65,81 @@ public class ConfigManager {
|
|||||||
// guardar configuraciones
|
// guardar configuraciones
|
||||||
public void save() {
|
public void save() {
|
||||||
if (!loaded) return;
|
if (!loaded) return;
|
||||||
ensureConfig();
|
writeSnapshot(false);
|
||||||
|
|
||||||
// serializar a bytes en el hilo principal (snapshot inmediato, evita race conditions)
|
|
||||||
final byte[] snapshot;
|
|
||||||
try {
|
|
||||||
snapshot = BinarySerializer.toBytes(config);
|
|
||||||
} catch (IOException e) {
|
|
||||||
Sputnik.LOGGER.error(Component.translatable("sputnik.config.error.serialization").getString(), e);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// si ya hay un guardado en cola, no añadir otro
|
|
||||||
if (!saveQueued.compareAndSet(false, true)) return;
|
|
||||||
|
|
||||||
saveExecutor.execute(() -> {
|
|
||||||
try {
|
|
||||||
BinarySerializer.writeBytes(snapshot, CONFIG_FILE);
|
|
||||||
Sputnik.LOGGER.info(Component.translatable("sputnik.config.info.saved").getString());
|
|
||||||
} catch (IOException e) {
|
|
||||||
Sputnik.LOGGER.error(Component.translatable("sputnik.config.error.saving").getString(), e);
|
|
||||||
} finally {
|
|
||||||
saveQueued.set(false);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void saveOnShutdown() {
|
public void saveOnShutdown() {
|
||||||
// esperar a que termine cualquier guardado en curso, luego guardar síncronamente
|
// no aceptar más tareas y esperar a que termine el guardado en curso
|
||||||
saveExecutor.shutdown();
|
saveExecutor.shutdown();
|
||||||
try {
|
try {
|
||||||
// dar hasta 5 segundos para que termine el guardado en curso
|
// dar hasta 5 segundos para que termine el guardado en curso
|
||||||
if (!saveExecutor.awaitTermination(5, TimeUnit.SECONDS)) {
|
if (!saveExecutor.awaitTermination(5, TimeUnit.SECONDS)) {
|
||||||
Sputnik.LOGGER.warn(Component.translatable("sputnik.config.warn.thread").getString());
|
Sputnik.LOGGER.warn(I18nUtil.fmt("sputnik.config.warn.thread",
|
||||||
|
"el hilo de guardado no terminó a tiempo"));
|
||||||
}
|
}
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
Thread.currentThread().interrupt();
|
Thread.currentThread().interrupt();
|
||||||
}
|
}
|
||||||
|
|
||||||
// guardado final sincrónico por si había cambios pendientes no guardados
|
// el guardado final va en este mismo hilo: el executor ya está cerrado, así que
|
||||||
if (dirty) save();
|
// encolar la escritura lanzaba RejectedExecutionException y no se guardaba NADA al
|
||||||
|
// cerrar el juego. o sea que se perdía todo lo hecho desde el último autoguardado
|
||||||
|
if (!loaded) return;
|
||||||
|
writeSnapshot(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// serializa en el hilo actual (instantánea inmediata, evita race conditions) y escribe
|
||||||
|
// en el de fondo, salvo que se pida síncrono (al cerrar)
|
||||||
|
private void writeSnapshot(boolean sync) {
|
||||||
|
ensureConfig();
|
||||||
|
|
||||||
|
final byte[] snapshot;
|
||||||
|
try {
|
||||||
|
snapshot = BinarySerializer.toBytes(config);
|
||||||
|
} catch (IOException e) {
|
||||||
|
Sputnik.LOGGER.error(I18nUtil.fmt("sputnik.config.error.serialization",
|
||||||
|
"error al serializar ajustes"), e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
dirty = false;
|
||||||
|
lastSaveTime = System.currentTimeMillis();
|
||||||
|
|
||||||
|
if (sync) {
|
||||||
|
writeToDisk(snapshot);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// si ya había una instantánea esperando, la tarea encolada recogerá ésta
|
||||||
|
if (pending.getAndSet(snapshot) != null) return;
|
||||||
|
|
||||||
|
saveExecutor.execute(() -> {
|
||||||
|
byte[] bytes = pending.getAndSet(null);
|
||||||
|
if (bytes != null) writeToDisk(bytes);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void writeToDisk(byte[] bytes) {
|
||||||
|
try {
|
||||||
|
BinarySerializer.writeBytes(bytes, CONFIG_FILE);
|
||||||
|
Sputnik.LOGGER.info(I18nUtil.fmt("sputnik.config.info.saved", "ajustes guardados"));
|
||||||
|
} catch (IOException e) {
|
||||||
|
Sputnik.LOGGER.error(I18nUtil.fmt("sputnik.config.error.saving",
|
||||||
|
"error al guardar ajustes"), e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void load() {
|
public void load() {
|
||||||
Sputnik.LOGGER.info(Component.translatable("sputnik.config.info.loading").getString());
|
Sputnik.LOGGER.info(I18nUtil.fmt("sputnik.config.info.loading", "cargando ajustes..."));
|
||||||
|
|
||||||
if (CONFIG_FILE.exists()) {
|
if (CONFIG_FILE.exists()) {
|
||||||
try {
|
try {
|
||||||
config = BinarySerializer.readConfig(CONFIG_FILE);
|
setConfig(BinarySerializer.readConfig(CONFIG_FILE));
|
||||||
Sputnik.LOGGER.info(Component.translatable("sputnik.config.info.loaded").getString());
|
Sputnik.LOGGER.info(I18nUtil.fmt("sputnik.config.info.loaded", "ajustes cargados"));
|
||||||
return;
|
return;
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
Sputnik.LOGGER.error(Component.translatable("sputnik.config.error.loading").getString(), e);
|
Sputnik.LOGGER.error(I18nUtil.fmt("sputnik.config.error.loading",
|
||||||
|
"error cargando ajustes, intentando json"), e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -119,35 +147,61 @@ public class ConfigManager {
|
|||||||
if (LEGACY_JSON_FILE.exists()) {
|
if (LEGACY_JSON_FILE.exists()) {
|
||||||
try (FileReader reader = new FileReader(LEGACY_JSON_FILE)) {
|
try (FileReader reader = new FileReader(LEGACY_JSON_FILE)) {
|
||||||
Gson gson = new GsonBuilder().setPrettyPrinting().create();
|
Gson gson = new GsonBuilder().setPrettyPrinting().create();
|
||||||
config = gson.fromJson(reader, ClientConfig.class);
|
setConfig(gson.fromJson(reader, ClientConfig.class));
|
||||||
Sputnik.LOGGER.info(Component.translatable("sputnik.config.info.json").getString());
|
Sputnik.LOGGER.info(I18nUtil.fmt("sputnik.config.info.json",
|
||||||
|
"ajustes json cargados (migración)"));
|
||||||
|
|
||||||
save();
|
// aquí `loaded` todavía es false (se pone al aplicar), así que save() no
|
||||||
|
// haría nada: la migración se escribe directamente
|
||||||
|
writeSnapshot(true);
|
||||||
return;
|
return;
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
Sputnik.LOGGER.error(Component.translatable("sputnik.config.error.json").getString(), e);
|
Sputnik.LOGGER.error(I18nUtil.fmt("sputnik.config.error.json",
|
||||||
|
"error cargando json, usando defaults"), e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// crear nuevo config
|
// crear nuevo config
|
||||||
ensureConfig();
|
ensureConfig();
|
||||||
save();
|
writeSnapshot(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// aplicar configuraciones cargadas
|
// aplicar configuraciones cargadas. devuelve false si todavía no se puede (falta algo por
|
||||||
public void applyConfig() {
|
// construir), para que se reintente en el siguiente tick en vez de quedarse sin aplicar
|
||||||
if (!shouldApply()) return;
|
public boolean applyConfig() {
|
||||||
|
if (!shouldApply()) return false;
|
||||||
|
|
||||||
applyModuleStates();
|
applying = true;
|
||||||
applyModuleSettings();
|
try {
|
||||||
applySettingsPanels();
|
// los del mod primero: entre ellos está "teclas multimódulo", que decide si al
|
||||||
applySearchBarPosition();
|
// asignar una tecla se le quita a los demás módulos. aplicándolos los últimos,
|
||||||
applyClientSettings();
|
// las teclas de los módulos se cargaban con el valor por defecto de ese ajuste
|
||||||
applyExtendablePanels();
|
applyClientSettings();
|
||||||
applyFriends();
|
applyModuleStates();
|
||||||
|
applyModuleSettings();
|
||||||
|
applySettingsPanels();
|
||||||
|
applySearchBarPosition();
|
||||||
|
applyExtendablePanels();
|
||||||
|
applyFriends();
|
||||||
|
|
||||||
loaded = true;
|
Sputnik.LOGGER.info(I18nUtil.fmt("sputnik.config.info.applied", "ajustes aplicados"));
|
||||||
Sputnik.LOGGER.info(Component.translatable("sputnik.config.info.applied").getString());
|
} catch (Exception e) {
|
||||||
|
// si algo peta a medio aplicar no se puede dejar `loaded` en false: save() no
|
||||||
|
// haría nada en toda la sesión y se perdería la config. entera al cerrar
|
||||||
|
Sputnik.LOGGER.error(I18nUtil.fmt("sputnik.config.error.applying",
|
||||||
|
"error aplicando ajustes"), e);
|
||||||
|
} finally {
|
||||||
|
applying = false;
|
||||||
|
loaded = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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
|
||||||
|
public boolean isApplying() {
|
||||||
|
return applying;
|
||||||
}
|
}
|
||||||
|
|
||||||
// obtener configuración actual
|
// obtener configuración actual
|
||||||
@@ -213,7 +267,8 @@ public class ConfigManager {
|
|||||||
friend.setName(name);
|
friend.setName(name);
|
||||||
FriendManager.INSTANCE.add(friend);
|
FriendManager.INSTANCE.add(friend);
|
||||||
});
|
});
|
||||||
Sputnik.LOGGER.info(Component.translatable("sputnik.config.info.friends").getString());
|
Sputnik.LOGGER.info(I18nUtil.fmt("sputnik.config.info.friends",
|
||||||
|
"amigos aplicados"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||||
@@ -233,8 +288,8 @@ public class ConfigManager {
|
|||||||
case ListSetting listSetting -> applyListSetting(listSetting, value);
|
case ListSetting listSetting -> applyListSetting(listSetting, value);
|
||||||
case ColorSetting colorSetting -> applyColorSetting(colorSetting, value);
|
case ColorSetting colorSetting -> applyColorSetting(colorSetting, value);
|
||||||
case OptionSetting optionSetting -> applyOptionSetting(optionSetting, value);
|
case OptionSetting optionSetting -> applyOptionSetting(optionSetting, value);
|
||||||
default -> Sputnik.LOGGER.warn(Component.translatable("sputnik.config.warn.unknownsetting",
|
default -> Sputnik.LOGGER.warn(I18nUtil.fmt("sputnik.config.warn.unknownsetting",
|
||||||
setting.getClass().getSimpleName()).getString());
|
"watafac queseso: %s", setting.getClass().getSimpleName()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -244,14 +299,16 @@ public class ConfigManager {
|
|||||||
module.setEnabled(config.moduleStates.get(module.getName()));
|
module.setEnabled(config.moduleStates.get(module.getName()));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
Sputnik.LOGGER.info(Component.translatable("sputnik.config.info.modulestates").getString());
|
Sputnik.LOGGER.info(I18nUtil.fmt("sputnik.config.info.modulestates",
|
||||||
|
"estados de módulos aplicados"));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void applyModuleSettings() {
|
private void applyModuleSettings() {
|
||||||
ModuleManager.INSTANCE.getModules().forEach(module -> {
|
ModuleManager.INSTANCE.getModules().forEach(module -> {
|
||||||
module.getSettings().forEach(this::applySetting);
|
module.getSettings().forEach(this::applySetting);
|
||||||
});
|
});
|
||||||
Sputnik.LOGGER.info(Component.translatable("sputnik.config.info.modulesettings").getString());
|
Sputnik.LOGGER.info(I18nUtil.fmt("sputnik.config.info.modulesettings",
|
||||||
|
"ajustes de módulos aplicados"));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void applySettingsPanels() {
|
private void applySettingsPanels() {
|
||||||
@@ -259,14 +316,16 @@ public class ConfigManager {
|
|||||||
Module module = ModuleManager.INSTANCE.getModuleByName(moduleName);
|
Module module = ModuleManager.INSTANCE.getModuleByName(moduleName);
|
||||||
|
|
||||||
if (module == null) {
|
if (module == null) {
|
||||||
Sputnik.LOGGER.warn(Component.translatable("sputnik.config.warn.nullmodule", moduleName).getString());
|
Sputnik.LOGGER.warn(I18nUtil.fmt("sputnik.config.warn.nullmodule",
|
||||||
|
"\"null\" como módulo (\"%s\")", moduleName));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ClickGui.INSTANCE.openSettingsPanel(module, position[0], position[1]);
|
ClickGui.INSTANCE.openSettingsPanel(module, position[0], position[1]);
|
||||||
});
|
});
|
||||||
|
|
||||||
Sputnik.LOGGER.info(Component.translatable("sputnik.config.info.settingspanels").getString());
|
Sputnik.LOGGER.info(I18nUtil.fmt("sputnik.config.info.settingspanels",
|
||||||
|
"estados de marcos de ajustes aplicados"));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void applySearchBarPosition() {
|
private void applySearchBarPosition() {
|
||||||
@@ -274,13 +333,15 @@ public class ConfigManager {
|
|||||||
ClickGui.INSTANCE.getSearchBar().setX(config.searchBarPosition[0]);
|
ClickGui.INSTANCE.getSearchBar().setX(config.searchBarPosition[0]);
|
||||||
ClickGui.INSTANCE.getSearchBar().setY(config.searchBarPosition[1]);
|
ClickGui.INSTANCE.getSearchBar().setY(config.searchBarPosition[1]);
|
||||||
}
|
}
|
||||||
Sputnik.LOGGER.info(Component.translatable("sputnik.config.info.searchbar").getString());
|
Sputnik.LOGGER.info(I18nUtil.fmt("sputnik.config.info.searchbar",
|
||||||
|
"posición de la barra de búsqueda aplicada"));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void applyClientSettings() {
|
private void applyClientSettings() {
|
||||||
ClientSettingsPanel.clientSettings.setEnabled(true);
|
ClientSettingsPanel.clientSettings.setEnabled(true);
|
||||||
ClientSettingsPanel.clientSettings.getSettings().forEach(this::applySetting);
|
ClientSettingsPanel.clientSettings.getSettings().forEach(this::applySetting);
|
||||||
Sputnik.LOGGER.info(Component.translatable("sputnik.config.info.clientsettings").getString());
|
Sputnik.LOGGER.info(I18nUtil.fmt("sputnik.config.info.clientsettings",
|
||||||
|
"ajustes del cliente aplicados"));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void applyExtendablePanels() {
|
private void applyExtendablePanels() {
|
||||||
@@ -290,7 +351,8 @@ public class ConfigManager {
|
|||||||
applyExtendablePanel(ClickGui.INSTANCE.getClientSettingsPanel());
|
applyExtendablePanel(ClickGui.INSTANCE.getClientSettingsPanel());
|
||||||
applyExtendablePanel(ClickGui.INSTANCE.getFriendsPanel());
|
applyExtendablePanel(ClickGui.INSTANCE.getFriendsPanel());
|
||||||
|
|
||||||
Sputnik.LOGGER.info(Component.translatable("sputnik.config.info.extendablepanels").getString());
|
Sputnik.LOGGER.info(I18nUtil.fmt("sputnik.config.info.extendablepanels",
|
||||||
|
"posiciones de marcos extendibles aplicadas"));
|
||||||
ClickGui.INSTANCE.refreshListButtons();
|
ClickGui.INSTANCE.refreshListButtons();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -359,8 +421,14 @@ public class ConfigManager {
|
|||||||
Map<T, Boolean> convertedValues = new HashMap<>();
|
Map<T, Boolean> convertedValues = new HashMap<>();
|
||||||
|
|
||||||
for (T option : setting.getOptions()) {
|
for (T option : setting.getOptions()) {
|
||||||
String key = setting.getDisplayName(option);
|
String key = setting.getConfigName(option);
|
||||||
Object booleanValue = map.get(key);
|
Object booleanValue = map.get(key);
|
||||||
|
|
||||||
|
// compatibilidad con configs. de antes, cuando la clave era el nombre ya
|
||||||
|
// traducido (el de vanilla en inglés). sin esto la lista entera se quedaba
|
||||||
|
// en false, o sea que al usuario se le borraba lo que tuviera marcado
|
||||||
|
if (booleanValue == null) booleanValue = map.get(I18nUtil.vanillaName(key));
|
||||||
|
|
||||||
convertedValues.put(option, booleanValue instanceof Boolean && (Boolean) booleanValue);
|
convertedValues.put(option, booleanValue instanceof Boolean && (Boolean) booleanValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -411,12 +479,24 @@ public class ConfigManager {
|
|||||||
return setting.getSg().getModule().getName() + ":" + setting.getTrueName();
|
return setting.getSg().getModule().getName() + ":" + setting.getTrueName();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ClickGui incluida: los marcos y la barra de búsqueda se aplican sobre ella, y se
|
||||||
|
// construye en una tarea aparte. si todavía no está, mejor esperar al siguiente tick
|
||||||
private boolean shouldApply() {
|
private boolean shouldApply() {
|
||||||
return Sputnik.mc != null && ModuleManager.INSTANCE != null && config != null;
|
return Sputnik.mc != null && ModuleManager.INSTANCE != null
|
||||||
|
&& ClickGui.INSTANCE != null && config != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ensureConfig() {
|
private void ensureConfig() {
|
||||||
if (config == null) config = new ClientConfig();
|
if (config == null) setConfig(new ClientConfig());
|
||||||
|
}
|
||||||
|
|
||||||
|
// ClientConfig se suscribe al bus en su constructor, así que al reemplazarla hay que
|
||||||
|
// dar de baja a la anterior: si no, la vieja seguía escuchando y escribiendo en un
|
||||||
|
// mapa que ya no era el que se guarda
|
||||||
|
private void setConfig(ClientConfig newConfig) {
|
||||||
|
if (config == newConfig) return;
|
||||||
|
if (config != null) Sputnik.EVENT_BUS.unsubscribe(config);
|
||||||
|
config = newConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasLoaded() {
|
public boolean hasLoaded() {
|
||||||
@@ -425,7 +505,6 @@ public class ConfigManager {
|
|||||||
|
|
||||||
public void markDirty() {
|
public void markDirty() {
|
||||||
this.dirty = true;
|
this.dirty = true;
|
||||||
this.lastDirtyTime = System.currentTimeMillis();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isDirty() {
|
public boolean isDirty() {
|
||||||
@@ -438,13 +517,14 @@ 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() - lastDirtyTime < intervalMs) return;
|
if (System.currentTimeMillis() - lastSaveTime < intervalMs) return;
|
||||||
|
|
||||||
HudRenderer.INSTANCE.pushNotification(
|
HudRenderer.INSTANCE.pushNotification(
|
||||||
Component.translatable("sputnik.config.autosaving.title").getString(),
|
Component.translatable("sputnik.config.autosaving.title").getString(),
|
||||||
Component.translatable("sputnik.config.autosaving.desc").getString());
|
Component.translatable("sputnik.config.autosaving.desc").getString());
|
||||||
save();
|
save();
|
||||||
dirty = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -10,6 +10,7 @@ import me.retucio.sputnik.event.render.Render3DEvent;
|
|||||||
import me.retucio.sputnik.event.render.RenderBlockOutlineEvent;
|
import me.retucio.sputnik.event.render.RenderBlockOutlineEvent;
|
||||||
import me.retucio.sputnik.module.ModuleManager;
|
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.util.render.SputnikBuffers;
|
||||||
import net.minecraft.client.DeltaTracker;
|
import net.minecraft.client.DeltaTracker;
|
||||||
import net.minecraft.client.renderer.LevelRenderer;
|
import net.minecraft.client.renderer.LevelRenderer;
|
||||||
import net.minecraft.client.renderer.SubmitNodeCollector;
|
import net.minecraft.client.renderer.SubmitNodeCollector;
|
||||||
@@ -42,6 +43,7 @@ public abstract class LevelRendererMixin {
|
|||||||
|
|
||||||
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, dt, cameraState));
|
||||||
|
SputnikBuffers.flush(); // antes de que empiece el hud
|
||||||
|
|
||||||
profiler.pop();
|
profiler.pop();
|
||||||
matrices.popPose();
|
matrices.popPose();
|
||||||
|
|||||||
@@ -83,10 +83,6 @@ public class Module {
|
|||||||
this.bind.setDefaultValue(key);
|
this.bind.setDefaultValue(key);
|
||||||
|
|
||||||
// puto marcos
|
// puto marcos
|
||||||
// la clave tiene que salir igual que en ConfigManager#getSettingKey, o sea con los
|
|
||||||
// nombres internos: Module#getName ya lo es, pero en los ajustes el traducido es
|
|
||||||
// getName() y el interno getTrueName(). si no cuadran no se encuentra la tecla
|
|
||||||
// guardada y se le pisa al usuario con la de por defecto
|
|
||||||
if (ConfigManager.INSTANCE.getConfig().settings
|
if (ConfigManager.INSTANCE.getConfig().settings
|
||||||
.get(this.getName() + ":" + bind.getTrueName()) == null)
|
.get(this.getName() + ":" + bind.getTrueName()) == null)
|
||||||
this.bind.setValue(key);
|
this.bind.setValue(key);
|
||||||
|
|||||||
@@ -89,6 +89,7 @@ public class ModuleManager {
|
|||||||
add(new AttributeSwapper());
|
add(new AttributeSwapper());
|
||||||
add(new ChestplateSwitch());
|
add(new ChestplateSwitch());
|
||||||
add(new CrystalAura());
|
add(new CrystalAura());
|
||||||
|
add(new HoldAttack());
|
||||||
add(new MaceKill());
|
add(new MaceKill());
|
||||||
add(new ProjectileTrajectories());
|
add(new ProjectileTrajectories());
|
||||||
add(new SpearKill());
|
add(new SpearKill());
|
||||||
|
|||||||
@@ -177,15 +177,14 @@ public class Freecam extends Module {
|
|||||||
super.onEnable();
|
super.onEnable();
|
||||||
}
|
}
|
||||||
|
|
||||||
// allChanged() ya no existe; ahora hay que pasarle el estado a mano
|
|
||||||
private static void invalidateChunks() {
|
private static void invalidateChunks() {
|
||||||
if (mc.level == null) return;
|
if (mc.level == null) return;
|
||||||
mc.levelRenderer.invalidateCompiledGeometry(mc.level, mc.options, mc.gameRenderer.mainCamera(), mc.getBlockColors());
|
mc.levelExtractor.allChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDisable() {
|
public void onDisable() {
|
||||||
if (reloadChunks.getValue()) mc.execute(Freecam::invalidateChunks);
|
if (reloadChunks.getValue()) invalidateChunks();
|
||||||
|
|
||||||
mc.options.setCameraType(perspective);
|
mc.options.setCameraType(perspective);
|
||||||
crouching = false;
|
crouching = false;
|
||||||
|
|||||||
@@ -0,0 +1,95 @@
|
|||||||
|
package me.retucio.sputnik.module.modules.combat;
|
||||||
|
|
||||||
|
import me.retucio.sputnik.module.Category;
|
||||||
|
import me.retucio.sputnik.module.Module;
|
||||||
|
import me.retucio.sputnik.module.setting.settings.BooleanSetting;
|
||||||
|
import me.retucio.sputnik.module.setting.settings.EnumSetting;
|
||||||
|
import me.retucio.sputnik.module.setting.settings.NumberSetting;
|
||||||
|
import net.minecraft.world.phys.EntityHitResult;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author retucio
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class HoldAttack extends Module {
|
||||||
|
|
||||||
|
private final EnumSetting<AttackMode> mode = sgGeneral.add(new EnumSetting<>(
|
||||||
|
"modo de ataque",
|
||||||
|
"cómo atacar",
|
||||||
|
AttackMode.class,
|
||||||
|
AttackMode.TIME
|
||||||
|
));
|
||||||
|
|
||||||
|
private final NumberSetting timeCooldown = sgGeneral.add(new NumberSetting(
|
||||||
|
"cooldown",
|
||||||
|
"cómo de llena tiene que estar la barra de ataque antes de atacar",
|
||||||
|
84.8f, 0.0f, 100.0f, 0.1f
|
||||||
|
)).visibility(() -> mode.is(AttackMode.TIME));
|
||||||
|
|
||||||
|
private final NumberSetting spamCooldown = sgGeneral.add(new NumberSetting(
|
||||||
|
"cooldown ",
|
||||||
|
"cada cuánto atacar, en ticks",
|
||||||
|
0, 0, 40, 1
|
||||||
|
)).visibility(() -> mode.is(AttackMode.SPAM));
|
||||||
|
|
||||||
|
private final BooleanSetting attackInScreens = sgGeneral.add(new BooleanSetting(
|
||||||
|
"atacar en pantallas",
|
||||||
|
"atacar aun estando en una pantalla",
|
||||||
|
false
|
||||||
|
));
|
||||||
|
|
||||||
|
private int counter = 0;
|
||||||
|
|
||||||
|
public HoldAttack() {
|
||||||
|
super("autoataque", "mantén pulsado el clic para atacar automáticamente", Category.COMBAT);
|
||||||
|
mode.onUpdate(v -> counter = 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onEnable() {
|
||||||
|
counter = 0;
|
||||||
|
super.onEnable();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onTick() {
|
||||||
|
if (mc.player == null || mc.gameMode == null || mc.getCameraEntity() == null) return;
|
||||||
|
|
||||||
|
counter++;
|
||||||
|
|
||||||
|
if (mc.gui.screen() != null && !attackInScreens.getValue()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!mc.options.keyAttack.isDown()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(mc.hitResult instanceof EntityHitResult ehr)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mode.is(AttackMode.TIME)) {
|
||||||
|
if (mc.player.getAttackStrengthScale(0) < timeCooldown.getNormalizedValue()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else if (mode.is(AttackMode.SPAM)) {
|
||||||
|
if (counter < spamCooldown.getIntValue()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mc.gameMode.attack(mc.player, ehr.getEntity());
|
||||||
|
counter = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private enum AttackMode {
|
||||||
|
SPAM("spamear"),
|
||||||
|
TIME("timear");
|
||||||
|
|
||||||
|
private final String name;
|
||||||
|
AttackMode(String name) { this.name = name; }
|
||||||
|
@Override public String toString() { return name; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -8,7 +8,6 @@ import me.retucio.sputnik.module.setting.settings.NumberSetting;
|
|||||||
import me.retucio.sputnik.util.Lists;
|
import me.retucio.sputnik.util.Lists;
|
||||||
import net.minecraft.core.particles.SimpleParticleType;
|
import net.minecraft.core.particles.SimpleParticleType;
|
||||||
import net.minecraft.core.registries.BuiltInRegistries;
|
import net.minecraft.core.registries.BuiltInRegistries;
|
||||||
import net.minecraft.network.chat.Component;
|
|
||||||
import net.minecraft.world.phys.Vec3;
|
import net.minecraft.world.phys.Vec3;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -26,9 +25,10 @@ public class Particles extends Module {
|
|||||||
.map(particleType -> (SimpleParticleType) particleType)
|
.map(particleType -> (SimpleParticleType) particleType)
|
||||||
.toList();
|
.toList();
|
||||||
|
|
||||||
|
// claves de traducción, no texto traducido (ver Lists#init)
|
||||||
Map<SimpleParticleType, String> particleNames = Lists.getMapOfLists(particleList,
|
Map<SimpleParticleType, String> particleNames = Lists.getMapOfLists(particleList,
|
||||||
particleList.stream().map(particle -> Component.translatable(
|
particleList.stream().map(particle ->
|
||||||
BuiltInRegistries.PARTICLE_TYPE.getKey(particle).toShortLanguageKey()).getString())
|
BuiltInRegistries.PARTICLE_TYPE.getKey(particle).toShortLanguageKey())
|
||||||
.toList());
|
.toList());
|
||||||
|
|
||||||
private final ListSetting<SimpleParticleType> particles = sgGeneral.add(new ListSetting<>(
|
private final ListSetting<SimpleParticleType> particles = sgGeneral.add(new ListSetting<>(
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package me.retucio.sputnik.module.setting.settings;
|
package me.retucio.sputnik.module.setting.settings;
|
||||||
|
|
||||||
|
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;
|
||||||
import me.retucio.sputnik.module.setting.Setting;
|
import me.retucio.sputnik.module.setting.Setting;
|
||||||
@@ -32,8 +33,17 @@ public class KeySetting extends Setting<Integer> {
|
|||||||
|
|
||||||
// con "teclas multimódulo" puesto se permite repetir tecla, que es justo lo que
|
// con "teclas multimódulo" puesto se permite repetir tecla, que es justo lo que
|
||||||
// dice el ajuste. antes se le quitaba la tecla al otro módulo igualmente, así que
|
// dice el ajuste. antes se le quitaba la tecla al otro módulo igualmente, así que
|
||||||
// el ajuste sólo servía para las teclas de vanilla
|
// 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
|
if (ModuleManager.INSTANCE != null
|
||||||
|
&& ClientSettingsPanel.clientSettings != null
|
||||||
|
&& !ConfigManager.INSTANCE.isApplying()
|
||||||
&& !ClientSettingsPanel.clientSettings.multipleKeybinds.getValue()) {
|
&& !ClientSettingsPanel.clientSettings.multipleKeybinds.getValue()) {
|
||||||
for (Module module : ModuleManager.INSTANCE.getModules())
|
for (Module module : ModuleManager.INSTANCE.getModules())
|
||||||
if (module.getKey() == value && value != -1) {
|
if (module.getKey() == value && value != -1) {
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package me.retucio.sputnik.module.setting.settings;
|
package me.retucio.sputnik.module.setting.settings;
|
||||||
|
|
||||||
import me.retucio.sputnik.module.setting.Setting;
|
import me.retucio.sputnik.module.setting.Setting;
|
||||||
|
import me.retucio.sputnik.util.I18nUtil;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
@@ -62,7 +63,7 @@ public class ListSetting<T> extends Setting<Map<T, Boolean>> {
|
|||||||
public Map<String, Boolean> getConfigValues() {
|
public Map<String, Boolean> getConfigValues() {
|
||||||
Map<String, Boolean> configValues = new HashMap<>();
|
Map<String, Boolean> configValues = new HashMap<>();
|
||||||
for (T option : options) {
|
for (T option : options) {
|
||||||
configValues.put(getDisplayName(option), value.getOrDefault(option, false));
|
configValues.put(getConfigName(option), value.getOrDefault(option, false));
|
||||||
}
|
}
|
||||||
return configValues;
|
return configValues;
|
||||||
}
|
}
|
||||||
@@ -103,10 +104,20 @@ public class ListSetting<T> extends Setting<Map<T, Boolean>> {
|
|||||||
return displayNames != null ? new HashMap<>(displayNames) : null;
|
return displayNames != null ? new HashMap<>(displayNames) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getDisplayName(T key) {
|
// OJO: nombre interno de la opción. es la clave de la config. (ver
|
||||||
|
// ConfigManager#applyListSetting) y para las listas del juego es la clave de
|
||||||
|
// traducción ("entity.minecraft.zombie"), que no depende del idioma. no traducir
|
||||||
|
public String getConfigName(T key) {
|
||||||
if (displayNames != null && displayNames.containsKey(key)) {
|
if (displayNames != null && displayNames.containsKey(key)) {
|
||||||
return displayNames.get(key);
|
return displayNames.get(key);
|
||||||
}
|
}
|
||||||
return key != null ? key.toString() : "?";
|
return key != null ? key.toString() : "?";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// nombre visible: se traduce aquí. antes se mostraba el nombre interno tal cual, o sea
|
||||||
|
// los nombres de vanilla en inglés aunque el juego estuviera en otro idioma
|
||||||
|
public String getDisplayName(T key) {
|
||||||
|
String name = getConfigName(key);
|
||||||
|
return I18nUtil.orElse(name, name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -57,6 +57,10 @@ public class NumberSetting extends Setting<Double> {
|
|||||||
return value.byteValue();
|
return value.byteValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public double getNormalizedValue() {
|
||||||
|
return (value - min ) / (max - min);
|
||||||
|
}
|
||||||
|
|
||||||
public void setValue(double value) {
|
public void setValue(double value) {
|
||||||
if (this.value == value || this.locked) return;
|
if (this.value == value || this.locked) return;
|
||||||
double clamped = clamp(value, min, max);
|
double clamped = clamp(value, min, max);
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package me.retucio.sputnik.module.setting.settings;
|
package me.retucio.sputnik.module.setting.settings;
|
||||||
|
|
||||||
import me.retucio.sputnik.module.setting.Setting;
|
import me.retucio.sputnik.module.setting.Setting;
|
||||||
|
import me.retucio.sputnik.util.I18nUtil;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@@ -26,14 +27,19 @@ public class OptionSetting<T> extends Setting<T> {
|
|||||||
if (options.contains(option)) super.setValue(option);
|
if (options.contains(option)) super.setValue(option);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// por nombre interno, no por el traducido: es lo que se guarda en la config.
|
||||||
public void setValueByName(String name) {
|
public void setValueByName(String name) {
|
||||||
for (T opt : options) {
|
for (T opt : options) {
|
||||||
if (displayNames != null && !displayNames.isEmpty()) {
|
if (getConfigName(opt).equals(name)) {
|
||||||
if (displayNames.get(opt).equals(name)) {
|
setValue(opt);
|
||||||
setValue(opt);
|
return;
|
||||||
return;
|
}
|
||||||
}
|
}
|
||||||
} else if (opt.toString().equals(name)) {
|
|
||||||
|
// compatibilidad con configs. de antes, cuando se guardaba el nombre ya traducido
|
||||||
|
// (el de vanilla en inglés). si no, la opción guardada se perdía y volvía a la de serie
|
||||||
|
for (T opt : options) {
|
||||||
|
if (I18nUtil.vanillaName(getConfigName(opt)).equals(name)) {
|
||||||
setValue(opt);
|
setValue(opt);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -82,9 +88,22 @@ public class OptionSetting<T> extends Setting<T> {
|
|||||||
return displayNames;
|
return displayNames;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// OJO: nombre interno de la opción, o sea la clave de la config. (ver ClientConfig
|
||||||
|
// #onUpdateSetting). igual que en ListSetting, para las listas del juego es la clave
|
||||||
|
// de traducción. no traducir
|
||||||
|
public String getConfigName(T key) {
|
||||||
|
if (displayNames != null && displayNames.containsKey(key)) return displayNames.get(key);
|
||||||
|
return key != null ? key.toString() : "?";
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getConfigName() {
|
||||||
|
return getConfigName(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// nombre visible, traducido
|
||||||
public String getDisplayName(T key) {
|
public String getDisplayName(T key) {
|
||||||
if (displayNames != null) return displayNames.get(key);
|
String name = getConfigName(key);
|
||||||
return key.toString();
|
return I18nUtil.orElse(name, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getDisplayName() {
|
public String getDisplayName() {
|
||||||
|
|||||||
@@ -4,11 +4,16 @@ import net.minecraft.client.gui.GuiGraphicsExtractor;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
|
||||||
public abstract class Panel<B extends Button> extends Widget {
|
public abstract class Panel<B extends Button> extends Widget {
|
||||||
|
|
||||||
protected String title;
|
// el título se resuelve al pintarlo, no al construir el marco: los marcos se crean en
|
||||||
|
// la inicialización del mod, cuando el idioma todavía no ha cargado, así que guardar el
|
||||||
|
// texto ya traducido dejaba los títulos en español para siempre (y no cambiaban aunque
|
||||||
|
// se cambiara el idioma del juego en marcha)
|
||||||
|
private Supplier<String> title;
|
||||||
|
|
||||||
protected final List<B> buttons = new ArrayList<>();
|
protected final List<B> buttons = new ArrayList<>();
|
||||||
protected List<B> visibleButtons = new ArrayList<>();
|
protected List<B> visibleButtons = new ArrayList<>();
|
||||||
@@ -20,10 +25,22 @@ public abstract class Panel<B extends Button> extends Widget {
|
|||||||
protected boolean dragging;
|
protected boolean dragging;
|
||||||
|
|
||||||
public Panel(String title, int x, int y, int w, int h) {
|
public Panel(String title, int x, int y, int w, int h) {
|
||||||
|
this(() -> title, x, y, w, h);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Panel(Supplier<String> title, int x, int y, int w, int h) {
|
||||||
super(x, y, w, h);
|
super(x, y, w, h);
|
||||||
this.title = title;
|
this.title = title;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getTitle() {
|
||||||
|
return title.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void setTitle(Supplier<String> title) {
|
||||||
|
this.title = title;
|
||||||
|
}
|
||||||
|
|
||||||
public void drawTooltips(GuiGraphicsExtractor gui, int mouseX, int mouseY) {
|
public void drawTooltips(GuiGraphicsExtractor gui, int mouseX, int mouseY) {
|
||||||
for (Button button : visibleButtons) button.drawTooltip(gui, mouseX, mouseY);
|
for (Button button : visibleButtons) button.drawTooltip(gui, mouseX, mouseY);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,12 +4,13 @@ import me.retucio.sputnik.ui.widgets.Button;
|
|||||||
import me.retucio.sputnik.ui.widgets.Panel;
|
import me.retucio.sputnik.ui.widgets.Panel;
|
||||||
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 java.util.function.Supplier;
|
||||||
|
|
||||||
public abstract class CloseablePanel<B extends Button> extends Panel<B> {
|
public abstract class CloseablePanel<B extends Button> extends Panel<B> {
|
||||||
|
|
||||||
protected static final int PADDING = 4;
|
protected static final int PADDING = 4;
|
||||||
|
|
||||||
public CloseablePanel(String title, int x, int y, int w, int h) {
|
public CloseablePanel(Supplier<String> title, int x, int y, int w, int h) {
|
||||||
super(title, x, y, w, h);
|
super(title, x, y, w, h);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,11 +4,12 @@ import me.retucio.sputnik.ui.widgets.Button;
|
|||||||
import me.retucio.sputnik.ui.widgets.Panel;
|
import me.retucio.sputnik.ui.widgets.Panel;
|
||||||
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 java.util.function.Supplier;
|
||||||
|
|
||||||
public abstract class ExtendablePanel<B extends Button> extends Panel<B> {
|
public abstract class ExtendablePanel<B extends Button> extends Panel<B> {
|
||||||
protected boolean extended;
|
protected boolean extended;
|
||||||
|
|
||||||
public ExtendablePanel(String title, int x, int y, int w, int h) {
|
public ExtendablePanel(Supplier<String> title, int x, int y, int w, int h) {
|
||||||
super(title, x, y, w, h);
|
super(title, x, y, w, h);
|
||||||
this.extended = true;
|
this.extended = true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import me.retucio.sputnik.friend.FriendManager;
|
|||||||
import me.retucio.sputnik.ui.screen.ClickGui;
|
import me.retucio.sputnik.ui.screen.ClickGui;
|
||||||
import me.retucio.sputnik.ui.widgets.buttons.FriendButton;
|
import me.retucio.sputnik.ui.widgets.buttons.FriendButton;
|
||||||
import me.retucio.sputnik.util.Colors;
|
import me.retucio.sputnik.util.Colors;
|
||||||
|
import me.retucio.sputnik.util.I18nUtil;
|
||||||
import net.minecraft.client.gui.GuiGraphicsExtractor;
|
import net.minecraft.client.gui.GuiGraphicsExtractor;
|
||||||
import net.minecraft.network.chat.Component;
|
import net.minecraft.network.chat.Component;
|
||||||
|
|
||||||
@@ -20,7 +21,7 @@ public class FriendsPanel extends ExtendablePanel<FriendButton> {
|
|||||||
private int offset;
|
private int offset;
|
||||||
|
|
||||||
public FriendsPanel(int x, int y, int w, int h) {
|
public FriendsPanel(int x, int y, int w, int h) {
|
||||||
super("amigos", x, y, w, h);
|
super(() -> I18nUtil.orElse("sputnik.ui.friends.title", "amigos"), x, y, w, h);
|
||||||
dragging = false;
|
dragging = false;
|
||||||
|
|
||||||
Sputnik.EVENT_BUS.subscribe(this);
|
Sputnik.EVENT_BUS.subscribe(this);
|
||||||
@@ -34,7 +35,7 @@ public class FriendsPanel extends ExtendablePanel<FriendButton> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void updateWidth() {
|
protected void updateWidth() {
|
||||||
int maxWidth = mc.font.width(title) + mc.font.width(" +");
|
int maxWidth = mc.font.width(getTitle()) + mc.font.width(" +");
|
||||||
for (FriendButton button : buttons) {
|
for (FriendButton button : buttons) {
|
||||||
int textWidth = mc.font.width(button.getFriend().getName());
|
int textWidth = mc.font.width(button.getFriend().getName());
|
||||||
maxWidth = Math.max(maxWidth, textWidth);
|
maxWidth = Math.max(maxWidth, textWidth);
|
||||||
@@ -47,7 +48,7 @@ public class FriendsPanel extends ExtendablePanel<FriendButton> {
|
|||||||
updateWidth();
|
updateWidth();
|
||||||
gui.fill(x, renderY, x + w, renderY + h, Colors.mainColor.getRGB());
|
gui.fill(x, renderY, x + w, renderY + h, Colors.mainColor.getRGB());
|
||||||
|
|
||||||
gui.text(mc.font, Component.literal(title),
|
gui.text(mc.font, Component.literal(getTitle()),
|
||||||
x + 8,
|
x + 8,
|
||||||
renderY + (h / 2) - (mc.font.lineHeight / 2),
|
renderY + (h / 2) - (mc.font.lineHeight / 2),
|
||||||
-1, true);
|
-1, true);
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ public class ModulePanel extends ExtendablePanel<ModuleButton> {
|
|||||||
public final Category category;
|
public final Category category;
|
||||||
|
|
||||||
public ModulePanel(Category category, int x, int y, int w, int h) {
|
public ModulePanel(Category category, int x, int y, int w, int h) {
|
||||||
super(category.getDisplayName(), x, y, w, h);
|
super(category::getDisplayName, x, y, w, h);
|
||||||
this.category = category;
|
this.category = category;
|
||||||
dragging = false;
|
dragging = false;
|
||||||
|
|
||||||
@@ -35,7 +35,7 @@ public class ModulePanel extends ExtendablePanel<ModuleButton> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void updateWidth() {
|
protected void updateWidth() {
|
||||||
int maxWidth = mc.font.width(title);
|
int maxWidth = mc.font.width(getTitle());
|
||||||
for (ModuleButton button : buttons) {
|
for (ModuleButton button : buttons) {
|
||||||
int textWidth = mc.font.width(button.getModule().getDisplayName());
|
int textWidth = mc.font.width(button.getModule().getDisplayName());
|
||||||
maxWidth = Math.max(maxWidth, textWidth);
|
maxWidth = Math.max(maxWidth, textWidth);
|
||||||
@@ -48,7 +48,7 @@ public class ModulePanel extends ExtendablePanel<ModuleButton> {
|
|||||||
updateWidth();
|
updateWidth();
|
||||||
gui.fill(x, renderY, x + w, renderY + h, Colors.mainColor.getRGB());
|
gui.fill(x, renderY, x + w, renderY + h, Colors.mainColor.getRGB());
|
||||||
|
|
||||||
gui.text(mc.font, Component.literal(title),
|
gui.text(mc.font, Component.literal(getTitle()),
|
||||||
x + 8,
|
x + 8,
|
||||||
renderY + (h / 2) - (mc.font.lineHeight / 2),
|
renderY + (h / 2) - (mc.font.lineHeight / 2),
|
||||||
-1, true);
|
-1, true);
|
||||||
|
|||||||
@@ -27,7 +27,8 @@ public class SettingsPanel extends CloseablePanel<SettingButton<? extends Settin
|
|||||||
public boolean drawHeader = true;
|
public boolean drawHeader = true;
|
||||||
|
|
||||||
public SettingsPanel(Module module, int x, int y, int w, int h) {
|
public SettingsPanel(Module module, int x, int y, int w, int h) {
|
||||||
super(I18nUtil.orElse("sputnik.ui.settingsof", "ajustes de " + module.getDisplayName(), module.getDisplayName()), x, y, w, h);
|
super(() -> I18nUtil.orElse("sputnik.ui.settingsof",
|
||||||
|
"ajustes de " + module.getDisplayName(), module.getDisplayName()), x, y, w, h);
|
||||||
|
|
||||||
this.module = module;
|
this.module = module;
|
||||||
this.settingGroups = module.getSgs();
|
this.settingGroups = module.getSgs();
|
||||||
@@ -59,7 +60,7 @@ public class SettingsPanel extends CloseablePanel<SettingButton<? extends Settin
|
|||||||
: -1;
|
: -1;
|
||||||
|
|
||||||
gui.fill(x, renderY, x + w, renderY + h, headerColor);
|
gui.fill(x, renderY, x + w, renderY + h, headerColor);
|
||||||
gui.text(mc.font, title, titleX, titleY, -1, true);
|
gui.text(mc.font, getTitle(), titleX, titleY, -1, true);
|
||||||
drawCloseButton(gui, mouseX, mouseY, closeButtonColor);
|
drawCloseButton(gui, mouseX, mouseY, closeButtonColor);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -69,7 +70,7 @@ public class SettingsPanel extends CloseablePanel<SettingButton<? extends Settin
|
|||||||
.toList();
|
.toList();
|
||||||
|
|
||||||
// descripción
|
// descripción
|
||||||
List<String> descLines = wrapDescription(module.getDescription(), w - 2 * PADDING);
|
List<String> descLines = wrapDescription(module.getDisplayDescription(), w - 2 * PADDING);
|
||||||
int lineSpacing = 2;
|
int lineSpacing = 2;
|
||||||
|
|
||||||
int descHeight = descLines.size() * mc.font.lineHeight + (descLines.size() - 1) * lineSpacing;
|
int descHeight = descLines.size() * mc.font.lineHeight + (descLines.size() - 1) * lineSpacing;
|
||||||
@@ -212,7 +213,7 @@ public class SettingsPanel extends CloseablePanel<SettingButton<? extends Settin
|
|||||||
@Override
|
@Override
|
||||||
public void updateWidth() {
|
public void updateWidth() {
|
||||||
// asegurarse de que todos los botones caben en el marco, haciendo que la anchura se ajuste al texto más largo
|
// asegurarse de que todos los botones caben en el marco, haciendo que la anchura se ajuste al texto más largo
|
||||||
int maxWidth = mc.font.width(title);
|
int maxWidth = mc.font.width(getTitle());
|
||||||
for (SettingButton<?> button : buttons) {
|
for (SettingButton<?> button : buttons) {
|
||||||
String text = button.getSetting().getName();
|
String text = button.getSetting().getName();
|
||||||
|
|
||||||
@@ -246,7 +247,7 @@ public class SettingsPanel extends CloseablePanel<SettingButton<? extends Settin
|
|||||||
|
|
||||||
public int getGroupHeaderY(int groupIndex) {
|
public int getGroupHeaderY(int groupIndex) {
|
||||||
int currentY = renderY + h + PADDING;
|
int currentY = renderY + h + PADDING;
|
||||||
List<String> descLines = wrapDescription(module.getDescription(), w - 2 * PADDING);
|
List<String> descLines = wrapDescription(module.getDisplayDescription(), w - 2 * PADDING);
|
||||||
int descHeight = descLines.size() * mc.font.lineHeight + (descLines.size() - 1) * 2;
|
int descHeight = descLines.size() * mc.font.lineHeight + (descLines.size() - 1) * 2;
|
||||||
currentY += descHeight + 3 * PADDING; // descBoxBottom + padding
|
currentY += descHeight + 3 * PADDING; // descBoxBottom + padding
|
||||||
|
|
||||||
|
|||||||
+3
-2
@@ -6,6 +6,7 @@ import me.retucio.sputnik.module.modules.client.ClientSettingsModule;
|
|||||||
import me.retucio.sputnik.ui.screen.ClickGui;
|
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.util.Colors;
|
import me.retucio.sputnik.util.Colors;
|
||||||
|
import me.retucio.sputnik.util.I18nUtil;
|
||||||
import net.minecraft.client.gui.GuiGraphicsExtractor;
|
import net.minecraft.client.gui.GuiGraphicsExtractor;
|
||||||
|
|
||||||
public class ClientSettingsPanel extends SettingsPanel {
|
public class ClientSettingsPanel extends SettingsPanel {
|
||||||
@@ -15,7 +16,7 @@ public class ClientSettingsPanel extends SettingsPanel {
|
|||||||
|
|
||||||
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, x, y, w, h);
|
||||||
this.title = "ajustes del mod";
|
setTitle(() -> I18nUtil.orElse("sputnik.ui.clientsettings.title", "ajustes del mod"));
|
||||||
this.drawHeader = false; // disable the original header
|
this.drawHeader = false; // disable the original header
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -25,7 +26,7 @@ public class ClientSettingsPanel extends SettingsPanel {
|
|||||||
|
|
||||||
// Draw our own custom header (no close button, with +/-
|
// Draw our own custom header (no close button, with +/-
|
||||||
gui.fill(x, renderY, x + w, renderY + h, Colors.mainColor.getRGB());
|
gui.fill(x, renderY, x + w, renderY + h, Colors.mainColor.getRGB());
|
||||||
gui.text(mc.font, title,
|
gui.text(mc.font, getTitle(),
|
||||||
x + 8,
|
x + 8,
|
||||||
renderY + (h / 2) - (mc.font.lineHeight / 2),
|
renderY + (h / 2) - (mc.font.lineHeight / 2),
|
||||||
-1, true);
|
-1, true);
|
||||||
|
|||||||
@@ -47,6 +47,21 @@ public class I18nUtil {
|
|||||||
return Language.getInstance().has(key) ? I18n.get(key, args) : fallback;
|
return Language.getInstance().has(key) ? I18n.get(key, args) : fallback;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// igual que orElse pero rellenando también los %s del texto de reserva.
|
||||||
|
// para lo que se registra durante el arranque (cargar la config., comprobar la versión...):
|
||||||
|
// ahí el idioma todavía no está cargado y Component#translatable escupía la clave pelada
|
||||||
|
public static String fmt(String key, String fallback, Object... args) {
|
||||||
|
if (Language.getInstance().has(key)) return I18n.get(key, args);
|
||||||
|
return args.length == 0 ? fallback : String.format(fallback, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
// texto que daba el en_us de vanilla para una clave. sólo para leer configs. viejas:
|
||||||
|
// las listas guardaban el nombre ya traducido y Language, durante el arranque, es
|
||||||
|
// siempre el en_us de vanilla, así que lo guardado eran los nombres en inglés
|
||||||
|
public static String vanillaName(String key) {
|
||||||
|
return Language.DEFAULT_INSTANCE.getOrDefault(key, key);
|
||||||
|
}
|
||||||
|
|
||||||
// nombre visible de una constante de enum. los EnumSetting se guardan por índice
|
// nombre visible de una constante de enum. los EnumSetting se guardan por índice
|
||||||
// (ver ConfigManager#applyEnumSetting), así que su toString() es sólo texto y se traduce.
|
// (ver ConfigManager#applyEnumSetting), así que su toString() es sólo texto y se traduce.
|
||||||
// la clave se deriva de la clase que la declara, así que dos enums con el mismo nombre
|
// la clave se deriva de la clase que la declara, así que dos enums con el mismo nombre
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package me.retucio.sputnik.util;
|
|||||||
|
|
||||||
import net.minecraft.core.particles.ParticleType;
|
import net.minecraft.core.particles.ParticleType;
|
||||||
import net.minecraft.core.registries.BuiltInRegistries;
|
import net.minecraft.core.registries.BuiltInRegistries;
|
||||||
import net.minecraft.network.chat.Component;
|
|
||||||
import net.minecraft.sounds.SoundEvent;
|
import net.minecraft.sounds.SoundEvent;
|
||||||
import net.minecraft.sounds.SoundEvents;
|
import net.minecraft.sounds.SoundEvents;
|
||||||
import net.minecraft.world.entity.EntityType;
|
import net.minecraft.world.entity.EntityType;
|
||||||
@@ -40,38 +39,36 @@ public class Lists {
|
|||||||
public static final List<Color> colorList = new ArrayList<>();
|
public static final List<Color> colorList = new ArrayList<>();
|
||||||
public static final List<String> fontList = new ArrayList<>();
|
public static final List<String> fontList = new ArrayList<>();
|
||||||
|
|
||||||
// intentar traducir nombres y fallar miserablemente
|
// estos mapas guardan la CLAVE de traducción, no el texto ya traducido: son los nombres
|
||||||
|
// internos de las opciones y por tanto claves de la config. (ver ListSetting#getConfigName).
|
||||||
|
// antes se resolvía aquí con Component#translatable, pero esto corre en la inicialización
|
||||||
|
// del mod, cuando Language todavía es el en_us de vanilla: salían los nombres en inglés
|
||||||
|
// pasara lo que pasara. ahora se traducen al mostrarlos (ListSetting#getDisplayName)
|
||||||
public static void init() {
|
public static void init() {
|
||||||
entityNames = getMapOfLists(entityList,
|
entityNames = getMapOfLists(entityList,
|
||||||
entityList.stream().map(entity -> Component.translatable(
|
entityList.stream().map(EntityType::getDescriptionId).toList());
|
||||||
entity.getDescriptionId()
|
|
||||||
).getString()).toList());
|
|
||||||
|
|
||||||
particleNames = getMapOfLists(particleList,
|
particleNames = getMapOfLists(particleList,
|
||||||
particleList.stream().map(particle -> Component.translatable(
|
particleList.stream().map(particle ->
|
||||||
BuiltInRegistries.PARTICLE_TYPE.getKey(particle).toLanguageKey()
|
BuiltInRegistries.PARTICLE_TYPE.getKey(particle).toLanguageKey()
|
||||||
).getString()).toList());
|
).toList());
|
||||||
|
|
||||||
itemNames = getMapOfLists(itemList,
|
itemNames = getMapOfLists(itemList,
|
||||||
itemList.stream().map(item -> Component.translatable(
|
itemList.stream().map(Item::getDescriptionId).toList());
|
||||||
item.getDescriptionId()
|
|
||||||
).getString()).toList());
|
|
||||||
|
|
||||||
blockNames = getMapOfLists(blockList,
|
blockNames = getMapOfLists(blockList,
|
||||||
blockList.stream().map(block -> Component.translatable(
|
blockList.stream().map(Block::getDescriptionId).toList());
|
||||||
block.getDescriptionId()
|
|
||||||
).getString()).toList());
|
|
||||||
|
|
||||||
soundNames = getMapOfLists(soundList,
|
soundNames = getMapOfLists(soundList,
|
||||||
soundList.stream().map(sound -> Component.translatable(
|
soundList.stream().map(sound ->
|
||||||
sound.location().toShortLanguageKey()
|
sound.location().toShortLanguageKey()
|
||||||
).getString()).toList());
|
).toList());
|
||||||
soundNames.replace(SoundEvents.EMPTY, "NINGUNO");
|
soundNames.replace(SoundEvents.EMPTY, "NINGUNO");
|
||||||
|
|
||||||
screenNames = getMapOfLists(screenList,
|
screenNames = getMapOfLists(screenList,
|
||||||
screenList.stream().map(screen -> Component.translatable(
|
screenList.stream().map(screen ->
|
||||||
BuiltInRegistries.MENU.getKey(screen).toLanguageKey()
|
BuiltInRegistries.MENU.getKey(screen).toLanguageKey()
|
||||||
).getString()).toList());
|
).toList());
|
||||||
|
|
||||||
colorList.addAll(Arrays.asList(
|
colorList.addAll(Arrays.asList(
|
||||||
RED, ORANGE, YELLOW, LIME, GREEN, CYAN,
|
RED, ORANGE, YELLOW, LIME, GREEN, CYAN,
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
package me.retucio.sputnik.util.render;
|
package me.retucio.sputnik.util.render;
|
||||||
|
|
||||||
import com.mojang.blaze3d.PrimitiveTopology;
|
import com.mojang.blaze3d.PrimitiveTopology;
|
||||||
|
import com.mojang.blaze3d.pipeline.DepthStencilState;
|
||||||
import com.mojang.blaze3d.pipeline.RenderPipeline;
|
import com.mojang.blaze3d.pipeline.RenderPipeline;
|
||||||
|
import com.mojang.blaze3d.platform.CompareOp;
|
||||||
import com.mojang.blaze3d.systems.GpuDevice;
|
import com.mojang.blaze3d.systems.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;
|
||||||
@@ -28,12 +30,15 @@ public class Pipelines {
|
|||||||
|
|
||||||
static List<RenderPipeline> PIPELINES = new ArrayList<>();
|
static List<RenderPipeline> PIPELINES = new ArrayList<>();
|
||||||
|
|
||||||
|
// 26.2 usa depth invertido (near = 1), así que el LEQUAL de siempre es GREATER_THAN_OR_EQUAL
|
||||||
|
private static final DepthStencilState NO_DEPTH = new DepthStencilState(CompareOp.ALWAYS_PASS, false);
|
||||||
|
private static final DepthStencilState DEPTH = new DepthStencilState(CompareOp.GREATER_THAN_OR_EQUAL, false);
|
||||||
|
|
||||||
static final RenderPipeline LINES_PIPELINE = add(RenderPipeline.builder(RenderPipelines.LINES_SNIPPET)
|
static final RenderPipeline LINES_PIPELINE = add(RenderPipeline.builder(RenderPipelines.LINES_SNIPPET)
|
||||||
.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)
|
||||||
// .withDepthTestFunction(DepthTestFunction.NO_DEPTH_TEST)
|
.withDepthStencilState(NO_DEPTH)
|
||||||
// .withDepthWrite(false)
|
|
||||||
.withCull(false)
|
.withCull(false)
|
||||||
.build());
|
.build());
|
||||||
|
|
||||||
@@ -41,8 +46,7 @@ public class Pipelines {
|
|||||||
.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)
|
||||||
// .withDepthTestFunction(DepthTestFunction.LEQUAL_DEPTH_TEST)
|
.withDepthStencilState(DEPTH)
|
||||||
// .withDepthWrite(false)
|
|
||||||
.withCull(true)
|
.withCull(true)
|
||||||
.build());
|
.build());
|
||||||
|
|
||||||
@@ -50,9 +54,7 @@ public class Pipelines {
|
|||||||
.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)
|
||||||
// .withDepthTestFunction(DepthTestFunction.NO_DEPTH_TEST)
|
.withDepthStencilState(NO_DEPTH)
|
||||||
// .withBlend(BlendFunction.TRANSLUCENT)
|
|
||||||
// .withDepthWrite(false)
|
|
||||||
.withCull(false)
|
.withCull(false)
|
||||||
.build());
|
.build());
|
||||||
|
|
||||||
@@ -60,9 +62,7 @@ public class Pipelines {
|
|||||||
.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)
|
||||||
// .withDepthTestFunction(DepthTestFunction.LEQUAL_DEPTH_TEST)
|
.withDepthStencilState(DEPTH)
|
||||||
// .withBlend(BlendFunction.TRANSLUCENT)
|
|
||||||
// .withDepthWrite(false)
|
|
||||||
.withCull(false)
|
.withCull(false)
|
||||||
.build());
|
.build());
|
||||||
|
|
||||||
@@ -76,9 +76,7 @@ public class Pipelines {
|
|||||||
// siguen usando uniforms con nombre (u_Texture, u_ProjectionMatrix) y seguramente
|
// siguen usando uniforms con nombre (u_Texture, u_ProjectionMatrix) y seguramente
|
||||||
// haya que reescribirlos para que casen con las convenciones nuevas
|
// haya que reescribirlos para que casen con las convenciones nuevas
|
||||||
.withBindGroupLayout(BindGroupLayouts.SAMPLER0)
|
.withBindGroupLayout(BindGroupLayouts.SAMPLER0)
|
||||||
// .withDepthTestFunction(DepthTestFunction.NO_DEPTH_TEST)
|
.withDepthStencilState(NO_DEPTH)
|
||||||
// .withDepthWrite(false)
|
|
||||||
// .withBlend(BlendFunction.TRANSLUCENT)
|
|
||||||
.withCull(false)
|
.withCull(false)
|
||||||
.build());
|
.build());
|
||||||
|
|
||||||
|
|||||||
@@ -5,24 +5,32 @@ import com.mojang.blaze3d.vertex.VertexConsumer;
|
|||||||
import com.mojang.blaze3d.vertex.VertexFormat;
|
import com.mojang.blaze3d.vertex.VertexFormat;
|
||||||
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.RenderType;
|
import net.minecraft.client.renderer.rendertype.RenderType;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
|
||||||
/** emula el antiguo Tesselator + RenderType.draw(MeshData), que 26.2 se cargó
|
/** emula el antiguo Tesselator + RenderType.draw(MeshData), que 26.2 se cargó
|
||||||
* <p>
|
* <p>
|
||||||
* ahora los vértices se escriben en un StagedVertexBuffer: se pide un draw, se
|
* el ciclo del StagedVertexBuffer es appendDraw -> upload -> drawFromBuffer -> endDraw,
|
||||||
* escriben los vértices, se sube todo a la gpu y se dibuja. el ciclo es
|
* y hay que respetarlo entero: los vértices no llegan al Draw hasta que upload() cierra
|
||||||
* appendDraw -> upload -> drawFromBuffer -> endDraw; upload() peta si se llama
|
* el BufferBuilder, y appendDraw() peta después de un upload(). de ahí que draw() sólo
|
||||||
* dos veces sin endDraw() de por medio.
|
* encole y sea flush() quien suba y dibuje todo de una.
|
||||||
* <p>
|
* <p>
|
||||||
* subimos y dibujamos en cada llamada (en vez de agrupar draws) para mantener el
|
* un upload() por caja tampoco vale: cada uno se pilla un buffer de 256 KB del pool que
|
||||||
* mismo orden de dibujado que antes; es menos eficiente pero se comporta igual.
|
* no vuelve hasta el final del frame.
|
||||||
*/
|
*/
|
||||||
public class SputnikBuffers {
|
public class SputnikBuffers {
|
||||||
|
|
||||||
private static StagedVertexBuffer buffer;
|
private static StagedVertexBuffer buffer;
|
||||||
private static StagedVertexBuffer.Draw current;
|
private static StagedVertexBuffer.Draw current;
|
||||||
|
|
||||||
|
private static final List<QueuedDraw> queue = new ArrayList<>();
|
||||||
|
|
||||||
|
private record QueuedDraw(PreparedRenderType type, StagedVertexBuffer.Draw draw) {}
|
||||||
|
|
||||||
// lazy: al cargar la clase todavía puede no haber device
|
// lazy: al cargar la clase todavía puede no haber device
|
||||||
private static StagedVertexBuffer buffer() {
|
private static StagedVertexBuffer buffer() {
|
||||||
if (buffer == null) {
|
if (buffer == null) {
|
||||||
@@ -32,8 +40,6 @@ public class SputnikBuffers {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static VertexConsumer begin(VertexFormat format, PrimitiveTopology topology) {
|
public static VertexConsumer begin(VertexFormat format, PrimitiveTopology topology) {
|
||||||
if (current != null) buffer().endDraw(); // por si quedó un draw a medias
|
|
||||||
|
|
||||||
current = buffer().appendDraw(format, topology);
|
current = buffer().appendDraw(format, topology);
|
||||||
return buffer().getVertexBuilder(current);
|
return buffer().getVertexBuilder(current);
|
||||||
}
|
}
|
||||||
@@ -41,20 +47,33 @@ public class SputnikBuffers {
|
|||||||
public static void draw(RenderType type) {
|
public static void draw(RenderType type) {
|
||||||
if (current == null) return;
|
if (current == null) return;
|
||||||
|
|
||||||
if (!current.isEmpty()) {
|
queue.add(new QueuedDraw(type.prepare(), current));
|
||||||
buffer().upload();
|
current = null;
|
||||||
type.prepare().drawFromBuffer(buffer().getExecuteInfo(current));
|
}
|
||||||
|
|
||||||
|
/** sube y dibuja lo encolado; hay que llamarlo antes de que el juego pinte el hud */
|
||||||
|
public static void flush() {
|
||||||
|
if (buffer == null) return;
|
||||||
|
|
||||||
|
current = null;
|
||||||
|
if (queue.isEmpty()) return;
|
||||||
|
|
||||||
|
buffer.upload();
|
||||||
|
|
||||||
|
for (QueuedDraw queued : queue) {
|
||||||
|
StagedVertexBuffer.ExecuteInfo info = buffer.getExecuteInfo(queued.draw());
|
||||||
|
if (info != null) queued.type().drawFromBuffer(info);
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer().endDraw();
|
queue.clear();
|
||||||
current = null;
|
buffer.endDraw();
|
||||||
}
|
}
|
||||||
|
|
||||||
// devuelve los buffers al pool; una vez por frame
|
// devuelve los buffers al pool; una vez por frame
|
||||||
public static void endFrame() {
|
public static void endFrame() {
|
||||||
if (buffer == null) return;
|
if (buffer == null) return;
|
||||||
|
|
||||||
current = null;
|
flush();
|
||||||
buffer.endFrame();
|
buffer.endFrame();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -55,6 +55,7 @@
|
|||||||
"sputnik.commands.wait.desc": "waits a given amount of time before running another command",
|
"sputnik.commands.wait.desc": "waits a given amount of time before running another command",
|
||||||
"sputnik.config.autosaving.desc": "saving settings...",
|
"sputnik.config.autosaving.desc": "saving settings...",
|
||||||
"sputnik.config.autosaving.title": "autosaving...",
|
"sputnik.config.autosaving.title": "autosaving...",
|
||||||
|
"sputnik.config.error.applying": "error applying settings",
|
||||||
"sputnik.config.error.empty": "config file empty or nonexistent",
|
"sputnik.config.error.empty": "config file empty or nonexistent",
|
||||||
"sputnik.config.error.invalidformat": "invalid file format: %s",
|
"sputnik.config.error.invalidformat": "invalid file format: %s",
|
||||||
"sputnik.config.error.invalidversion": "invalid version: %s",
|
"sputnik.config.error.invalidversion": "invalid version: %s",
|
||||||
@@ -105,6 +106,8 @@
|
|||||||
"sputnik.enum.module.modules.client.hud.dynosaurs.velocirraptor": "velociraptor",
|
"sputnik.enum.module.modules.client.hud.dynosaurs.velocirraptor": "velociraptor",
|
||||||
"sputnik.enum.module.modules.client.hud.timeformat.twelve_hour": "12h",
|
"sputnik.enum.module.modules.client.hud.timeformat.twelve_hour": "12h",
|
||||||
"sputnik.enum.module.modules.client.hud.timeformat.twenty_four_hour": "24h",
|
"sputnik.enum.module.modules.client.hud.timeformat.twenty_four_hour": "24h",
|
||||||
|
"sputnik.enum.module.modules.combat.holdattack.attackmode.spam": "spam",
|
||||||
|
"sputnik.enum.module.modules.combat.holdattack.attackmode.time": "time",
|
||||||
"sputnik.enum.module.modules.combat.projectiletrajectories.trajectorystyle.dashed": "dashed",
|
"sputnik.enum.module.modules.combat.projectiletrajectories.trajectorystyle.dashed": "dashed",
|
||||||
"sputnik.enum.module.modules.combat.projectiletrajectories.trajectorystyle.dotted": "points",
|
"sputnik.enum.module.modules.combat.projectiletrajectories.trajectorystyle.dotted": "points",
|
||||||
"sputnik.enum.module.modules.combat.projectiletrajectories.trajectorystyle.solid": "solid",
|
"sputnik.enum.module.modules.combat.projectiletrajectories.trajectorystyle.solid": "solid",
|
||||||
@@ -327,6 +330,8 @@
|
|||||||
"sputnik.module.auradecristales.name": "crystal aura",
|
"sputnik.module.auradecristales.name": "crystal aura",
|
||||||
"sputnik.module.autismo.desc": "hehe",
|
"sputnik.module.autismo.desc": "hehe",
|
||||||
"sputnik.module.autismo.name": "autism",
|
"sputnik.module.autismo.name": "autism",
|
||||||
|
"sputnik.module.autoataque.desc": "hold the attack button down to attack automatically",
|
||||||
|
"sputnik.module.autoataque.name": "autoattack",
|
||||||
"sputnik.module.autocartel.desc": "lets you place signs with the same text without typing it out one by one",
|
"sputnik.module.autocartel.desc": "lets you place signs with the same text without typing it out one by one",
|
||||||
"sputnik.module.autocartel.name": "auto sign",
|
"sputnik.module.autocartel.name": "auto sign",
|
||||||
"sputnik.module.autofish.rodbreaking": "the rod is about to break",
|
"sputnik.module.autofish.rodbreaking": "the rod is about to break",
|
||||||
@@ -646,6 +651,14 @@
|
|||||||
"sputnik.setting.autismo.general.direccion.name": "direction",
|
"sputnik.setting.autismo.general.direccion.name": "direction",
|
||||||
"sputnik.setting.autismo.general.intervalo.desc": "rotation interval",
|
"sputnik.setting.autismo.general.intervalo.desc": "rotation interval",
|
||||||
"sputnik.setting.autismo.general.intervalo.name": "interval",
|
"sputnik.setting.autismo.general.intervalo.name": "interval",
|
||||||
|
"sputnik.setting.autoataque.general.atacarenpantallas.desc": "attack even while in a screen",
|
||||||
|
"sputnik.setting.autoataque.general.atacarenpantallas.name": "attack in screens",
|
||||||
|
"sputnik.setting.autoataque.general.cooldown.desc": "how full the attack bar has to be before attacking",
|
||||||
|
"sputnik.setting.autoataque.general.cooldown.name": "cooldown",
|
||||||
|
"sputnik.setting.autoataque.general.cooldown1.desc": "how often to attack, in ticks",
|
||||||
|
"sputnik.setting.autoataque.general.cooldown1.name": "cooldown",
|
||||||
|
"sputnik.setting.autoataque.general.mododeataque.desc": "how to attack",
|
||||||
|
"sputnik.setting.autoataque.general.mododeataque.name": "attack mode",
|
||||||
"sputnik.setting.autoherramienta.general.cambiardevuelta.desc": "switch back to the original tool",
|
"sputnik.setting.autoherramienta.general.cambiardevuelta.desc": "switch back to the original tool",
|
||||||
"sputnik.setting.autoherramienta.general.cambiardevuelta.name": "switch back",
|
"sputnik.setting.autoherramienta.general.cambiardevuelta.name": "switch back",
|
||||||
"sputnik.setting.autoherramienta.general.delay.desc": "delay when switching tools",
|
"sputnik.setting.autoherramienta.general.delay.desc": "delay when switching tools",
|
||||||
@@ -1434,8 +1447,10 @@
|
|||||||
"sputnik.setting.zoom.visual.mostrarmanos.name": "show hands",
|
"sputnik.setting.zoom.visual.mostrarmanos.name": "show hands",
|
||||||
"sputnik.ui.availablemodes": "available modes:",
|
"sputnik.ui.availablemodes": "available modes:",
|
||||||
"sputnik.ui.clickgui.title": "gui",
|
"sputnik.ui.clickgui.title": "gui",
|
||||||
|
"sputnik.ui.clientsettings.title": "mod settings",
|
||||||
"sputnik.ui.friend.manage": "manage %s",
|
"sputnik.ui.friend.manage": "manage %s",
|
||||||
"sputnik.ui.friend.remove": "remove friend",
|
"sputnik.ui.friend.remove": "remove friend",
|
||||||
|
"sputnik.ui.friends.title": "friends",
|
||||||
"sputnik.ui.list.tooltip": "%s (%s of %s)",
|
"sputnik.ui.list.tooltip": "%s (%s of %s)",
|
||||||
"sputnik.ui.preview.echest": "echest",
|
"sputnik.ui.preview.echest": "echest",
|
||||||
"sputnik.ui.preview.shulker": "shulker preview",
|
"sputnik.ui.preview.shulker": "shulker preview",
|
||||||
|
|||||||
@@ -55,6 +55,7 @@
|
|||||||
"sputnik.commands.wait.desc": "espera un tiempo determinado antes de ejecutar otro comando",
|
"sputnik.commands.wait.desc": "espera un tiempo determinado antes de ejecutar otro comando",
|
||||||
"sputnik.config.autosaving.desc": "guardando configuración...",
|
"sputnik.config.autosaving.desc": "guardando configuración...",
|
||||||
"sputnik.config.autosaving.title": "autoguardando...",
|
"sputnik.config.autosaving.title": "autoguardando...",
|
||||||
|
"sputnik.config.error.applying": "error aplicando ajustes",
|
||||||
"sputnik.config.error.empty": "archivo de config. vacío o inexistente",
|
"sputnik.config.error.empty": "archivo de config. vacío o inexistente",
|
||||||
"sputnik.config.error.invalidformat": "formato de archivo inválido: %s",
|
"sputnik.config.error.invalidformat": "formato de archivo inválido: %s",
|
||||||
"sputnik.config.error.invalidversion": "versión inválida: %s",
|
"sputnik.config.error.invalidversion": "versión inválida: %s",
|
||||||
@@ -105,6 +106,8 @@
|
|||||||
"sputnik.enum.module.modules.client.hud.dynosaurs.velocirraptor": "velocirráptor",
|
"sputnik.enum.module.modules.client.hud.dynosaurs.velocirraptor": "velocirráptor",
|
||||||
"sputnik.enum.module.modules.client.hud.timeformat.twelve_hour": "12h",
|
"sputnik.enum.module.modules.client.hud.timeformat.twelve_hour": "12h",
|
||||||
"sputnik.enum.module.modules.client.hud.timeformat.twenty_four_hour": "24h",
|
"sputnik.enum.module.modules.client.hud.timeformat.twenty_four_hour": "24h",
|
||||||
|
"sputnik.enum.module.modules.combat.holdattack.attackmode.spam": "spamear",
|
||||||
|
"sputnik.enum.module.modules.combat.holdattack.attackmode.time": "timear",
|
||||||
"sputnik.enum.module.modules.combat.projectiletrajectories.trajectorystyle.dashed": "discontinua",
|
"sputnik.enum.module.modules.combat.projectiletrajectories.trajectorystyle.dashed": "discontinua",
|
||||||
"sputnik.enum.module.modules.combat.projectiletrajectories.trajectorystyle.dotted": "puntos",
|
"sputnik.enum.module.modules.combat.projectiletrajectories.trajectorystyle.dotted": "puntos",
|
||||||
"sputnik.enum.module.modules.combat.projectiletrajectories.trajectorystyle.solid": "continua",
|
"sputnik.enum.module.modules.combat.projectiletrajectories.trajectorystyle.solid": "continua",
|
||||||
@@ -327,6 +330,8 @@
|
|||||||
"sputnik.module.auradecristales.name": "aura de cristales",
|
"sputnik.module.auradecristales.name": "aura de cristales",
|
||||||
"sputnik.module.autismo.desc": "jeje",
|
"sputnik.module.autismo.desc": "jeje",
|
||||||
"sputnik.module.autismo.name": "autismo",
|
"sputnik.module.autismo.name": "autismo",
|
||||||
|
"sputnik.module.autoataque.desc": "mantén pulsado el clic para atacar automáticamente",
|
||||||
|
"sputnik.module.autoataque.name": "autoataque",
|
||||||
"sputnik.module.autocartel.desc": "te permite colocar carteles con el mismo texto sin tener que escribirlo uno por uno",
|
"sputnik.module.autocartel.desc": "te permite colocar carteles con el mismo texto sin tener que escribirlo uno por uno",
|
||||||
"sputnik.module.autocartel.name": "autocartel",
|
"sputnik.module.autocartel.name": "autocartel",
|
||||||
"sputnik.module.autofish.rodbreaking": "caña a punto de romperse",
|
"sputnik.module.autofish.rodbreaking": "caña a punto de romperse",
|
||||||
@@ -646,6 +651,14 @@
|
|||||||
"sputnik.setting.autismo.general.direccion.name": "dirección",
|
"sputnik.setting.autismo.general.direccion.name": "dirección",
|
||||||
"sputnik.setting.autismo.general.intervalo.desc": "intervalo de rotación",
|
"sputnik.setting.autismo.general.intervalo.desc": "intervalo de rotación",
|
||||||
"sputnik.setting.autismo.general.intervalo.name": "intervalo",
|
"sputnik.setting.autismo.general.intervalo.name": "intervalo",
|
||||||
|
"sputnik.setting.autoataque.general.atacarenpantallas.desc": "atacar aun estando en una pantalla",
|
||||||
|
"sputnik.setting.autoataque.general.atacarenpantallas.name": "atacar en pantallas",
|
||||||
|
"sputnik.setting.autoataque.general.cooldown.desc": "cómo de llena tiene que estar la barra de ataque antes de atacar",
|
||||||
|
"sputnik.setting.autoataque.general.cooldown.name": "cooldown",
|
||||||
|
"sputnik.setting.autoataque.general.cooldown1.desc": "cada cuánto atacar, en ticks",
|
||||||
|
"sputnik.setting.autoataque.general.cooldown1.name": "cooldown",
|
||||||
|
"sputnik.setting.autoataque.general.mododeataque.desc": "cómo atacar",
|
||||||
|
"sputnik.setting.autoataque.general.mododeataque.name": "modo de ataque",
|
||||||
"sputnik.setting.autoherramienta.general.cambiardevuelta.desc": "cambiar de vuelta a la herramienta inicial",
|
"sputnik.setting.autoherramienta.general.cambiardevuelta.desc": "cambiar de vuelta a la herramienta inicial",
|
||||||
"sputnik.setting.autoherramienta.general.cambiardevuelta.name": "cambiar de vuelta",
|
"sputnik.setting.autoherramienta.general.cambiardevuelta.name": "cambiar de vuelta",
|
||||||
"sputnik.setting.autoherramienta.general.delay.desc": "delay al cambiar de herramienta",
|
"sputnik.setting.autoherramienta.general.delay.desc": "delay al cambiar de herramienta",
|
||||||
@@ -1434,8 +1447,10 @@
|
|||||||
"sputnik.setting.zoom.visual.mostrarmanos.name": "mostrar manos",
|
"sputnik.setting.zoom.visual.mostrarmanos.name": "mostrar manos",
|
||||||
"sputnik.ui.availablemodes": "modos disponibles:",
|
"sputnik.ui.availablemodes": "modos disponibles:",
|
||||||
"sputnik.ui.clickgui.title": "interfaz",
|
"sputnik.ui.clickgui.title": "interfaz",
|
||||||
|
"sputnik.ui.clientsettings.title": "ajustes del mod",
|
||||||
"sputnik.ui.friend.manage": "gestiona a %s",
|
"sputnik.ui.friend.manage": "gestiona a %s",
|
||||||
"sputnik.ui.friend.remove": "eliminar amigo",
|
"sputnik.ui.friend.remove": "eliminar amigo",
|
||||||
|
"sputnik.ui.friends.title": "amigos",
|
||||||
"sputnik.ui.list.tooltip": "%s (%s de %s)",
|
"sputnik.ui.list.tooltip": "%s (%s de %s)",
|
||||||
"sputnik.ui.preview.echest": "echest",
|
"sputnik.ui.preview.echest": "echest",
|
||||||
"sputnik.ui.preview.shulker": "previsualización del shulker",
|
"sputnik.ui.preview.shulker": "previsualización del shulker",
|
||||||
|
|||||||
Reference in new issue
Block a user