Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4307b0a479 | ||
|
|
ab191a9016 | ||
|
|
629d03ff92 | ||
|
|
c1a03f3ddb | ||
|
|
44494830be | ||
|
|
73682cb85d | ||
|
|
ac7de7a07a | ||
|
|
0bd31971a0 | ||
|
|
3010b164ab | ||
|
|
6cb4656365 | ||
|
|
272c1059ef | ||
|
|
e0f8523809 | ||
|
|
81fc25c33d | ||
|
|
81b043270b | ||
|
|
3913b31374 | ||
|
|
aeadfb28b1 | ||
|
|
957fab15aa | ||
|
|
321505657c | ||
|
|
b2bc2b36ab | ||
|
|
09ed268576 | ||
|
|
531c3ef9aa | ||
|
|
67cc34a08c | ||
|
|
c7b8e96d68 | ||
|
|
65afbf6ae6 | ||
|
|
8933565e07 | ||
|
|
47ad2c67c5 | ||
|
|
e84382367e | ||
|
|
ac99a609a0 | ||
|
|
1d22ec5176 | ||
|
|
05c5300cd8 | ||
|
|
a879458b4a | ||
|
|
bab752c589 | ||
|
|
4d30a16a6a | ||
|
|
412fe93a89 | ||
|
|
acecda3c0d | ||
|
|
ad0349aa29 |
No files matched your search
@@ -17,7 +17,7 @@ jobs:
|
|||||||
- name: setup jdk
|
- name: setup jdk
|
||||||
uses: actions/setup-java@v4
|
uses: actions/setup-java@v4
|
||||||
with:
|
with:
|
||||||
java-version: '21'
|
java-version: '25'
|
||||||
distribution: 'microsoft'
|
distribution: 'microsoft'
|
||||||
- name: make gradle wrapper executable
|
- name: make gradle wrapper executable
|
||||||
run: chmod +x ./gradlew
|
run: chmod +x ./gradlew
|
||||||
|
|||||||
@@ -43,4 +43,5 @@ replay_*.log
|
|||||||
|
|
||||||
todo.txt
|
todo.txt
|
||||||
cambios.md
|
cambios.md
|
||||||
remappedSrc/
|
remappedSrc/
|
||||||
|
.claude/
|
||||||
@@ -0,0 +1,82 @@
|
|||||||
|
<p align="center">
|
||||||
|
<a href="README.md"><img src="https://img.shields.io/badge/lang-Español-yellow.svg" alt="español"></a>
|
||||||
|
<a href="README.en.md"><img src="https://img.shields.io/badge/lang-English-blue.svg" alt="english"></a>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
# jenny's mod 2 (100% real)
|
||||||
|
|
||||||
|
> Minecraft Fabric 26.3 mod that adds some "QOL" features, mostly related to the camera.
|
||||||
|
|
||||||
|
## installation
|
||||||
|
|
||||||
|
### for normal people:
|
||||||
|
1. go to [releases](https://git.retucio.me/retucio/sputnik/releases)
|
||||||
|
2. choose the most recent version
|
||||||
|
3. download the .jar file
|
||||||
|
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.3`; Fabric `0.19.5`)
|
||||||
|
|
||||||
|
issues could arise when using it with other mods, especially other clients, since they could conflict
|
||||||
|
|
||||||
|
### for nerds
|
||||||
|
1. clone the repo (`git clone https://git.retucio.me/retucio/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)
|
||||||
|
4. the built .jar will be found in `/build/libs/sputnik-X.X.jar`
|
||||||
|
|
||||||
|
## usage
|
||||||
|
|
||||||
|
`rshift` by default to open the GUI
|
||||||
|
|
||||||
|
`insert` by default to open the HUD editor
|
||||||
|
|
||||||
|
`$` as prefix for commands (autocompleted)
|
||||||
|
|
||||||
|
some modules have keys assigned by default, assign them `ESC` to unbind them.
|
||||||
|
|
||||||
|
## ui
|
||||||
|
|
||||||
|
- left click to toggle modules
|
||||||
|
- right click to open its settings
|
||||||
|
- left click + drag to move a panel
|
||||||
|
- right click on a panel's header to expand/contract it, or to close it
|
||||||
|
- left click over settings to change them
|
||||||
|
- shift + right click on a setting to reset it to its default value
|
||||||
|
- place the mouse cursor over a module/setting to read its description
|
||||||
|
|
||||||
|
## screenshots
|
||||||
|
|
||||||
|
<img src="screenshots/automine.png" alt="auto mine">
|
||||||
|
<img src="screenshots/blockesp.png" alt="block ESP + light overlay">
|
||||||
|
<img src="screenshots/camtweaks.png" alt="perspective plus">
|
||||||
|
<img src="screenshots/chatplus.png" alt="chatplus + nametags + screenshots plus">
|
||||||
|
<img src="screenshots/clickgui.png" alt="click GUI">
|
||||||
|
<img src="screenshots/freecam.png" alt="freecam + tracers">
|
||||||
|
<img src="screenshots/hudeditor.png" alt="HUD editor">
|
||||||
|
<img src="screenshots/itemphysics.png" alt="item physics">
|
||||||
|
<img src="screenshots/lsd.png" alt="lsd module">
|
||||||
|
<img src="screenshots/macros.png" alt="macros tab">
|
||||||
|
<img src="screenshots/trajectories.png" alt="projectile trajectories">
|
||||||
|
|
||||||
|
|
||||||
|
## contribution
|
||||||
|
|
||||||
|
yes please (PRs are welcome)
|
||||||
|
|
||||||
|
## license
|
||||||
|
|
||||||
|
[CC0 license](LICENSE)
|
||||||
|
|
||||||
|
## disclaimer
|
||||||
|
|
||||||
|
i don't give a single fuck what happens to you when using this mod on servers where its features are bannable and such.
|
||||||
|
|
||||||
|
## deps
|
||||||
|
|
||||||
|
- [fabric api](https://modrinth.com/mod/fabric-api/)
|
||||||
|
|
||||||
|
## notes
|
||||||
|
|
||||||
|
this mod IS BUGGY. VERY BUGGY, i know. i started this project when i was 14 and the codebase is such a mess i refuse to fix it. i might rewrite it in a future, though.
|
||||||
@@ -1,29 +1,34 @@
|
|||||||
|
<p align="center">
|
||||||
|
<a href="README.md"><img src="https://img.shields.io/badge/lang-Español-yellow.svg" alt="español"></a>
|
||||||
|
<a href="README.en.md"><img src="https://img.shields.io/badge/lang-English-blue.svg" alt="english"></a>
|
||||||
|
</p>
|
||||||
|
|
||||||
# jenny's mod 2 100% real
|
# jenny's mod 2 100% real
|
||||||
|
|
||||||
mod para Minecraft Fabric 1.21.11 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://github.com/retuci0/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 `1.21.11`; Fabric `0.17.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://github.com/retuci0/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 o `chmod +x gradlew` + `./gradlew build` para Linux (Mac es Linux)
|
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` (el que no lleva "sources" en el nombre)
|
4. el resultado estará en `/build/libs/sputnik-X.X.jar`
|
||||||
|
|
||||||
## uso
|
## uso
|
||||||
|
|
||||||
`shift derecho` por defecto para abrir la interfaz
|
`shift derecho` por defecto para abrir la interfaz
|
||||||
|
|
||||||
`pág. arriba` por defecto para abrir el editor del hud
|
`insertar` por defecto para abrir el editor del hud
|
||||||
|
|
||||||
`$` como prefijo por defecto para comandos (se autocompletan)
|
`$` como prefijo por defecto para comandos (se autocompletan)
|
||||||
|
|
||||||
@@ -33,55 +38,42 @@ algunos módulos tienen teclas asignadas por defecto, asígnales `ESC` para desa
|
|||||||
|
|
||||||
- clic izquierdo para activar / desactivar módulos
|
- clic izquierdo para activar / desactivar módulos
|
||||||
- clic derecho para abrir sus ajustes
|
- clic derecho para abrir sus ajustes
|
||||||
- clic izquierdo + arrastrar para mover marcos
|
- clic izquierdo + arrastrar para mover paneles
|
||||||
- clic derecho en la cabeza del marco para expandirlo / contraerlo o para cerrarlo
|
- clic derecho en la cabeza del marco para expandirlo / contraerlo o para cerrarlo
|
||||||
- clic izquierdo sobre ajustes para modificarlos
|
- clic izquierdo sobre ajustes para modificarlos
|
||||||
- shift + clic derecho sobre ajustes para restablecerlos
|
- shift + clic derecho sobre ajustes para restablecerlos
|
||||||
- posiciona el puntero del ratón sobre un módulo o ajuste para leer su descripción
|
- posiciona el puntero del ratón sobre un módulo o ajuste para leer su descripción
|
||||||
|
|
||||||
### protips
|
|
||||||
- shift mientras pasas el puntero por encima de un ajuste de modos para ver los modos disponibles
|
|
||||||
- clic derecho para ciclar hacia atrás en ajustes de modo
|
|
||||||
- usa la rueda del ratón para mover la interfaz verticalmente
|
|
||||||
- shift + rueda del ratón para mover todos los marcos a un rango visible en la pantalla
|
|
||||||
|
|
||||||
## capturas
|
## capturas
|
||||||
|
|
||||||
<img src="screenshots/ui.png" alt="interfaz">
|
<img src="screenshots/automine.png" alt="auto minado">
|
||||||
<img src="screenshots/nametags.png" alt="nametags mostrando daño de un tridente">
|
<img src="screenshots/blockesp.png" alt="resaltado de bloques + superposición de luz">
|
||||||
<img src="screenshots/chatplus.png" alt="chatplus y capturas en uso">
|
<img src="screenshots/camtweaks.png" alt="perspectiva plus">
|
||||||
<img src="screenshots/crits.png" alt="críticos">
|
<img src="screenshots/chatplus.png" alt="chatplus + nametags + capturas">
|
||||||
<img src="screenshots/fullbright.png" alt="fullbright en modo gamma cambiando el color de los shaders">
|
<img src="screenshots/clickgui.png" alt="interfaz">
|
||||||
<img src="screenshots/hud.png" alt="HUD">
|
<img src="screenshots/freecam.png" alt="cámara libre + trazos">
|
||||||
<img src="screenshots/hudeditor.png" alt="editor de HUD">
|
<img src="screenshots/hudeditor.png" alt="editor de HUD">
|
||||||
<img src="screenshots/colorpicker.png" alt="selector de colores">
|
<img src="screenshots/itemphysics.png" alt="físicas de items">
|
||||||
|
<img src="screenshots/lsd.png" alt="LSD">
|
||||||
|
<img src="screenshots/macros.png" alt="macros">
|
||||||
|
<img src="screenshots/trajectories.png" alt="trayectorias">
|
||||||
|
|
||||||
## contibuciones
|
## contribuciones
|
||||||
|
|
||||||
sí por favor
|
sí por favor
|
||||||
|
|
||||||
## licencia
|
## licencia
|
||||||
|
|
||||||
no sé, haz lo que quieras con esto, es puta basura xd
|
[licencia CC0](LICENSE)
|
||||||
|
|
||||||
aunque estaría guay que acreditases
|
|
||||||
|
|
||||||
pero bueno
|
|
||||||
|
|
||||||
## descargo de responsabilidad
|
## descargo de responsabilidad
|
||||||
|
|
||||||
me importa una puta mierda lo que pase al usar este mod en servers donde es baneable y así.
|
me importa una puta mierda lo que pase al usar este mod en servers donde es baneable y así.
|
||||||
|
|
||||||
## mods recomendados
|
## dependencias
|
||||||
|
|
||||||
> mods que recomiendo usar junto a este:
|
- [fabric api](https://modrinth.com/mod/fabric-api/)
|
||||||
|
|
||||||
- [fabric api (necesario)](https://modrinth.com/mod/fabric-api/): necesario para el mod
|
## notas
|
||||||
- [sodium](https://modrinth.com/mod/sodium): mejora el rendimiento general del juego
|
|
||||||
- [viafabricplus](https://modrinth.com/mod/viafabricplus): te permite conectarte a servidores que tengan una versión distinta a la de tu cliente
|
este mod tiene MUCHOS bugs. empecé este proyecto cuando tenía 14 años y no sabía una mierda de programar. el código es un puto desastre y me niego a arreglarlo. puede que en un futuro reescriba el mod o algo. no sé.
|
||||||
- [xaero's world map](https://modrinth.com/mod/xaeros-world-map/) y [xaero's minimap](https://modrinth.com/mod/xaeros-minimap/): mapa chulo
|
|
||||||
- [mod menu](https://modrinth.com/mod/modmenu): lista de los mods instalados, y sus ajustes
|
|
||||||
- [iris](https://modrinth.com/mod/iris): shaders
|
|
||||||
- [lambdynamiclights](https://modrinth.com/mod/lambdynamiclights): iluminación dinámica
|
|
||||||
- [appleskin](https://modrinth.com/mod/appleskin/): información relacionada con la comida
|
|
||||||
- [baritone (desactualizado)](https://github.com/cabaletta/baritone): google maps para juego de cubos
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
plugins {
|
plugins {
|
||||||
id 'fabric-loom' version "${loom_version}"
|
id "net.fabricmc.fabric-loom" version "${loom_version}"
|
||||||
id 'maven-publish'
|
id 'maven-publish'
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -7,74 +7,79 @@ version = project.mod_version
|
|||||||
group = project.maven_group
|
group = project.maven_group
|
||||||
|
|
||||||
base {
|
base {
|
||||||
archivesName = project.archives_base_name
|
archivesName = project.archives_base_name
|
||||||
}
|
}
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
maven { url 'https://jitpack.io' }
|
maven { url 'https://jitpack.io' }
|
||||||
maven {
|
maven {
|
||||||
name = "FDD Maven"
|
name = "FDD Maven"
|
||||||
url = "https://maven.firstdark.dev/releases"
|
url = "https://maven.firstdark.dev/releases"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
// mc
|
// mc
|
||||||
minecraft "com.mojang:minecraft:${project.minecraft_version}"
|
minecraft "com.mojang:minecraft:${project.minecraft_version}"
|
||||||
|
|
||||||
// mappings
|
// fabric & su api
|
||||||
mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2"
|
implementation "net.fabricmc:fabric-loader:${project.loader_version}"
|
||||||
|
implementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_api_version}"
|
||||||
|
|
||||||
// fabric & su api
|
// sistema de eventos
|
||||||
modImplementation "net.fabricmc:fabric-loader:${project.loader_version}"
|
include(implementation "com.github.retuci0:neutrino:${project.neutrino_version}")
|
||||||
modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_api_version}"
|
|
||||||
|
|
||||||
// sistema de eventos
|
|
||||||
modImplementation "com.github.retuci0:neutrino:${project.neutrino_version}"
|
|
||||||
|
|
||||||
// rpc de discord
|
// rpc de discord
|
||||||
include(modImplementation "dev.firstdark.discordrpc:discord-rpc:1.0.3")
|
include(implementation "dev.firstdark.discordrpc:discord-rpc:${project.discord_rpc_version}")
|
||||||
}
|
}
|
||||||
|
|
||||||
loom {
|
loom {
|
||||||
accessWidenerPath = file("src/main/resources/sputnik.accesswidener")
|
accessWidenerPath = file("src/main/resources/sputnik.accesswidener")
|
||||||
}
|
}
|
||||||
|
|
||||||
processResources {
|
processResources {
|
||||||
inputs.property "version", project.version
|
inputs.property "version", project.version
|
||||||
|
inputs.property "loader_version", project.loader_version
|
||||||
|
inputs.property "minecraft_version", project.minecraft_version
|
||||||
|
inputs.property "jdk_version", project.jdk_version
|
||||||
|
|
||||||
filesMatching("fabric.mod.json") {
|
filesMatching("fabric.mod.json") {
|
||||||
expand "version": inputs.properties.version
|
expand(
|
||||||
}
|
"version": project.version,
|
||||||
|
"loader_version": project.loader_version,
|
||||||
|
"minecraft_version": project.minecraft_version,
|
||||||
|
"jdk_version": project.jdk_version
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.withType(JavaCompile).configureEach {
|
tasks.withType(JavaCompile).configureEach {
|
||||||
it.options.release = 21
|
it.options.release = jdk_version.toInteger()
|
||||||
}
|
}
|
||||||
|
|
||||||
java {
|
java {
|
||||||
sourceCompatibility = JavaVersion.VERSION_21
|
sourceCompatibility = JavaVersion.toVersion(jdk_version)
|
||||||
targetCompatibility = JavaVersion.VERSION_21
|
targetCompatibility = JavaVersion.toVersion(jdk_version)
|
||||||
}
|
}
|
||||||
|
|
||||||
jar {
|
jar {
|
||||||
inputs.property "archivesName", project.base.archivesName
|
inputs.property "archivesName", project.base.archivesName
|
||||||
|
|
||||||
from("LICENSE") {
|
from("LICENSE") {
|
||||||
rename {
|
rename {
|
||||||
"${it}_${inputs.properties.archivesName}"
|
"${it}_${inputs.properties.archivesName}"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
publishing {
|
publishing {
|
||||||
publications {
|
publications {
|
||||||
create("mavenJava", MavenPublication) {
|
create("mavenJava", MavenPublication) {
|
||||||
artifactId = project.archives_base_name
|
artifactId = project.archives_base_name
|
||||||
from components.java
|
from components.java
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
repositories {}
|
repositories {}
|
||||||
}
|
}
|
||||||
@@ -1,22 +1,17 @@
|
|||||||
# v3.3
|
# v6.7
|
||||||
|
|
||||||
## novedades
|
## novedades
|
||||||
|
|
||||||
- cambiado de sistema de eventos
|
- SIC SEBEN
|
||||||
- categoría de inventario
|
- migrado de Codeberg a mi propia instancia de Gitea
|
||||||
|
|
||||||
### adiciones
|
### adiciones
|
||||||
|
|
||||||
#### módulos nuevos:
|
|
||||||
|
|
||||||
- reponer: repone items a medida que se usan de forma automática
|
|
||||||
|
|
||||||
### arreglos / mejoras
|
### arreglos / mejoras
|
||||||
|
|
||||||
- ahora el grosor de línea de hitboxes funciona
|
|
||||||
- ahora cabezas de chatplus funciona, a medias
|
|
||||||
|
|
||||||
## problemas reconocidos
|
## problemas reconocidos
|
||||||
|
|
||||||
- es posible que algunos módulos hayan dejado de funcionar correctamente, ya que he cambiado de sistema de eventos
|
- `reponer` no funciona
|
||||||
- muchos, pero repórtalos en la página de problemas si quieres para que queden bien registrados
|
- `copiar` tras sacar una captura con `capturas` no funciona correctamente
|
||||||
|
- `manos` no funciona del todo
|
||||||
|
- \+ lo de siempre.
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
Meteor Client: https://github.com/MeteorDevelopment/meteor-client | https://meteorclient.com
|
Meteor Client: https://github.com/MeteorDevelopment/meteor-client | https://meteorclient.com
|
||||||
OyVey Port: https://github.com/mioclient/oyvey-ported/
|
OyVey Port: https://github.com/mioclient/oyvey-ported/
|
||||||
Lenny Boi: https://www.youtube.com/@lennyboi7195
|
Lenny Boi: https://www.youtube.com/@lennyboi7195
|
||||||
Shotify: https://modrinth.com/mod/shotify
|
Shotify: https://modrinth.com/mod/shotify
|
||||||
@@ -9,7 +9,9 @@ bypass-resource-pack: https://github.com/emilyy-dev/bypass-resource-pack
|
|||||||
elytra-recast: https://github.com/InLieuOfLuna/elytra-recast/
|
elytra-recast: https://github.com/InLieuOfLuna/elytra-recast/
|
||||||
SpearHax: https://github.com/etianl/spearHax/
|
SpearHax: https://github.com/etianl/spearHax/
|
||||||
ProjectileTrajectoryPreview: https://github.com/maDU59/ProjectilesTrajectoryPreview
|
ProjectileTrajectoryPreview: https://github.com/maDU59/ProjectilesTrajectoryPreview
|
||||||
DupersUnited public addon: https://discord.gg/dupes | https://dupers.wtf
|
DupersUnited public addon: https://discord.gg/dupes | https://dupers.wtf
|
||||||
|
Stardust: https://github.com/0xTas/stardust/
|
||||||
|
|
||||||
probablemente más pero como tengo demencia se me olvida
|
probablemente más pero como tengo demencia se me olvida
|
||||||
si quieres que te acredite o quite tu código de mi mod, mándame un mensaje en discord (username: retucio) y sin problemas :)
|
si quieres que te acredite o quite tu código de mi mod, mándame un mensaje en discord (username: retucio) y sin problemas :)
|
||||||
|
también es probable que haya créditos sueltos en forma de comentarios donde haya usado código ajeno
|
||||||
@@ -1,15 +1,15 @@
|
|||||||
org.gradle.jvmargs=-Xmx2G
|
org.gradle.jvmargs=-Xmx2G
|
||||||
org.gradle.parallel=true
|
org.gradle.parallel=true
|
||||||
|
|
||||||
minecraft_version=1.21.11
|
minecraft_version=26.3
|
||||||
yarn_mappings=1.21.11+build.3
|
loader_version=0.19.5
|
||||||
loader_version=0.18.4
|
loom_version=1.18-SNAPSHOT
|
||||||
loom_version=1.13-SNAPSHOT
|
|
||||||
|
|
||||||
fabric_api_version=0.140.2+1.21.11
|
|
||||||
|
|
||||||
|
fabric_api_version=0.160.7+26.3
|
||||||
|
discord_rpc_version=1.0.3
|
||||||
neutrino_version=1.1.0
|
neutrino_version=1.1.0
|
||||||
|
jdk_version=25
|
||||||
|
|
||||||
mod_version=3.3
|
mod_version=6.7
|
||||||
maven_group=me.retucio
|
maven_group=me.retucio
|
||||||
archives_base_name=sputnik
|
archives_base_name=sputnik
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
|
#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-8.14.2-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-9.8.0-bin.zip
|
||||||
networkTimeout=10000
|
|
||||||
validateDistributionUrl=true
|
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
|
After Width: | Height: | Size: 2.2 MiB |
|
After Width: | Height: | Size: 1.3 MiB |
|
After Width: | Height: | Size: 3.4 MiB |
|
Before Width: | Height: | Size: 864 KiB After Width: | Height: | Size: 1.2 MiB |
|
After Width: | Height: | Size: 796 KiB |
|
Before Width: | Height: | Size: 915 KiB |
|
Before Width: | Height: | Size: 1.3 MiB |
|
Before Width: | Height: | Size: 1.1 MiB |
|
After Width: | Height: | Size: 1.9 MiB |
|
Before Width: | Height: | Size: 566 KiB |
|
Before Width: | Height: | Size: 469 KiB |
|
Before Width: | Height: | Size: 243 KiB After Width: | Height: | Size: 700 KiB |
|
After Width: | Height: | Size: 1.3 MiB |
|
After Width: | Height: | Size: 1.1 MiB |
|
After Width: | Height: | Size: 1.0 MiB |
|
Before Width: | Height: | Size: 506 KiB |
|
After Width: | Height: | Size: 1.5 MiB |
|
Before Width: | Height: | Size: 691 KiB |
@@ -1,36 +1,42 @@
|
|||||||
package me.retucio.sputnik;
|
package me.retucio.sputnik;
|
||||||
|
|
||||||
import com.github.retucio.neutrino.EventBus;
|
import com.github.retucio.neutrino.EventBus;
|
||||||
|
import com.github.retucio.neutrino.EventListener;
|
||||||
|
import com.mojang.blaze3d.platform.InputConstants;
|
||||||
import me.retucio.sputnik.cape.CapeManager;
|
import me.retucio.sputnik.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;
|
||||||
|
|
||||||
import me.retucio.sputnik.config.ConfigManager;
|
import me.retucio.sputnik.config.ConfigManager;
|
||||||
|
import me.retucio.sputnik.config.ProfileManager;
|
||||||
|
import me.retucio.sputnik.macro.MacroManager;
|
||||||
|
|
||||||
import me.retucio.sputnik.event.ShutdownEvent;
|
import me.retucio.sputnik.event.ShutdownEvent;
|
||||||
import me.retucio.sputnik.event.interact.OpenScreenEvent;
|
import me.retucio.sputnik.event.interact.OpenScreenEvent;
|
||||||
import me.retucio.sputnik.event.sputnik.LoadCapeManagerEvent;
|
import me.retucio.sputnik.event.sputnik.*;
|
||||||
import me.retucio.sputnik.event.sputnik.LoadClickGUIEvent;
|
|
||||||
import me.retucio.sputnik.event.sputnik.LoadCommandManagerEvent;
|
|
||||||
import me.retucio.sputnik.event.sputnik.LoadModuleManagerEvent;
|
|
||||||
|
|
||||||
|
import me.retucio.sputnik.friend.FriendManager;
|
||||||
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.modules.client.HUD;
|
import me.retucio.sputnik.module.modules.client.Hud;
|
||||||
|
|
||||||
|
import me.retucio.sputnik.ui.hud.HudEditor;
|
||||||
import me.retucio.sputnik.ui.hud.HudRenderer;
|
import me.retucio.sputnik.ui.hud.HudRenderer;
|
||||||
import me.retucio.sputnik.ui.screen.ClickGUI;
|
import me.retucio.sputnik.ui.screen.ClickGui;
|
||||||
import me.retucio.sputnik.ui.hud.HudEditorScreen;
|
import me.retucio.sputnik.ui.hud.HudEditorScreen;
|
||||||
import me.retucio.sputnik.ui.screen.UpdateScreen;
|
import me.retucio.sputnik.ui.screen.UpdateScreen;
|
||||||
import me.retucio.sputnik.ui.widgets.buttons.settings.BindButton;
|
import me.retucio.sputnik.ui.widgets.buttons.settings.BindButton;
|
||||||
import me.retucio.sputnik.ui.widgets.buttons.SettingButton;
|
import me.retucio.sputnik.ui.widgets.buttons.SettingButton;
|
||||||
|
import me.retucio.sputnik.ui.widgets.buttons.settings.FileButton;
|
||||||
import me.retucio.sputnik.ui.widgets.buttons.settings.TextButton;
|
import me.retucio.sputnik.ui.widgets.buttons.settings.TextButton;
|
||||||
import me.retucio.sputnik.ui.widgets.frames.settings.ClientSettingsFrame;
|
import me.retucio.sputnik.ui.widgets.panels.settings.ClientSettingsPanel;
|
||||||
import me.retucio.sputnik.ui.widgets.frames.SettingsFrame;
|
import me.retucio.sputnik.ui.widgets.panels.SettingsPanel;
|
||||||
import me.retucio.sputnik.ui.widgets.Button;
|
import me.retucio.sputnik.ui.widgets.Button;
|
||||||
|
|
||||||
import me.retucio.sputnik.util.*;
|
import me.retucio.sputnik.util.*;
|
||||||
import me.retucio.sputnik.util.KeyUtil;
|
import me.retucio.sputnik.util.KeyUtil;
|
||||||
|
import me.retucio.sputnik.util.misc.BlockIterator;
|
||||||
|
import me.retucio.sputnik.util.misc.VersionChecker;
|
||||||
import me.retucio.sputnik.util.render.DrawUtil;
|
import me.retucio.sputnik.util.render.DrawUtil;
|
||||||
import me.retucio.sputnik.util.render.RenderUtil;
|
import me.retucio.sputnik.util.render.RenderUtil;
|
||||||
|
|
||||||
@@ -39,26 +45,27 @@ import net.fabricmc.api.ClientModInitializer;
|
|||||||
import net.fabricmc.loader.api.FabricLoader;
|
import net.fabricmc.loader.api.FabricLoader;
|
||||||
|
|
||||||
import net.minecraft.SharedConstants;
|
import net.minecraft.SharedConstants;
|
||||||
import net.minecraft.client.MinecraftClient;
|
import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.client.gui.screen.ChatScreen;
|
import net.minecraft.client.gui.screens.ChatScreen;
|
||||||
import net.minecraft.client.gui.screen.Screen;
|
import net.minecraft.client.gui.screens.Screen;
|
||||||
import net.minecraft.client.gui.screen.TitleScreen;
|
import net.minecraft.client.gui.screens.TitleScreen;
|
||||||
import net.minecraft.client.gui.screen.ingame.AbstractCommandBlockScreen;
|
import net.minecraft.client.gui.screens.inventory.AbstractCommandBlockEditScreen;
|
||||||
import net.minecraft.client.gui.screen.ingame.AbstractSignEditScreen;
|
import net.minecraft.client.gui.screens.inventory.AbstractSignEditScreen;
|
||||||
import net.minecraft.client.gui.screen.ingame.AnvilScreen;
|
import net.minecraft.client.gui.screens.inventory.AnvilScreen;
|
||||||
|
import net.minecraft.network.chat.Component;
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.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 {
|
||||||
|
|
||||||
// cosas necesarias
|
|
||||||
public static final Sputnik INSTANCE = new Sputnik();
|
public static final Sputnik INSTANCE = new Sputnik();
|
||||||
|
|
||||||
|
// cosas del mod
|
||||||
public static final EventBus EVENT_BUS = new EventBus();
|
public static final EventBus EVENT_BUS = new EventBus();
|
||||||
public static final Logger LOGGER = LogManager.getLogger(Sputnik.class);
|
public static final Logger LOGGER = LogManager.getLogger(Sputnik.class);
|
||||||
public static MinecraftClient mc;
|
public static final long LAUNCH_TIME = System.currentTimeMillis();
|
||||||
|
public static Minecraft mc;
|
||||||
|
|
||||||
// id y versión
|
// id y versión
|
||||||
public static final String MOD_ID = "sputnik";
|
public static final String MOD_ID = "sputnik";
|
||||||
@@ -79,10 +86,12 @@ public class Sputnik implements ClientModInitializer {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onInitializeClient() {
|
public void onInitializeClient() {
|
||||||
mc = MinecraftClient.getInstance();
|
mc = Minecraft.getInstance();
|
||||||
ConfigManager.load();
|
|
||||||
|
|
||||||
VersionChecker.check();
|
ConfigManager.INSTANCE = new ConfigManager();
|
||||||
|
ConfigManager.INSTANCE.load();
|
||||||
|
|
||||||
|
VersionChecker.INSTANCE.check();
|
||||||
|
|
||||||
EVENT_BUS.subscribe(this);
|
EVENT_BUS.subscribe(this);
|
||||||
|
|
||||||
@@ -93,24 +102,39 @@ public class Sputnik implements ClientModInitializer {
|
|||||||
EVENT_BUS.subscribe(MiscUtil.class);
|
EVENT_BUS.subscribe(MiscUtil.class);
|
||||||
EVENT_BUS.subscribe(NetworkUtil.class);
|
EVENT_BUS.subscribe(NetworkUtil.class);
|
||||||
EVENT_BUS.subscribe(RenderUtil.class);
|
EVENT_BUS.subscribe(RenderUtil.class);
|
||||||
|
EVENT_BUS.subscribe(RotationUtil.class);
|
||||||
|
|
||||||
|
EVENT_BUS.subscribe(BlockIterator.class);
|
||||||
|
|
||||||
Lists.init();
|
Lists.init();
|
||||||
Textures.init();
|
|
||||||
|
HudRenderer.INSTANCE = new HudRenderer();
|
||||||
|
HudEditor.INSTANCE = new HudEditor();
|
||||||
|
|
||||||
|
MacroManager.INSTANCE = new MacroManager();
|
||||||
|
ProfileManager.INSTANCE = new ProfileManager();
|
||||||
|
|
||||||
CapeManager.INSTANCE = new CapeManager();
|
CapeManager.INSTANCE = new CapeManager();
|
||||||
EVENT_BUS.post(new LoadCapeManagerEvent());
|
EVENT_BUS.post(new LoadCapeManagerEvent());
|
||||||
|
|
||||||
ModuleManager.INSTANCE = new ModuleManager();
|
ModuleManager.INSTANCE = new ModuleManager();
|
||||||
EVENT_BUS.post(new LoadModuleManagerEvent());
|
EVENT_BUS.post(new LoadModuleManagerEvent());
|
||||||
|
|
||||||
CommandManager.INSTANCE = new CommandManager();
|
CommandManager.INSTANCE = new CommandManager();
|
||||||
EVENT_BUS.post(new LoadCommandManagerEvent());
|
EVENT_BUS.post(new LoadCommandManagerEvent());
|
||||||
|
|
||||||
ClickGUI.INSTANCE = new ClickGUI();
|
FriendManager.INSTANCE = new FriendManager();
|
||||||
HudEditorScreen.INSTANCE = new HudEditorScreen();
|
EVENT_BUS.post(new LoadFriendManagerEvent());
|
||||||
EVENT_BUS.post(new LoadClickGUIEvent());
|
|
||||||
|
|
||||||
mc.execute(HudRenderer::init);
|
mc.execute(() -> {
|
||||||
|
Textures.init();
|
||||||
|
|
||||||
|
ClickGui.INSTANCE = new ClickGui();
|
||||||
|
HudEditorScreen.INSTANCE = new HudEditorScreen();
|
||||||
|
EVENT_BUS.post(new LoadClickGuiEvent());
|
||||||
|
|
||||||
|
HudRenderer.INSTANCE.init();
|
||||||
|
});
|
||||||
|
|
||||||
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
|
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
|
||||||
EVENT_BUS.post(new ShutdownEvent());
|
EVENT_BUS.post(new ShutdownEvent());
|
||||||
@@ -119,53 +143,95 @@ 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.getConfig() != null
|
settingsApplied = ConfigManager.INSTANCE.applyConfig();
|
||||||
&& !ConfigManager.hasLoaded()) {
|
|
||||||
ConfigManager.applyConfig();
|
|
||||||
settingsApplied = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ModuleManager.INSTANCE.getEnabledModules().forEach(Module::onTick);
|
ModuleManager.INSTANCE.getEnabledModules().forEach(Module::onTick);
|
||||||
mc.getWindow().setTitle(ClientSettingsFrame.guiSettings.windowTitle.getValue());
|
mc.getWindow().setTitle(ClientSettingsPanel.clientSettings.windowTitle.getValue());
|
||||||
|
|
||||||
|
ConfigManager.INSTANCE.tickAutosave();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// se ejecuta cada vez que se presiona una tecla
|
// se ejecuta cada vez que se presiona una tecla
|
||||||
public void onKey(int key, int action) {
|
public void onInput(int key, int action) {
|
||||||
if (key == GLFW.GLFW_KEY_F3) return; // prevenir activación de módulos al usar combinaciones de F3
|
// En SDL el valor 0 es UNKNOWN (y los botones del ratón empiezan en 1).
|
||||||
|
if (key == InputConstants.UNKNOWN.getValue() || key == -1) return;
|
||||||
|
// prevenir interrumpir combos de F3
|
||||||
|
if (key == InputConstants.KEY_F3) return;
|
||||||
|
|
||||||
boolean anyFocused = isAnySettingButtonFocused() || ClickGUI.INSTANCE.getSearchBar().isFocused();
|
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) {
|
if (action == InputConstants.PRESS && MacroManager.INSTANCE.onKeyPress(key)) return;
|
||||||
|
if (action == InputConstants.PRESS) {
|
||||||
handleModuleToggle(key, anyFocused);
|
handleModuleToggle(key, anyFocused);
|
||||||
handleClickGUIKey(key, anyFocused);
|
handleClickGuiKey(key, anyFocused);
|
||||||
handleHudEditorKey(key, anyFocused);
|
handleHudEditorKey(key, anyFocused);
|
||||||
}
|
}
|
||||||
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() {
|
||||||
for (SettingsFrame sf : ClickGUI.INSTANCE.getSettingsFrames())
|
if (ClickGui.INSTANCE == null) return false;
|
||||||
|
for (Button button : ClickGui.INSTANCE.getClientSettingsPanel().getButtons())
|
||||||
|
if ((button instanceof BindButton bindButton && bindButton.isFocused())
|
||||||
|
|| (button instanceof TextButton textButton && textButton.isFocused())
|
||||||
|
|| (button instanceof FileButton fileButton && fileButton.isFocused())) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
for (SettingsPanel sf : ClickGui.INSTANCE.getSettingsPanels())
|
||||||
for (Button sb : sf.getButtons())
|
for (Button sb : sf.getButtons())
|
||||||
if ((sb instanceof BindButton b && b.isFocused()) || (sb instanceof TextButton t && t.isFocused()))
|
if ((sb instanceof BindButton b && b.isFocused())
|
||||||
|
|| (sb instanceof TextButton t && t.isFocused())
|
||||||
|
|| (sb instanceof FileButton f && f.isFocused())
|
||||||
|
) {
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// se ocupa de la lógica de encendido y apagado de los módulos
|
// se ocupa de la lógica de encendido y apagado de los módulos
|
||||||
private void handleModuleToggle(int key, boolean anyFocused) {
|
private void handleModuleToggle(int key, boolean anyFocused) {
|
||||||
if (mc.currentScreen != null && mc.currentScreen != ClickGUI.INSTANCE) return;
|
if (mc.gui.screen() != null && mc.gui.screen() != ClickGui.INSTANCE) return;
|
||||||
|
|
||||||
for (Module module : ModuleManager.INSTANCE.getModules()) {
|
for (Module module : ModuleManager.INSTANCE.getModules()) {
|
||||||
if (key != module.getKey() || anyFocused || KeyUtil.isKeyDown(GLFW.GLFW_KEY_F3)) continue; // evitar interrumpir combinaciones de teclas del F3
|
// evitar interrumpir combinaciones de teclas del F3
|
||||||
|
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);
|
||||||
@@ -176,49 +242,51 @@ 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) {
|
||||||
for (SettingsFrame sf : ClickGUI.INSTANCE.getSettingsFrames()) {
|
ClickGui.INSTANCE.getClientSettingsPanel().onKey(key, action);
|
||||||
|
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);
|
||||||
|
if (sb instanceof FileButton fb) fb.onKey(key, action);
|
||||||
if (sb instanceof TextButton tb) tb.onKey(key, action);
|
if (sb instanceof TextButton tb) tb.onKey(key, action);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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 != ClientSettingsFrame.guiSettings.getKey() || anyFocused || isOnTypingScreen())
|
if (key != ClientSettingsPanel.clientSettings.getKey() || anyFocused || isOnTypingScreen())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (mc.currentScreen != ClickGUI.INSTANCE) {
|
if (mc.gui.screen() != ClickGui.INSTANCE) {
|
||||||
prevScreen = mc.currentScreen;
|
prevScreen = mc.gui.screen();
|
||||||
mc.setScreen(ClickGUI.INSTANCE);
|
mc.gui.setScreen(ClickGui.INSTANCE);
|
||||||
} else {
|
} else {
|
||||||
ClickGUI.INSTANCE.close();
|
ClickGui.INSTANCE.onClose();
|
||||||
mc.setScreen(prevScreen);
|
mc.gui.setScreen(prevScreen);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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;
|
||||||
|
|
||||||
if (mc.currentScreen != HudEditorScreen.INSTANCE) {
|
if (mc.gui.screen() != HudEditorScreen.INSTANCE) {
|
||||||
if (!hud.isEnabled()) {
|
if (!hud.isEnabled()) {
|
||||||
ChatUtil.warn("HUD está desactivado, lumbreras");
|
ChatUtil.warn(Component.translatable("sputnik.hud.disabled"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
prevScreen = mc.currentScreen;
|
prevScreen = mc.gui.screen();
|
||||||
mc.setScreen(HudEditorScreen.INSTANCE);
|
mc.gui.setScreen(HudEditorScreen.INSTANCE);
|
||||||
} else {
|
} else {
|
||||||
HudEditorScreen.INSTANCE.close();
|
HudEditorScreen.INSTANCE.onClose();
|
||||||
mc.setScreen(prevScreen);
|
mc.gui.setScreen(prevScreen);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// se ocupa de apagar los módulos que tengan configurado hacerlo tras soltar su tecla
|
// se ocupa de apagar los módulos que tengan configurado hacerlo tras soltar su tecla
|
||||||
private void handleModuleRelease(int key) {
|
private void handleModuleRelease(int key) {
|
||||||
if (mc.currentScreen != null && mc.currentScreen != ClickGUI.INSTANCE) return;
|
if (mc.gui.screen() != null && mc.gui.screen() != ClickGui.INSTANCE) return;
|
||||||
|
|
||||||
for (Module module : ModuleManager.INSTANCE.getEnabledModules())
|
for (Module module : ModuleManager.INSTANCE.getEnabledModules())
|
||||||
if (module.shouldToggleOnBindRelease() && key == module.getKey())
|
if (module.shouldToggleOnBindRelease() && key == module.getKey())
|
||||||
@@ -226,26 +294,38 @@ public class Sputnik implements ClientModInitializer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean isOnTypingScreen() {
|
private boolean isOnTypingScreen() {
|
||||||
return mc.currentScreen instanceof ChatScreen
|
return mc.gui.screen() instanceof ChatScreen
|
||||||
|| mc.currentScreen instanceof AnvilScreen
|
|| mc.gui.screen() instanceof AnvilScreen
|
||||||
|| mc.currentScreen instanceof AbstractSignEditScreen
|
|| mc.gui.screen() instanceof AbstractSignEditScreen
|
||||||
|| mc.currentScreen instanceof AbstractCommandBlockScreen;
|
|| mc.gui.screen() instanceof AbstractCommandBlockEditScreen;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean keysVerified = false;
|
||||||
|
|
||||||
|
@EventListener
|
||||||
// notificar al usuario de que hay una actualización disponible, si la hay
|
// notificar al usuario de que hay una actualización disponible, si la hay
|
||||||
public void onSetScreen(OpenScreenEvent event) {
|
public void onSetScreen(OpenScreenEvent event) {
|
||||||
if (VersionChecker.shouldShowScreen && event.getScreen() instanceof TitleScreen) {
|
if (event.getScreen() instanceof TitleScreen) {
|
||||||
event.cancel();
|
// aquí el idioma ya está cargado, que en onInitializeClient todavía no
|
||||||
VersionChecker.shouldShowScreen = false;
|
if (!keysVerified) {
|
||||||
mc.execute(() -> mc.currentScreen = new UpdateScreen());
|
keysVerified = true;
|
||||||
|
I18nUtil.verifyKeys();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (VersionChecker.INSTANCE.shouldShowScreen) {
|
||||||
|
event.cancel();
|
||||||
|
VersionChecker.INSTANCE.shouldShowScreen = false;
|
||||||
|
mc.execute(() -> mc.gui.setScreen(new UpdateScreen()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@EventListener
|
||||||
public void onStop(ShutdownEvent event) {
|
public void onStop(ShutdownEvent event) {
|
||||||
ConfigManager.save();
|
ConfigManager.INSTANCE.saveOnShutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getVersionName() {
|
public static String getVersionName() {
|
||||||
return MOD_ID + "_v" + MOD_VERSION + "_" + SharedConstants.getGameVersion().name();
|
return MOD_ID + "_v" + MOD_VERSION + "_" + SharedConstants.getCurrentVersion().name();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,26 +1,27 @@
|
|||||||
package me.retucio.sputnik.cape;
|
package me.retucio.sputnik.cape;
|
||||||
|
|
||||||
import me.retucio.sputnik.Sputnik;
|
import me.retucio.sputnik.Sputnik;
|
||||||
import net.minecraft.client.MinecraftClient;
|
import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.client.texture.NativeImage;
|
import com.mojang.blaze3d.platform.NativeImage;
|
||||||
import net.minecraft.client.texture.NativeImageBackedTexture;
|
import net.minecraft.client.renderer.texture.DynamicTexture;
|
||||||
import net.minecraft.util.Identifier;
|
import net.minecraft.resources.Identifier;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
|
||||||
public class Cape {
|
public class Cape {
|
||||||
|
|
||||||
private final MinecraftClient mc = MinecraftClient.getInstance();
|
private final Minecraft mc = Minecraft.getInstance();
|
||||||
|
|
||||||
private final String name;
|
private final String name;
|
||||||
private final Identifier id;
|
private final Identifier id;
|
||||||
private NativeImage img;
|
private NativeImage img;
|
||||||
private NativeImageBackedTexture texture;
|
private DynamicTexture texture;
|
||||||
|
|
||||||
public Cape(String name) {
|
public Cape(String name) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.id = Identifier.of(Sputnik.MOD_ID, "textures/capes/" + name + ".png");
|
this.id = Identifier.fromNamespaceAndPath(Sputnik.MOD_ID, "textures/capes/" + name + ".png");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void load() {
|
public void load() {
|
||||||
@@ -28,7 +29,7 @@ public class Cape {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public NativeImage loadTexture(Identifier id) {
|
public NativeImage loadTexture(Identifier id) {
|
||||||
try (InputStream inputStream = mc.getResourceManager().getResource(id).get().getInputStream()) {
|
try (InputStream inputStream = mc.getResourceManager().getResource(id).get().open()) {
|
||||||
return NativeImage.read(inputStream);
|
return NativeImage.read(inputStream);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
Sputnik.LOGGER.error("ups: {}", e.getMessage());
|
Sputnik.LOGGER.error("ups: {}", e.getMessage());
|
||||||
@@ -37,8 +38,8 @@ public class Cape {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void register() {
|
public void register() {
|
||||||
texture = new NativeImageBackedTexture(null, img);
|
texture = new DynamicTexture(null, img);
|
||||||
mc.getTextureManager().registerTexture(id, texture);
|
mc.getTextureManager().register(id, texture);
|
||||||
img = null;
|
img = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -50,7 +51,7 @@ public class Cape {
|
|||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
public NativeImageBackedTexture getTexture() {
|
public DynamicTexture getTexture() {
|
||||||
return texture;
|
return texture;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,60 +4,67 @@ import com.mojang.brigadier.CommandDispatcher;
|
|||||||
import com.mojang.brigadier.arguments.ArgumentType;
|
import com.mojang.brigadier.arguments.ArgumentType;
|
||||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||||
import com.mojang.brigadier.builder.RequiredArgumentBuilder;
|
import com.mojang.brigadier.builder.RequiredArgumentBuilder;
|
||||||
import net.minecraft.client.MinecraftClient;
|
import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.command.CommandRegistryAccess;
|
import net.minecraft.commands.CommandBuildContext;
|
||||||
import net.minecraft.command.CommandSource;
|
import net.minecraft.commands.Commands;
|
||||||
import net.minecraft.registry.BuiltinRegistries;
|
import net.minecraft.commands.SharedSuggestionProvider;
|
||||||
import net.minecraft.server.command.CommandManager;
|
import net.minecraft.data.registries.VanillaRegistries;
|
||||||
|
import net.minecraft.network.chat.Component;
|
||||||
|
|
||||||
import java.util.List;
|
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 CommandRegistryAccess REGISTRY_ACCESS = CommandManager.createRegistryAccess(BuiltinRegistries.createWrapperLookup());
|
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 MinecraftClient mc = MinecraftClient.getInstance();
|
protected static final Minecraft mc = Minecraft.getInstance();
|
||||||
|
|
||||||
private final String name, description;
|
private final String name, descriptionKey;
|
||||||
private final List<String> aliases;
|
private final List<String> aliases;
|
||||||
|
|
||||||
public Command(String name, String description, String... aliases) {
|
// la descripción se guarda como clave de traducción, no como texto ya resuelto: los comandos
|
||||||
|
// se construyen antes de que se cargue el idioma, así que hay que traducirla al mostrarla
|
||||||
|
public Command(String name, String descriptionKey, String... aliases) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.description = description;
|
this.descriptionKey = descriptionKey;
|
||||||
this.aliases = List.of(aliases);
|
this.aliases = List.of(aliases);
|
||||||
}
|
}
|
||||||
|
|
||||||
// métodos "helper" para reducir el "boilerplate"
|
// métodos "helper" para reducir el "boilerplate"
|
||||||
protected static <T> RequiredArgumentBuilder<CommandSource, T> argument(final String name, final ArgumentType<T> type) {
|
protected static <T> RequiredArgumentBuilder<SharedSuggestionProvider, T> argument(final String name, final ArgumentType<T> type) {
|
||||||
return RequiredArgumentBuilder.argument(name, type);
|
return RequiredArgumentBuilder.argument(name, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static LiteralArgumentBuilder<CommandSource> literal(final String name) {
|
protected static LiteralArgumentBuilder<SharedSuggestionProvider> literal(final String name) {
|
||||||
return LiteralArgumentBuilder.literal(name);
|
return LiteralArgumentBuilder.literal(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
// para registrar comandos
|
// para registrar comandos
|
||||||
public final void registerTo(CommandDispatcher<CommandSource> dispatcher) {
|
public final void registerTo(CommandDispatcher<SharedSuggestionProvider> dispatcher) {
|
||||||
register(dispatcher, name);
|
register(dispatcher, name);
|
||||||
for (String alias : aliases) register(dispatcher, alias);
|
for (String alias : aliases) register(dispatcher, alias);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void register(CommandDispatcher<CommandSource> dispatcher, String name) {
|
public void register(CommandDispatcher<SharedSuggestionProvider> dispatcher, String name) {
|
||||||
LiteralArgumentBuilder<CommandSource> builder = LiteralArgumentBuilder.literal(name);
|
LiteralArgumentBuilder<SharedSuggestionProvider> builder = LiteralArgumentBuilder.literal(name);
|
||||||
build(builder);
|
build(builder);
|
||||||
dispatcher.register(builder);
|
dispatcher.register(builder);
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract void build(LiteralArgumentBuilder<CommandSource> builder);
|
public abstract void build(LiteralArgumentBuilder<SharedSuggestionProvider> builder);
|
||||||
|
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getDescription() {
|
public String getDescriptionKey() {
|
||||||
return description;
|
return descriptionKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Component getDescription() {
|
||||||
|
return Component.translatable(descriptionKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<String> getAliases() {
|
public List<String> getAliases() {
|
||||||
|
|||||||
@@ -5,8 +5,8 @@ import com.mojang.brigadier.CommandDispatcher;
|
|||||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||||
import me.retucio.sputnik.Sputnik;
|
import me.retucio.sputnik.Sputnik;
|
||||||
import me.retucio.sputnik.command.commands.*;
|
import me.retucio.sputnik.command.commands.*;
|
||||||
import net.minecraft.client.MinecraftClient;
|
import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.command.CommandSource;
|
import net.minecraft.commands.SharedSuggestionProvider;
|
||||||
|
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@@ -22,9 +22,9 @@ public class CommandManager {
|
|||||||
private String prefix = "$";
|
private String prefix = "$";
|
||||||
|
|
||||||
public static final List<Command> commands = new ArrayList<>();
|
public static final List<Command> commands = new ArrayList<>();
|
||||||
public static final CommandDispatcher<CommandSource> dispatcher = new CommandDispatcher<>();
|
public static final CommandDispatcher<SharedSuggestionProvider> dispatcher = new CommandDispatcher<>();
|
||||||
|
|
||||||
private static final MinecraftClient mc = MinecraftClient.getInstance();
|
private static final Minecraft mc = Minecraft.getInstance();
|
||||||
|
|
||||||
public CommandManager() {
|
public CommandManager() {
|
||||||
registerCommands();
|
registerCommands();
|
||||||
@@ -36,12 +36,18 @@ public class CommandManager {
|
|||||||
addCommand(new ConfigCommand());
|
addCommand(new ConfigCommand());
|
||||||
addCommand(new CopyScreenshotCommand());
|
addCommand(new CopyScreenshotCommand());
|
||||||
addCommand(new EnderChestCommand());
|
addCommand(new EnderChestCommand());
|
||||||
|
addCommand(new FriendCommand());
|
||||||
addCommand(new GarbageCleanerCommand());
|
addCommand(new GarbageCleanerCommand());
|
||||||
|
addCommand(new HelpCommand());
|
||||||
|
addCommand(new MacroCommand());
|
||||||
|
addCommand(new PanoramaCommand());
|
||||||
addCommand(new PeekCommand());
|
addCommand(new PeekCommand());
|
||||||
addCommand(new PluginsCommand());
|
addCommand(new PluginsCommand());
|
||||||
addCommand(new PrefixCommand());
|
addCommand(new PrefixCommand());
|
||||||
|
addCommand(new ProfileCommand());
|
||||||
addCommand(new PurgeCommand());
|
addCommand(new PurgeCommand());
|
||||||
addCommand(new RepeatCommand());
|
addCommand(new RepeatCommand());
|
||||||
|
addCommand(new RepeatWaitCommand());
|
||||||
addCommand(new SaveScreenshotCommand());
|
addCommand(new SaveScreenshotCommand());
|
||||||
addCommand(new SendCommand());
|
addCommand(new SendCommand());
|
||||||
addCommand(new SpectateCommand());
|
addCommand(new SpectateCommand());
|
||||||
@@ -67,7 +73,7 @@ public class CommandManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void dispatch(String message) throws CommandSyntaxException {
|
public static void dispatch(String message) throws CommandSyntaxException {
|
||||||
dispatcher.execute(message, Objects.requireNonNull(mc.getNetworkHandler()).getCommandSource());
|
dispatcher.execute(message, Objects.requireNonNull(mc.getConnection()).getSuggestionsProvider());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Command getCommandByName(String name) {
|
public static Command getCommandByName(String name) {
|
||||||
|
|||||||
@@ -9,9 +9,9 @@ import com.mojang.brigadier.suggestion.Suggestions;
|
|||||||
import com.mojang.brigadier.suggestion.SuggestionsBuilder;
|
import com.mojang.brigadier.suggestion.SuggestionsBuilder;
|
||||||
|
|
||||||
import me.retucio.sputnik.util.EntityUtil;
|
import me.retucio.sputnik.util.EntityUtil;
|
||||||
import net.minecraft.entity.Entity;
|
import net.minecraft.network.chat.Component;
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
import net.minecraft.world.entity.Entity;
|
||||||
import net.minecraft.text.Text;
|
import net.minecraft.world.entity.player.Player;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
@@ -25,7 +25,7 @@ public class EntityArgumentType implements ArgumentType<Entity> {
|
|||||||
|
|
||||||
public static final EntityArgumentType INSTANCE = new EntityArgumentType();
|
public static final EntityArgumentType INSTANCE = new EntityArgumentType();
|
||||||
private static final DynamicCommandExceptionType NO_SUCH_ENTITY = new DynamicCommandExceptionType(
|
private static final DynamicCommandExceptionType NO_SUCH_ENTITY = new DynamicCommandExceptionType(
|
||||||
name -> Text.literal("Entidad \"" + name + "\" no encontrada"));
|
name -> Component.translatable("sputnik.args.entity.notfound", name));
|
||||||
|
|
||||||
private static final Collection<String> EXAMPLES = List.of(
|
private static final Collection<String> EXAMPLES = List.of(
|
||||||
"AdlerHitdolf",
|
"AdlerHitdolf",
|
||||||
@@ -42,7 +42,7 @@ public class EntityArgumentType implements ArgumentType<Entity> {
|
|||||||
public Entity parse(StringReader reader) throws CommandSyntaxException {
|
public Entity parse(StringReader reader) throws CommandSyntaxException {
|
||||||
String argument = reader.readString();
|
String argument = reader.readString();
|
||||||
|
|
||||||
if (mc.world == null)
|
if (mc.level == null)
|
||||||
throw NO_SUCH_ENTITY.create(argument);
|
throw NO_SUCH_ENTITY.create(argument);
|
||||||
|
|
||||||
if (argument.startsWith("@"))
|
if (argument.startsWith("@"))
|
||||||
@@ -83,13 +83,13 @@ public class EntityArgumentType implements ArgumentType<Entity> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Entity findNearestPlayer() throws CommandSyntaxException {
|
private Entity findNearestPlayer() throws CommandSyntaxException {
|
||||||
PlayerEntity nearest = null;
|
Player nearest = null;
|
||||||
double nearestDistance = Double.MAX_VALUE;
|
double nearestDistance = Double.MAX_VALUE;
|
||||||
|
|
||||||
for (PlayerEntity player : mc.world.getPlayers()) {
|
for (Player player : mc.level.players()) {
|
||||||
if (player == mc.player) continue;
|
if (player == mc.player) continue;
|
||||||
|
|
||||||
double distance = mc.player.squaredDistanceTo(player);
|
double distance = mc.player.distanceToSqr(player);
|
||||||
if (distance < nearestDistance) {
|
if (distance < nearestDistance) {
|
||||||
nearestDistance = distance;
|
nearestDistance = distance;
|
||||||
nearest = player;
|
nearest = player;
|
||||||
@@ -103,7 +103,7 @@ public class EntityArgumentType implements ArgumentType<Entity> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Entity findRandomPlayer() throws CommandSyntaxException {
|
private Entity findRandomPlayer() throws CommandSyntaxException {
|
||||||
List<PlayerEntity> players = new ArrayList<>(mc.world.getPlayers());
|
List<Player> players = new ArrayList<>(mc.level.players());
|
||||||
if (players.isEmpty()) throw NO_SUCH_ENTITY.create("@r");
|
if (players.isEmpty()) throw NO_SUCH_ENTITY.create("@r");
|
||||||
|
|
||||||
players.remove(mc.player);
|
players.remove(mc.player);
|
||||||
@@ -116,8 +116,8 @@ public class EntityArgumentType implements ArgumentType<Entity> {
|
|||||||
private Entity parseEntitySelector(String selector) throws CommandSyntaxException {
|
private Entity parseEntitySelector(String selector) throws CommandSyntaxException {
|
||||||
if (selector.equals("@e")) {
|
if (selector.equals("@e")) {
|
||||||
List<Entity> entities = new ArrayList<>();
|
List<Entity> entities = new ArrayList<>();
|
||||||
for (Entity entity : mc.world.getEntities())
|
for (Entity entity : mc.level.getEntities().getAll())
|
||||||
if (!(entity instanceof PlayerEntity))
|
if (!(entity instanceof Player))
|
||||||
entities.add(entity);
|
entities.add(entity);
|
||||||
|
|
||||||
if (entities.isEmpty()) throw NO_SUCH_ENTITY.create(selector);
|
if (entities.isEmpty()) throw NO_SUCH_ENTITY.create(selector);
|
||||||
@@ -141,8 +141,8 @@ public class EntityArgumentType implements ArgumentType<Entity> {
|
|||||||
private Entity findEntityByType(String type) throws CommandSyntaxException {
|
private Entity findEntityByType(String type) throws CommandSyntaxException {
|
||||||
List<Entity> matchingEntities = new ArrayList<>();
|
List<Entity> matchingEntities = new ArrayList<>();
|
||||||
|
|
||||||
for (Entity entity : mc.world.getEntities()) {
|
for (Entity entity : mc.level.getEntities().getAll()) {
|
||||||
String entityType = entity.getType().getTranslationKey();
|
String entityType = entity.getType().getDescriptionId();
|
||||||
if (entityType.contains(type.toLowerCase().replace("minecraft:", "")))
|
if (entityType.contains(type.toLowerCase().replace("minecraft:", "")))
|
||||||
matchingEntities.add(entity);
|
matchingEntities.add(entity);
|
||||||
}
|
}
|
||||||
@@ -153,7 +153,7 @@ public class EntityArgumentType implements ArgumentType<Entity> {
|
|||||||
double nearestDistance = Double.MAX_VALUE;
|
double nearestDistance = Double.MAX_VALUE;
|
||||||
|
|
||||||
for (Entity entity : matchingEntities) {
|
for (Entity entity : matchingEntities) {
|
||||||
double distance = mc.player.squaredDistanceTo(entity);
|
double distance = mc.player.distanceToSqr(entity);
|
||||||
if (distance < nearestDistance) {
|
if (distance < nearestDistance) {
|
||||||
nearestDistance = distance;
|
nearestDistance = distance;
|
||||||
nearest = entity;
|
nearest = entity;
|
||||||
@@ -164,15 +164,15 @@ public class EntityArgumentType implements ArgumentType<Entity> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Entity findEntityByUUID(UUID uuid) throws CommandSyntaxException {
|
private Entity findEntityByUUID(UUID uuid) throws CommandSyntaxException {
|
||||||
for (Entity entity : mc.world.getEntities())
|
for (Entity entity : mc.level.getEntities().getAll())
|
||||||
if (entity.getUuid().equals(uuid))
|
if (entity.getUUID().equals(uuid))
|
||||||
return entity;
|
return entity;
|
||||||
|
|
||||||
throw NO_SUCH_ENTITY.create(uuid.toString());
|
throw NO_SUCH_ENTITY.create(uuid.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
private PlayerEntity findPlayerByName(String name) throws CommandSyntaxException {
|
private Player findPlayerByName(String name) throws CommandSyntaxException {
|
||||||
for (PlayerEntity player : mc.world.getPlayers())
|
for (Player player : mc.level.players())
|
||||||
if (player.getName().getString().equalsIgnoreCase(name))
|
if (player.getName().getString().equalsIgnoreCase(name))
|
||||||
return player;
|
return player;
|
||||||
|
|
||||||
@@ -181,8 +181,8 @@ public class EntityArgumentType implements ArgumentType<Entity> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <S> CompletableFuture<Suggestions> listSuggestions(CommandContext<S> context, SuggestionsBuilder builder) {
|
public <S> CompletableFuture<Suggestions> listSuggestions(CommandContext<S> context, SuggestionsBuilder builder) {
|
||||||
if (mc.world != null)
|
if (mc.level != null)
|
||||||
for (PlayerEntity player : mc.world.getPlayers())
|
for (Player player : mc.level.players())
|
||||||
builder.suggest(player.getName().getString());
|
builder.suggest(player.getName().getString());
|
||||||
|
|
||||||
|
|
||||||
@@ -192,7 +192,7 @@ public class EntityArgumentType implements ArgumentType<Entity> {
|
|||||||
|
|
||||||
Entity lookingAt = EntityUtil.getEntityPlayerIsLookingAt();
|
Entity lookingAt = EntityUtil.getEntityPlayerIsLookingAt();
|
||||||
if (lookingAt != null)
|
if (lookingAt != null)
|
||||||
builder.suggest(lookingAt.getUuid().toString());
|
builder.suggest(lookingAt.getUUID().toString());
|
||||||
|
|
||||||
return builder.buildFuture();
|
return builder.buildFuture();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,15 +7,16 @@ import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
|||||||
import com.mojang.brigadier.exceptions.DynamicCommandExceptionType;
|
import com.mojang.brigadier.exceptions.DynamicCommandExceptionType;
|
||||||
import com.mojang.brigadier.suggestion.Suggestions;
|
import com.mojang.brigadier.suggestion.Suggestions;
|
||||||
import com.mojang.brigadier.suggestion.SuggestionsBuilder;
|
import com.mojang.brigadier.suggestion.SuggestionsBuilder;
|
||||||
import net.minecraft.command.CommandSource;
|
import net.minecraft.commands.SharedSuggestionProvider;
|
||||||
import net.minecraft.text.Text;
|
import net.minecraft.network.chat.Component;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
public class EnumArgumentType<T extends Enum<T>> implements ArgumentType<T> {
|
public class EnumArgumentType<T extends Enum<T>> implements ArgumentType<T> {
|
||||||
|
|
||||||
private static final DynamicCommandExceptionType NO_SUCH_TYPE = new DynamicCommandExceptionType((value) -> Text.of(" argumento inválido: " + value));
|
private static final DynamicCommandExceptionType NO_SUCH_TYPE = new DynamicCommandExceptionType(
|
||||||
|
(value) -> Component.translatable("sputnik.args.enum.invalid", value));
|
||||||
|
|
||||||
private final T[] values;
|
private final T[] values;
|
||||||
|
|
||||||
@@ -33,14 +34,16 @@ public class EnumArgumentType<T extends Enum<T>> implements ArgumentType<T> {
|
|||||||
|
|
||||||
public T parse(StringReader reader) throws CommandSyntaxException {
|
public T parse(StringReader reader) throws CommandSyntaxException {
|
||||||
String argument = reader.readString();
|
String argument = reader.readString();
|
||||||
|
// ignorando mayúsculas: listSuggestions sugiere en minúsculas, así que comparar
|
||||||
|
// con equals() hacía que las propias sugerencias no se pudieran parsear
|
||||||
return Arrays.stream(this.values)
|
return Arrays.stream(this.values)
|
||||||
.filter((value) -> value.toString().equals(argument))
|
.filter((value) -> value.toString().equalsIgnoreCase(argument))
|
||||||
.findFirst()
|
.findFirst()
|
||||||
.orElseThrow(() -> NO_SUCH_TYPE.create(argument)
|
.orElseThrow(() -> NO_SUCH_TYPE.create(argument)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public <S> CompletableFuture<Suggestions> listSuggestions(CommandContext<S> context, SuggestionsBuilder builder) {
|
public <S> CompletableFuture<Suggestions> listSuggestions(CommandContext<S> context, SuggestionsBuilder builder) {
|
||||||
return CommandSource.suggestMatching(Arrays.stream(this.values).map(e -> e.toString().toLowerCase()), builder);
|
return SharedSuggestionProvider.suggest(Arrays.stream(this.values).map(e -> e.toString().toLowerCase()), builder);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -10,8 +10,8 @@ import com.mojang.brigadier.suggestion.SuggestionsBuilder;
|
|||||||
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.util.MiscUtil;
|
import me.retucio.sputnik.util.MiscUtil;
|
||||||
import net.minecraft.command.CommandSource;
|
import net.minecraft.commands.SharedSuggestionProvider;
|
||||||
import net.minecraft.text.Text;
|
import net.minecraft.network.chat.Component;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
@@ -22,23 +22,23 @@ public class ModuleArgumentType implements ArgumentType<Module> {
|
|||||||
public static final ModuleArgumentType INSTANCE = new ModuleArgumentType();
|
public static final ModuleArgumentType INSTANCE = new ModuleArgumentType();
|
||||||
|
|
||||||
private static final DynamicCommandExceptionType UNKNOWN_MODULE = new DynamicCommandExceptionType(
|
private static final DynamicCommandExceptionType UNKNOWN_MODULE = new DynamicCommandExceptionType(
|
||||||
name -> Text.literal("módulo \"" + name + "\" no encontrado"));
|
name -> Component.translatable("sputnik.args.module.notfound", name));
|
||||||
|
|
||||||
private static final Collection<String> examples = ModuleManager.INSTANCE.getModules()
|
private static final Collection<String> examples = ModuleManager.INSTANCE.getModules()
|
||||||
.stream().limit(3).map(module -> module.getName().replace(" ", "_")).toList();
|
.stream().limit(3).map(module -> module.getDisplayName().replace(" ", "_")).toList();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Module parse(StringReader reader) throws CommandSyntaxException {
|
public Module parse(StringReader reader) throws CommandSyntaxException {
|
||||||
String argument = reader.readString().replace("_", " ");
|
String argument = reader.readString().replace("_", " ");
|
||||||
Module module = ModuleManager.INSTANCE.getModuleByName(argument);
|
Module module = ModuleManager.INSTANCE.getModuleByDisplayName(argument);
|
||||||
if (module == null) throw UNKNOWN_MODULE.create(argument);
|
if (module == null) throw UNKNOWN_MODULE.create(argument);
|
||||||
return module;
|
return module;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <S> CompletableFuture<Suggestions> listSuggestions(CommandContext<S> context, SuggestionsBuilder builder) {
|
public <S> CompletableFuture<Suggestions> listSuggestions(CommandContext<S> context, SuggestionsBuilder builder) {
|
||||||
return CommandSource.suggestMatching(ModuleManager.INSTANCE.getModules()
|
return SharedSuggestionProvider.suggest(ModuleManager.INSTANCE.getModules()
|
||||||
.stream().map(module -> MiscUtil.removeAccentMarks(module.getName().replace(" ", "_"))), builder);
|
.stream().map(module -> MiscUtil.removeAccentMarks(module.getDisplayName().replace(" ", "_"))), builder);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -46,7 +46,7 @@ public class ModuleArgumentType implements ArgumentType<Module> {
|
|||||||
return examples;
|
return examples;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Module get(CommandContext<CommandSource> ctx) {
|
public static Module get(CommandContext<SharedSuggestionProvider> ctx) {
|
||||||
return ctx.getArgument("módulo", Module.class);
|
return ctx.getArgument("módulo", Module.class);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -7,9 +7,9 @@ import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
|||||||
import com.mojang.brigadier.exceptions.DynamicCommandExceptionType;
|
import com.mojang.brigadier.exceptions.DynamicCommandExceptionType;
|
||||||
import com.mojang.brigadier.suggestion.Suggestions;
|
import com.mojang.brigadier.suggestion.Suggestions;
|
||||||
import com.mojang.brigadier.suggestion.SuggestionsBuilder;
|
import com.mojang.brigadier.suggestion.SuggestionsBuilder;
|
||||||
import net.minecraft.command.CommandSource;
|
import net.minecraft.commands.SharedSuggestionProvider;
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
import net.minecraft.network.chat.Component;
|
||||||
import net.minecraft.text.Text;
|
import net.minecraft.world.entity.player.Player;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -18,21 +18,22 @@ import java.util.concurrent.CompletableFuture;
|
|||||||
import static me.retucio.sputnik.Sputnik.mc;
|
import static me.retucio.sputnik.Sputnik.mc;
|
||||||
|
|
||||||
// para autocompletar nombres de jugadores
|
// para autocompletar nombres de jugadores
|
||||||
public class PlayerArgumentType implements ArgumentType<PlayerEntity> {
|
public class PlayerArgumentType implements ArgumentType<Player> {
|
||||||
|
|
||||||
public static final PlayerArgumentType INSTANCE = new PlayerArgumentType();
|
public static final PlayerArgumentType INSTANCE = new PlayerArgumentType();
|
||||||
private static final DynamicCommandExceptionType NO_SUCH_PLAYER = new DynamicCommandExceptionType(name -> Text.literal("Player with name " + name + " doesn't exist."));
|
private static final DynamicCommandExceptionType NO_SUCH_PLAYER = new DynamicCommandExceptionType(
|
||||||
|
name -> Component.translatable("sputnik.args.player.notfound", name));
|
||||||
|
|
||||||
private static final Collection<String> EXAMPLES = List.of("retucio", "prepucio", "postpucio", "pucio", "adler hitdolf");
|
private static final Collection<String> EXAMPLES = List.of("retucio", "prepucio", "postpucio", "pucio", "adler hitdolf");
|
||||||
|
|
||||||
private PlayerArgumentType() {}
|
private PlayerArgumentType() {}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PlayerEntity parse(StringReader reader) throws CommandSyntaxException {
|
public Player parse(StringReader reader) throws CommandSyntaxException {
|
||||||
String argument = reader.readString();
|
String argument = reader.readString();
|
||||||
PlayerEntity playerEntity = null;
|
Player playerEntity = null;
|
||||||
|
|
||||||
for (PlayerEntity p : mc.world.getPlayers())
|
for (Player p : mc.level.players())
|
||||||
if (p.getName().getString().equalsIgnoreCase(argument)) {
|
if (p.getName().getString().equalsIgnoreCase(argument)) {
|
||||||
playerEntity = p;
|
playerEntity = p;
|
||||||
break;
|
break;
|
||||||
@@ -45,7 +46,7 @@ public class PlayerArgumentType implements ArgumentType<PlayerEntity> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <S> CompletableFuture<Suggestions> listSuggestions(CommandContext<S> context, SuggestionsBuilder builder) {
|
public <S> CompletableFuture<Suggestions> listSuggestions(CommandContext<S> context, SuggestionsBuilder builder) {
|
||||||
return CommandSource.suggestMatching(mc.world.getPlayers().stream().map(
|
return SharedSuggestionProvider.suggest(mc.level.players().stream().map(
|
||||||
abstractClientPlayerEntity -> abstractClientPlayerEntity.getName().getString()), builder);
|
abstractClientPlayerEntity -> abstractClientPlayerEntity.getName().getString()), builder);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,8 +55,8 @@ public class PlayerArgumentType implements ArgumentType<PlayerEntity> {
|
|||||||
return EXAMPLES;
|
return EXAMPLES;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static PlayerEntity get(CommandContext<?> context) {
|
public static Player get(CommandContext<?> context) {
|
||||||
return context.getArgument("jugador", PlayerEntity.class);
|
return context.getArgument("jugador", Player.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -5,11 +5,18 @@ import me.retucio.sputnik.command.Command;
|
|||||||
import me.retucio.sputnik.command.args.ModuleArgumentType;
|
import me.retucio.sputnik.command.args.ModuleArgumentType;
|
||||||
import me.retucio.sputnik.module.Module;
|
import me.retucio.sputnik.module.Module;
|
||||||
import me.retucio.sputnik.module.setting.settings.KeySetting;
|
import me.retucio.sputnik.module.setting.settings.KeySetting;
|
||||||
|
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.command.CommandSource;
|
import net.minecraft.ChatFormatting;
|
||||||
import net.minecraft.text.Text;
|
import net.minecraft.client.KeyMapping;
|
||||||
import net.minecraft.util.Formatting;
|
import net.minecraft.client.input.KeyEvent;
|
||||||
|
import net.minecraft.client.resources.language.I18n;
|
||||||
|
import net.minecraft.commands.SharedSuggestionProvider;
|
||||||
|
import net.minecraft.network.chat.Component;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
// asignar una tecla a un módulo, lógica similar a BindButton
|
// asignar una tecla a un módulo, lógica similar a BindButton
|
||||||
public class BindCommand extends Command {
|
public class BindCommand extends Command {
|
||||||
@@ -17,23 +24,26 @@ public class BindCommand extends Command {
|
|||||||
private static Module listeningModule = null;
|
private static Module listeningModule = null;
|
||||||
|
|
||||||
public BindCommand() {
|
public BindCommand() {
|
||||||
super("bind", "asigna una tecla a un módulo", "keybind");
|
super("bind", "sputnik.commands.bind.desc", "keybind", "kb", "tecla");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void build(LiteralArgumentBuilder<CommandSource> builder) {
|
public void build(LiteralArgumentBuilder<SharedSuggestionProvider> builder) {
|
||||||
builder
|
builder
|
||||||
.then(argument("módulo", ModuleArgumentType.INSTANCE)
|
.then(argument("módulo", ModuleArgumentType.INSTANCE)
|
||||||
.executes(ctx -> {
|
.executes(ctx -> {
|
||||||
Module module = ctx.getArgument("módulo", Module.class);
|
Module module = ctx.getArgument("módulo", Module.class);
|
||||||
listeningModule = module;
|
listeningModule = module;
|
||||||
ChatUtil.info("presiona una tecla para asignarla al módulo " + Formatting.GREEN + module.getName());
|
ChatUtil.info(Component.translatable("sputnik.commands.bind.presskey", ChatFormatting.GREEN + module.getDisplayName()));
|
||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
})
|
})
|
||||||
.then(literal("reset").executes(ctx -> {
|
.then(literal("reset").executes(ctx -> {
|
||||||
Module module = ctx.getArgument("módulo", Module.class);
|
Module module = ctx.getArgument("módulo", Module.class);
|
||||||
module.getBind().reset();
|
module.getBind().reset();
|
||||||
ChatUtil.info("tecla para el módulo " + Formatting.GREEN + module.getName() + " restablecida a " + Formatting.AQUA + KeyUtil.getKeyName(module.getKey()));
|
ChatUtil.info(Component.translatable("sputnik.commands.bind.keyreset",
|
||||||
|
ChatFormatting.GREEN + module.getDisplayName(),
|
||||||
|
ChatFormatting.AQUA + KeyUtil.getKeyName(module.getKey())
|
||||||
|
));
|
||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
}))
|
}))
|
||||||
);
|
);
|
||||||
@@ -42,12 +52,31 @@ public class BindCommand extends Command {
|
|||||||
public static boolean onKeyPress(int key) {
|
public static boolean onKeyPress(int key) {
|
||||||
if (listeningModule == null) return false;
|
if (listeningModule == null) return false;
|
||||||
KeySetting bind = listeningModule.getBind();
|
KeySetting bind = listeningModule.getBind();
|
||||||
|
|
||||||
|
// solo hay que avisar de que la tecla está cogida cuando NO se permiten teclas repetidas.
|
||||||
|
// antes esto entraba con multipleKeybinds activado y luego comprobaba !allowMultiple con el
|
||||||
|
// mismo valor, así que nunca se llegaba a avisar
|
||||||
|
if (!ClientSettingsPanel.clientSettings.multipleKeybinds.getValue()) {
|
||||||
|
List<KeyMapping> keys = new ArrayList<>(List.of(mc.options.keyMappings));
|
||||||
|
keys.removeAll(List.of(mc.options.debugKeys));
|
||||||
|
|
||||||
|
for (KeyMapping kb : keys) {
|
||||||
|
if (kb.matches(new KeyEvent(key, 0, 0))) {
|
||||||
|
// la comilla iba dentro del I18n.get, así que buscaba una clave inexistente
|
||||||
|
ChatUtil.warn(Component.translatable("sputnik.commands.bind.keytaken",
|
||||||
|
ChatFormatting.GREEN + "\"" + I18n.get(kb.getName()) + "\""));
|
||||||
|
listeningModule = null;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (bind != null) bind.setValue(key);
|
if (bind != null) bind.setValue(key);
|
||||||
|
|
||||||
ChatUtil.info(
|
ChatUtil.info(Component.translatable("sputnik.commands.bind.keybound",
|
||||||
Text.of("la tecla " + Formatting.AQUA + KeyUtil.getKeyName(key) + Formatting.RESET +
|
ChatFormatting.AQUA + KeyUtil.getKeyName(key) + ChatFormatting.RESET,
|
||||||
" ha sido asignada al módulo " + Formatting.GREEN + listeningModule.getName())
|
ChatFormatting.GREEN + listeningModule.getDisplayName()
|
||||||
);
|
));
|
||||||
|
|
||||||
listeningModule = null;
|
listeningModule = null;
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -4,28 +4,29 @@ import com.mojang.brigadier.arguments.IntegerArgumentType;
|
|||||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||||
import me.retucio.sputnik.command.Command;
|
import me.retucio.sputnik.command.Command;
|
||||||
import me.retucio.sputnik.command.args.EnumArgumentType;
|
import me.retucio.sputnik.command.args.EnumArgumentType;
|
||||||
import net.minecraft.client.gui.screen.Screen;
|
import net.minecraft.client.gui.screens.Screen;
|
||||||
import net.minecraft.client.gui.screen.ingame.GenericContainerScreen;
|
import net.minecraft.client.gui.screens.inventory.ContainerScreen;
|
||||||
import net.minecraft.command.CommandSource;
|
import net.minecraft.commands.SharedSuggestionProvider;
|
||||||
import net.minecraft.screen.slot.SlotActionType;
|
import net.minecraft.world.inventory.ContainerInput;
|
||||||
|
|
||||||
// https://cdn.discordapp.com/attachments/1456079799045980400/1457154232737206375/dupersunited-public-addon-1.21.11-3.1.3.jar?ex=69735be1&is=69720a61&hm=77fb6faee49762e0a812661f0d98931e89cb725db711c45722249d0efe3b91e4&
|
// https://cdn.discordapp.com/attachments/1456079799045980400/1457154232737206375/dupersunited-public-addon-1.21.11-3.1.3.jar?ex=69735be1&is=69720a61&hm=77fb6faee49762e0a812661f0d98931e89cb725db711c45722249d0efe3b91e4&
|
||||||
public class ClickSlotCommand extends Command {
|
public class ClickSlotCommand extends Command {
|
||||||
|
|
||||||
public ClickSlotCommand() {
|
public ClickSlotCommand() {
|
||||||
super("clickslot", "simula un clic a un slot");
|
super("clickslot", "sputnik.commands.clickslot.desc", "cs");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void build(LiteralArgumentBuilder<CommandSource> builder) {
|
public void build(LiteralArgumentBuilder<SharedSuggestionProvider> builder) {
|
||||||
builder.then(argument("slot", IntegerArgumentType.integer())
|
builder.then(argument("slot", IntegerArgumentType.integer())
|
||||||
.then(argument("botón", IntegerArgumentType.integer())
|
.then(argument("botón", IntegerArgumentType.integer())
|
||||||
.then(argument("acción", EnumArgumentType.enumArgument(SlotActionType.SWAP))
|
.then(argument("acción", EnumArgumentType.enumArgument(ContainerInput.SWAP))
|
||||||
.executes(context -> {
|
.executes(context -> {
|
||||||
int slot = context.getArgument("slot", Integer.class), button = context.getArgument("botón", Integer.class);
|
int slot = context.getArgument("slot", Integer.class), button = context.getArgument("botón", Integer.class);
|
||||||
SlotActionType action = context.getArgument("acción", SlotActionType.class);
|
ContainerInput action = context.getArgument("acción", ContainerInput.class);
|
||||||
Screen screen = mc.currentScreen;
|
Screen screen = mc.gui.screen();
|
||||||
int syncId = (screen instanceof GenericContainerScreen gcScreen) ? gcScreen.getScreenHandler().syncId : 0;
|
int syncId = (screen instanceof ContainerScreen cScreen) ? cScreen.getMenu().containerId : 0;
|
||||||
mc.interactionManager.clickSlot(syncId, slot, button, action, mc.player);
|
if (mc.gameMode == null) return 0;
|
||||||
|
mc.gameMode.handleContainerInput(syncId, slot, button, action, mc.player);
|
||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -5,19 +5,19 @@ import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
|||||||
import com.mojang.brigadier.context.CommandContext;
|
import com.mojang.brigadier.context.CommandContext;
|
||||||
import me.retucio.sputnik.command.Command;
|
import me.retucio.sputnik.command.Command;
|
||||||
import me.retucio.sputnik.command.args.ModuleArgumentType;
|
import me.retucio.sputnik.command.args.ModuleArgumentType;
|
||||||
import me.retucio.sputnik.ui.screen.ClickGUI;
|
import me.retucio.sputnik.ui.screen.ClickGui;
|
||||||
import me.retucio.sputnik.ui.widgets.frames.SettingsFrame;
|
import me.retucio.sputnik.ui.widgets.panels.SettingsPanel;
|
||||||
import net.minecraft.command.CommandSource;
|
import net.minecraft.commands.SharedSuggestionProvider;
|
||||||
import me.retucio.sputnik.module.Module;
|
import me.retucio.sputnik.module.Module;
|
||||||
|
|
||||||
public class ConfigCommand extends Command {
|
public class ConfigCommand extends Command {
|
||||||
|
|
||||||
public ConfigCommand() {
|
public ConfigCommand() {
|
||||||
super("config", "abre el marco de ajustes de un módulo", "ajustes", "settings");
|
super("config", "sputnik.commands.config.desc", "ajustes", "settings");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void build(LiteralArgumentBuilder<CommandSource> builder) {
|
public void build(LiteralArgumentBuilder<SharedSuggestionProvider> builder) {
|
||||||
builder
|
builder
|
||||||
.then(argument("módulo", ModuleArgumentType.INSTANCE)
|
.then(argument("módulo", ModuleArgumentType.INSTANCE)
|
||||||
.executes(ctx -> {
|
.executes(ctx -> {
|
||||||
@@ -38,29 +38,29 @@ public class ConfigCommand extends Command {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void openSf(CommandContext<CommandSource> ctx) {
|
private void openSf(CommandContext<SharedSuggestionProvider> ctx) {
|
||||||
Module module = ctx.getArgument("módulo", Module.class);
|
Module module = ctx.getArgument("módulo", Module.class);
|
||||||
mc.setScreen(ClickGUI.INSTANCE);
|
mc.gui.setScreen(ClickGui.INSTANCE);
|
||||||
|
|
||||||
if (ClickGUI.INSTANCE.isSettingsFrameOpen(module)) return;
|
if (ClickGui.INSTANCE.isSettingsPanelOpen(module)) return;
|
||||||
|
|
||||||
SettingsFrame sf = ClickGUI.INSTANCE.getSfOfModule(module);
|
SettingsPanel sf = ClickGui.INSTANCE.getSettingsPanelOfModule(module);
|
||||||
int x = mc.getWindow().getScaledWidth() / 2 - sf.getW() / 2;
|
int x = mc.getWindow().getGuiScaledWidth() / 2 - sf.getW() / 2;
|
||||||
int y = 67;
|
int y = 67;
|
||||||
|
|
||||||
ClickGUI.INSTANCE.openSettingsFrame(module, x, y);
|
ClickGui.INSTANCE.openSettingsPanel(module, x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void openSfWithPos(CommandContext<CommandSource> ctx, int x, int y) {
|
private void openSfWithPos(CommandContext<SharedSuggestionProvider> ctx, int x, int y) {
|
||||||
Module module = ctx.getArgument("módulo", Module.class);
|
Module module = ctx.getArgument("módulo", Module.class);
|
||||||
mc.setScreen(ClickGUI.INSTANCE);
|
mc.gui.setScreen(ClickGui.INSTANCE);
|
||||||
|
|
||||||
if (ClickGUI.INSTANCE.isSettingsFrameOpen(module)) {
|
if (ClickGui.INSTANCE.isSettingsPanelOpen(module)) {
|
||||||
SettingsFrame sf = ClickGUI.INSTANCE.getSfOfModule(module);
|
SettingsPanel sf = ClickGui.INSTANCE.getSettingsPanelOfModule(module);
|
||||||
sf.setX(x);
|
sf.setX(x);
|
||||||
sf.setY(y);
|
sf.setY(y);
|
||||||
}
|
}
|
||||||
|
|
||||||
ClickGUI.INSTANCE.openSettingsFrame(module, x, y);
|
ClickGui.INSTANCE.openSettingsPanel(module, x, y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4,17 +4,17 @@ import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
|||||||
import me.retucio.sputnik.command.Command;
|
import me.retucio.sputnik.command.Command;
|
||||||
import me.retucio.sputnik.module.ModuleManager;
|
import me.retucio.sputnik.module.ModuleManager;
|
||||||
import me.retucio.sputnik.module.modules.misc.ScreenshotPlus;
|
import me.retucio.sputnik.module.modules.misc.ScreenshotPlus;
|
||||||
import net.minecraft.command.CommandSource;
|
import net.minecraft.commands.SharedSuggestionProvider;
|
||||||
|
|
||||||
// se usa principalmente para el módulo ScreenshotPlus, pero también se puede usar sin él supongo
|
// se usa principalmente para el módulo ScreenshotPlus, pero también se puede usar sin él supongo
|
||||||
public class CopyScreenshotCommand extends Command {
|
public class CopyScreenshotCommand extends Command {
|
||||||
|
|
||||||
public CopyScreenshotCommand() {
|
public CopyScreenshotCommand() {
|
||||||
super("copiarcaptura", "copia la captura más reciente al portapapeles");
|
super("copiarcaptura", "sputnik.commands.copyscreenshot.desc", "copyscreenshot");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void build(LiteralArgumentBuilder<CommandSource> builder) {
|
public void build(LiteralArgumentBuilder<SharedSuggestionProvider> builder) {
|
||||||
builder.executes(ctx -> {
|
builder.executes(ctx -> {
|
||||||
ScreenshotPlus screenshotPlus = ModuleManager.INSTANCE.getModuleByClass(ScreenshotPlus.class);
|
ScreenshotPlus screenshotPlus = ModuleManager.INSTANCE.getModuleByClass(ScreenshotPlus.class);
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,14 @@
|
|||||||
package me.retucio.sputnik.command.commands;
|
package me.retucio.sputnik.command.commands;
|
||||||
|
|
||||||
|
import com.github.retucio.neutrino.EventListener;
|
||||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||||
import me.retucio.sputnik.command.Command;
|
import me.retucio.sputnik.command.Command;
|
||||||
import me.retucio.sputnik.event.TickEvent;
|
import me.retucio.sputnik.event.TickEvent;
|
||||||
import me.retucio.sputnik.ui.screen.PreviewScreen;
|
import me.retucio.sputnik.ui.screen.PreviewScreen;
|
||||||
import me.retucio.sputnik.util.ChatUtil;
|
import me.retucio.sputnik.util.ChatUtil;
|
||||||
import me.retucio.sputnik.util.InventoryUtil;
|
import me.retucio.sputnik.util.InventoryUtil;
|
||||||
import net.minecraft.command.CommandSource;
|
import net.minecraft.commands.SharedSuggestionProvider;
|
||||||
|
import net.minecraft.network.chat.Component;
|
||||||
|
|
||||||
// accede a los contenidos de tu enderchest
|
// accede a los contenidos de tu enderchest
|
||||||
public class EnderChestCommand extends Command {
|
public class EnderChestCommand extends Command {
|
||||||
@@ -14,16 +16,16 @@ public class EnderChestCommand extends Command {
|
|||||||
private boolean shouldOpenEchest = false;
|
private boolean shouldOpenEchest = false;
|
||||||
|
|
||||||
public EnderChestCommand() {
|
public EnderChestCommand() {
|
||||||
super("echest", "muestra el contenido de tu enderchest (solo de ver)", "ec", "enderchest");
|
super("echest", "sputnik.commands.echest.desc", "ec", "enderchest");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void build(LiteralArgumentBuilder<CommandSource> builder) {
|
public void build(LiteralArgumentBuilder<SharedSuggestionProvider> builder) {
|
||||||
builder.executes(ctx -> {
|
builder.executes(ctx -> {
|
||||||
mc.execute(() -> {
|
mc.execute(() -> {
|
||||||
if (mc.player == null) return;
|
if (mc.player == null) return;
|
||||||
if (InventoryUtil.getEchestInv() == null) {
|
if (InventoryUtil.getEchestInv() == null) {
|
||||||
ChatUtil.warn("necesitas abrir un enderchest una vez primero");
|
ChatUtil.warn(Component.translatable( "sputnik.commands.echest.openfirst"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -34,11 +36,12 @@ public class EnderChestCommand extends Command {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@EventListener
|
||||||
public void onTick(TickEvent.Post event) {
|
public void onTick(TickEvent.Post event) {
|
||||||
if (shouldOpenEchest) {
|
if (shouldOpenEchest) {
|
||||||
shouldOpenEchest = false;
|
shouldOpenEchest = false;
|
||||||
if (InventoryUtil.getEchestInv() != null)
|
if (InventoryUtil.getEchestInv() != null)
|
||||||
mc.setScreen(new PreviewScreen(InventoryUtil.getEchestInv(), null));
|
mc.gui.setScreen(new PreviewScreen(InventoryUtil.getEchestInv(), null));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
package me.retucio.sputnik.command.commands;
|
||||||
|
|
||||||
|
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||||
|
import me.retucio.sputnik.command.Command;
|
||||||
|
import me.retucio.sputnik.command.args.PlayerArgumentType;
|
||||||
|
import me.retucio.sputnik.friend.Friend;
|
||||||
|
import me.retucio.sputnik.friend.FriendManager;
|
||||||
|
import me.retucio.sputnik.util.ChatUtil;
|
||||||
|
import net.minecraft.ChatFormatting;
|
||||||
|
import net.minecraft.commands.SharedSuggestionProvider;
|
||||||
|
import net.minecraft.network.chat.Component;
|
||||||
|
import net.minecraft.world.entity.player.Player;
|
||||||
|
|
||||||
|
|
||||||
|
public class FriendCommand extends Command {
|
||||||
|
|
||||||
|
public FriendCommand() {
|
||||||
|
super("friend", "sputnik.commands.friend.desc", "amigo", "f");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void build(LiteralArgumentBuilder<SharedSuggestionProvider> builder) {
|
||||||
|
builder
|
||||||
|
.then(literal("add")
|
||||||
|
.then(argument("amigo", PlayerArgumentType.INSTANCE)
|
||||||
|
.executes(ctx -> {
|
||||||
|
Player friend = ctx.getArgument("amigo", Player.class);
|
||||||
|
FriendManager.INSTANCE.add(friend.getUUID());
|
||||||
|
ChatUtil.info(Component.translatable(
|
||||||
|
"sputnik.commands.friend.added",
|
||||||
|
ChatFormatting.GREEN + friend.getName().getString() + ChatFormatting.RESET
|
||||||
|
));
|
||||||
|
return SUCCESS;
|
||||||
|
})
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.then(literal("remove")
|
||||||
|
.then(argument("amigo", PlayerArgumentType.INSTANCE)
|
||||||
|
.executes(ctx -> {
|
||||||
|
Player friend = ctx.getArgument("amigo", Player.class);
|
||||||
|
FriendManager.INSTANCE.remove(friend.getUUID());
|
||||||
|
ChatUtil.info(Component.translatable(
|
||||||
|
"sputnik.commands.friend.removed",
|
||||||
|
ChatFormatting.GREEN + friend.getName().getString() + ChatFormatting.RESET
|
||||||
|
));
|
||||||
|
return SUCCESS;
|
||||||
|
})
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.then(literal("list")
|
||||||
|
.executes(ctx -> {
|
||||||
|
ChatUtil.info(ChatFormatting.GOLD + Component.translatable("sputnik.commands.friend.list").getString());
|
||||||
|
for (Friend friend : FriendManager.INSTANCE.getFriends()) {
|
||||||
|
ChatUtil.info("- " + friend.getName());
|
||||||
|
}
|
||||||
|
return SUCCESS;
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,20 +3,20 @@ package me.retucio.sputnik.command.commands;
|
|||||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||||
import me.retucio.sputnik.command.Command;
|
import me.retucio.sputnik.command.Command;
|
||||||
import me.retucio.sputnik.util.ChatUtil;
|
import me.retucio.sputnik.util.ChatUtil;
|
||||||
import net.minecraft.command.CommandSource;
|
import net.minecraft.commands.SharedSuggestionProvider;
|
||||||
import net.minecraft.text.Text;
|
import net.minecraft.network.chat.Component;
|
||||||
|
|
||||||
public class GarbageCleanerCommand extends Command {
|
public class GarbageCleanerCommand extends Command {
|
||||||
|
|
||||||
public GarbageCleanerCommand() {
|
public GarbageCleanerCommand() {
|
||||||
super("gc", "limpia la ram mediante el recolector de basura (gc)", "garbagecollect");
|
super("gc", "sputnik.commands.gc.desc", "garbagecollect");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void build(LiteralArgumentBuilder<CommandSource> builder) {
|
public void build(LiteralArgumentBuilder<SharedSuggestionProvider> builder) {
|
||||||
builder.executes(context -> {
|
builder.executes(ctx -> {
|
||||||
System.gc();
|
System.gc();
|
||||||
ChatUtil.info(Text.of("basura recolectada"));
|
ChatUtil.info(Component.translatable("sputnik.commands.gc.collected"));
|
||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
package me.retucio.sputnik.command.commands;
|
||||||
|
|
||||||
|
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||||
|
import me.retucio.sputnik.command.Command;
|
||||||
|
import me.retucio.sputnik.command.CommandManager;
|
||||||
|
import me.retucio.sputnik.util.ChatUtil;
|
||||||
|
import net.minecraft.ChatFormatting;
|
||||||
|
import net.minecraft.commands.SharedSuggestionProvider;
|
||||||
|
import net.minecraft.network.chat.Component;
|
||||||
|
|
||||||
|
public class HelpCommand extends Command {
|
||||||
|
|
||||||
|
public HelpCommand() {
|
||||||
|
super("help", Component.translatable("sputnik.commands.help.desc").getString(), "?", "ayuda", "h");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void build(LiteralArgumentBuilder<SharedSuggestionProvider> builder) {
|
||||||
|
builder.executes(ctx -> {
|
||||||
|
for (Command command : CommandManager.commands) {
|
||||||
|
ChatUtil.info(CommandManager.INSTANCE.getPrefix()
|
||||||
|
+ ChatFormatting.BOLD + command.getName() + ": "
|
||||||
|
+ ChatFormatting.RESET + ChatFormatting.GRAY + command.getDescription().getString());
|
||||||
|
}
|
||||||
|
return SUCCESS;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,136 @@
|
|||||||
|
package me.retucio.sputnik.command.commands;
|
||||||
|
|
||||||
|
import com.mojang.brigadier.arguments.StringArgumentType;
|
||||||
|
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||||
|
import com.mojang.brigadier.suggestion.SuggestionProvider;
|
||||||
|
import me.retucio.sputnik.command.Command;
|
||||||
|
import me.retucio.sputnik.macro.Macro;
|
||||||
|
import me.retucio.sputnik.macro.MacroManager;
|
||||||
|
import me.retucio.sputnik.util.ChatUtil;
|
||||||
|
import me.retucio.sputnik.util.KeyUtil;
|
||||||
|
import net.minecraft.ChatFormatting;
|
||||||
|
import net.minecraft.commands.SharedSuggestionProvider;
|
||||||
|
import net.minecraft.network.chat.Component;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
|
||||||
|
public class MacroCommand extends Command {
|
||||||
|
|
||||||
|
private static final SuggestionProvider<SharedSuggestionProvider> MACROS = (ctx, builder) ->
|
||||||
|
SharedSuggestionProvider.suggest(
|
||||||
|
MacroManager.INSTANCE.getMacros().stream().map(Macro::getName), builder);
|
||||||
|
|
||||||
|
public MacroCommand() {
|
||||||
|
super("macro", "sputnik.commands.macro.desc", "macros");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void build(LiteralArgumentBuilder<SharedSuggestionProvider> builder) {
|
||||||
|
builder
|
||||||
|
.executes(ctx -> {
|
||||||
|
list();
|
||||||
|
return SUCCESS;
|
||||||
|
})
|
||||||
|
.then(literal("list").executes(ctx -> {
|
||||||
|
list();
|
||||||
|
return SUCCESS;
|
||||||
|
}))
|
||||||
|
// por ahora "add" solo crea macros de chat
|
||||||
|
.then(literal("add")
|
||||||
|
.then(argument("nombre", StringArgumentType.word()).executes(ctx -> {
|
||||||
|
String name = ctx.getArgument("nombre", String.class);
|
||||||
|
|
||||||
|
if (MacroManager.INSTANCE.add(new Macro.Chat(name)))
|
||||||
|
ChatUtil.info(Component.translatable("sputnik.commands.macro.added",
|
||||||
|
ChatFormatting.AQUA + name));
|
||||||
|
else
|
||||||
|
ChatUtil.error(Component.translatable("sputnik.commands.macro.exists", name));
|
||||||
|
return SUCCESS;
|
||||||
|
})))
|
||||||
|
.then(literal("remove")
|
||||||
|
.then(argument("nombre", StringArgumentType.word()).suggests(MACROS).executes(ctx -> {
|
||||||
|
Macro macro = get(ctx.getArgument("nombre", String.class));
|
||||||
|
if (macro == null) return SUCCESS;
|
||||||
|
|
||||||
|
MacroManager.INSTANCE.remove(macro);
|
||||||
|
ChatUtil.info(Component.translatable("sputnik.commands.macro.removed",
|
||||||
|
ChatFormatting.AQUA + macro.getName()));
|
||||||
|
return SUCCESS;
|
||||||
|
})))
|
||||||
|
.then(literal("line")
|
||||||
|
.then(argument("nombre", StringArgumentType.word()).suggests(MACROS)
|
||||||
|
.then(argument("línea", StringArgumentType.greedyString()).executes(ctx -> {
|
||||||
|
Macro.Chat macro = getChat(ctx.getArgument("nombre", String.class));
|
||||||
|
if (macro == null) return SUCCESS;
|
||||||
|
|
||||||
|
String line = ctx.getArgument("línea", String.class);
|
||||||
|
macro.getLines().add(line);
|
||||||
|
MacroManager.INSTANCE.save();
|
||||||
|
|
||||||
|
ChatUtil.info(Component.translatable("sputnik.commands.macro.lineadded",
|
||||||
|
ChatFormatting.AQUA + macro.getName()));
|
||||||
|
return SUCCESS;
|
||||||
|
}))))
|
||||||
|
.then(literal("clear")
|
||||||
|
.then(argument("nombre", StringArgumentType.word()).suggests(MACROS).executes(ctx -> {
|
||||||
|
Macro.Chat macro = getChat(ctx.getArgument("nombre", String.class));
|
||||||
|
if (macro == null) return SUCCESS;
|
||||||
|
|
||||||
|
macro.getLines().clear();
|
||||||
|
MacroManager.INSTANCE.save();
|
||||||
|
|
||||||
|
ChatUtil.info(Component.translatable("sputnik.commands.macro.cleared",
|
||||||
|
ChatFormatting.AQUA + macro.getName()));
|
||||||
|
return SUCCESS;
|
||||||
|
})))
|
||||||
|
.then(literal("run")
|
||||||
|
.then(argument("nombre", StringArgumentType.word()).suggests(MACROS).executes(ctx -> {
|
||||||
|
Macro macro = get(ctx.getArgument("nombre", String.class));
|
||||||
|
if (macro != null) macro.run();
|
||||||
|
return SUCCESS;
|
||||||
|
})));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Macro get(String name) {
|
||||||
|
Macro macro = MacroManager.INSTANCE.getByName(name);
|
||||||
|
if (macro == null) ChatUtil.error(Component.translatable("sputnik.commands.macro.notfound", name));
|
||||||
|
return macro;
|
||||||
|
}
|
||||||
|
|
||||||
|
// para los subcomandos que solo tienen sentido con líneas de chat (line, clear): si la
|
||||||
|
// macro existe pero es de otro tipo, avisa y devuelve null
|
||||||
|
private static Macro.Chat getChat(String name) {
|
||||||
|
Macro macro = get(name);
|
||||||
|
if (macro == null) return null;
|
||||||
|
|
||||||
|
if (!(macro instanceof Macro.Chat chat)) {
|
||||||
|
ChatUtil.error(Component.translatable("sputnik.commands.macro.notchat", macro.getName()));
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return chat;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void list() {
|
||||||
|
List<Macro> macros = MacroManager.INSTANCE.getMacros();
|
||||||
|
|
||||||
|
if (macros.isEmpty()) {
|
||||||
|
ChatUtil.info(Component.translatable("sputnik.commands.macro.none"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ChatUtil.info(Component.translatable("sputnik.commands.macro.list", macros.size()));
|
||||||
|
for (Macro macro : macros) {
|
||||||
|
// líneas en las de chat, teclas en las Keybind
|
||||||
|
int count = switch (macro) {
|
||||||
|
case Macro.Chat chat -> chat.getLines().size();
|
||||||
|
case Macro.Keybind keybind -> keybind.getKeys().size();
|
||||||
|
default -> 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
ChatUtil.addMessage(ChatFormatting.GRAY + " - " + macro.getName()
|
||||||
|
+ ChatFormatting.DARK_GRAY + " [" + KeyUtil.getKeyName(macro.getKey()) + "] "
|
||||||
|
+ count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,265 @@
|
|||||||
|
package me.retucio.sputnik.command.commands;
|
||||||
|
|
||||||
|
|
||||||
|
import com.github.retucio.neutrino.EventListener;
|
||||||
|
import me.retucio.sputnik.Sputnik;
|
||||||
|
import me.retucio.sputnik.command.Command;
|
||||||
|
import me.retucio.sputnik.event.TickEvent;
|
||||||
|
import me.retucio.sputnik.util.ChatUtil;
|
||||||
|
import me.retucio.sputnik.util.MiscUtil;
|
||||||
|
|
||||||
|
import net.fabricmc.loader.api.FabricLoader;
|
||||||
|
import net.minecraft.SharedConstants;
|
||||||
|
import net.minecraft.WorldVersion;
|
||||||
|
import net.minecraft.client.Screenshot;
|
||||||
|
import net.minecraft.commands.SharedSuggestionProvider;
|
||||||
|
import net.minecraft.network.chat.Component;
|
||||||
|
import net.minecraft.server.packs.PackType;
|
||||||
|
import net.minecraft.server.packs.metadata.pack.PackFormat;
|
||||||
|
import net.minecraft.sounds.SoundEvents;
|
||||||
|
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||||
|
import com.mojang.brigadier.arguments.StringArgumentType;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import org.jspecify.annotations.NonNull;
|
||||||
|
|
||||||
|
import javax.imageio.ImageIO;
|
||||||
|
import java.awt.image.BufferedImage;
|
||||||
|
import java.io.File;
|
||||||
|
import java.nio.file.FileVisitResult;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.SimpleFileVisitor;
|
||||||
|
import java.nio.file.attribute.BasicFileAttributes;
|
||||||
|
import java.util.concurrent.ThreadLocalRandom;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* literalmente robado de <a href="https://github.com/0xTas/stardust/blob/main/src/main/java/dev/stardust/commands/Panorama.java">aquí</a>
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class PanoramaCommand extends Command {
|
||||||
|
|
||||||
|
private int i = -1;
|
||||||
|
int timer = 10;
|
||||||
|
|
||||||
|
boolean ready = false;
|
||||||
|
boolean warming = false;
|
||||||
|
|
||||||
|
private float prevYaw;
|
||||||
|
private float prevPitch;
|
||||||
|
|
||||||
|
private int prevWidth;
|
||||||
|
private int prevHeight;
|
||||||
|
|
||||||
|
private boolean prevHudHidden;
|
||||||
|
|
||||||
|
@Nullable Path dir = null;
|
||||||
|
|
||||||
|
public PanoramaCommand() {
|
||||||
|
super("panorama", "sputnik.commands.panorama.desc");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void takeScreenshot() {
|
||||||
|
if (dir == null) return;
|
||||||
|
|
||||||
|
Screenshot.grab(
|
||||||
|
dir.toFile(),
|
||||||
|
"panorama_" + i + ".png",
|
||||||
|
mc.gameRenderer.mainRenderTarget(),
|
||||||
|
1, msg -> Sputnik.LOGGER.info(msg.getString())
|
||||||
|
);
|
||||||
|
|
||||||
|
i++;
|
||||||
|
warming = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void begin(String name) {
|
||||||
|
if (mc.player == null) return;
|
||||||
|
|
||||||
|
dir = FabricLoader.getInstance().getGameDir().resolve(Sputnik.MOD_ID + "/panoramas/" + name);
|
||||||
|
dir.toFile().mkdirs();
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
warming = false;
|
||||||
|
|
||||||
|
prevYaw = mc.player.getYRot();
|
||||||
|
prevPitch = mc.player.getXRot();
|
||||||
|
prevWidth = mc.getWindow().getWidth();
|
||||||
|
prevHeight = mc.getWindow().getHeight();
|
||||||
|
prevHudHidden = mc.gui.hud.isHidden();
|
||||||
|
|
||||||
|
mc.getWindow().setWidth(4096);
|
||||||
|
mc.getWindow().setHeight(4096);
|
||||||
|
mc.gameRenderer.mainRenderTarget().resize(4096, 4096);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void assembleResourcePack() {
|
||||||
|
if (dir == null) return;
|
||||||
|
|
||||||
|
Path resourcePacks = FabricLoader.getInstance().getGameDir().resolve("resourcepacks");
|
||||||
|
Path screenshotsFolder = FabricLoader.getInstance().getGameDir().resolve(Sputnik.MOD_ID + "/panoramas/" + dir.getFileName() + "/screenshots");
|
||||||
|
Path customBaseFolder = resourcePacks.resolve(dir.getFileName());
|
||||||
|
Path customPackFolder = customBaseFolder.resolve("assets/minecraft/textures/gui/title/background/");
|
||||||
|
customPackFolder.toFile().mkdirs();
|
||||||
|
|
||||||
|
String mcMeta =
|
||||||
|
"""
|
||||||
|
{
|
||||||
|
"pack":
|
||||||
|
{
|
||||||
|
"min_format": [65, 0],
|
||||||
|
"max_format": [%d, 0],
|
||||||
|
"description": "%s"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
""".formatted(
|
||||||
|
getPackVersion(),
|
||||||
|
Component.translatable("sputnik.commands.panorama.packdesc").getString()
|
||||||
|
);
|
||||||
|
|
||||||
|
try {
|
||||||
|
int luckyNumber = ThreadLocalRandom.current().nextInt(6);
|
||||||
|
Files.walkFileTree(screenshotsFolder, new SimpleFileVisitor<>() {
|
||||||
|
public @NonNull FileVisitResult visitFile(@NonNull Path file, @NonNull BasicFileAttributes attrs) {
|
||||||
|
MiscUtil.copy(file.toFile(), customPackFolder.resolve(file.getFileName()).toFile());
|
||||||
|
|
||||||
|
// pack.png random de alguna de los screenshots
|
||||||
|
if (file.getFileName().toString().contains(String.valueOf(luckyNumber))) {
|
||||||
|
MiscUtil.copy(file.toFile(), customBaseFolder.resolve("pack.png").toFile());
|
||||||
|
}
|
||||||
|
|
||||||
|
return FileVisitResult.CONTINUE;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
File packMeta = customBaseFolder.resolve("pack.mcmeta").toFile();
|
||||||
|
if (!packMeta.createNewFile()) {
|
||||||
|
ChatUtil.error(Component.translatable("sputnik.commands.panorama.errorassemble").getString());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Files.write(packMeta.toPath(), mcMeta.getBytes());
|
||||||
|
|
||||||
|
// eliminar el efecto vignette feo de cojones que usa Minecraft por defecto
|
||||||
|
BufferedImage transparentOverlay = new BufferedImage(16, 128, BufferedImage.TYPE_INT_ARGB);
|
||||||
|
File overlayImage = customPackFolder.resolve("panorama_overlay.png").toFile();
|
||||||
|
ImageIO.write(transparentOverlay, "PNG", overlayImage);
|
||||||
|
} catch (Exception e) {
|
||||||
|
ChatUtil.error("error de i/o");
|
||||||
|
Sputnik.LOGGER.error(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
ready = false;
|
||||||
|
if (mc.player != null) {
|
||||||
|
mc.player.playSound(SoundEvents.AMETHYST_BLOCK_CHIME, 1f, 1f);
|
||||||
|
ChatUtil.info(Component.translatable("sputnik.commands.panorama.ready").getString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventListener
|
||||||
|
private void onTick(TickEvent.Post event) {
|
||||||
|
if (mc.player == null || dir == null) return;
|
||||||
|
|
||||||
|
if (timer > 0) {
|
||||||
|
--timer;
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
timer = 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ready) {
|
||||||
|
assembleResourcePack();
|
||||||
|
}
|
||||||
|
if (i < 0) return;
|
||||||
|
|
||||||
|
switch (i) {
|
||||||
|
case 0 -> {
|
||||||
|
if (!warming) {
|
||||||
|
mc.gameRenderer.mainCamera().enablePanoramicMode();
|
||||||
|
mc.gameRenderer.setRenderBlockOutline(false);
|
||||||
|
mc.execute(() -> {
|
||||||
|
synchronized (mc.levelRenderer) {
|
||||||
|
mc.levelRenderer.notifyAll();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (!mc.gui.hud.isHidden()) mc.gui.hud.toggle();
|
||||||
|
mc.player.setYRot(prevYaw);
|
||||||
|
mc.player.setXRot(0f);
|
||||||
|
warming = true;
|
||||||
|
} else takeScreenshot();
|
||||||
|
}
|
||||||
|
case 1 -> {
|
||||||
|
if (!warming) {
|
||||||
|
mc.player.setYRot((prevYaw + 90f) % 360f);
|
||||||
|
mc.player.setXRot(0f);
|
||||||
|
warming = true;
|
||||||
|
} else takeScreenshot();
|
||||||
|
}
|
||||||
|
case 2 -> {
|
||||||
|
if (!warming) {
|
||||||
|
mc.player.setYRot((prevYaw + 180f) % 360f);
|
||||||
|
mc.player.setXRot(0f);
|
||||||
|
warming = true;
|
||||||
|
} else takeScreenshot();
|
||||||
|
}
|
||||||
|
case 3 -> {
|
||||||
|
if (!warming) {
|
||||||
|
mc.player.setYRot((prevYaw - 90f) % 360f);
|
||||||
|
mc.player.setXRot(0f);
|
||||||
|
warming = true;
|
||||||
|
} else takeScreenshot();
|
||||||
|
}
|
||||||
|
case 4 -> {
|
||||||
|
if (!warming) {
|
||||||
|
mc.player.setYRot(prevYaw);
|
||||||
|
mc.player.setXRot(-90f);
|
||||||
|
warming = true;
|
||||||
|
} else takeScreenshot();
|
||||||
|
}
|
||||||
|
default -> {
|
||||||
|
if (!warming) {
|
||||||
|
mc.player.setYRot(prevYaw);
|
||||||
|
mc.player.setXRot(90f);
|
||||||
|
warming = true;
|
||||||
|
} else {
|
||||||
|
takeScreenshot();
|
||||||
|
i = -1;
|
||||||
|
mc.player.setYRot(prevYaw);
|
||||||
|
mc.player.setXRot(prevPitch);
|
||||||
|
mc.gameRenderer.mainCamera().disablePanoramicMode();
|
||||||
|
mc.gameRenderer.setRenderBlockOutline(true);
|
||||||
|
mc.getWindow().setWidth(prevWidth);
|
||||||
|
mc.getWindow().setHeight(prevHeight);
|
||||||
|
if (mc.gui.hud.isHidden() != prevHudHidden) mc.gui.hud.toggle();
|
||||||
|
mc.gameRenderer.mainRenderTarget().resize(prevWidth, prevHeight);
|
||||||
|
mc.execute(() -> {
|
||||||
|
synchronized (mc.levelRenderer) {
|
||||||
|
mc.levelRenderer.notifyAll();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
timer = 100; // esperar a que las capturas se escriban
|
||||||
|
ready = true;
|
||||||
|
ChatUtil.info(Component.translatable("sputnik.commands.panorama.finalizing").getString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void build(LiteralArgumentBuilder<SharedSuggestionProvider> builder) {
|
||||||
|
builder.then(
|
||||||
|
argument("name", StringArgumentType.word()).executes(ctx -> {
|
||||||
|
String name = ctx.getArgument("name", String.class);
|
||||||
|
begin(name);
|
||||||
|
return SUCCESS;
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int getPackVersion() {
|
||||||
|
WorldVersion version = SharedConstants.getCurrentVersion();
|
||||||
|
PackFormat format = version.packVersion(PackType.CLIENT_RESOURCES);
|
||||||
|
return format.major();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,18 +4,20 @@ import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
|||||||
import me.retucio.sputnik.command.Command;
|
import me.retucio.sputnik.command.Command;
|
||||||
import me.retucio.sputnik.command.args.PlayerArgumentType;
|
import me.retucio.sputnik.command.args.PlayerArgumentType;
|
||||||
import me.retucio.sputnik.util.MiscUtil;
|
import me.retucio.sputnik.util.MiscUtil;
|
||||||
import net.minecraft.client.gui.screen.ingame.InventoryScreen;
|
import net.minecraft.client.gui.screens.inventory.InventoryScreen;
|
||||||
import net.minecraft.command.CommandSource;
|
import net.minecraft.commands.SharedSuggestionProvider;
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
|
|
||||||
// comando que debería de mostrar el inventario de un jugador, pero por cómo funcionan los servers, solo te deja ver el ítem que tenga en la mano
|
// comando que debería de mostrar el inventario de un jugador, pero por cómo funcionan los servers, solo te deja ver el ítem que tenga en la mano
|
||||||
public class PeekCommand extends Command {
|
public class PeekCommand extends Command {
|
||||||
|
|
||||||
public PeekCommand() {
|
public PeekCommand() {
|
||||||
super("inventario", "cotillea el inventario de otro jugador", "invsee", "peek", "inv");
|
super("inventario", "sputnik.commands.peek.desc", "invsee", "peek", "inv");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void build(LiteralArgumentBuilder<CommandSource> builder) {
|
public void build(LiteralArgumentBuilder<SharedSuggestionProvider> builder) {
|
||||||
builder
|
builder
|
||||||
.then(argument("jugador", PlayerArgumentType.INSTANCE)
|
.then(argument("jugador", PlayerArgumentType.INSTANCE)
|
||||||
.executes(ctx -> {
|
.executes(ctx -> {
|
||||||
|
|||||||
@@ -9,10 +9,11 @@ import me.retucio.sputnik.command.Command;
|
|||||||
import me.retucio.sputnik.event.network.PacketEvent;
|
import me.retucio.sputnik.event.network.PacketEvent;
|
||||||
import me.retucio.sputnik.util.ChatUtil;
|
import me.retucio.sputnik.util.ChatUtil;
|
||||||
|
|
||||||
import net.minecraft.client.network.ClientCommandSource;
|
import net.minecraft.client.multiplayer.ClientPacketListener;
|
||||||
import net.minecraft.client.network.ClientPlayNetworkHandler;
|
import net.minecraft.client.multiplayer.ClientSuggestionProvider;
|
||||||
import net.minecraft.command.CommandSource;
|
import net.minecraft.commands.SharedSuggestionProvider;
|
||||||
import net.minecraft.network.packet.s2c.play.CommandTreeS2CPacket;
|
import net.minecraft.network.chat.Component;
|
||||||
|
import net.minecraft.network.protocol.game.ClientboundCommandsPacket;
|
||||||
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
@@ -23,20 +24,20 @@ public class PluginsCommand extends Command {
|
|||||||
private boolean scanning = false;
|
private boolean scanning = false;
|
||||||
|
|
||||||
public PluginsCommand() {
|
public PluginsCommand() {
|
||||||
super("plugins", "busca los plugins que tenga el server", "pl", "serverplugins");
|
super("plugins", "sputnik.commands.plugins.desc", "pl", "serverplugins");
|
||||||
Sputnik.EVENT_BUS.subscribe(this);
|
Sputnik.EVENT_BUS.subscribe(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void build(LiteralArgumentBuilder<CommandSource> builder) {
|
public void build(LiteralArgumentBuilder<SharedSuggestionProvider> builder) {
|
||||||
builder.executes(context -> {
|
builder.executes(context -> {
|
||||||
if (mc.isIntegratedServerRunning()) {
|
if (mc.hasSingleplayerServer()) {
|
||||||
ChatUtil.error("estás en un solo jugador");
|
ChatUtil.error(Component.translatable("sputnik.commands.plugins.singleplayer"));
|
||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (scanning) {
|
if (scanning) {
|
||||||
ChatUtil.error("calmaaa");
|
ChatUtil.error(Component.translatable("sputnik.commands.plugins.calmdown"));
|
||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,16 +52,16 @@ public class PluginsCommand extends Command {
|
|||||||
|
|
||||||
private void findNamespaces() {
|
private void findNamespaces() {
|
||||||
try {
|
try {
|
||||||
ClientPlayNetworkHandler networkHandler = mc.getNetworkHandler();
|
ClientPacketListener networkHandler = mc.getConnection();
|
||||||
if (networkHandler == null || networkHandler.getCommandDispatcher() == null) {
|
if (networkHandler == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
RootCommandNode<ClientCommandSource> root = networkHandler.getCommandDispatcher().getRoot();
|
RootCommandNode<ClientSuggestionProvider> root = networkHandler.getCommands().getRoot();
|
||||||
root.getChildren().forEach(this::checkNodeForPlugins);
|
root.getChildren().forEach(this::checkNodeForPlugins);
|
||||||
|
|
||||||
if (!plugins.isEmpty()) {
|
if (!plugins.isEmpty()) {
|
||||||
ChatUtil.info(plugins.size() + " namespace(s) encontrado(s) de comandos:");
|
ChatUtil.info(Component.translatable("sputnik.commands.plugins.namespacesfound", plugins.size()));
|
||||||
plugins.stream()
|
plugins.stream()
|
||||||
.sorted()
|
.sorted()
|
||||||
.forEach(plugin -> ChatUtil.info(" - " + plugin));
|
.forEach(plugin -> ChatUtil.info(" - " + plugin));
|
||||||
@@ -69,11 +70,11 @@ public class PluginsCommand extends Command {
|
|||||||
displayResults();
|
displayResults();
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
ChatUtil.error("error analizando comandos: " + e.getMessage());
|
ChatUtil.error(Component.translatable("sputnik.commands.plugins.erroranalyzingcommands", e.getMessage()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkNodeForPlugins(CommandNode<ClientCommandSource> node) {
|
private void checkNodeForPlugins(CommandNode<ClientSuggestionProvider> node) {
|
||||||
String name = node.getName();
|
String name = node.getName();
|
||||||
|
|
||||||
if (name.contains(":")) {
|
if (name.contains(":")) {
|
||||||
@@ -92,18 +93,18 @@ public class PluginsCommand extends Command {
|
|||||||
private void onPacketReceive(PacketEvent.Receive event) {
|
private void onPacketReceive(PacketEvent.Receive event) {
|
||||||
if (!scanning) return;
|
if (!scanning) return;
|
||||||
|
|
||||||
if (event.getPacket() instanceof CommandTreeS2CPacket) {
|
if (event.getPacket() instanceof ClientboundCommandsPacket) {
|
||||||
findNamespaces();
|
findNamespaces();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void displayResults() {
|
private void displayResults() {
|
||||||
if (!plugins.isEmpty()) {
|
if (!plugins.isEmpty()) {
|
||||||
ChatUtil.info(plugins.size() + " plugin(s) encontrado(s)");
|
ChatUtil.info(Component.translatable("sputnik.commands.plugins.pluginsfound", plugins.size()));
|
||||||
plugins.stream().sorted()
|
plugins.stream().sorted()
|
||||||
.forEach(plugin -> ChatUtil.info(" - " + plugin));
|
.forEach(plugin -> ChatUtil.info(" - " + plugin));
|
||||||
} else {
|
} else {
|
||||||
ChatUtil.warn("sin plugins (probablemente)");
|
ChatUtil.warn(Component.translatable("sputnik.commands.plugins.noplugins"));
|
||||||
}
|
}
|
||||||
|
|
||||||
scanning = false;
|
scanning = false;
|
||||||
|
|||||||
@@ -3,27 +3,27 @@ package me.retucio.sputnik.command.commands;
|
|||||||
import com.mojang.brigadier.arguments.StringArgumentType;
|
import com.mojang.brigadier.arguments.StringArgumentType;
|
||||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||||
import me.retucio.sputnik.command.Command;
|
import me.retucio.sputnik.command.Command;
|
||||||
import me.retucio.sputnik.ui.widgets.frames.settings.ClientSettingsFrame;
|
import me.retucio.sputnik.ui.widgets.panels.settings.ClientSettingsPanel;
|
||||||
import me.retucio.sputnik.util.ChatUtil;
|
import me.retucio.sputnik.util.ChatUtil;
|
||||||
import net.minecraft.command.CommandSource;
|
import net.minecraft.ChatFormatting;
|
||||||
import net.minecraft.text.Text;
|
import net.minecraft.commands.SharedSuggestionProvider;
|
||||||
import net.minecraft.util.Formatting;
|
import net.minecraft.network.chat.Component;
|
||||||
|
|
||||||
// también se puede hacer desde los ajustes de la interfaz
|
// también se puede hacer desde los ajustes de la interfaz
|
||||||
public class PrefixCommand extends Command {
|
public class PrefixCommand extends Command {
|
||||||
|
|
||||||
public PrefixCommand() {
|
public PrefixCommand() {
|
||||||
super("prefijo", "cambia el prefijo de los comandos", "prefix");
|
super("prefijo", "sputnik.commands.prefix.desc", "prefix");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void build(LiteralArgumentBuilder<CommandSource> builder) {
|
public void build(LiteralArgumentBuilder<SharedSuggestionProvider> builder) {
|
||||||
builder
|
builder
|
||||||
.then(argument("prefijo", StringArgumentType.word()).executes(ctx -> {
|
.then(argument("prefijo", StringArgumentType.word()).executes(ctx -> {
|
||||||
String prefix = ctx.getArgument("prefijo", String.class);
|
String prefix = ctx.getArgument("prefijo", String.class);
|
||||||
ClientSettingsFrame.guiSettings.commandPrefix.setValue(prefix);
|
ClientSettingsPanel.clientSettings.commandPrefix.setValue(prefix);
|
||||||
ChatUtil.info(Text.literal("prefijo cambiado a " + Formatting.AQUA + prefix));
|
ChatUtil.info(Component.translatable("sputnik.commands.prefix.changed", ChatFormatting.AQUA + prefix));
|
||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,92 @@
|
|||||||
|
package me.retucio.sputnik.command.commands;
|
||||||
|
|
||||||
|
import com.mojang.brigadier.arguments.StringArgumentType;
|
||||||
|
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||||
|
import com.mojang.brigadier.suggestion.SuggestionProvider;
|
||||||
|
import me.retucio.sputnik.command.Command;
|
||||||
|
import me.retucio.sputnik.config.ConfigManager;
|
||||||
|
import me.retucio.sputnik.config.ProfileManager;
|
||||||
|
import me.retucio.sputnik.util.ChatUtil;
|
||||||
|
import net.minecraft.ChatFormatting;
|
||||||
|
import net.minecraft.commands.SharedSuggestionProvider;
|
||||||
|
import net.minecraft.network.chat.Component;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
|
||||||
|
public class ProfileCommand extends Command {
|
||||||
|
|
||||||
|
private static final SuggestionProvider<SharedSuggestionProvider> PROFILES = (ctx, builder) ->
|
||||||
|
SharedSuggestionProvider.suggest(ProfileManager.INSTANCE.getProfileNames(), builder);
|
||||||
|
|
||||||
|
public ProfileCommand() {
|
||||||
|
super("perfil", "sputnik.commands.profile.desc", "profile", "perfiles", "profiles");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void build(LiteralArgumentBuilder<SharedSuggestionProvider> builder) {
|
||||||
|
builder
|
||||||
|
.executes(ctx -> {
|
||||||
|
list();
|
||||||
|
return SUCCESS;
|
||||||
|
})
|
||||||
|
.then(literal("list").executes(ctx -> {
|
||||||
|
list();
|
||||||
|
return SUCCESS;
|
||||||
|
}))
|
||||||
|
.then(literal("save")
|
||||||
|
.then(argument("nombre", StringArgumentType.word()).executes(ctx -> {
|
||||||
|
String name = ctx.getArgument("nombre", String.class);
|
||||||
|
|
||||||
|
if (!ProfileManager.isValidName(name)) {
|
||||||
|
ChatUtil.error(Component.translatable("sputnik.commands.profile.invalidname", name));
|
||||||
|
return SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ProfileManager.INSTANCE.save(name)) {
|
||||||
|
ConfigManager.INSTANCE.save();
|
||||||
|
ChatUtil.info(Component.translatable("sputnik.commands.profile.saved",
|
||||||
|
ChatFormatting.AQUA + name));
|
||||||
|
} else {
|
||||||
|
ChatUtil.error(Component.translatable("sputnik.commands.profile.savefailed", name));
|
||||||
|
}
|
||||||
|
return SUCCESS;
|
||||||
|
})))
|
||||||
|
.then(literal("load")
|
||||||
|
.then(argument("nombre", StringArgumentType.word()).suggests(PROFILES).executes(ctx -> {
|
||||||
|
String name = ctx.getArgument("nombre", String.class);
|
||||||
|
|
||||||
|
if (ProfileManager.INSTANCE.load(name))
|
||||||
|
ChatUtil.info(Component.translatable("sputnik.commands.profile.loaded",
|
||||||
|
ChatFormatting.AQUA + name));
|
||||||
|
else
|
||||||
|
ChatUtil.error(Component.translatable("sputnik.commands.profile.notfound", name));
|
||||||
|
return SUCCESS;
|
||||||
|
})))
|
||||||
|
.then(literal("delete")
|
||||||
|
.then(argument("nombre", StringArgumentType.word()).suggests(PROFILES).executes(ctx -> {
|
||||||
|
String name = ctx.getArgument("nombre", String.class);
|
||||||
|
|
||||||
|
if (ProfileManager.INSTANCE.delete(name))
|
||||||
|
ChatUtil.info(Component.translatable("sputnik.commands.profile.deleted",
|
||||||
|
ChatFormatting.AQUA + name));
|
||||||
|
else
|
||||||
|
ChatUtil.error(Component.translatable("sputnik.commands.profile.notfound", name));
|
||||||
|
return SUCCESS;
|
||||||
|
})));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void list() {
|
||||||
|
List<String> profiles = ProfileManager.INSTANCE.getProfileNames();
|
||||||
|
|
||||||
|
if (profiles.isEmpty()) {
|
||||||
|
ChatUtil.info(Component.translatable("sputnik.commands.profile.none"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String current = ProfileManager.INSTANCE.getCurrent();
|
||||||
|
ChatUtil.info(Component.translatable("sputnik.commands.profile.list", profiles.size()));
|
||||||
|
for (String profile : profiles)
|
||||||
|
ChatUtil.addMessage((profile.equals(current) ? ChatFormatting.GREEN : ChatFormatting.GRAY) + " - " + profile);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,21 +3,21 @@ package me.retucio.sputnik.command.commands;
|
|||||||
import com.mojang.brigadier.arguments.IntegerArgumentType;
|
import com.mojang.brigadier.arguments.IntegerArgumentType;
|
||||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||||
import me.retucio.sputnik.command.Command;
|
import me.retucio.sputnik.command.Command;
|
||||||
import me.retucio.sputnik.util.interfaces.IChatHud;
|
import me.retucio.sputnik.mixinterfaces.IChatComponent;
|
||||||
import net.minecraft.client.gui.hud.ChatHud;
|
import net.minecraft.client.gui.components.ChatComponent;
|
||||||
import net.minecraft.client.gui.hud.ChatHudLine;
|
import net.minecraft.client.multiplayer.chat.GuiMessage;
|
||||||
import net.minecraft.command.CommandSource;
|
import net.minecraft.commands.SharedSuggestionProvider;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class PurgeCommand extends Command {
|
public class PurgeCommand extends Command {
|
||||||
|
|
||||||
public PurgeCommand() {
|
public PurgeCommand() {
|
||||||
super("purgar", "elimina mensajes del chat", "purge");
|
super("purgar", "sputnik.commands.purge.desc", "purge");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void build(LiteralArgumentBuilder<CommandSource> builder) {
|
public void build(LiteralArgumentBuilder<SharedSuggestionProvider> builder) {
|
||||||
builder.then(argument("cantidad", IntegerArgumentType.integer(1))
|
builder.then(argument("cantidad", IntegerArgumentType.integer(1))
|
||||||
.executes(context -> {
|
.executes(context -> {
|
||||||
int amount = IntegerArgumentType.getInteger(context, "cantidad");
|
int amount = IntegerArgumentType.getInteger(context, "cantidad");
|
||||||
@@ -28,10 +28,10 @@ public class PurgeCommand extends Command {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void purgeMessages(int amount) {
|
private void purgeMessages(int amount) {
|
||||||
ChatHud chatHud = mc.inGameHud.getChatHud();
|
ChatComponent chatHud = mc.gui.hud.getChat();
|
||||||
|
|
||||||
synchronized (chatHud) {
|
synchronized (chatHud) {
|
||||||
List<ChatHudLine.Visible> visibleMessages = ((IChatHud) chatHud).sputnik$getVisibleMessages();
|
List<GuiMessage.Line> visibleMessages = ((IChatComponent) chatHud).sputnik$getVisibleMessages();
|
||||||
int toRemove = Math.min(amount, visibleMessages.size());
|
int toRemove = Math.min(amount, visibleMessages.size());
|
||||||
for (int i = 0; i < toRemove; i++)
|
for (int i = 0; i < toRemove; i++)
|
||||||
visibleMessages.removeFirst();
|
visibleMessages.removeFirst();
|
||||||
|
|||||||
@@ -5,16 +5,16 @@ import com.mojang.brigadier.arguments.StringArgumentType;
|
|||||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||||
import me.retucio.sputnik.command.Command;
|
import me.retucio.sputnik.command.Command;
|
||||||
import me.retucio.sputnik.util.ChatUtil;
|
import me.retucio.sputnik.util.ChatUtil;
|
||||||
import net.minecraft.command.CommandSource;
|
import net.minecraft.commands.SharedSuggestionProvider;
|
||||||
|
|
||||||
public class RepeatCommand extends Command {
|
public class RepeatCommand extends Command {
|
||||||
|
|
||||||
public RepeatCommand() {
|
public RepeatCommand() {
|
||||||
super("repetir", "repite un comando x veces", "repeat");
|
super("repetir", "sputnik.commands.repeat.desc", "repeat");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void build(LiteralArgumentBuilder<CommandSource> builder) {
|
public void build(LiteralArgumentBuilder<SharedSuggestionProvider> builder) {
|
||||||
builder
|
builder
|
||||||
.then(argument("veces", IntegerArgumentType.integer(1))
|
.then(argument("veces", IntegerArgumentType.integer(1))
|
||||||
.then(argument("comando", StringArgumentType.greedyString())
|
.then(argument("comando", StringArgumentType.greedyString())
|
||||||
|
|||||||
@@ -0,0 +1,46 @@
|
|||||||
|
package me.retucio.sputnik.command.commands;
|
||||||
|
|
||||||
|
import com.mojang.brigadier.arguments.IntegerArgumentType;
|
||||||
|
import com.mojang.brigadier.arguments.StringArgumentType;
|
||||||
|
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||||
|
import me.retucio.sputnik.command.Command;
|
||||||
|
import me.retucio.sputnik.util.ChatUtil;
|
||||||
|
import net.minecraft.commands.SharedSuggestionProvider;
|
||||||
|
|
||||||
|
import java.util.concurrent.ScheduledThreadPoolExecutor;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
public class RepeatWaitCommand extends Command {
|
||||||
|
|
||||||
|
public RepeatWaitCommand() {
|
||||||
|
super("repesperar", "sputnik.commands.repeatwait.desc", "repeatwait");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void build(LiteralArgumentBuilder<SharedSuggestionProvider> builder) {
|
||||||
|
builder.then(argument("ms", IntegerArgumentType.integer(1))
|
||||||
|
.then(argument("veces", IntegerArgumentType.integer(1))
|
||||||
|
.then(argument("comando", StringArgumentType.greedyString())
|
||||||
|
.executes((context) -> {
|
||||||
|
int ms = context.getArgument("ms", Integer.class);
|
||||||
|
int times = context.getArgument("veces", Integer.class);
|
||||||
|
String cmd = context.getArgument("comando", String.class);
|
||||||
|
|
||||||
|
for (int i = 0; i < times; i++) {
|
||||||
|
int delay = i * ms;
|
||||||
|
int finalI = i;
|
||||||
|
new ScheduledThreadPoolExecutor(2).schedule(
|
||||||
|
() -> ChatUtil.info(
|
||||||
|
cmd.replaceAll("(?i)%index%",
|
||||||
|
String.valueOf(finalI))),
|
||||||
|
delay,
|
||||||
|
TimeUnit.MILLISECONDS
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return SUCCESS;
|
||||||
|
})
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,7 +5,8 @@ import me.retucio.sputnik.command.Command;
|
|||||||
import me.retucio.sputnik.module.ModuleManager;
|
import me.retucio.sputnik.module.ModuleManager;
|
||||||
import me.retucio.sputnik.module.modules.misc.ScreenshotPlus;
|
import me.retucio.sputnik.module.modules.misc.ScreenshotPlus;
|
||||||
import me.retucio.sputnik.util.ChatUtil;
|
import me.retucio.sputnik.util.ChatUtil;
|
||||||
import net.minecraft.command.CommandSource;
|
import net.minecraft.commands.SharedSuggestionProvider;
|
||||||
|
import net.minecraft.network.chat.Component;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
@@ -13,11 +14,11 @@ import java.io.IOException;
|
|||||||
public class SaveScreenshotCommand extends Command {
|
public class SaveScreenshotCommand extends Command {
|
||||||
|
|
||||||
public SaveScreenshotCommand() {
|
public SaveScreenshotCommand() {
|
||||||
super("guardarcaptura", "guarda localmente la captura más reciente");
|
super("guardarcaptura", "sputnik.commands.savescreenshot.desc", "savescreenshot");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void build(LiteralArgumentBuilder<CommandSource> builder) {
|
public void build(LiteralArgumentBuilder<SharedSuggestionProvider> builder) {
|
||||||
builder.executes(ctx -> {
|
builder.executes(ctx -> {
|
||||||
ScreenshotPlus screenshotPlus = ModuleManager.INSTANCE.getModuleByClass(ScreenshotPlus.class);
|
ScreenshotPlus screenshotPlus = ModuleManager.INSTANCE.getModuleByClass(ScreenshotPlus.class);
|
||||||
|
|
||||||
@@ -26,7 +27,7 @@ public class SaveScreenshotCommand extends Command {
|
|||||||
try {
|
try {
|
||||||
screenshotPlus.saveScreenshot();
|
screenshotPlus.saveScreenshot();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
ChatUtil.error("no se pudo guardar la captura");
|
ChatUtil.error(Component.translatable("sputnik.commands.savescreenshot.error"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -3,50 +3,54 @@ package me.retucio.sputnik.command.commands;
|
|||||||
import com.mojang.brigadier.arguments.StringArgumentType;
|
import com.mojang.brigadier.arguments.StringArgumentType;
|
||||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||||
import me.retucio.sputnik.command.Command;
|
import me.retucio.sputnik.command.Command;
|
||||||
import me.retucio.sputnik.mixin.accessors.ClientPlayNetworkHandlerAccessor;
|
import me.retucio.sputnik.mixin.accessors.ClientPacketListenerAccessor;
|
||||||
import net.minecraft.client.network.ClientPlayNetworkHandler;
|
import net.minecraft.client.multiplayer.ClientPacketListener;
|
||||||
import net.minecraft.command.CommandSource;
|
import net.minecraft.commands.SharedSuggestionProvider;
|
||||||
import net.minecraft.network.encryption.NetworkEncryptionUtils;
|
import net.minecraft.network.chat.LastSeenMessagesTracker;
|
||||||
import net.minecraft.network.message.LastSeenMessagesCollector;
|
import net.minecraft.network.chat.MessageSignature;
|
||||||
import net.minecraft.network.message.MessageBody;
|
import net.minecraft.network.chat.SignedMessageBody;
|
||||||
import net.minecraft.network.message.MessageSignatureData;
|
import net.minecraft.network.protocol.game.ServerboundChatPacket;
|
||||||
import net.minecraft.network.packet.c2s.play.ChatMessageC2SPacket;
|
import net.minecraft.util.Crypt;
|
||||||
|
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
|
|
||||||
// uso principal: protección de coordenadas de ChatPlus, que ni siquiera funciona
|
// uso principal: protección de coordenadas de ChatPlus
|
||||||
public class SendCommand extends Command {
|
public class SendCommand extends Command {
|
||||||
|
|
||||||
public SendCommand() {
|
public SendCommand() {
|
||||||
super("enviar", "manda un mensaje en el chat", "send");
|
super("enviar", "sputnik.commands.send.desc", "send");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void build(LiteralArgumentBuilder<CommandSource> builder) {
|
public void build(LiteralArgumentBuilder<SharedSuggestionProvider> builder) {
|
||||||
builder.then(argument("message", StringArgumentType.greedyString()).executes(context -> {
|
builder.then(argument("message", StringArgumentType.greedyString()).executes(context -> {
|
||||||
String message = context.getArgument("message", String.class);
|
String message = context.getArgument("message", String.class);
|
||||||
|
|
||||||
if (message != null && !message.isEmpty()) {
|
if (message != null && !message.isEmpty()) {
|
||||||
Instant instant = Instant.now();
|
Instant instant = Instant.now();
|
||||||
long salt = NetworkEncryptionUtils.SecureRandomUtil.nextLong();
|
long salt = Crypt.SaltSupplier.getLong();
|
||||||
ClientPlayNetworkHandler handler = mc.getNetworkHandler();
|
ClientPacketListener handler = mc.getConnection();
|
||||||
|
|
||||||
// obtener últimos mensajes vistos para la firma
|
// obtener últimos mensajes vistos para la firma
|
||||||
LastSeenMessagesCollector.LastSeenMessages lastSeenMessages =
|
ClientPacketListenerAccessor listener = ((ClientPacketListenerAccessor) handler);
|
||||||
((ClientPlayNetworkHandlerAccessor) handler).getLastSeenMessagesCollector().collect();
|
if (listener == null) return 0;
|
||||||
|
LastSeenMessagesTracker tracker = ((ClientPacketListenerAccessor) handler).getLastSeenMessagesTracker();
|
||||||
|
LastSeenMessagesTracker.Update lastSeenMessages = tracker.generateAndApplyUpdate();
|
||||||
|
|
||||||
// empacar firma para un chat seguro
|
// empacar firma
|
||||||
MessageSignatureData messageSignatureData =
|
MessageSignature messageSignature = ((ClientPacketListenerAccessor) handler)
|
||||||
((ClientPlayNetworkHandlerAccessor) handler).getMessagePacker().pack(
|
.getSignedMessageEncoder()
|
||||||
new MessageBody(message, instant, salt, lastSeenMessages.lastSeen())
|
.pack(new SignedMessageBody(
|
||||||
);
|
message, instant, salt, lastSeenMessages.lastSeen()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
// enviar paquete para enviar mensaje
|
// enviar paquete para enviar mensaje
|
||||||
handler.sendPacket(new ChatMessageC2SPacket(
|
handler.send(new ServerboundChatPacket(
|
||||||
message,
|
message,
|
||||||
instant,
|
instant,
|
||||||
salt,
|
salt,
|
||||||
messageSignatureData,
|
java.util.Optional.ofNullable(messageSignature),
|
||||||
lastSeenMessages.update()
|
lastSeenMessages.update()
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
@@ -54,4 +58,4 @@ public class SendCommand extends Command {
|
|||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,24 +1,27 @@
|
|||||||
package me.retucio.sputnik.command.commands;
|
package me.retucio.sputnik.command.commands;
|
||||||
|
|
||||||
|
import com.github.retucio.neutrino.EventListener;
|
||||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||||
import me.retucio.sputnik.command.Command;
|
import me.retucio.sputnik.command.Command;
|
||||||
import me.retucio.sputnik.command.args.EntityArgumentType;
|
import me.retucio.sputnik.command.args.EntityArgumentType;
|
||||||
import me.retucio.sputnik.event.input.KeyEvent;
|
import me.retucio.sputnik.event.input.KeyEvent;
|
||||||
import me.retucio.sputnik.util.EntityUtil;
|
import me.retucio.sputnik.util.EntityUtil;
|
||||||
import net.minecraft.command.CommandSource;
|
import net.minecraft.commands.SharedSuggestionProvider;
|
||||||
import net.minecraft.entity.Entity;
|
import net.minecraft.world.entity.Entity;
|
||||||
import org.lwjgl.glfw.GLFW;
|
import com.mojang.blaze3d.platform.InputConstants;
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
|
|
||||||
public class SpectateCommand extends Command {
|
public class SpectateCommand extends Command {
|
||||||
|
|
||||||
public SpectateCommand() {
|
public SpectateCommand() {
|
||||||
super("espectar", "te permite adquirir el punto de vista de una entidad", "spectate", "spec");
|
super("espectar", "sputnik.commands.spectate.desc", "spectate", "spec");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void build(LiteralArgumentBuilder<CommandSource> builder) {
|
public void build(LiteralArgumentBuilder<SharedSuggestionProvider> builder) {
|
||||||
builder
|
builder
|
||||||
.executes(ctx -> { // If no argument, use the entity player is looking at
|
.executes(ctx -> {
|
||||||
mc.execute(() -> {
|
mc.execute(() -> {
|
||||||
Entity target = EntityUtil.getEntityPlayerIsLookingAt();
|
Entity target = EntityUtil.getEntityPlayerIsLookingAt();
|
||||||
if (target != null)
|
if (target != null)
|
||||||
@@ -37,9 +40,10 @@ public class SpectateCommand extends Command {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@EventListener
|
||||||
public void onKey(KeyEvent event) {
|
public void onKey(KeyEvent event) {
|
||||||
if (mc.getCameraEntity() != mc.player && mc.currentScreen == 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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,17 +5,19 @@ import me.retucio.sputnik.command.Command;
|
|||||||
import me.retucio.sputnik.command.args.ModuleArgumentType;
|
import me.retucio.sputnik.command.args.ModuleArgumentType;
|
||||||
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 net.minecraft.command.CommandSource;
|
import net.minecraft.commands.SharedSuggestionProvider;
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
|
|
||||||
// porque usar el ratón es más lento que escribir, a menos que tengas toque con el teclado como yo
|
// porque usar el ratón es más lento que escribir, a menos que tengas toque con el teclado como yo
|
||||||
public class ToggleCommand extends Command {
|
public class ToggleCommand extends Command {
|
||||||
|
|
||||||
public ToggleCommand() {
|
public ToggleCommand() {
|
||||||
super("alternar", "enciende / apaga módulos", "toggle");
|
super("alternar", "sputnik.commands.toggle.desc", "toggle");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void build(LiteralArgumentBuilder<CommandSource> builder) {
|
public void build(LiteralArgumentBuilder<SharedSuggestionProvider> builder) {
|
||||||
builder
|
builder
|
||||||
.then(literal("todos")
|
.then(literal("todos")
|
||||||
.then(literal("on")
|
.then(literal("on")
|
||||||
|
|||||||
@@ -3,12 +3,9 @@ package me.retucio.sputnik.command.commands;
|
|||||||
import com.mojang.brigadier.arguments.IntegerArgumentType;
|
import com.mojang.brigadier.arguments.IntegerArgumentType;
|
||||||
import com.mojang.brigadier.arguments.StringArgumentType;
|
import com.mojang.brigadier.arguments.StringArgumentType;
|
||||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
|
||||||
import me.retucio.sputnik.command.Command;
|
import me.retucio.sputnik.command.Command;
|
||||||
import me.retucio.sputnik.command.CommandManager;
|
|
||||||
import me.retucio.sputnik.ui.widgets.frames.settings.ClientSettingsFrame;
|
|
||||||
import me.retucio.sputnik.util.ChatUtil;
|
import me.retucio.sputnik.util.ChatUtil;
|
||||||
import net.minecraft.command.CommandSource;
|
import net.minecraft.commands.SharedSuggestionProvider;
|
||||||
|
|
||||||
import java.util.concurrent.ScheduledExecutorService;
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
import java.util.concurrent.ScheduledThreadPoolExecutor;
|
import java.util.concurrent.ScheduledThreadPoolExecutor;
|
||||||
@@ -19,22 +16,22 @@ public class WaitCommand extends Command {
|
|||||||
private static final ScheduledExecutorService DELAYED_EXECUTOR = new ScheduledThreadPoolExecutor(2);
|
private static final ScheduledExecutorService DELAYED_EXECUTOR = new ScheduledThreadPoolExecutor(2);
|
||||||
|
|
||||||
public WaitCommand() {
|
public WaitCommand() {
|
||||||
super("wait", "espera un tiempo determinado antes de ejecutar otro comando", "esperar", "sleep", "delay");
|
super("wait", "sputnik.commands.wait.desc", "esperar", "sleep", "delay");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void build(LiteralArgumentBuilder<CommandSource> builder) {
|
public void build(LiteralArgumentBuilder<SharedSuggestionProvider> builder) {
|
||||||
builder
|
builder
|
||||||
.then(argument("delay", IntegerArgumentType.integer(0))
|
.then(argument("delay", IntegerArgumentType.integer(0))
|
||||||
.then(argument("comando", StringArgumentType.greedyString())
|
.then(argument("comando", StringArgumentType.greedyString())
|
||||||
.executes(ctx -> {
|
.executes(ctx -> {
|
||||||
int delay = ctx.getArgument("delay", Integer.class);
|
int delay = ctx.getArgument("delay", Integer.class);
|
||||||
String command = ctx.getArgument("comando", String.class);
|
String command = ctx.getArgument("comando", String.class);
|
||||||
|
|
||||||
DELAYED_EXECUTOR.schedule(() -> ChatUtil.simulateChatMessage(command), delay, TimeUnit.MILLISECONDS);
|
DELAYED_EXECUTOR.schedule(() -> ChatUtil.simulateChatMessage(command), delay, TimeUnit.MILLISECONDS);
|
||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,14 +1,22 @@
|
|||||||
package me.retucio.sputnik.config;
|
package me.retucio.sputnik.config;
|
||||||
|
|
||||||
|
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;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.StandardCopyOption;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
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 = 1;
|
private static final int VERSION = 6;
|
||||||
|
private static final int MIN_VERSION = 2;
|
||||||
|
|
||||||
private static final byte TYPE_NULL = 0;
|
private static final byte TYPE_NULL = 0;
|
||||||
private static final byte TYPE_BOOLEAN = 1;
|
private static final byte TYPE_BOOLEAN = 1;
|
||||||
@@ -19,79 +27,151 @@ 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;
|
||||||
|
|
||||||
public static void writeConfig(ClientConfig config, File file)
|
private static final byte MACRO_CHAT = 0;
|
||||||
throws IOException {
|
private static final byte MACRO_KEYBIND = 1;
|
||||||
try (DataOutputStream out = new DataOutputStream(
|
|
||||||
new BufferedOutputStream(new FileOutputStream(file)))) {
|
|
||||||
|
|
||||||
// cabezal
|
public static void writeConfig(ClientConfig config, File file) throws IOException {
|
||||||
out.writeInt(MAGIC_NUMBER);
|
byte[] bytes = toBytes(config);
|
||||||
out.writeInt(VERSION);
|
writeBytes(bytes, file);
|
||||||
|
}
|
||||||
|
|
||||||
// mapas
|
// serializar a bytes en memoria
|
||||||
writeStringBooleanMap(out, config.moduleStates);
|
public static byte[] toBytes(ClientConfig config) throws IOException {
|
||||||
writeSettingsMap(out, config.settings);
|
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||||
writeStringIntArrayMap(out, config.settingsFrames);
|
try (DataOutputStream out = new DataOutputStream(baos)) {
|
||||||
writeExtendableFrames(out, config.extendableFrames);
|
writeConfigTo(config, out);
|
||||||
writeStringIntArrayMap(out, config.hudPositions);
|
}
|
||||||
writeStringBooleanMap(out, config.hudVisibilities);
|
return baos.toByteArray();
|
||||||
writeStringStringMap(out, config.hudImagePaths);
|
}
|
||||||
|
|
||||||
// posición de la barra de búsqueda
|
// escribir bytes a disco (puede llamarse desde un hilo de fondo)
|
||||||
if (config.searchBarPosition != null) {
|
public static void writeBytes(byte[] bytes, File file) throws IOException {
|
||||||
out.writeBoolean(true);
|
// escribir a archivo temporal primero para evitar corrupción si el proceso muere a mitad
|
||||||
out.writeInt(config.searchBarPosition[0]);
|
File temp = new File(file.getParent(), file.getName() + ".tmp");
|
||||||
out.writeInt(config.searchBarPosition[1]);
|
try (FileOutputStream fos = new FileOutputStream(temp);
|
||||||
} else {
|
BufferedOutputStream out = new BufferedOutputStream(fos)) {
|
||||||
out.writeBoolean(false);
|
out.write(bytes);
|
||||||
}
|
out.flush();
|
||||||
|
fos.getFD().sync(); // forzar flush al disco antes de renombrar
|
||||||
|
}
|
||||||
|
|
||||||
|
// renombrar atómicamente
|
||||||
|
if (!temp.renameTo(file)) {
|
||||||
|
// renameTo puede fallar entre sistemas de archivos distintos
|
||||||
|
Files.move(temp.toPath(), file.toPath(), StandardCopyOption.REPLACE_EXISTING);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// lógica de serialización compartida
|
||||||
|
private static void writeConfigTo(ClientConfig config, DataOutputStream out) throws IOException {
|
||||||
|
// cabezal
|
||||||
|
out.writeInt(MAGIC_NUMBER);
|
||||||
|
out.writeInt(VERSION);
|
||||||
|
|
||||||
|
// el resto
|
||||||
|
writeStringBooleanMap(out, config.moduleStates);
|
||||||
|
writeSettingsMap(out, config.settings);
|
||||||
|
writeStringIntArrayMap(out, config.settingsPanels);
|
||||||
|
writeExtendableFrames(out, config.extendablePanels);
|
||||||
|
writeStringIntArrayMap(out, config.hudPositions);
|
||||||
|
writeStringBooleanMap(out, config.hudVisibilities);
|
||||||
|
writeStringStringMap(out, config.hudImagePaths);
|
||||||
|
writeFriendsMap(out, config.friends);
|
||||||
|
writeMacros(out, config.macros);
|
||||||
|
writeString(out, config.currentProfile);
|
||||||
|
|
||||||
|
if (config.searchBarPosition != null) {
|
||||||
|
out.writeBoolean(true);
|
||||||
|
out.writeInt(config.searchBarPosition[0]);
|
||||||
|
out.writeInt(config.searchBarPosition[1]);
|
||||||
|
} else {
|
||||||
|
out.writeBoolean(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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("archivo de config. vacío o inexistente");
|
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("archivo demasiado pequeño para ser válido");
|
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("formato de archivo inválido: " + magic);
|
throw new IOException(I18nUtil.fmt("sputnik.config.error.invalidformat",
|
||||||
|
"formato de archivo inválido: %s", magic));
|
||||||
}
|
}
|
||||||
|
|
||||||
int version = in.readInt();
|
int version = in.readInt();
|
||||||
if (version != VERSION) {
|
if (version < MIN_VERSION || version > VERSION) {
|
||||||
throw new IOException("versión inválida: " + version);
|
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
|
||||||
|
// de leer dejaba una config. huérfana escuchando si el archivo estaba corrupto
|
||||||
|
Map<String, Boolean> moduleStates = readStringBooleanMap(in);
|
||||||
|
Map<String, Object> settings = readSettingsMap(in);
|
||||||
|
Map<String, int[]> settingsPanels = readStringIntArrayMap(in);
|
||||||
|
Map<String, ClientConfig.PanelData> extendablePanels = readExtendablePanels(in);
|
||||||
|
Map<String, int[]> hudPositions = readStringIntArrayMap(in);
|
||||||
|
Map<String, Boolean> hudVisibilities = readStringBooleanMap(in);
|
||||||
|
Map<String, String> hudImagePaths = readStringStringMap(in);
|
||||||
|
Map<String, ClientConfig.FriendData> friends = version >= 4
|
||||||
|
? readFriendsMap(in)
|
||||||
|
: migrateFriendsMap(readStringStringMap(in));
|
||||||
|
|
||||||
// leer mapas
|
// v3 y v4: macros sin tipo (todas eran de chat). v5+: con tipo
|
||||||
config.moduleStates = readStringBooleanMap(in);
|
List<ClientConfig.MacroData> macros;
|
||||||
config.settings = readSettingsMap(in);
|
if (version >= 5) macros = readMacros(in);
|
||||||
config.settingsFrames = readStringIntArrayMap(in);
|
else if (version >= 3) macros = readLegacyMacros(in);
|
||||||
config.extendableFrames = readExtendableFrames(in);
|
else macros = new ArrayList<>();
|
||||||
config.hudPositions = readStringIntArrayMap(in);
|
|
||||||
config.hudVisibilities = readStringBooleanMap(in);
|
String currentProfile = version >= 3 ? readString(in) : "";
|
||||||
config.hudImagePaths = 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;
|
||||||
|
config.macros = macros;
|
||||||
|
config.currentProfile = currentProfile == null ? "" : currentProfile;
|
||||||
|
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) {
|
||||||
@@ -281,38 +361,37 @@ public class BinarySerializer {
|
|||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void writeExtendableFrames(DataOutputStream out, Map<String, ClientConfig.FrameData> map)
|
private static void writeExtendableFrames(DataOutputStream out, Map<String, ClientConfig.PanelData> map)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
if (map == null) {
|
if (map == null) {
|
||||||
out.writeInt(0);
|
out.writeInt(0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
out.writeInt(map.size());
|
out.writeInt(map.size());
|
||||||
for (Map.Entry<String, ClientConfig.FrameData> entry : map.entrySet()) {
|
for (Map.Entry<String, ClientConfig.PanelData> entry : map.entrySet()) {
|
||||||
writeString(out, entry.getKey());
|
writeString(out, entry.getKey());
|
||||||
ClientConfig.FrameData data = entry.getValue();
|
ClientConfig.PanelData data = entry.getValue();
|
||||||
out.writeInt(data.x());
|
out.writeInt(data.x());
|
||||||
out.writeInt(data.y());
|
out.writeInt(data.y());
|
||||||
out.writeBoolean(data.extended());
|
out.writeBoolean(data.extended());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Map<String, ClientConfig.FrameData> readExtendableFrames(DataInputStream in)
|
private static Map<String, ClientConfig.PanelData> readExtendablePanels(DataInputStream in) throws IOException {
|
||||||
throws IOException {
|
|
||||||
int size = in.readInt();
|
int size = in.readInt();
|
||||||
Map<String, ClientConfig.FrameData> map = new HashMap<>(size);
|
Map<String, ClientConfig.PanelData> map = new HashMap<>(size);
|
||||||
for (int i = 0; i < size; i++) {
|
for (int i = 0; i < size; i++) {
|
||||||
String key = readString(in);
|
String key = readString(in);
|
||||||
int x = in.readInt();
|
int x = in.readInt();
|
||||||
int y = in.readInt();
|
int y = in.readInt();
|
||||||
boolean extended = in.readBoolean();
|
boolean extended = in.readBoolean();
|
||||||
map.put(key, new ClientConfig.FrameData(x, y, extended));
|
map.put(key, new ClientConfig.PanelData(x, y, extended));
|
||||||
}
|
}
|
||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void writeStringStringMap(DataOutputStream out, Map<String, String> map)
|
private static void writeStringStringMap(DataOutputStream out, Map<String, String> map)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
if (map == null) {
|
if (map == null) {
|
||||||
out.writeInt(0);
|
out.writeInt(0);
|
||||||
return;
|
return;
|
||||||
@@ -325,7 +404,7 @@ public class BinarySerializer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static Map<String, String> readStringStringMap(DataInputStream in)
|
private static Map<String, String> readStringStringMap(DataInputStream in)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
int size = in.readInt();
|
int size = in.readInt();
|
||||||
Map<String, String> map = new HashMap<>(size);
|
Map<String, String> map = new HashMap<>(size);
|
||||||
for (int i = 0; i < size; i++) {
|
for (int i = 0; i < size; i++) {
|
||||||
@@ -336,7 +415,122 @@ public class BinarySerializer {
|
|||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Optimized string writing (UTF-8 with length prefix)
|
// 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)
|
||||||
|
throws IOException {
|
||||||
|
if (macros == null) {
|
||||||
|
out.writeInt(0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
out.writeInt(macros.size());
|
||||||
|
for (ClientConfig.MacroData macro : macros) {
|
||||||
|
boolean keybind = macro.type() == ClientConfig.MacroType.KEYBIND;
|
||||||
|
|
||||||
|
out.writeByte(keybind ? MACRO_KEYBIND : MACRO_CHAT);
|
||||||
|
writeString(out, macro.name());
|
||||||
|
out.writeInt(macro.key());
|
||||||
|
|
||||||
|
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 {
|
||||||
|
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();
|
||||||
|
List<ClientConfig.MacroData> macros = new ArrayList<>(size);
|
||||||
|
for (int i = 0; i < size; i++) {
|
||||||
|
String name = readString(in);
|
||||||
|
int key = in.readInt();
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
return macros;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void writeFriendsMap(DataOutputStream out, Map<String, ClientConfig.FriendData> map)
|
||||||
|
throws IOException {
|
||||||
|
if (map == null) {
|
||||||
|
out.writeInt(0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
out.writeInt(map.size());
|
||||||
|
for (Map.Entry<String, ClientConfig.FriendData> entry : map.entrySet()) {
|
||||||
|
writeString(out, entry.getKey());
|
||||||
|
ClientConfig.FriendData data = entry.getValue();
|
||||||
|
writeString(out, data.name());
|
||||||
|
writeString(out, data.nick());
|
||||||
|
out.writeLong(data.befriendedAt());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Map<String, ClientConfig.FriendData> readFriendsMap(DataInputStream in)
|
||||||
|
throws IOException {
|
||||||
|
int size = in.readInt();
|
||||||
|
Map<String, ClientConfig.FriendData> map = new HashMap<>(size);
|
||||||
|
for (int i = 0; i < size; i++) {
|
||||||
|
String uuid = readString(in);
|
||||||
|
String name = readString(in);
|
||||||
|
String nick = readString(in);
|
||||||
|
long befriendedAt = in.readLong();
|
||||||
|
map.put(uuid, new ClientConfig.FriendData(name, nick, befriendedAt));
|
||||||
|
}
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Map<String, ClientConfig.FriendData> migrateFriendsMap(Map<String, String> legacy) {
|
||||||
|
Map<String, ClientConfig.FriendData> map = new HashMap<>(legacy.size());
|
||||||
|
long now = System.currentTimeMillis();
|
||||||
|
for (Map.Entry<String, String> entry : legacy.entrySet()) {
|
||||||
|
map.put(entry.getKey(), new ClientConfig.FriendData(entry.getValue(), entry.getValue(), now));
|
||||||
|
}
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
private static void writeString(DataOutputStream out, String str) throws IOException {
|
private static void writeString(DataOutputStream out, String str) throws IOException {
|
||||||
if (str == null) {
|
if (str == null) {
|
||||||
out.writeInt(-1);
|
out.writeInt(-1);
|
||||||
@@ -352,6 +546,6 @@ public class BinarySerializer {
|
|||||||
if (length == -1) return null;
|
if (length == -1) return null;
|
||||||
byte[] bytes = new byte[length];
|
byte[] bytes = new byte[length];
|
||||||
in.readFully(bytes);
|
in.readFully(bytes);
|
||||||
return new String(bytes, "UTF-8");
|
return new String(bytes, StandardCharsets.UTF_8);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,18 +1,21 @@
|
|||||||
package me.retucio.sputnik.config;
|
package me.retucio.sputnik.config;
|
||||||
|
|
||||||
|
import com.github.retucio.neutrino.EventListener;
|
||||||
import me.retucio.sputnik.event.sputnik.*;
|
import me.retucio.sputnik.event.sputnik.*;
|
||||||
import me.retucio.sputnik.module.setting.settings.*;
|
import me.retucio.sputnik.module.setting.settings.*;
|
||||||
import me.retucio.sputnik.ui.screen.ClickGUI;
|
import me.retucio.sputnik.ui.screen.ClickGui;
|
||||||
|
|
||||||
import java.io.Serial;
|
import java.io.Serial;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import static me.retucio.sputnik.Sputnik.EVENT_BUS;
|
import static me.retucio.sputnik.Sputnik.EVENT_BUS;
|
||||||
import static me.retucio.sputnik.Sputnik.mc;
|
import static me.retucio.sputnik.Sputnik.mc;
|
||||||
|
|
||||||
// clase donde se guardan las configuraciones temporalmente hasta escribirlas en camera_tweaks.json
|
// clase donde se guardan las configuraciones temporalmente hasta escribirlas en sputnik.dat
|
||||||
public class ClientConfig {
|
public class ClientConfig {
|
||||||
|
|
||||||
// nombre del módulo -> estado del módulo
|
// nombre del módulo -> estado del módulo
|
||||||
@@ -22,10 +25,10 @@ public class ClientConfig {
|
|||||||
public Map<String, Object> settings = new HashMap<>();
|
public Map<String, Object> settings = new HashMap<>();
|
||||||
|
|
||||||
// nombre del módulo -> posición (x, y)
|
// nombre del módulo -> posición (x, y)
|
||||||
public Map<String, int[]> settingsFrames = new HashMap<>();
|
public Map<String, int[]> settingsPanels = new HashMap<>();
|
||||||
|
|
||||||
// nombre del frame -> FrameData (que contiene extended, x & y)
|
// nombre del frame -> FrameData (que contiene extended, x & y)
|
||||||
public Map<String, FrameData> extendableFrames = new HashMap<>();
|
public Map<String, PanelData> extendablePanels = new HashMap<>();
|
||||||
|
|
||||||
// id del elemento del hud -> posición (x, y)
|
// id del elemento del hud -> posición (x, y)
|
||||||
public Map<String, int[]> hudPositions = new HashMap<>();
|
public Map<String, int[]> hudPositions = new HashMap<>();
|
||||||
@@ -33,23 +36,44 @@ public class ClientConfig {
|
|||||||
// id del elemento del hud -> true: visible / false: no visible
|
// id del elemento del hud -> true: visible / false: no visible
|
||||||
public Map<String, Boolean> hudVisibilities = new HashMap<>();
|
public Map<String, Boolean> hudVisibilities = new HashMap<>();
|
||||||
|
|
||||||
// id del elemento del hud -> ruta de la imagen (NEW)
|
// id del elemento del hud -> ruta de la imagen
|
||||||
public Map<String, String> hudImagePaths = new HashMap<>();
|
public Map<String, String> hudImagePaths = new HashMap<>();
|
||||||
|
|
||||||
// posición de la barra de búsqueda (x, y)
|
// posición de la barra de búsqueda (x, y)
|
||||||
public int[] searchBarPosition = new int[] { 340, 16 };
|
public int[] searchBarPosition = new int[] { 340, 16 };
|
||||||
|
|
||||||
|
// amigos: uuid -> FriendData (nombre, apodo, fecha)
|
||||||
|
public Map<String, FriendData> friends = new HashMap<>();
|
||||||
|
|
||||||
|
// macros, de cualquier tipo (ver MacroData)
|
||||||
|
public List<MacroData> macros = new ArrayList<>();
|
||||||
|
|
||||||
|
// perfil cargado actualmente, vacío si es la config. suelta
|
||||||
|
public String currentProfile = "";
|
||||||
|
|
||||||
|
// Set only when loading a config written with GLFW keycodes (pre-26.3).
|
||||||
|
public transient boolean legacyKeyCodes;
|
||||||
|
|
||||||
public ClientConfig() {
|
public ClientConfig() {
|
||||||
EVENT_BUS.subscribe(this);
|
EVENT_BUS.subscribe(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// mientras se aplica una config. los cambios vienen de ella, así que reescribirla es
|
||||||
|
// como poco redundante, y al cambiar de perfil pisaba lo que aún no se había aplicado
|
||||||
|
private static boolean isApplying() {
|
||||||
|
return ConfigManager.INSTANCE != null && ConfigManager.INSTANCE.isApplying();
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventListener
|
||||||
public void onToggleModule(ToggleModuleEvent event) {
|
public void onToggleModule(ToggleModuleEvent event) {
|
||||||
ConfigManager.setModuleState(event.getModule());
|
if (isApplying()) return;
|
||||||
|
ConfigManager.INSTANCE.setModuleState(event.getModule());
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("rawtypes")
|
@SuppressWarnings("rawtypes")
|
||||||
|
@EventListener
|
||||||
public void onUpdateSetting(UpdateSettingEvent event) {
|
public void onUpdateSetting(UpdateSettingEvent event) {
|
||||||
if (mc == null || !event.shouldSave()) return;
|
if (mc == null || !event.shouldSave() || isApplying()) return;
|
||||||
|
|
||||||
// guardar ajustes con su respectivo tipo de valor, en formato "nombreMódulo:nombreAjuste"
|
// guardar ajustes con su respectivo tipo de valor, en formato "nombreMódulo:nombreAjuste"
|
||||||
Object value = null;
|
Object value = null;
|
||||||
@@ -61,56 +85,125 @@ 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;
|
||||||
|
case FileSetting f: value = f.getValue(); break;
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
|
|
||||||
ConfigManager.setSetting(event.getSetting(), value);
|
ConfigManager.INSTANCE.setSetting(event.getSetting(), value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onOpenSettingsFrame(SettingsFrameEvent.Open event) {
|
@EventListener
|
||||||
ConfigManager.setFramePosition(event.getFrame());
|
public void onOpenSettingsPanel(SettingsPanelEvent.Open event) {
|
||||||
|
ConfigManager.INSTANCE.setPanelPosition(event.getPanel());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onCloseSettingsFrame(SettingsFrameEvent.Close event) {
|
@EventListener
|
||||||
settingsFrames.remove(event.getFrame().getModule().getName());
|
public void onCloseSettingsPanel(SettingsPanelEvent.Close event) {
|
||||||
ConfigManager.save();
|
settingsPanels.remove(event.getPanel().getModule().getName());
|
||||||
|
ConfigManager.INSTANCE.markDirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onMoveSettingsFrame(SettingsFrameEvent.Move event) {
|
@EventListener
|
||||||
settingsFrames.replace(event.getFrame().getModule().getName(), new int[]{event.getFrame().getX(), event.getFrame().getY()});
|
public void onMoveSettingsPanel(SettingsPanelEvent.Move event) {
|
||||||
ConfigManager.save();
|
settingsPanels.replace(event.getPanel().getModule().getName(), new int[]{event.getPanel().getX(), event.getPanel().getY()});
|
||||||
|
ConfigManager.INSTANCE.markDirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onExtendModuleFrame(ModuleFrameEvent.Extend event) {
|
@EventListener
|
||||||
extendableFrames.put("M", new FrameData(
|
public void onExtendModulePanel(ModulePanelEvent.Extend event) {
|
||||||
ClickGUI.INSTANCE.getModulesFrame().getX(),
|
extendablePanels.put(event.getPanel().category.toString(), new PanelData(
|
||||||
ClickGUI.INSTANCE.getModulesFrame().getY(),
|
event.getPanel().getX(),
|
||||||
ClickGUI.INSTANCE.getModulesFrame().extended));
|
event.getPanel().getY(),
|
||||||
|
event.getPanel().isExtended()));
|
||||||
|
ConfigManager.INSTANCE.markDirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onMoveModuleFrame(ModuleFrameEvent.Move event) {
|
// put y no replace: replace no hace nada si la clave no está todavía, así que mover un
|
||||||
extendableFrames.replace("M", new FrameData(
|
// marco sin haberlo plegado antes (que es lo que crea la entrada) no se guardaba
|
||||||
ClickGUI.INSTANCE.getModulesFrame().getX(),
|
@EventListener
|
||||||
ClickGUI.INSTANCE.getModulesFrame().getY(),
|
public void onMoveModulePanel(ModulePanelEvent.Move event) {
|
||||||
ClickGUI.INSTANCE.getModulesFrame().extended));
|
extendablePanels.put(event.getPanel().category.toString(), new PanelData(
|
||||||
|
event.getPanel().getX(),
|
||||||
|
event.getPanel().getY(),
|
||||||
|
event.getPanel().isExtended()));
|
||||||
|
ConfigManager.INSTANCE.markDirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onExtendGUISettingsFrame(GUISettingsFrameEvent.Extend event) {
|
@EventListener
|
||||||
extendableFrames.put("S", new FrameData(
|
public void onExtendClientSettingsPanel(ClientSettingsPanelEvent.Extend event) {
|
||||||
ClickGUI.INSTANCE.getGuiSettingsFrame().getX(),
|
extendablePanels.put("ajustes", new PanelData(
|
||||||
ClickGUI.INSTANCE.getGuiSettingsFrame().getY(),
|
ClickGui.INSTANCE.getClientSettingsPanel().getX(),
|
||||||
ClickGUI.INSTANCE.getGuiSettingsFrame().extended));
|
ClickGui.INSTANCE.getClientSettingsPanel().getY(),
|
||||||
|
ClickGui.INSTANCE.getClientSettingsPanel().isExtended()));
|
||||||
|
ConfigManager.INSTANCE.markDirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onMoveGUISettingsFrame(GUISettingsFrameEvent.Move event) {
|
@EventListener
|
||||||
extendableFrames.replace("S", new FrameData(
|
public void onMoveClientSettingsPanel(ClientSettingsPanelEvent.Move event) {
|
||||||
ClickGUI.INSTANCE.getGuiSettingsFrame().getX(),
|
extendablePanels.put("ajustes", new PanelData(
|
||||||
ClickGUI.INSTANCE.getGuiSettingsFrame().getY(),
|
ClickGui.INSTANCE.getClientSettingsPanel().getX(),
|
||||||
ClickGUI.INSTANCE.getGuiSettingsFrame().extended));
|
ClickGui.INSTANCE.getClientSettingsPanel().getY(),
|
||||||
|
ClickGui.INSTANCE.getClientSettingsPanel().isExtended()));
|
||||||
|
ConfigManager.INSTANCE.markDirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
public record FrameData(int x, int y, boolean extended) implements Serializable {
|
@EventListener
|
||||||
|
public void onAddFriend(FriendEvent.Add event) {
|
||||||
|
if (isApplying()) return;
|
||||||
|
String uuid = event.getFriend().getUuid().toString();
|
||||||
|
if (!friends.containsKey(uuid)) {
|
||||||
|
friends.put(uuid, new FriendData(
|
||||||
|
event.getFriend().getName(),
|
||||||
|
event.getFriend().getNick(),
|
||||||
|
event.getFriend().getBefriendedAt()));
|
||||||
|
}
|
||||||
|
ConfigManager.INSTANCE.markDirty();
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventListener
|
||||||
|
public void onRemoveFriend(FriendEvent.Remove event) {
|
||||||
|
if (isApplying()) return;
|
||||||
|
friends.remove(event.getFriend().getUuid().toString());
|
||||||
|
ConfigManager.INSTANCE.markDirty();
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventListener
|
||||||
|
public void onRenameFriend(FriendEvent.Rename event) {
|
||||||
|
if (isApplying()) return;
|
||||||
|
String uuid = event.getFriend().getUuid().toString();
|
||||||
|
FriendData existing = friends.get(uuid);
|
||||||
|
if (existing == null) return; // no debería pasar, pero porsiaca
|
||||||
|
|
||||||
|
friends.put(uuid, new FriendData(existing.name(), event.getFriend().getNick(), existing.befriendedAt()));
|
||||||
|
ConfigManager.INSTANCE.markDirty();
|
||||||
|
}
|
||||||
|
|
||||||
|
public record PanelData(int x, int y, boolean extended) implements Serializable {
|
||||||
@Serial private static final long serialVersionUID = 1L;
|
@Serial private static final long serialVersionUID = 1L;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public record FriendData(String name, String nick, long befriendedAt) implements Serializable {
|
||||||
|
@Serial private static final long serialVersionUID = 1L;
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum MacroType { CHAT, KEYBIND }
|
||||||
|
|
||||||
|
public record KeyData(int key, int action) implements Serializable {
|
||||||
|
@Serial private static final long serialVersionUID = 1L;
|
||||||
|
}
|
||||||
|
|
||||||
|
public record MacroData(MacroType type, String name, int key,
|
||||||
|
List<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));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -3,21 +3,39 @@ package me.retucio.sputnik.config;
|
|||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
import com.google.gson.GsonBuilder;
|
import com.google.gson.GsonBuilder;
|
||||||
import me.retucio.sputnik.Sputnik;
|
import me.retucio.sputnik.Sputnik;
|
||||||
|
import me.retucio.sputnik.friend.Friend;
|
||||||
|
import me.retucio.sputnik.friend.FriendManager;
|
||||||
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.modules.client.ClientSettingsModule;
|
||||||
|
import me.retucio.sputnik.macro.Macro;
|
||||||
|
import me.retucio.sputnik.macro.MacroManager;
|
||||||
import me.retucio.sputnik.module.setting.*;
|
import me.retucio.sputnik.module.setting.*;
|
||||||
import me.retucio.sputnik.module.setting.settings.*;
|
import me.retucio.sputnik.module.setting.settings.*;
|
||||||
import me.retucio.sputnik.ui.widgets.Frame;
|
import me.retucio.sputnik.ui.hud.HudElement;
|
||||||
import me.retucio.sputnik.ui.widgets.frames.ModuleFrame;
|
import me.retucio.sputnik.ui.hud.HudRenderer;
|
||||||
import me.retucio.sputnik.ui.screen.ClickGUI;
|
import me.retucio.sputnik.ui.widgets.Panel;
|
||||||
import me.retucio.sputnik.ui.widgets.frames.settings.ClientSettingsFrame;
|
import me.retucio.sputnik.ui.widgets.panels.ExtendablePanel;
|
||||||
import me.retucio.sputnik.ui.widgets.frames.SettingsFrame;
|
import me.retucio.sputnik.ui.widgets.panels.ModulePanel;
|
||||||
|
import me.retucio.sputnik.ui.screen.ClickGui;
|
||||||
|
import me.retucio.sputnik.ui.widgets.panels.settings.ClientSettingsPanel;
|
||||||
|
import me.retucio.sputnik.ui.widgets.panels.SettingsPanel;
|
||||||
|
import me.retucio.sputnik.util.I18nUtil;
|
||||||
|
import me.retucio.sputnik.util.KeyUtil;
|
||||||
|
import net.minecraft.network.chat.Component;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileReader;
|
import java.io.FileReader;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
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
|
||||||
@@ -26,74 +44,233 @@ public class ConfigManager {
|
|||||||
private static final File CONFIG_FILE = new File("sputnik.dat");
|
private static final File CONFIG_FILE = new File("sputnik.dat");
|
||||||
private static final File LEGACY_JSON_FILE = new File("sputnik.json");
|
private static final File LEGACY_JSON_FILE = new File("sputnik.json");
|
||||||
|
|
||||||
private static boolean loaded = false;
|
public static ConfigManager INSTANCE;
|
||||||
private static ClientConfig config = null;
|
|
||||||
|
private boolean loaded = false;
|
||||||
|
private boolean applying = false;
|
||||||
|
private boolean dirty = false;
|
||||||
|
private long lastSaveTime = System.currentTimeMillis();
|
||||||
|
private ClientConfig config = null;
|
||||||
|
|
||||||
|
private final ExecutorService saveExecutor = Executors.newSingleThreadExecutor(r -> {
|
||||||
|
Thread t = new Thread(r, "sputnik-config-save");
|
||||||
|
t.setDaemon(true); // no bloquear el cierre de la JVM
|
||||||
|
return t;
|
||||||
|
});
|
||||||
|
|
||||||
|
// 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 ------------------
|
||||||
|
|
||||||
// guardar configuraciones
|
// guardar configuraciones
|
||||||
public static void save() {
|
public void save() {
|
||||||
if (!loaded) return;
|
if (!loaded) return;
|
||||||
|
writeSnapshot(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void saveOnShutdown() {
|
||||||
|
// no aceptar más tareas y esperar a que termine el guardado en curso
|
||||||
|
saveExecutor.shutdown();
|
||||||
|
try {
|
||||||
|
// dar hasta 5 segundos para que termine el guardado en curso
|
||||||
|
if (!saveExecutor.awaitTermination(5, TimeUnit.SECONDS)) {
|
||||||
|
Sputnik.LOGGER.warn(I18nUtil.fmt("sputnik.config.warn.thread",
|
||||||
|
"el hilo de guardado no terminó a tiempo"));
|
||||||
|
}
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
Thread.currentThread().interrupt();
|
||||||
|
}
|
||||||
|
|
||||||
|
// el guardado final va en este mismo hilo: el executor ya está cerrado, así que
|
||||||
|
// 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();
|
ensureConfig();
|
||||||
|
|
||||||
|
final byte[] snapshot;
|
||||||
try {
|
try {
|
||||||
BinarySerializer.writeConfig(config, CONFIG_FILE);
|
snapshot = BinarySerializer.toBytes(config);
|
||||||
Sputnik.LOGGER.info("ajustes guardados");
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
Sputnik.LOGGER.error("error al guardar ajustes", 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 static void load() {
|
public void load() {
|
||||||
Sputnik.LOGGER.info("cargando ajustes...");
|
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("ajustes cargados");
|
Sputnik.LOGGER.info(I18nUtil.fmt("sputnik.config.info.loaded", "ajustes cargados"));
|
||||||
return;
|
return;
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
Sputnik.LOGGER.error("error cargando ajustes, intentando json", e);
|
Sputnik.LOGGER.error(I18nUtil.fmt("sputnik.config.error.loading",
|
||||||
|
"error cargando ajustes, intentando json"), e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fallback to legacy JSON
|
// fallback to legacy JSON
|
||||||
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("ajustes json cargados (migración)");
|
config.legacyKeyCodes = true;
|
||||||
|
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("error cargando json, usando defaults", e);
|
Sputnik.LOGGER.error(I18nUtil.fmt("sputnik.config.error.json",
|
||||||
|
"error cargando json, usando defaults"), e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// crear nuevo config
|
// crear nuevo config
|
||||||
ensureConfig();
|
ensureConfig();
|
||||||
|
writeSnapshot(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// aplicar configuraciones cargadas. devuelve false si todavía no se puede (falta algo por
|
||||||
|
// construir), para que se reintente en el siguiente tick en vez de quedarse sin aplicar
|
||||||
|
public boolean applyConfig() {
|
||||||
|
if (!shouldApply()) return false;
|
||||||
|
|
||||||
|
applying = true;
|
||||||
|
boolean migratedKeys = config.legacyKeyCodes;
|
||||||
|
try {
|
||||||
|
migrateLegacyKeyCodes();
|
||||||
|
// los del mod primero: entre ellos está "teclas multimódulo", que decide si al
|
||||||
|
// asignar una tecla se le quita a los demás módulos. aplicándolos los últimos,
|
||||||
|
// las teclas de los módulos se cargaban con el valor por defecto de ese ajuste
|
||||||
|
applyClientSettings();
|
||||||
|
applyModuleStates();
|
||||||
|
applyModuleSettings();
|
||||||
|
applySettingsPanels();
|
||||||
|
applySearchBarPosition();
|
||||||
|
applyExtendablePanels();
|
||||||
|
applyFriends();
|
||||||
|
applyMacros();
|
||||||
|
applyHudElements();
|
||||||
|
|
||||||
|
Sputnik.LOGGER.info(I18nUtil.fmt("sputnik.config.info.applied", "ajustes aplicados"));
|
||||||
|
} 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (migratedKeys) writeSnapshot(true);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void migrateLegacyKeyCodes() {
|
||||||
|
if (!config.legacyKeyCodes) return;
|
||||||
|
|
||||||
|
ClientSettingsPanel.clientSettings.getSettings().forEach(this::migrateLegacyKeySetting);
|
||||||
|
ModuleManager.INSTANCE.getModules().forEach(module ->
|
||||||
|
module.getSettings().forEach(this::migrateLegacyKeySetting));
|
||||||
|
BinarySerializer.migrateLegacyKeyCodes(config);
|
||||||
|
config.legacyKeyCodes = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void migrateLegacyKeySetting(Setting<?> setting) {
|
||||||
|
if (!(setting instanceof KeySetting)) return;
|
||||||
|
String key = getSettingKey(setting);
|
||||||
|
Object value = config.settings.get(key);
|
||||||
|
if (value instanceof Integer code) {
|
||||||
|
config.settings.put(key, KeyUtil.fromLegacyGlfwKey(code));
|
||||||
|
} else if (value instanceof Double code) {
|
||||||
|
config.settings.put(key, KeyUtil.fromLegacyGlfwKey(code.intValue()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// true mientras se está cargando la config. sobre los ajustes. lo mira KeySetting para no
|
||||||
|
// tratar las teclas guardadas como si el usuario las acabara de asignar, y ClientConfig
|
||||||
|
// para no reescribir en la config. lo que se le está aplicando
|
||||||
|
public boolean isApplying() {
|
||||||
|
return applying;
|
||||||
|
}
|
||||||
|
|
||||||
|
// sustituye la config. viva por otra y la vuelca sobre el estado actual del cliente
|
||||||
|
public void replaceConfig(ClientConfig newConfig) {
|
||||||
|
applying = true;
|
||||||
|
try {
|
||||||
|
resetLiveState();
|
||||||
|
} finally {
|
||||||
|
applying = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
setConfig(newConfig);
|
||||||
|
loaded = false;
|
||||||
|
applyConfig();
|
||||||
save();
|
save();
|
||||||
}
|
}
|
||||||
|
|
||||||
// aplicar configuraciones cargadas
|
// lo que no venga en la config. nueva tiene que quedarse en su valor por defecto, no en
|
||||||
public static void applyConfig() {
|
// el que tuviera el perfil anterior
|
||||||
if (!shouldApply()) return;
|
private void resetLiveState() {
|
||||||
|
if (ClickGui.INSTANCE != null) ClickGui.INSTANCE.closeAllSettingsPanels();
|
||||||
|
|
||||||
applyModuleStates();
|
for (Module module : ModuleManager.INSTANCE.getModules()) {
|
||||||
applyModuleSettings();
|
module.setEnabled(false);
|
||||||
applySettingsFrames();
|
module.getSettings().forEach(Setting::reset);
|
||||||
applySearchBarPosition();
|
}
|
||||||
applyGuiSettings();
|
ClientSettingsPanel.clientSettings.getSettings().forEach(Setting::reset);
|
||||||
applyExtendableFrames();
|
|
||||||
|
|
||||||
loaded = true;
|
for (Friend friend : new ArrayList<>(FriendManager.INSTANCE.getFriends()))
|
||||||
Sputnik.LOGGER.info("ajustes aplicados");
|
FriendManager.INSTANCE.remove(friend);
|
||||||
|
|
||||||
|
MacroManager.INSTANCE.setMacros(List.of());
|
||||||
}
|
}
|
||||||
|
|
||||||
// obtener configuración actual
|
// obtener configuración actual
|
||||||
public static ClientConfig getConfig() {
|
public ClientConfig getConfig() {
|
||||||
ensureConfig();
|
ensureConfig();
|
||||||
return config;
|
return config;
|
||||||
}
|
}
|
||||||
@@ -101,56 +278,128 @@ public class ConfigManager {
|
|||||||
|
|
||||||
// ------------------ GUARDAR VALORES INDIVIDUALES EN LA CONFIG. ------------------
|
// ------------------ GUARDAR VALORES INDIVIDUALES EN LA CONFIG. ------------------
|
||||||
|
|
||||||
public static void setModuleState(Module module) {
|
public void setModuleState(Module module) {
|
||||||
ensureConfig();
|
ensureConfig();
|
||||||
config.moduleStates.put(module.getName(), module.isEnabled());
|
config.moduleStates.put(module.getName(), module.isEnabled());
|
||||||
save();
|
markDirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void setSetting(Setting<?> setting, Object value) {
|
public void setSetting(Setting<?> setting, Object value) {
|
||||||
ensureConfig();
|
ensureConfig();
|
||||||
config.settings.put(getSettingKey(setting), value);
|
config.settings.put(getSettingKey(setting), value);
|
||||||
save();
|
markDirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void setFramePosition(SettingsFrame frame) {
|
public void setPanelPosition(SettingsPanel panel) {
|
||||||
ensureConfig();
|
ensureConfig();
|
||||||
if (!config.settingsFrames.containsKey(frame.getModule().getName()))
|
if (!config.settingsPanels.containsKey(panel.getModule().getName()))
|
||||||
config.settingsFrames.put(frame.getModule().getName(), new int[] {frame.getX(), frame.getY()});
|
config.settingsPanels.put(panel.getModule().getName(), new int[] {panel.getX(), panel.getY()});
|
||||||
else
|
else
|
||||||
config.settingsFrames.replace(frame.getModule().getName(), new int[] {frame.getX(), frame.getY()});
|
config.settingsPanels.replace(panel.getModule().getName(), new int[] {panel.getX(), panel.getY()});
|
||||||
save();
|
markDirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void setExtendableFrame(String key, ClientConfig.FrameData data) {
|
public void setExtendablePanel(String key, ClientConfig.PanelData data) {
|
||||||
ensureConfig();
|
ensureConfig();
|
||||||
config.extendableFrames.put(key, data);
|
config.extendablePanels.put(key, data);
|
||||||
save();
|
markDirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void setHudPosition(String id, int x, int y) {
|
public void setHudPosition(String id, int x, int y) {
|
||||||
ensureConfig();
|
ensureConfig();
|
||||||
config.hudPositions.put(id, new int[] {x, y});
|
config.hudPositions.put(id, new int[] {x, y});
|
||||||
save();
|
markDirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void setHudVisibility(String id, Boolean visible) {
|
public void setHudVisibility(String id, Boolean visible) {
|
||||||
ensureConfig();
|
ensureConfig();
|
||||||
config.hudVisibilities.put(id, visible);
|
config.hudVisibilities.put(id, visible);
|
||||||
save();
|
markDirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void setSearchBarPosition(int x, int y) {
|
public void setSearchBarPosition(int x, int y) {
|
||||||
ensureConfig();
|
ensureConfig();
|
||||||
config.searchBarPosition = new int[] {x, y};
|
config.searchBarPosition = new int[] {x, y};
|
||||||
save();
|
markDirty();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMacros(List<Macro> macros) {
|
||||||
|
ensureConfig();
|
||||||
|
config.macros = macros.stream()
|
||||||
|
.map(ConfigManager::toMacroData)
|
||||||
|
.toList();
|
||||||
|
markDirty();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCurrentProfile(String name) {
|
||||||
|
ensureConfig();
|
||||||
|
config.currentProfile = name;
|
||||||
|
markDirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// ------------------ APLICAR AJUSTES ------------------
|
// ------------------ APLICAR AJUSTES ------------------
|
||||||
|
|
||||||
|
public void applyFriends() {
|
||||||
|
config.friends.forEach((uuid, data) -> {
|
||||||
|
Friend friend = new Friend(UUID.fromString(uuid), data.befriendedAt());
|
||||||
|
friend.setName(data.name());
|
||||||
|
friend.setNick(data.nick());
|
||||||
|
FriendManager.INSTANCE.add(friend);
|
||||||
|
});
|
||||||
|
Sputnik.LOGGER.info(I18nUtil.fmt("sputnik.config.info.friends",
|
||||||
|
"amigos aplicados"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void applyMacros() {
|
||||||
|
MacroManager.INSTANCE.setMacros(config.macros.stream()
|
||||||
|
.map(ConfigManager::fromMacroData)
|
||||||
|
.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ClientConfig.MacroData toMacroData(Macro macro) {
|
||||||
|
return switch (macro) {
|
||||||
|
case Macro.Chat chat -> ClientConfig.MacroData.chat(
|
||||||
|
chat.getName(), chat.getKey(), chat.getLines());
|
||||||
|
|
||||||
|
case Macro.Keybind keybind -> ClientConfig.MacroData.keybind(
|
||||||
|
keybind.getName(), keybind.getKey(),
|
||||||
|
keybind.getKeys().stream()
|
||||||
|
.map(k -> new ClientConfig.KeyData(k.key(), k.action()))
|
||||||
|
.toList());
|
||||||
|
|
||||||
|
default -> throw new IllegalArgumentException(
|
||||||
|
"tipo de macro sin serializar: " + macro.getClass().getName());
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Macro fromMacroData(ClientConfig.MacroData data) {
|
||||||
|
if (data.type() == ClientConfig.MacroType.KEYBIND) {
|
||||||
|
List<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
|
||||||
|
public void applyHudElements() {
|
||||||
|
if (HudRenderer.INSTANCE == null) return;
|
||||||
|
|
||||||
|
for (HudElement element : HudRenderer.INSTANCE.getElements()) {
|
||||||
|
int[] position = config.hudPositions.get(element.getId());
|
||||||
|
if (position != null && position.length == 2) element.setPosition(position[0], position[1]);
|
||||||
|
else element.resetPosition();
|
||||||
|
|
||||||
|
Boolean visible = config.hudVisibilities.get(element.getId());
|
||||||
|
element.setVisible(visible == null || visible);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||||
public static void applySetting(Module parent, Setting<?> setting) {
|
public void applySetting(Setting<?> setting) {
|
||||||
String key = getSettingKey(setting);
|
String key = getSettingKey(setting);
|
||||||
|
|
||||||
if (!config.settings.containsKey(key)) return;
|
if (!config.settings.containsKey(key)) return;
|
||||||
@@ -166,81 +415,91 @@ 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("watafac queseso: {}", setting.getClass().getSimpleName());
|
case FileSetting fileSetting -> applyFileSetting(fileSetting, value);
|
||||||
|
default -> Sputnik.LOGGER.warn(I18nUtil.fmt("sputnik.config.warn.unknownsetting",
|
||||||
|
"watafac queseso: %s", setting.getClass().getSimpleName()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void applyModuleStates() {
|
private void applyModuleStates() {
|
||||||
ModuleManager.INSTANCE.getModules().forEach(module -> {
|
ModuleManager.INSTANCE.getModules().forEach(module -> {
|
||||||
if (config.moduleStates.containsKey(module.getName())) {
|
if (config.moduleStates.containsKey(module.getName())) {
|
||||||
module.setEnabled(config.moduleStates.get(module.getName()));
|
module.setEnabled(config.moduleStates.get(module.getName()));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
Sputnik.LOGGER.info("estados de módulos aplicados");
|
Sputnik.LOGGER.info(I18nUtil.fmt("sputnik.config.info.modulestates",
|
||||||
|
"estados de módulos aplicados"));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void applyModuleSettings() {
|
private void applyModuleSettings() {
|
||||||
ModuleManager.INSTANCE.getModules().forEach(module -> {
|
ModuleManager.INSTANCE.getModules().forEach(module -> {
|
||||||
module.getSettings().forEach(setting -> applySetting(module, setting));
|
module.getSettings().forEach(this::applySetting);
|
||||||
});
|
});
|
||||||
Sputnik.LOGGER.info("ajustes de módulos aplicados");
|
Sputnik.LOGGER.info(I18nUtil.fmt("sputnik.config.info.modulesettings",
|
||||||
|
"ajustes de módulos aplicados"));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void applySettingsFrames() {
|
private void applySettingsPanels() {
|
||||||
config.settingsFrames.forEach((moduleName, position) -> {
|
config.settingsPanels.forEach((moduleName, position) -> {
|
||||||
Module module = ModuleManager.INSTANCE.getModuleByName(moduleName);
|
Module module = ModuleManager.INSTANCE.getModuleByName(moduleName);
|
||||||
|
|
||||||
if (module == null) {
|
if (module == null) {
|
||||||
Sputnik.LOGGER.warn("\"null\" como módulo (\"{}\")", moduleName);
|
Sputnik.LOGGER.warn(I18nUtil.fmt("sputnik.config.warn.nullmodule",
|
||||||
|
"\"null\" como módulo (\"%s\")", moduleName));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ClickGUI.INSTANCE.openSettingsFrame(module, position[0], position[1]);
|
ClickGui.INSTANCE.openSettingsPanel(module, position[0], position[1]);
|
||||||
});
|
});
|
||||||
|
|
||||||
Sputnik.LOGGER.info("estados de marcos de ajustes aplicados");
|
Sputnik.LOGGER.info(I18nUtil.fmt("sputnik.config.info.settingspanels",
|
||||||
|
"estados de marcos de ajustes aplicados"));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void applySearchBarPosition() {
|
private void applySearchBarPosition() {
|
||||||
if (config.searchBarPosition != null && config.searchBarPosition.length == 2) {
|
if (config.searchBarPosition != null && config.searchBarPosition.length == 2) {
|
||||||
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("posición de la barra de búsqueda aplicada");
|
Sputnik.LOGGER.info(I18nUtil.fmt("sputnik.config.info.searchbar",
|
||||||
|
"posición de la barra de búsqueda aplicada"));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void applyGuiSettings() {
|
private void applyClientSettings() {
|
||||||
ClientSettingsFrame.guiSettings.setEnabled(true);
|
ClientSettingsPanel.clientSettings.setEnabled(true);
|
||||||
ClientSettingsFrame.guiSettings.getSettings().forEach(setting -> {
|
ClientSettingsPanel.clientSettings.getSettings().forEach(this::applySetting);
|
||||||
applySetting(ClientSettingsFrame.guiSettings, setting);
|
Sputnik.LOGGER.info(I18nUtil.fmt("sputnik.config.info.clientsettings",
|
||||||
});
|
"ajustes del cliente aplicados"));
|
||||||
Sputnik.LOGGER.info("ajustes del cliente aplicados");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void applyExtendableFrames() {
|
private void applyExtendablePanels() {
|
||||||
applyExtendableFrame(ClickGUI.INSTANCE.getModulesFrame());
|
for (ModulePanel panel : ClickGui.INSTANCE.getModulePanels()) {
|
||||||
applyExtendableFrame(ClickGUI.INSTANCE.getGuiSettingsFrame());
|
applyExtendablePanel(panel);
|
||||||
|
}
|
||||||
|
applyExtendablePanel(ClickGui.INSTANCE.getClientSettingsPanel());
|
||||||
|
|
||||||
Sputnik.LOGGER.info("posiciones de marcos extendibles aplicadas");
|
Sputnik.LOGGER.info(I18nUtil.fmt("sputnik.config.info.extendablepanels",
|
||||||
ClickGUI.INSTANCE.refreshListButtons();
|
"posiciones de marcos extendibles aplicadas"));
|
||||||
|
ClickGui.INSTANCE.refreshListButtons();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void applyExtendableFrame(Frame<?> frame) {
|
private void applyExtendablePanel(Panel<?> panel) {
|
||||||
ClientConfig.FrameData frameData = null;
|
ClientConfig.PanelData panelData = null;
|
||||||
if (frame instanceof ModuleFrame)
|
|
||||||
frameData = config.extendableFrames.get("M");
|
|
||||||
|
|
||||||
if (frame instanceof ClientSettingsFrame)
|
if (panel instanceof ModulePanel mp) {
|
||||||
frameData = config.extendableFrames.get("S");
|
panelData = config.extendablePanels.get(mp.category.toString());
|
||||||
|
}
|
||||||
|
if (panel instanceof ClientSettingsPanel) {
|
||||||
|
panelData = config.extendablePanels.get("ajustes");
|
||||||
|
}
|
||||||
|
|
||||||
if (frameData != null) {
|
if (panelData != null) {
|
||||||
frame.setX(frameData.x());
|
panel.setX(panelData.x());
|
||||||
frame.setY(frameData.y());
|
panel.setY(panelData.y());
|
||||||
|
|
||||||
if (frame instanceof ModuleFrame mFrame)
|
if (panel instanceof ExtendablePanel<?> ePanel) {
|
||||||
mFrame.extended = frameData.extended();
|
ePanel.setExtended(panelData.extended());
|
||||||
if (frame instanceof ClientSettingsFrame sFrame)
|
}
|
||||||
sFrame.extended = frameData.extended();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -268,8 +527,8 @@ public class ConfigManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static void applyStringSetting(StringSetting setting, Object value) {
|
private static void applyStringSetting(StringSetting setting, Object value) {
|
||||||
if (value instanceof String) {
|
if (value instanceof String v) {
|
||||||
setting.setValue((String) value);
|
setting.setValue(v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -286,8 +545,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);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -324,6 +589,12 @@ public class ConfigManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void applyFileSetting(FileSetting setting, Object value) {
|
||||||
|
if (value instanceof String v) {
|
||||||
|
setting.setValue(v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static <T> void applyOptionalProperty(Map<?, ?> map, String key, Class<T> type, Consumer<T> setter) {
|
private static <T> void applyOptionalProperty(Map<?, ?> map, String key, Class<T> type, Consumer<T> setter) {
|
||||||
Object value = map.get(key);
|
Object value = map.get(key);
|
||||||
if (type.isInstance(value)) {
|
if (type.isInstance(value)) {
|
||||||
@@ -334,19 +605,54 @@ public class ConfigManager {
|
|||||||
|
|
||||||
// ------------------ MÉTODOS DE AYUDA ------------------
|
// ------------------ MÉTODOS DE AYUDA ------------------
|
||||||
|
|
||||||
private static boolean shouldApply() {
|
|
||||||
return Sputnik.mc != null && ModuleManager.INSTANCE != null && config != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void ensureConfig() {
|
|
||||||
if (config == null) config = new ClientConfig();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String getSettingKey(Setting<?> setting) {
|
private static String getSettingKey(Setting<?> setting) {
|
||||||
return setting.getSg().getModule().getName() + ":" + setting.getTrueName();
|
return setting.getSg().getModule().getName() + ":" + setting.getTrueName();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean hasLoaded() {
|
// 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() {
|
||||||
|
return Sputnik.mc != null && ModuleManager.INSTANCE != null
|
||||||
|
&& ClickGui.INSTANCE != null && config != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ensureConfig() {
|
||||||
|
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() {
|
||||||
return loaded;
|
return loaded;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
public void markDirty() {
|
||||||
|
this.dirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isDirty() {
|
||||||
|
return dirty;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void tickAutosave() {
|
||||||
|
if (!loaded || !dirty) return;
|
||||||
|
|
||||||
|
ClientSettingsModule settings = ClientSettingsPanel.clientSettings;
|
||||||
|
if (!settings.autosave.getValue()) return;
|
||||||
|
|
||||||
|
long intervalMs = (long) (settings.autosaveInterval.getValue() * 1000);
|
||||||
|
if (System.currentTimeMillis() - lastSaveTime < intervalMs) return;
|
||||||
|
|
||||||
|
HudRenderer.INSTANCE.pushNotification(
|
||||||
|
Component.translatable("sputnik.config.autosaving.title").getString(),
|
||||||
|
Component.translatable("sputnik.config.autosaving.desc").getString());
|
||||||
|
save();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,99 @@
|
|||||||
|
package me.retucio.sputnik.config;
|
||||||
|
|
||||||
|
import me.retucio.sputnik.Sputnik;
|
||||||
|
import me.retucio.sputnik.util.I18nUtil;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
|
||||||
|
public class ProfileManager {
|
||||||
|
|
||||||
|
public static final int MAX_NAME_LENGTH = 32;
|
||||||
|
|
||||||
|
private static final File DIR = new File("sputnik/profiles");
|
||||||
|
private static final String EXTENSION = ".dat";
|
||||||
|
|
||||||
|
public static ProfileManager INSTANCE;
|
||||||
|
|
||||||
|
public List<String> getProfileNames() {
|
||||||
|
File[] files = DIR.listFiles((dir, name) -> name.endsWith(EXTENSION));
|
||||||
|
if (files == null) return List.of();
|
||||||
|
|
||||||
|
List<String> names = new ArrayList<>();
|
||||||
|
for (File file : files) {
|
||||||
|
String name = file.getName();
|
||||||
|
names.add(name.substring(0, name.length() - EXTENSION.length()));
|
||||||
|
}
|
||||||
|
names.sort(Comparator.naturalOrder());
|
||||||
|
return names;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean exists(String name) {
|
||||||
|
return fileOf(name).exists();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCurrent() {
|
||||||
|
return ConfigManager.INSTANCE.getConfig().currentProfile;
|
||||||
|
}
|
||||||
|
|
||||||
|
// vuelca la config. viva en el perfil y lo deja como actual
|
||||||
|
public boolean save(String name) {
|
||||||
|
if (!isValidName(name)) return false;
|
||||||
|
|
||||||
|
if (!DIR.exists() && !DIR.mkdirs()) {
|
||||||
|
Sputnik.LOGGER.error(I18nUtil.fmt("sputnik.profile.error.dir",
|
||||||
|
"no se pudo crear el directorio de perfiles"));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ConfigManager.INSTANCE.setCurrentProfile(name);
|
||||||
|
try {
|
||||||
|
BinarySerializer.writeConfig(ConfigManager.INSTANCE.getConfig(), fileOf(name));
|
||||||
|
return true;
|
||||||
|
} catch (IOException e) {
|
||||||
|
Sputnik.LOGGER.error(I18nUtil.fmt("sputnik.profile.error.saving",
|
||||||
|
"error al guardar el perfil \"%s\"", name), e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean load(String name) {
|
||||||
|
if (!exists(name)) return false;
|
||||||
|
|
||||||
|
ClientConfig profile;
|
||||||
|
try {
|
||||||
|
profile = BinarySerializer.readConfig(fileOf(name));
|
||||||
|
} catch (IOException e) {
|
||||||
|
Sputnik.LOGGER.error(I18nUtil.fmt("sputnik.profile.error.loading",
|
||||||
|
"error al cargar el perfil \"%s\"", name), e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
profile.currentProfile = name;
|
||||||
|
ConfigManager.INSTANCE.replaceConfig(profile);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean delete(String name) {
|
||||||
|
if (!exists(name)) return false;
|
||||||
|
if (!fileOf(name).delete()) return false;
|
||||||
|
|
||||||
|
if (name.equals(getCurrent())) ConfigManager.INSTANCE.setCurrentProfile("");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isValidName(String name) {
|
||||||
|
return name != null
|
||||||
|
&& !name.isBlank()
|
||||||
|
&& name.length() <= MAX_NAME_LENGTH
|
||||||
|
&& name.matches("[a-zA-Z0-9 _-]+");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static File fileOf(String name) {
|
||||||
|
return new File(DIR, name + EXTENSION);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,11 +1,11 @@
|
|||||||
package me.retucio.sputnik.event;
|
package me.retucio.sputnik.event;
|
||||||
|
|
||||||
import com.github.retucio.neutrino.Event;
|
import com.github.retucio.neutrino.Event;
|
||||||
import me.retucio.sputnik.mixin.mixins.misc.MinecraftClientMixin;
|
import me.retucio.sputnik.mixin.mixins.misc.MinecraftMixin;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see MinecraftClientMixin#onStop
|
* @see MinecraftMixin#onStop
|
||||||
*/
|
*/
|
||||||
public class ShutdownEvent extends Event {
|
public class ShutdownEvent extends Event {
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
package me.retucio.sputnik.event;
|
package me.retucio.sputnik.event;
|
||||||
|
|
||||||
import com.github.retucio.neutrino.Event;
|
import com.github.retucio.neutrino.Event;
|
||||||
import me.retucio.sputnik.mixin.mixins.misc.MinecraftClientMixin;
|
import me.retucio.sputnik.mixin.mixins.misc.MinecraftMixin;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see MinecraftClientMixin#onTickPre
|
* @see MinecraftMixin#onTickPre
|
||||||
* @see MinecraftClientMixin#onTickPost
|
* @see MinecraftMixin#onTickPost
|
||||||
*/
|
*/
|
||||||
public class TickEvent {
|
public class TickEvent {
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,14 @@
|
|||||||
package me.retucio.sputnik.event.input;
|
package me.retucio.sputnik.event.input;
|
||||||
|
|
||||||
import me.retucio.sputnik.module.modules.misc.ChatPlus;
|
import me.retucio.sputnik.module.modules.misc.ChatPlus;
|
||||||
import net.minecraft.text.ClickEvent;
|
import net.minecraft.network.chat.ClickEvent;
|
||||||
|
import org.jspecify.annotations.NonNull;
|
||||||
|
|
||||||
|
|
||||||
/** este evento es solo para asegurarse de que comandos del mod se puedan ejecutar solo desde el lado del cliente
|
/** este evento es solo para asegurarse de que comandos del mod se puedan ejecutar solo desde el lado del cliente
|
||||||
* @see ChatPlus#getSendButton
|
* @see ChatPlus#getSendButton
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class ClientClickEvent implements ClickEvent {
|
public class ClientClickEvent implements ClickEvent {
|
||||||
|
|
||||||
private final String value;
|
private final String value;
|
||||||
@@ -20,7 +22,7 @@ public class ClientClickEvent implements ClickEvent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Action getAction() {
|
public @NonNull Action action() {
|
||||||
return Action.RUN_COMMAND;
|
return Action.RUN_COMMAND;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
package me.retucio.sputnik.event.input;
|
package me.retucio.sputnik.event.input;
|
||||||
|
|
||||||
import com.github.retucio.neutrino.Event;
|
import com.github.retucio.neutrino.Event;
|
||||||
import me.retucio.sputnik.mixin.mixins.io.KeyboardMixin;
|
import me.retucio.sputnik.mixin.mixins.io.KeyboardHandlerMixin;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see KeyboardMixin#onKeyPress
|
* @see KeyboardHandlerMixin#onKeyPress
|
||||||
*/
|
*/
|
||||||
public class KeyEvent extends Event {
|
public class KeyEvent extends Event {
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
package me.retucio.sputnik.event.input;
|
package me.retucio.sputnik.event.input;
|
||||||
|
|
||||||
import com.github.retucio.neutrino.Event;
|
import com.github.retucio.neutrino.Event;
|
||||||
import me.retucio.sputnik.mixin.mixins.io.MouseMixin;
|
import me.retucio.sputnik.mixin.mixins.io.MouseHandlerMixin;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see MouseMixin#onMouseButton
|
* @see MouseHandlerMixin#onMouseButton
|
||||||
*/
|
*/
|
||||||
public class MouseClickEvent extends Event {
|
public class MouseClickEvent extends Event {
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
package me.retucio.sputnik.event.input;
|
package me.retucio.sputnik.event.input;
|
||||||
|
|
||||||
import com.github.retucio.neutrino.Event;
|
import com.github.retucio.neutrino.Event;
|
||||||
import me.retucio.sputnik.mixin.mixins.io.MouseMixin;
|
import me.retucio.sputnik.mixin.mixins.io.MouseHandlerMixin;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see MouseMixin#onMouseScroll
|
* @see MouseHandlerMixin#onMouseScroll
|
||||||
*/
|
*/
|
||||||
public class MouseScrollEvent extends Event {
|
public class MouseScrollEvent extends Event {
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
package me.retucio.sputnik.event.input;
|
||||||
|
|
||||||
|
import com.github.retucio.neutrino.Event;
|
||||||
|
|
||||||
|
public class SneakEvent extends Event {}
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
package me.retucio.sputnik.event.interact;
|
package me.retucio.sputnik.event.interact;
|
||||||
|
|
||||||
import com.github.retucio.neutrino.Event;
|
import com.github.retucio.neutrino.Event;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
import net.minecraft.util.math.Direction;
|
import net.minecraft.core.Direction;
|
||||||
|
|
||||||
public class AttackBlockEvent extends Event {
|
public class AttackBlockEvent extends Event {
|
||||||
|
|
||||||
|
|||||||
@@ -1,13 +1,14 @@
|
|||||||
package me.retucio.sputnik.event.interact;
|
package me.retucio.sputnik.event.interact;
|
||||||
|
|
||||||
import com.github.retucio.neutrino.Event;
|
import com.github.retucio.neutrino.Event;
|
||||||
import me.retucio.sputnik.mixin.mixins.player.ClientPlayerInteractionManagerMixin;
|
import me.retucio.sputnik.mixin.mixins.player.MultiPlayerGameModeMixin;
|
||||||
import net.minecraft.entity.Entity;
|
import net.minecraft.world.entity.Entity;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see ClientPlayerInteractionManagerMixin#onAttackEntity
|
* @see MultiPlayerGameModeMixin#onAttackEntity
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class AttackEntityEvent extends Event {
|
public class AttackEntityEvent extends Event {
|
||||||
|
|
||||||
private final Entity entity;
|
private final Entity entity;
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
package me.retucio.sputnik.event.interact;
|
package me.retucio.sputnik.event.interact;
|
||||||
|
|
||||||
import com.github.retucio.neutrino.Event;
|
import com.github.retucio.neutrino.Event;
|
||||||
import net.minecraft.block.BlockState;
|
import net.minecraft.core.BlockPos;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
import net.minecraft.util.shape.VoxelShape;
|
import net.minecraft.world.phys.shapes.VoxelShape;
|
||||||
|
|
||||||
public class BlockShapeEvent extends Event {
|
public class BlockShapeEvent extends Event {
|
||||||
|
|
||||||
|
|||||||
@@ -1,28 +1,28 @@
|
|||||||
package me.retucio.sputnik.event.interact;
|
package me.retucio.sputnik.event.interact;
|
||||||
|
|
||||||
import com.github.retucio.neutrino.Event;
|
import com.github.retucio.neutrino.Event;
|
||||||
import net.minecraft.entity.vehicle.AbstractBoatEntity;
|
import net.minecraft.world.entity.vehicle.boat.AbstractBoat;
|
||||||
import net.minecraft.util.math.Vec3d;
|
import net.minecraft.world.phys.Vec3;
|
||||||
|
|
||||||
public class BoatMoveEvent extends Event {
|
public class BoatMoveEvent extends Event {
|
||||||
|
|
||||||
private final AbstractBoatEntity boat;
|
private final AbstractBoat boat;
|
||||||
private Vec3d pos;
|
private Vec3 pos;
|
||||||
|
|
||||||
public BoatMoveEvent(AbstractBoatEntity boat, Vec3d pos) {
|
public BoatMoveEvent(AbstractBoat boat, Vec3 pos) {
|
||||||
this.boat = boat;
|
this.boat = boat;
|
||||||
this.pos = pos;
|
this.pos = pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
public AbstractBoatEntity getBoat() {
|
public AbstractBoat getBoat() {
|
||||||
return boat;
|
return boat;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Vec3d getPos() {
|
public Vec3 getPos() {
|
||||||
return pos;
|
return pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setPos(Vec3d pos) {
|
public void setPos(Vec3 pos) {
|
||||||
this.pos = pos;
|
this.pos = pos;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,13 +1,14 @@
|
|||||||
package me.retucio.sputnik.event.interact;
|
package me.retucio.sputnik.event.interact;
|
||||||
|
|
||||||
import com.github.retucio.neutrino.Event;
|
import com.github.retucio.neutrino.Event;
|
||||||
import me.retucio.sputnik.mixin.mixins.player.ClientPlayerInteractionManagerMixin;
|
import me.retucio.sputnik.mixin.mixins.player.MultiPlayerGameModeMixin;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see ClientPlayerInteractionManagerMixin#onBlockBreak
|
* @see MultiPlayerGameModeMixin#onBlockBreak
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class BreakBlockEvent extends Event {
|
public class BreakBlockEvent extends Event {
|
||||||
|
|
||||||
private BlockPos pos;
|
private BlockPos pos;
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ package me.retucio.sputnik.event.interact;
|
|||||||
|
|
||||||
import com.github.retucio.neutrino.Event;
|
import com.github.retucio.neutrino.Event;
|
||||||
import me.retucio.sputnik.mixin.mixins.item.ItemStackMixin;
|
import me.retucio.sputnik.mixin.mixins.item.ItemStackMixin;
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.world.item.ItemStack;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,20 +1,21 @@
|
|||||||
package me.retucio.sputnik.event.interact;
|
package me.retucio.sputnik.event.interact;
|
||||||
|
|
||||||
import com.github.retucio.neutrino.Event;
|
import com.github.retucio.neutrino.Event;
|
||||||
import me.retucio.sputnik.mixin.mixins.player.ClientPlayerInteractionManagerMixin;
|
import me.retucio.sputnik.mixin.mixins.player.MultiPlayerGameModeMixin;
|
||||||
import net.minecraft.entity.Entity;
|
import net.minecraft.world.InteractionHand;
|
||||||
import net.minecraft.util.Hand;
|
import net.minecraft.world.entity.Entity;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see ClientPlayerInteractionManagerMixin#onEntityInteract
|
* @see MultiPlayerGameModeMixin#onEntityInteract
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class InteractEntityEvent extends Event {
|
public class InteractEntityEvent extends Event {
|
||||||
|
|
||||||
private final Entity entity;
|
private final Entity entity;
|
||||||
private Hand hand;
|
private InteractionHand hand;
|
||||||
|
|
||||||
public InteractEntityEvent(Entity entity, Hand hand) {
|
public InteractEntityEvent(Entity entity, InteractionHand hand) {
|
||||||
this.entity = entity;
|
this.entity = entity;
|
||||||
this.hand = hand;
|
this.hand = hand;
|
||||||
}
|
}
|
||||||
@@ -23,11 +24,11 @@ public class InteractEntityEvent extends Event {
|
|||||||
return entity;
|
return entity;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Hand getHand() {
|
public InteractionHand getHand() {
|
||||||
return hand;
|
return hand;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setHand(Hand hand) {
|
public void setHand(InteractionHand hand) {
|
||||||
this.hand = hand;
|
this.hand = hand;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
package me.retucio.sputnik.event.interact;
|
||||||
|
|
||||||
|
import com.github.retucio.neutrino.Event;
|
||||||
|
import net.minecraft.world.entity.LivingEntity;
|
||||||
|
|
||||||
|
public class KnockbackEvent extends Event {
|
||||||
|
|
||||||
|
private double strength;
|
||||||
|
private double x, z;
|
||||||
|
private final LivingEntity target;
|
||||||
|
|
||||||
|
public KnockbackEvent(LivingEntity target, double z, double x, double strength) {
|
||||||
|
this.target = target;
|
||||||
|
this.z = z;
|
||||||
|
this.x = x;
|
||||||
|
this.strength = strength;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getStrength() {
|
||||||
|
return strength;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStrength(double strength) {
|
||||||
|
this.strength = strength;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getX() {
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setX(double x) {
|
||||||
|
this.x = x;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getZ() {
|
||||||
|
return z;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setZ(double z) {
|
||||||
|
this.z = z;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LivingEntity getTarget() {
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,12 +1,12 @@
|
|||||||
package me.retucio.sputnik.event.interact;
|
package me.retucio.sputnik.event.interact;
|
||||||
|
|
||||||
import com.github.retucio.neutrino.Event;
|
import com.github.retucio.neutrino.Event;
|
||||||
import me.retucio.sputnik.mixin.mixins.misc.MinecraftClientMixin;
|
import me.retucio.sputnik.mixin.mixins.misc.MinecraftMixin;
|
||||||
import net.minecraft.client.gui.screen.Screen;
|
import net.minecraft.client.gui.screens.Screen;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see MinecraftClientMixin#onOpenScreen
|
* @see MinecraftMixin#onOpenScreen
|
||||||
*/
|
*/
|
||||||
public class OpenScreenEvent extends Event {
|
public class OpenScreenEvent extends Event {
|
||||||
|
|
||||||
|
|||||||
@@ -1,29 +1,29 @@
|
|||||||
package me.retucio.sputnik.event.interact;
|
package me.retucio.sputnik.event.interact;
|
||||||
|
|
||||||
import com.github.retucio.neutrino.Event;
|
import com.github.retucio.neutrino.Event;
|
||||||
import me.retucio.sputnik.mixin.mixins.player.ClientPlayerInteractionManagerMixin;
|
import me.retucio.sputnik.mixin.mixins.player.MultiPlayerGameModeMixin;
|
||||||
import net.minecraft.util.Hand;
|
import net.minecraft.world.InteractionHand;
|
||||||
import net.minecraft.util.hit.BlockHitResult;
|
import net.minecraft.world.phys.BlockHitResult;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see ClientPlayerInteractionManagerMixin#onBlockPlace
|
* @see MultiPlayerGameModeMixin#onBlockPlace
|
||||||
*/
|
*/
|
||||||
public class PlaceBlockEvent extends Event {
|
public class PlaceBlockEvent extends Event {
|
||||||
|
|
||||||
private Hand hand;
|
private InteractionHand hand;
|
||||||
private BlockHitResult result;
|
private BlockHitResult result;
|
||||||
|
|
||||||
public PlaceBlockEvent(Hand hand, BlockHitResult result) {
|
public PlaceBlockEvent(InteractionHand hand, BlockHitResult result) {
|
||||||
this.hand = hand;
|
this.hand = hand;
|
||||||
this.result = result;
|
this.result = result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Hand getHand() {
|
public InteractionHand getHand() {
|
||||||
return hand;
|
return hand;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setHand(Hand hand) {
|
public void setHand(InteractionHand hand) {
|
||||||
this.hand = hand;
|
this.hand = hand;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
package me.retucio.sputnik.event.interact;
|
||||||
|
|
||||||
|
import com.github.retucio.neutrino.Event;
|
||||||
|
import net.minecraft.world.item.ItemStack;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
|
||||||
|
public class UpdateInventoryEvent extends Event {
|
||||||
|
|
||||||
|
private final List<ItemStack> prev;
|
||||||
|
|
||||||
|
public UpdateInventoryEvent(List<ItemStack> prev) {
|
||||||
|
this.prev = prev;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<ItemStack> getPrev() {
|
||||||
|
return prev;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,20 +1,21 @@
|
|||||||
package me.retucio.sputnik.event.interact;
|
package me.retucio.sputnik.event.interact;
|
||||||
|
|
||||||
import com.github.retucio.neutrino.Event;
|
import com.github.retucio.neutrino.Event;
|
||||||
import me.retucio.sputnik.mixin.mixins.misc.MinecraftClientMixin;
|
import me.retucio.sputnik.mixin.mixins.misc.MinecraftMixin;
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.world.InteractionHand;
|
||||||
import net.minecraft.util.Hand;
|
import net.minecraft.world.item.Item;
|
||||||
|
import net.minecraft.world.item.ItemStack;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see MinecraftClientMixin#onUseItem
|
* @see MinecraftMixin#onUseItem
|
||||||
*/
|
*/
|
||||||
public class UseItemEvent extends Event {
|
public class UseItemEvent extends Event {
|
||||||
|
|
||||||
private ItemStack stack;
|
private ItemStack stack;
|
||||||
private Hand hand;
|
private InteractionHand hand;
|
||||||
|
|
||||||
public UseItemEvent(ItemStack stack, Hand hand) {
|
public UseItemEvent(ItemStack stack, InteractionHand hand) {
|
||||||
this.stack = stack;
|
this.stack = stack;
|
||||||
this.hand = hand;
|
this.hand = hand;
|
||||||
}
|
}
|
||||||
@@ -27,11 +28,15 @@ public class UseItemEvent extends Event {
|
|||||||
this.stack = stack;
|
this.stack = stack;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Hand getHand() {
|
public Item getItem() {
|
||||||
|
return stack.getItem();
|
||||||
|
}
|
||||||
|
|
||||||
|
public InteractionHand getHand() {
|
||||||
return hand;
|
return hand;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setHand(Hand hand) {
|
public void setHand(InteractionHand hand) {
|
||||||
this.hand = hand;
|
this.hand = hand;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,12 +1,12 @@
|
|||||||
package me.retucio.sputnik.event.network;
|
package me.retucio.sputnik.event.network;
|
||||||
|
|
||||||
import com.github.retucio.neutrino.Event;
|
import com.github.retucio.neutrino.Event;
|
||||||
import me.retucio.sputnik.mixin.mixins.world.ClientWorldMixin;
|
import me.retucio.sputnik.mixin.mixins.world.ClientLevelMixin;
|
||||||
import net.minecraft.entity.Entity;
|
import net.minecraft.world.entity.Entity;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see ClientWorldMixin#onAddEntity
|
* @see ClientLevelMixin#onAddEntity
|
||||||
*/
|
*/
|
||||||
public class AddEntityEvent extends Event {
|
public class AddEntityEvent extends Event {
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
package me.retucio.sputnik.event.network;
|
package me.retucio.sputnik.event.network;
|
||||||
|
|
||||||
import com.github.retucio.neutrino.Event;
|
import com.github.retucio.neutrino.Event;
|
||||||
import me.retucio.sputnik.mixin.mixins.world.ChunkOcclusionDataBuilderMixin;
|
import me.retucio.sputnik.mixin.mixins.world.VisGraphMixin;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see ChunkOcclusionDataBuilderMixin#onChunkOcclusion
|
* @see VisGraphMixin#onChunkOcclusion
|
||||||
*/
|
*/
|
||||||
public class ChunkOcclusionEvent extends Event {}
|
public class ChunkOcclusionEvent extends Event {}
|
||||||
@@ -1,29 +1,29 @@
|
|||||||
package me.retucio.sputnik.event.network;
|
package me.retucio.sputnik.event.network;
|
||||||
|
|
||||||
import com.github.retucio.neutrino.Event;
|
import com.github.retucio.neutrino.Event;
|
||||||
import me.retucio.sputnik.mixin.mixins.network.ClientConnectionMixin;
|
import me.retucio.sputnik.mixin.mixins.network.ConnectionMixin;
|
||||||
import net.minecraft.client.network.ServerInfo;
|
import net.minecraft.client.multiplayer.ServerData;
|
||||||
import net.minecraft.network.DisconnectionInfo;
|
import net.minecraft.network.DisconnectionDetails;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see ClientConnectionMixin#onDisconnect
|
* @see ConnectionMixin#onDisconnect
|
||||||
*/
|
*/
|
||||||
public class DisconnectEvent extends Event {
|
public class DisconnectEvent extends Event {
|
||||||
|
|
||||||
private final DisconnectionInfo info;
|
private final DisconnectionDetails details;
|
||||||
private final ServerInfo server;
|
private final ServerData server;
|
||||||
|
|
||||||
public DisconnectEvent(DisconnectionInfo info, ServerInfo server) {
|
public DisconnectEvent(DisconnectionDetails details, ServerData server) {
|
||||||
this.info = info;
|
this.details = details;
|
||||||
this.server = server;
|
this.server = server;
|
||||||
}
|
}
|
||||||
|
|
||||||
public DisconnectionInfo getInfo() {
|
public DisconnectionDetails getDetails() {
|
||||||
return info;
|
return details;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ServerInfo getServer() {
|
public ServerData getServer() {
|
||||||
return server;
|
return server;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,22 +1,23 @@
|
|||||||
package me.retucio.sputnik.event.network;
|
package me.retucio.sputnik.event.network;
|
||||||
|
|
||||||
import com.github.retucio.neutrino.Event;
|
import com.github.retucio.neutrino.Event;
|
||||||
import me.retucio.sputnik.mixin.mixins.misc.MinecraftClientMixin;
|
import me.retucio.sputnik.mixin.mixins.misc.MinecraftMixin;
|
||||||
import net.minecraft.client.world.ClientWorld;
|
import net.minecraft.client.multiplayer.ClientLevel;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see MinecraftClientMixin#onJoinWorld
|
* @see MinecraftMixin#onJoinWorld
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class JoinWorldEvent extends Event {
|
public class JoinWorldEvent extends Event {
|
||||||
|
|
||||||
private final ClientWorld world;
|
private final ClientLevel world;
|
||||||
|
|
||||||
public JoinWorldEvent(ClientWorld world) {
|
public JoinWorldEvent(ClientLevel world) {
|
||||||
this.world = world;
|
this.world = world;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ClientWorld getWorld() {
|
public ClientLevel getWorld() {
|
||||||
return world;
|
return world;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,14 +1,14 @@
|
|||||||
package me.retucio.sputnik.event.network;
|
package me.retucio.sputnik.event.network;
|
||||||
|
|
||||||
import com.github.retucio.neutrino.Event;
|
import com.github.retucio.neutrino.Event;
|
||||||
import me.retucio.sputnik.mixin.mixins.network.ClientConnectionMixin;
|
import me.retucio.sputnik.mixin.mixins.network.ConnectionMixin;
|
||||||
import net.minecraft.network.packet.Packet;
|
import net.minecraft.network.protocol.Packet;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see ClientConnectionMixin#onSendPacketPre
|
* @see ConnectionMixin#onSendPacketPre
|
||||||
* @see ClientConnectionMixin#onSendPacketPost
|
* @see ConnectionMixin#onSendPacketPost
|
||||||
* @see ClientConnectionMixin#onReceivePacket
|
* @see ConnectionMixin#onReceivePacket
|
||||||
*/
|
*/
|
||||||
public class PacketEvent {
|
public class PacketEvent {
|
||||||
|
|
||||||
|
|||||||
@@ -1,41 +1,43 @@
|
|||||||
package me.retucio.sputnik.event.network;
|
package me.retucio.sputnik.event.network;
|
||||||
|
|
||||||
import com.github.retucio.neutrino.Event;
|
import com.github.retucio.neutrino.Event;
|
||||||
import me.retucio.sputnik.mixin.mixins.hud.ChatHudMixin;
|
import me.retucio.sputnik.mixin.mixins.hud.ChatComponentMixin;
|
||||||
import net.minecraft.client.gui.hud.MessageIndicator;
|
import net.minecraft.client.multiplayer.chat.GuiMessageTag;
|
||||||
import net.minecraft.text.Text;
|
import net.minecraft.network.chat.Component;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see ChatHudMixin#onAddMessage
|
* @see ChatComponentMixin#onAddMessage
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class ReceiveMessageEvent extends Event {
|
public class ReceiveMessageEvent extends Event {
|
||||||
|
|
||||||
private Text text;
|
private Component text;
|
||||||
private MessageIndicator indicator;
|
private GuiMessageTag tag;
|
||||||
private final int id;
|
private final int id;
|
||||||
private boolean modified = false;
|
private boolean modified = false;
|
||||||
|
|
||||||
public ReceiveMessageEvent(Text text, MessageIndicator indicator, int id) {
|
public ReceiveMessageEvent(Component text, GuiMessageTag tag, int id) {
|
||||||
this.text = text;
|
this.text = text;
|
||||||
this.indicator = indicator;
|
this.tag = tag;
|
||||||
this.id = id;
|
this.id = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Text getMessage() {
|
public Component getMessage() {
|
||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
|
|
||||||
public MessageIndicator getIndicator() {
|
public GuiMessageTag getTag() {
|
||||||
return indicator;
|
return tag;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setMessage(Text message) {
|
public void setMessage(Component message) {
|
||||||
this.text = message;
|
this.text = message;
|
||||||
this.modified = true;
|
this.modified = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setIndicator(MessageIndicator indicator) {
|
public void setTag(GuiMessageTag tag) {
|
||||||
this.indicator = indicator;
|
this.tag = tag;
|
||||||
this.modified = true;
|
this.modified = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
package me.retucio.sputnik.event.network;
|
package me.retucio.sputnik.event.network;
|
||||||
|
|
||||||
import com.github.retucio.neutrino.Event;
|
import com.github.retucio.neutrino.Event;
|
||||||
import me.retucio.sputnik.mixin.mixins.world.ClientWorldMixin;
|
import me.retucio.sputnik.mixin.mixins.world.ClientLevelMixin;
|
||||||
import net.minecraft.entity.Entity;
|
import net.minecraft.world.entity.Entity;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see ClientWorldMixin#onRemoveEntity
|
* @see ClientLevelMixin#onRemoveEntity
|
||||||
*/
|
*/
|
||||||
public class RemoveEntityEvent extends Event {
|
public class RemoveEntityEvent extends Event {
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
package me.retucio.sputnik.event.network;
|
package me.retucio.sputnik.event.network;
|
||||||
|
|
||||||
import com.github.retucio.neutrino.Event;
|
import com.github.retucio.neutrino.Event;
|
||||||
import me.retucio.sputnik.mixin.mixins.network.ClientPlayNetworkHandlerMixin;
|
import me.retucio.sputnik.mixin.mixins.network.ClientPacketListenerMixin;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see ClientPlayNetworkHandlerMixin#onSendMessage
|
* @see ClientPacketListenerMixin#onSendMessage
|
||||||
*/
|
*/
|
||||||
public class SendMessageEvent extends Event {
|
public class SendMessageEvent extends Event {
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
package me.retucio.sputnik.event.render;
|
||||||
|
|
||||||
|
import com.github.retucio.neutrino.Event;
|
||||||
|
import net.minecraft.client.resources.model.cuboid.ItemTransform;
|
||||||
|
|
||||||
|
|
||||||
|
public class ApplyTransformationEvent extends Event {
|
||||||
|
|
||||||
|
private final ItemTransform transformation;
|
||||||
|
private final boolean leftHanded;
|
||||||
|
|
||||||
|
public ApplyTransformationEvent(ItemTransform transformation, boolean leftHanded) {
|
||||||
|
this.transformation = transformation;
|
||||||
|
this.leftHanded = leftHanded;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ItemTransform getTransformation() {
|
||||||
|
return transformation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isLeftHanded() {
|
||||||
|
return leftHanded;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,26 +1,26 @@
|
|||||||
package me.retucio.sputnik.event.render;
|
package me.retucio.sputnik.event.render;
|
||||||
|
|
||||||
import com.github.retucio.neutrino.Event;
|
import com.github.retucio.neutrino.Event;
|
||||||
import me.retucio.sputnik.mixin.mixins.misc.GameOptionsMixin;
|
import me.retucio.sputnik.mixin.mixins.misc.OptionsMixin;
|
||||||
import net.minecraft.client.option.Perspective;
|
import net.minecraft.client.CameraType;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see GameOptionsMixin#changePerspective
|
* @see OptionsMixin#changePerspective
|
||||||
*/
|
*/
|
||||||
public class PerspectiveChangeEvent extends Event {
|
public class PerspectiveChangeEvent extends Event {
|
||||||
|
|
||||||
private Perspective perspective;
|
private CameraType perspective;
|
||||||
|
|
||||||
public PerspectiveChangeEvent(Perspective perspective) {
|
public PerspectiveChangeEvent(CameraType perspective) {
|
||||||
this.perspective = perspective;
|
this.perspective = perspective;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Perspective getPerspective() {
|
public CameraType getPerspective() {
|
||||||
return perspective;
|
return perspective;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setPerspective(Perspective perspective) {
|
public void setPerspective(CameraType perspective) {
|
||||||
this.perspective = perspective;
|
this.perspective = perspective;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,24 +1,26 @@
|
|||||||
package me.retucio.sputnik.event.render;
|
package me.retucio.sputnik.event.render;
|
||||||
|
|
||||||
import com.github.retucio.neutrino.Event;
|
import com.github.retucio.neutrino.Event;
|
||||||
import net.minecraft.client.gui.DrawContext;
|
|
||||||
import net.minecraft.client.render.RenderTickCounter;
|
import net.minecraft.client.DeltaTracker;
|
||||||
|
import net.minecraft.client.gui.GuiGraphicsExtractor;
|
||||||
|
|
||||||
|
|
||||||
public class Render2DEvent extends Event {
|
public class Render2DEvent extends Event {
|
||||||
|
|
||||||
private final DrawContext ctx;
|
private final GuiGraphicsExtractor gui;
|
||||||
private final RenderTickCounter tc;
|
private final DeltaTracker dt;
|
||||||
|
|
||||||
public Render2DEvent(DrawContext ctx, RenderTickCounter tc) {
|
public Render2DEvent(GuiGraphicsExtractor gui, DeltaTracker dt) {
|
||||||
this.ctx = ctx;
|
this.gui = gui;
|
||||||
this.tc = tc;
|
this.dt = dt;
|
||||||
}
|
}
|
||||||
|
|
||||||
public DrawContext getCtx() {
|
public GuiGraphicsExtractor getGui() {
|
||||||
return ctx;
|
return gui;
|
||||||
}
|
}
|
||||||
|
|
||||||
public RenderTickCounter getTc() {
|
public DeltaTracker getDt() {
|
||||||
return tc;
|
return dt;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,36 +1,42 @@
|
|||||||
package me.retucio.sputnik.event.render;
|
package me.retucio.sputnik.event.render;
|
||||||
|
|
||||||
import com.github.retucio.neutrino.Event;
|
import com.github.retucio.neutrino.Event;
|
||||||
import me.retucio.sputnik.mixin.mixins.render.WorldRendererMixin;
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
import net.minecraft.client.render.Camera;
|
import me.retucio.sputnik.mixin.mixins.render.LevelRendererMixin;
|
||||||
import net.minecraft.client.render.RenderTickCounter;
|
import net.minecraft.client.Camera;
|
||||||
import net.minecraft.client.util.math.MatrixStack;
|
import net.minecraft.client.DeltaTracker;
|
||||||
|
import net.minecraft.client.renderer.state.level.CameraRenderState;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see WorldRendererMixin#render
|
* @see LevelRendererMixin#renderLevel
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class Render3DEvent extends Event {
|
public class Render3DEvent extends Event {
|
||||||
|
|
||||||
private final MatrixStack matrices;
|
private final PoseStack matrices;
|
||||||
private final RenderTickCounter tc;
|
private final DeltaTracker dt;
|
||||||
private final Camera camera;
|
private final CameraRenderState cameraState;
|
||||||
|
|
||||||
public Render3DEvent(MatrixStack matrices, RenderTickCounter tc, Camera camera) {
|
public Render3DEvent(PoseStack matrices, DeltaTracker dt, CameraRenderState cameraState) {
|
||||||
this.matrices = matrices;
|
this.matrices = matrices;
|
||||||
this.tc = tc;
|
this.dt = dt;
|
||||||
this.camera = camera;
|
this.cameraState = cameraState;
|
||||||
}
|
}
|
||||||
|
|
||||||
public MatrixStack getMatrices() {
|
public PoseStack getMatrices() {
|
||||||
return matrices;
|
return matrices;
|
||||||
}
|
}
|
||||||
|
|
||||||
public RenderTickCounter getTickCounter() {
|
public DeltaTracker getDeltaTracker() {
|
||||||
return tc;
|
return dt;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Camera getCamera() {
|
public CameraRenderState getCamera() {
|
||||||
return camera;
|
return cameraState;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getTickDelta() {
|
||||||
|
return dt.getGameTimeDeltaTicks();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,37 +1,37 @@
|
|||||||
package me.retucio.sputnik.event.render;
|
package me.retucio.sputnik.event.render;
|
||||||
|
|
||||||
import com.github.retucio.neutrino.Event;
|
import com.github.retucio.neutrino.Event;
|
||||||
import me.retucio.sputnik.mixin.mixins.render.HeldItemRendererMixin;
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
import net.minecraft.client.util.math.MatrixStack;
|
import me.retucio.sputnik.mixin.mixins.render.ItemInHandRendererMixin;
|
||||||
import net.minecraft.util.Hand;
|
import net.minecraft.world.InteractionHand;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see HeldItemRendererMixin#onRenderArm
|
* @see ItemInHandRendererMixin#onRenderArm
|
||||||
*/
|
*/
|
||||||
public class RenderArmEvent extends Event {
|
public class RenderArmEvent extends Event {
|
||||||
|
|
||||||
private MatrixStack matrices;
|
private PoseStack matrices;
|
||||||
private Hand hand;
|
private InteractionHand hand;
|
||||||
|
|
||||||
public RenderArmEvent(MatrixStack matrices, Hand hand) {
|
public RenderArmEvent(PoseStack matrices, InteractionHand hand) {
|
||||||
this.matrices = matrices;
|
this.matrices = matrices;
|
||||||
this.hand = hand;
|
this.hand = hand;
|
||||||
}
|
}
|
||||||
|
|
||||||
public MatrixStack getMatrices() {
|
public PoseStack getMatrices() {
|
||||||
return matrices;
|
return matrices;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setMatrices(MatrixStack matrices) {
|
public void setMatrices(PoseStack matrices) {
|
||||||
this.matrices = matrices;
|
this.matrices = matrices;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Hand getHand() {
|
public InteractionHand getHand() {
|
||||||
return hand;
|
return hand;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setHand(Hand hand) {
|
public void setHand(InteractionHand hand) {
|
||||||
this.hand = hand;
|
this.hand = hand;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2,9 +2,10 @@ package me.retucio.sputnik.event.render;
|
|||||||
|
|
||||||
import com.github.retucio.neutrino.Event;
|
import com.github.retucio.neutrino.Event;
|
||||||
import me.retucio.sputnik.mixin.mixins.hud.BossBarHudMixin;
|
import me.retucio.sputnik.mixin.mixins.hud.BossBarHudMixin;
|
||||||
import net.minecraft.client.gui.hud.ClientBossBar;
|
import net.minecraft.client.gui.components.LerpingBossEvent;
|
||||||
import net.minecraft.text.Text;
|
import net.minecraft.network.chat.MutableComponent;
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
|
||||||
|
|
||||||
@@ -17,27 +18,27 @@ public class RenderBossbarEvent {
|
|||||||
|
|
||||||
public static class BossText extends Event {
|
public static class BossText extends Event {
|
||||||
|
|
||||||
private ClientBossBar bossBar;
|
private LerpingBossEvent bossBar;
|
||||||
private Text name;
|
private MutableComponent name;
|
||||||
|
|
||||||
public BossText(ClientBossBar bossBar, Text name) {
|
public BossText(LerpingBossEvent bossBar, MutableComponent name) {
|
||||||
this.bossBar = bossBar;
|
this.bossBar = bossBar;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ClientBossBar getBossBar() {
|
public LerpingBossEvent getBossBar() {
|
||||||
return bossBar;
|
return bossBar;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setBossBar(ClientBossBar bossBar) {
|
public void setBossBar(LerpingBossEvent bossBar) {
|
||||||
this.bossBar = bossBar;
|
this.bossBar = bossBar;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Text getName() {
|
public MutableComponent getName() {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setName(Text name) {
|
public void setName(MutableComponent name) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -61,17 +62,17 @@ public class RenderBossbarEvent {
|
|||||||
|
|
||||||
public static class BossIterator extends Event {
|
public static class BossIterator extends Event {
|
||||||
|
|
||||||
private Iterator<ClientBossBar> iterator;
|
private Iterator<LerpingBossEvent> iterator;
|
||||||
|
|
||||||
public BossIterator(Iterator<ClientBossBar> iterator) {
|
public BossIterator(Iterator<LerpingBossEvent> iterator) {
|
||||||
this.iterator = iterator;
|
this.iterator = iterator;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Iterator<ClientBossBar> getIterator() {
|
public Iterator<LerpingBossEvent> getIterator() {
|
||||||
return iterator;
|
return iterator;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setIterator(Iterator<ClientBossBar> iterator) {
|
public void setIterator(Iterator<LerpingBossEvent> iterator) {
|
||||||
this.iterator = iterator;
|
this.iterator = iterator;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,37 +1,38 @@
|
|||||||
package me.retucio.sputnik.event.render;
|
package me.retucio.sputnik.event.render;
|
||||||
|
|
||||||
import com.github.retucio.neutrino.Event;
|
import com.github.retucio.neutrino.Event;
|
||||||
import me.retucio.sputnik.mixin.mixins.render.HeldItemRendererMixin;
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
import net.minecraft.client.util.math.MatrixStack;
|
import me.retucio.sputnik.mixin.mixins.render.ItemInHandRendererMixin;
|
||||||
import net.minecraft.util.Hand;
|
import net.minecraft.world.InteractionHand;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see HeldItemRendererMixin#onRenderItem
|
* @see ItemInHandRendererMixin#onRenderItem
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class RenderHeldItemEvent extends Event {
|
public class RenderHeldItemEvent extends Event {
|
||||||
|
|
||||||
private MatrixStack matrices;
|
private PoseStack matrices;
|
||||||
private Hand hand;
|
private InteractionHand hand;
|
||||||
|
|
||||||
public RenderHeldItemEvent(MatrixStack matrices, Hand hand) {
|
public RenderHeldItemEvent(PoseStack matrices, InteractionHand hand) {
|
||||||
this.matrices = matrices;
|
this.matrices = matrices;
|
||||||
this.hand = hand;
|
this.hand = hand;
|
||||||
}
|
}
|
||||||
|
|
||||||
public MatrixStack getMatrices() {
|
public PoseStack getMatrices() {
|
||||||
return matrices;
|
return matrices;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setMatrices(MatrixStack matrices) {
|
public void setMatrices(PoseStack matrices) {
|
||||||
this.matrices = matrices;
|
this.matrices = matrices;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Hand getHand() {
|
public InteractionHand getHand() {
|
||||||
return hand;
|
return hand;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setHand(Hand hand) {
|
public void setHand(InteractionHand hand) {
|
||||||
this.hand = hand;
|
this.hand = hand;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
package me.retucio.sputnik.event.render;
|
||||||
|
|
||||||
|
import com.github.retucio.neutrino.Event;
|
||||||
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
|
import me.retucio.sputnik.mixinterfaces.IEntityRenderState;
|
||||||
|
import net.minecraft.client.renderer.SubmitNodeCollector;
|
||||||
|
import net.minecraft.client.renderer.entity.state.ItemEntityRenderState;
|
||||||
|
import net.minecraft.world.entity.item.ItemEntity;
|
||||||
|
|
||||||
|
public class RenderItemEntityEvent extends Event {
|
||||||
|
|
||||||
|
public final ItemEntity itemEntity;
|
||||||
|
public final ItemEntityRenderState renderState;
|
||||||
|
public final PoseStack matrixStack;
|
||||||
|
public final SubmitNodeCollector renderCommandQueue;
|
||||||
|
public final int light;
|
||||||
|
|
||||||
|
public RenderItemEntityEvent(ItemEntityRenderState renderState, PoseStack matrixStack, SubmitNodeCollector renderCommandQueue, int light) {
|
||||||
|
this.itemEntity = (ItemEntity) ((IEntityRenderState) renderState).sputnik$getEntity();
|
||||||
|
this.renderState = renderState;
|
||||||
|
this.matrixStack = matrixStack;
|
||||||
|
this.renderCommandQueue = renderCommandQueue;
|
||||||
|
this.light = light;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,7 +3,7 @@ package me.retucio.sputnik.event.sputnik;
|
|||||||
import com.github.retucio.neutrino.Event;
|
import com.github.retucio.neutrino.Event;
|
||||||
|
|
||||||
// se genera cada que se interactúa con el marco de ajustes de la interfaz
|
// se genera cada que se interactúa con el marco de ajustes de la interfaz
|
||||||
public class GUISettingsFrameEvent {
|
public class ClientSettingsPanelEvent {
|
||||||
|
|
||||||
public static class Extend extends Event {} // al extenderlo / contraerlo
|
public static class Extend extends Event {} // al extenderlo / contraerlo
|
||||||
public static class Move extends Event {} // al cambiarlo de posición
|
public static class Move extends Event {} // al cambiarlo de posición
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
package me.retucio.sputnik.event.sputnik;
|
||||||
|
|
||||||
|
import com.github.retucio.neutrino.Event;
|
||||||
|
import me.retucio.sputnik.friend.Friend;
|
||||||
|
|
||||||
|
|
||||||
|
// evento lanzado cuando se agrega, elimina o renombra un amigo
|
||||||
|
public class FriendEvent extends Event {
|
||||||
|
|
||||||
|
private final Friend friend;
|
||||||
|
|
||||||
|
public FriendEvent(Friend friend) {
|
||||||
|
this.friend = friend;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Friend getFriend() {
|
||||||
|
return friend;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Add extends FriendEvent {
|
||||||
|
public Add(Friend friend) { super(friend); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Remove extends FriendEvent {
|
||||||
|
public Remove(Friend friend) { super(friend); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Rename extends FriendEvent {
|
||||||
|
public Rename(Friend friend) { super(friend); }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,4 +3,4 @@ package me.retucio.sputnik.event.sputnik;
|
|||||||
import com.github.retucio.neutrino.Event;
|
import com.github.retucio.neutrino.Event;
|
||||||
|
|
||||||
// se genera cuando carga la interfaz del mod
|
// se genera cuando carga la interfaz del mod
|
||||||
public class LoadClickGUIEvent extends Event {}
|
public class LoadClickGuiEvent extends Event {}
|
||||||