This commit is contained in:
retucio committed 2026-09-06 11:55:58 +02:00
1 parent 44494830be
commit c1a03f3ddb
26 files changed
+226 -105

No files matched your search

@@ -3,6 +3,7 @@ package me.retucio.sputnik.module.modules.render;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import me.retucio.sputnik.Sputnik;
import me.retucio.sputnik.config.ConfigManager;
import me.retucio.sputnik.mixin.mixins.entity.EntityMixin;
import me.retucio.sputnik.mixin.mixins.entity.ItemEntityMixin;
import me.retucio.sputnik.mixin.mixins.player.PlayerMixin;
@@ -90,7 +91,7 @@ public class Nametags extends Module {
defaultEntities.replace(EntityTypes.TNT, true);
entities.setDefaultValue(defaultEntities);
health.onUpdate(v -> healthMode.visibility(v));
health.onUpdate(healthMode::visibility);
entities.onUpdate(entities -> {
items.visibility(entities.get(EntityTypes.ITEM));
@@ -131,7 +132,7 @@ public class Nametags extends Module {
@SuppressWarnings("deprecation")
public String getOwnerName(EntityReference<LivingEntity> owner) {
// si el dueño está en línea (de manera segura)
if (mc.level instanceof UniquelyIdentifyable queriableWorld) { // UUIDLookup<?> ??
if (mc.level instanceof UniquelyIdentifyable queriableWorld) {
LivingEntity ownerEntity = owner.resolve(queriableWorld, LivingEntity.class);
if (ownerEntity instanceof Player playerEntity) return playerEntity.getName().getString();
}
@@ -79,6 +79,8 @@ public class ClickGui extends Screen {
private final ProfilesTab profilesTab = new ProfilesTab();
private final MacrosTab macrosTab = new MacrosTab();
private static final int PLACEMENT_SEARCH_STEP = 8;
public ClickGui() {
super(Component.translatable("sputnik.ui.clickgui.title"));
Sputnik.EVENT_BUS.subscribe(this);
@@ -202,6 +204,49 @@ public class ClickGui extends Screen {
return bottom + 20; // padding
}
private int[] findEmptyPosition(int w, int h, int preferredX, int preferredY) {
int screenWidth = mc.getWindow().getGuiScaledWidth();
int maxX = Math.max(0, screenWidth - w);
int startX = Math.clamp(preferredX, 0, maxX);
int startY = Math.max(preferredY, 0);
int searchBottom = calculateContentHeight() + h;
for (int y = startY; y <= searchBottom; y += PLACEMENT_SEARCH_STEP) {
for (int candidateX = 0; candidateX <= maxX; candidateX += PLACEMENT_SEARCH_STEP) {
if (!overlapsAnything(candidateX, y, w, h)) {
return new int[]{candidateX, y};
}
}
}
// no hay hueco: colocarlo debajo de todo lo demás, para llegar a él haciendo scroll
return new int[]{startX, calculateContentHeight()};
}
private boolean overlapsAnything(int x, int y, int w, int h) {
for (ModulePanel mp : modulePanels) {
int mpHeight = mp.getH() + (mp.isExtended() ? mp.getTotalHeight() : 0);
if (rectsOverlap(x, y, w, h, mp.getX(), mp.getY(), mp.getW(), mpHeight)) return true;
}
for (SettingsPanel sp : settingsPanels) {
int spHeight = sp.getH() + sp.getTotalHeight();
if (rectsOverlap(x, y, w, h, sp.getX(), sp.getY(), sp.getW(), spHeight)) return true;
}
int friendsHeight = friendsPanel.getH() + (friendsPanel.isExtended() ? friendsPanel.getTotalHeight() : 0);
if (rectsOverlap(x, y, w, h, friendsPanel.getX(), friendsPanel.getY(), friendsPanel.getW(), friendsHeight)) return true;
int clientHeight = clientSettingsPanel.getH() + (clientSettingsPanel.isExtended() ? clientSettingsPanel.getTotalHeight() : 0);
return rectsOverlap(x, y, w, h, clientSettingsPanel.getX(), clientSettingsPanel.getY(), clientSettingsPanel.getW(), clientHeight);
}
private boolean rectsOverlap(int ax, int ay, int aw, int ah, int bx, int by, int bw, int bh) {
return ax < bx + bw && ax + aw > bx
&& ay < by + bh && ay + ah > by;
}
@Override
public boolean mouseClicked(MouseButtonEvent click, boolean doubled) {
int x = (int) click.x();
@@ -433,12 +478,18 @@ public class ClickGui extends Screen {
);
}
// abrir un marco donde se encuentran los ajustes del módulo deseado
// abrir un marco donde se encuentran los ajustes del módulo deseado, buscando un
// hueco libre cerca de (x, y) para que no se solape con otros paneles ya abiertos
public void openSettingsPanel(Module module, int x, int y) {
// asegurarse de que no se sale de la pantalla
x = Math.clamp(x, 0, mc.getWindow().getGuiScaledWidth() - 80);
SettingsPanel panel = new SettingsPanel(module, 0, 0, 100, 20);
panel.updateTotalHeight(); // altura real disponible ya tras el constructor
int panelHeight = panel.getH() + panel.getTotalHeight();
int[] position = findEmptyPosition(panel.getW(), panelHeight, x, y);
panel.setX(position[0]);
panel.setY(position[1]);
SettingsPanel panel = new SettingsPanel(module, x, y, 100, 20);
settingsPanels.add(panel);
Sputnik.EVENT_BUS.post(new SettingsPanelEvent.Open(panel));
@@ -9,10 +9,6 @@ import java.util.function.Supplier;
public abstract class Panel<B extends Button> extends Widget {
// el título se resuelve al pintarlo, no al construir el marco: los marcos se crean en
// la inicialización del mod, cuando el idioma todavía no ha cargado, así que guardar el
// texto ya traducido dejaba los títulos en español para siempre (y no cambiaban aunque
// se cambiara el idioma del juego en marcha)
private Supplier<String> title;
protected final List<B> buttons = new ArrayList<>();
@@ -8,7 +8,6 @@ import me.retucio.sputnik.module.setting.settings.*;
import me.retucio.sputnik.ui.widgets.buttons.settings.*;
import me.retucio.sputnik.ui.screen.ClickGui;
import me.retucio.sputnik.ui.widgets.buttons.*;
import me.retucio.sputnik.ui.widgets.Panel;
import me.retucio.sputnik.util.Colors;
import me.retucio.sputnik.util.I18nUtil;
@@ -43,6 +42,7 @@ public class SettingsPanel extends CloseablePanel<SettingButton<? extends Settin
@Override
public void render(GuiGraphicsExtractor gui, int mouseX, int mouseY, float delta) {
updateWidth();
updateTotalHeight();
int centerX = x + w / 2;
int centerY = renderY + h / 2;
@@ -77,31 +77,8 @@ public class SettingsPanel extends CloseablePanel<SettingButton<? extends Settin
int descBoxTop = renderY + h + PADDING;
int descBoxBottom = descBoxTop + descHeight + PADDING * 2;
totalHeight = descHeight + 3 * PADDING;
int currentY;
// obtener valores de altura y tal
for (SettingGroup group : settingGroups) {
if (hasVisibleSettingsInGroup(group)) {
totalHeight += h + PADDING;
if (group.isExtended()) {
List<SettingButton<?>> groupButtons = getButtonsForGroup(group);
for (int j = 0; j < groupButtons.size(); j++) {
SettingButton<?> sb = groupButtons.get(j);
if (sb.getSetting().isVisible() && sb.getSetting().isSearchMatch()) {
if (j < groupButtons.size() - 1) {
totalHeight += (h - h / 4) + PADDING;
} else {
totalHeight += (h - h / 4);
}
}
}
totalHeight += PADDING;
}
}
}
// fondo del marco
gui.fill(x, descBoxTop - PADDING + 1, x + w, descBoxTop + totalHeight, Colors.panelBgColor.getRGB());
@@ -112,10 +89,9 @@ public class SettingsPanel extends CloseablePanel<SettingButton<? extends Settin
currentY = descBoxBottom + PADDING;
// dibujar botones y cabezales
for (int i = 0; i < settingGroups.size(); i++) {
SettingGroup group = settingGroups.get(i);
for (SettingGroup group : settingGroups) {
if (hasVisibleSettingsInGroup(group)) {
int groupHeaderColor = isGroupHeaderHovered(mouseX, mouseY, i)
int groupHeaderColor = isGroupHeaderHovered(mouseX, mouseY, group)
? Colors.buttonColor.brighter().getRGB()
: Colors.buttonColor.getRGB();
@@ -176,9 +152,8 @@ public class SettingsPanel extends CloseablePanel<SettingButton<? extends Settin
}
}
for (int i = 0; i < settingGroups.size(); i++) {
SettingGroup group = settingGroups.get(i);
if (hasVisibleSettingsInGroup(group) && isGroupHeaderHovered(mouseX, mouseY, i)) {
for (SettingGroup group : settingGroups) {
if (hasVisibleSettingsInGroup(group) && isGroupHeaderHovered(mouseX, mouseY, group)) {
group.setExtended(!group.isExtended());
updateVisibleButtonsForGroup(group);
return;
@@ -239,6 +214,36 @@ public class SettingsPanel extends CloseablePanel<SettingButton<? extends Settin
this.w = maxWidth + 30;
}
public void updateTotalHeight() {
List<String> descLines = wrapDescription(module.getDisplayDescription(), w - 2 * PADDING);
int descHeight = descLines.size() * mc.font.lineHeight + (descLines.size() - 1) * 2;
int height = descHeight + 3 * PADDING;
for (SettingGroup group : settingGroups) {
if (!hasVisibleSettingsInGroup(group)) continue;
height += h + PADDING;
if (group.isExtended()) {
List<SettingButton<?>> groupButtons = getButtonsForGroup(group);
for (int j = 0; j < groupButtons.size(); j++) {
SettingButton<?> sb = groupButtons.get(j);
if (sb.getSetting().isVisible() && sb.getSetting().isSearchMatch()) {
if (j < groupButtons.size() - 1) {
height += (h - h / 4) + PADDING;
} else {
height += (h - h / 4);
}
}
}
height += PADDING;
}
}
totalHeight = height;
}
public void updatePosition(double mouseX, double mouseY) {
if (dragging) {
x = (int) (mouseX - dragX);
@@ -246,44 +251,40 @@ public class SettingsPanel extends CloseablePanel<SettingButton<? extends Settin
}
}
public int getGroupHeaderY(int groupIndex) {
public int getGroupHeaderY(SettingGroup targetGroup) {
int currentY = renderY + h + PADDING;
List<String> descLines = wrapDescription(module.getDisplayDescription(), w - 2 * PADDING);
int descHeight = descLines.size() * mc.font.lineHeight + (descLines.size() - 1) * 2;
currentY += descHeight + 3 * PADDING; // descBoxBottom + padding
// iterar hasta llegar al grupo deseado
int currentIndex = 0;
for (SettingGroup group : settingGroups) {
if (hasVisibleSettingsInGroup(group)) {
if (currentIndex == groupIndex) {
return currentY;
}
if (!hasVisibleSettingsInGroup(group)) continue;
if (group == targetGroup) {
return currentY;
}
currentY += h + PADDING;
currentY += h + PADDING;
if (group.isExtended()) {
List<SettingButton<?>> groupButtons = getButtonsForGroup(group);
for (int j = 0; j < groupButtons.size(); j++) {
SettingButton<?> sb = groupButtons.get(j);
if (sb.getSetting().isVisible() && sb.getSetting().isSearchMatch()) {
if (j < groupButtons.size() - 1) {
currentY += (h - h / 4) + PADDING;
} else {
currentY += (h - h / 4);
}
if (group.isExtended()) {
List<SettingButton<?>> groupButtons = getButtonsForGroup(group);
for (int j = 0; j < groupButtons.size(); j++) {
SettingButton<?> sb = groupButtons.get(j);
if (sb.getSetting().isVisible() && sb.getSetting().isSearchMatch()) {
if (j < groupButtons.size() - 1) {
currentY += (h - h / 4) + PADDING;
} else {
currentY += (h - h / 4);
}
}
currentY += PADDING;
}
currentIndex++;
currentY += PADDING;
}
} // fallback
return currentY;
}
public boolean isGroupHeaderHovered(int mouseX, int mouseY, int groupIndex) {
int headerY = getGroupHeaderY(groupIndex);
public boolean isGroupHeaderHovered(int mouseX, int mouseY, SettingGroup group) {
int headerY = getGroupHeaderY(group);
return mouseX > x + PADDING && mouseX < x + w - PADDING &&
mouseY > headerY && mouseY < headerY + h;