From 629d03ff92e50a63610aa1cffbc669e45a02c9cb Mon Sep 17 00:00:00 2001 From: retucio Date: Mon, 14 Sep 2026 19:17:07 +0200 Subject: [PATCH] v6.5 --- cambios.md | 12 +- gradle.properties | 2 +- .../sputnik/config/BinarySerializer.java | 47 +++++- .../retucio/sputnik/config/ClientConfig.java | 45 +++-- .../retucio/sputnik/config/ConfigManager.java | 14 +- .../sputnik/event/sputnik/FriendEvent.java | 9 +- .../event/sputnik/FriendPanelEvent.java | 9 - .../me/retucio/sputnik/friend/Friend.java | 33 +++- .../retucio/sputnik/friend/FriendManager.java | 6 + .../mixins/render/LevelRendererMixin.java | 32 +++- .../modules/render/BreakingProgress.java | 6 + .../retucio/sputnik/ui/screen/ClickGui.java | 75 +-------- .../me/retucio/sputnik/ui/screen/Tab.java | 3 +- .../sputnik/ui/screen/tabs/FriendsTab.java | 101 ++++++++++++ .../ui/widgets/buttons/FriendButton.java | 75 --------- .../sputnik/ui/widgets/misc/FriendWidget.java | 156 ++++++++++++++++++ .../ui/widgets/misc/TextFieldWidget.java | 5 + .../ui/widgets/panels/FriendsPanel.java | 143 ---------------- .../panels/settings/FriendSettingsPanel.java | 102 ------------ .../resources/assets/sputnik/lang/en_us.json | 7 +- .../resources/assets/sputnik/lang/es_es.json | 7 +- 21 files changed, 433 insertions(+), 456 deletions(-) delete mode 100644 src/main/java/me/retucio/sputnik/event/sputnik/FriendPanelEvent.java create mode 100644 src/main/java/me/retucio/sputnik/ui/screen/tabs/FriendsTab.java delete mode 100644 src/main/java/me/retucio/sputnik/ui/widgets/buttons/FriendButton.java create mode 100644 src/main/java/me/retucio/sputnik/ui/widgets/misc/FriendWidget.java delete mode 100644 src/main/java/me/retucio/sputnik/ui/widgets/panels/FriendsPanel.java delete mode 100644 src/main/java/me/retucio/sputnik/ui/widgets/panels/settings/FriendSettingsPanel.java diff --git a/cambios.md b/cambios.md index 7131a93..7c1ac45 100644 --- a/cambios.md +++ b/cambios.md @@ -1,20 +1,16 @@ -# v6.4 +# v6.5 ## novedades -- README en inglés -- capturas actualizadas (las de los README) - ### adiciones -#### módulos nuevos: - ### arreglos / mejoras -- ahora la detección de clics sobre cabezales de grupos de ajustes funciona correctamente +- opción para cancelar la animación original para `progreso de minado` +- ahora los amigos se muestran en una pestaña separada en la interfaz ## problemas reconocidos - `reponer` no funciona - `copiar` tras sacar una captura con `capturas` no funciona correctamente -- lo de siempre. +- \+ lo de siempre. diff --git a/gradle.properties b/gradle.properties index a8ad369..51ea4f8 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,6 +10,6 @@ discord_rpc_version=1.0.3 neutrino_version=1.1.0 jdk_version=25 -mod_version=6.4 +mod_version=6.5 maven_group=me.retucio archives_base_name=sputnik \ No newline at end of file diff --git a/src/main/java/me/retucio/sputnik/config/BinarySerializer.java b/src/main/java/me/retucio/sputnik/config/BinarySerializer.java index 64e3d89..ab90edd 100644 --- a/src/main/java/me/retucio/sputnik/config/BinarySerializer.java +++ b/src/main/java/me/retucio/sputnik/config/BinarySerializer.java @@ -14,7 +14,7 @@ import java.util.Map; public class BinarySerializer { private static final int MAGIC_NUMBER = 0x53505554; // "SPUT" - private static final int VERSION = 3; + private static final int VERSION = 4; private static final int MIN_VERSION = 2; private static final byte TYPE_NULL = 0; @@ -72,7 +72,7 @@ public class BinarySerializer { writeStringIntArrayMap(out, config.hudPositions); writeStringBooleanMap(out, config.hudVisibilities); writeStringStringMap(out, config.hudImagePaths); - writeStringStringMap(out, config.friends); + writeFriendsMap(out, config.friends); writeMacros(out, config.macros); writeString(out, config.currentProfile); @@ -123,7 +123,9 @@ public class BinarySerializer { Map hudPositions = readStringIntArrayMap(in); Map hudVisibilities = readStringBooleanMap(in); Map hudImagePaths = readStringStringMap(in); - Map friends = readStringStringMap(in); + Map friends = version >= 4 + ? readFriendsMap(in) + : migrateFriendsMap(readStringStringMap(in)); List macros = version >= 3 ? readMacros(in) : new ArrayList<>(); String currentProfile = version >= 3 ? readString(in) : ""; @@ -422,6 +424,45 @@ public class BinarySerializer { return macros; } + private static void writeFriendsMap(DataOutputStream out, Map map) + throws IOException { + if (map == null) { + out.writeInt(0); + return; + } + out.writeInt(map.size()); + for (Map.Entry 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 readFriendsMap(DataInputStream in) + throws IOException { + int size = in.readInt(); + Map 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 migrateFriendsMap(Map legacy) { + Map map = new HashMap<>(legacy.size()); + long now = System.currentTimeMillis(); + for (Map.Entry 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 { if (str == null) { out.writeInt(-1); diff --git a/src/main/java/me/retucio/sputnik/config/ClientConfig.java b/src/main/java/me/retucio/sputnik/config/ClientConfig.java index a0061ec..f0a9b35 100644 --- a/src/main/java/me/retucio/sputnik/config/ClientConfig.java +++ b/src/main/java/me/retucio/sputnik/config/ClientConfig.java @@ -4,8 +4,6 @@ import com.github.retucio.neutrino.EventListener; import me.retucio.sputnik.event.sputnik.*; import me.retucio.sputnik.module.setting.settings.*; import me.retucio.sputnik.ui.screen.ClickGui; -import me.retucio.sputnik.ui.widgets.panels.FriendsPanel; -import me.retucio.sputnik.util.ChatUtil; import java.io.Serial; import java.io.Serializable; @@ -44,8 +42,8 @@ public class ClientConfig { // posición de la barra de búsqueda (x, y) public int[] searchBarPosition = new int[] { 340, 16 }; - // amigos: uuid -> nombre - public Map friends = new HashMap<>(); + // amigos: uuid -> FriendData (nombre, apodo, fecha) + public Map friends = new HashMap<>(); public List macros = new ArrayList<>(); @@ -146,31 +144,15 @@ public class ClientConfig { ConfigManager.INSTANCE.markDirty(); } - @EventListener - public void onExtendFriendsPanel(FriendPanelEvent.Extend event) { - extendablePanels.put("amigos", new PanelData( - ClickGui.INSTANCE.getFriendsPanel().getX(), - ClickGui.INSTANCE.getFriendsPanel().getY(), - ClickGui.INSTANCE.getFriendsPanel().isExtended())); - ConfigManager.INSTANCE.markDirty(); - } - - @EventListener - public void onMoveFriendsPanel(FriendPanelEvent.Move event) { - extendablePanels.put("amigos", new PanelData( - ClickGui.INSTANCE.getFriendsPanel().getX(), - ClickGui.INSTANCE.getFriendsPanel().getY(), - ClickGui.INSTANCE.getFriendsPanel().isExtended())); - ConfigManager.INSTANCE.markDirty(); - } - @EventListener public void onAddFriend(FriendEvent.Add event) { if (isApplying()) return; String uuid = event.getFriend().getUuid().toString(); - String name = event.getFriend().getName(); if (!friends.containsKey(uuid)) { - friends.put(uuid, name); + friends.put(uuid, new FriendData( + event.getFriend().getName(), + event.getFriend().getNick(), + event.getFriend().getBefriendedAt())); } ConfigManager.INSTANCE.markDirty(); } @@ -182,10 +164,25 @@ public class ClientConfig { 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; } + public record FriendData(String name, String nick, long befriendedAt) implements Serializable { + @Serial private static final long serialVersionUID = 1L; + } + public record MacroData(String name, int key, List lines) implements Serializable { @Serial private static final long serialVersionUID = 1L; } diff --git a/src/main/java/me/retucio/sputnik/config/ConfigManager.java b/src/main/java/me/retucio/sputnik/config/ConfigManager.java index 565a7bf..b5040af 100644 --- a/src/main/java/me/retucio/sputnik/config/ConfigManager.java +++ b/src/main/java/me/retucio/sputnik/config/ConfigManager.java @@ -16,12 +16,10 @@ import me.retucio.sputnik.ui.hud.HudElement; import me.retucio.sputnik.ui.hud.HudRenderer; import me.retucio.sputnik.ui.widgets.Panel; import me.retucio.sputnik.ui.widgets.panels.ExtendablePanel; -import me.retucio.sputnik.ui.widgets.panels.FriendsPanel; 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.ChatUtil; import me.retucio.sputnik.util.I18nUtil; import net.minecraft.network.chat.Component; @@ -316,15 +314,15 @@ public class ConfigManager { // ------------------ APLICAR AJUSTES ------------------ public void applyFriends() { - config.friends.forEach((uuid, name) -> { - Friend friend = new Friend(UUID.fromString(uuid)); - friend.setName(name); + 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(data -> new Macro(data.name(), data.key(), data.lines())) @@ -424,7 +422,6 @@ public class ConfigManager { applyExtendablePanel(panel); } applyExtendablePanel(ClickGui.INSTANCE.getClientSettingsPanel()); - applyExtendablePanel(ClickGui.INSTANCE.getFriendsPanel()); Sputnik.LOGGER.info(I18nUtil.fmt("sputnik.config.info.extendablepanels", "posiciones de marcos extendibles aplicadas")); @@ -440,9 +437,6 @@ public class ConfigManager { if (panel instanceof ClientSettingsPanel) { panelData = config.extendablePanels.get("ajustes"); } - if (panel instanceof FriendsPanel) { - panelData = config.extendablePanels.get("amigos"); - } if (panelData != null) { panel.setX(panelData.x()); diff --git a/src/main/java/me/retucio/sputnik/event/sputnik/FriendEvent.java b/src/main/java/me/retucio/sputnik/event/sputnik/FriendEvent.java index 31450c8..d0f7a97 100644 --- a/src/main/java/me/retucio/sputnik/event/sputnik/FriendEvent.java +++ b/src/main/java/me/retucio/sputnik/event/sputnik/FriendEvent.java @@ -3,7 +3,8 @@ package me.retucio.sputnik.event.sputnik; import com.github.retucio.neutrino.Event; import me.retucio.sputnik.friend.Friend; -// evento lanzado cuando se agrega o se elimina un amigo + +// evento lanzado cuando se agrega, elimina o renombra un amigo public class FriendEvent extends Event { private final Friend friend; @@ -23,4 +24,8 @@ public class FriendEvent extends Event { public static class Remove extends FriendEvent { public Remove(Friend friend) { super(friend); } } -} + + public static class Rename extends FriendEvent { + public Rename(Friend friend) { super(friend); } + } +} \ No newline at end of file diff --git a/src/main/java/me/retucio/sputnik/event/sputnik/FriendPanelEvent.java b/src/main/java/me/retucio/sputnik/event/sputnik/FriendPanelEvent.java deleted file mode 100644 index 565a54f..0000000 --- a/src/main/java/me/retucio/sputnik/event/sputnik/FriendPanelEvent.java +++ /dev/null @@ -1,9 +0,0 @@ -package me.retucio.sputnik.event.sputnik; - -import com.github.retucio.neutrino.Event; - -public class FriendPanelEvent { - - public static class Extend extends Event {} // al extenderlo / contraerlo - public static class Move extends Event {} // al cambiarlo de posición -} \ No newline at end of file diff --git a/src/main/java/me/retucio/sputnik/friend/Friend.java b/src/main/java/me/retucio/sputnik/friend/Friend.java index 60964c3..adfc844 100644 --- a/src/main/java/me/retucio/sputnik/friend/Friend.java +++ b/src/main/java/me/retucio/sputnik/friend/Friend.java @@ -1,6 +1,7 @@ package me.retucio.sputnik.friend; import net.minecraft.client.Minecraft; +import net.minecraft.client.multiplayer.PlayerInfo; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.player.Player; import org.jetbrains.annotations.Nullable; @@ -13,12 +14,20 @@ public class Friend { private static final Minecraft mc = Minecraft.getInstance(); private String name; + private String nick; private final UUID uuid; + private final long befriendedAt; private boolean searchMatch; public Friend(UUID uuid) { this.uuid = uuid; + this.befriendedAt = System.currentTimeMillis(); + } + + public Friend(UUID uuid, long befriendedAt) { + this.uuid = uuid; + this.befriendedAt = befriendedAt; } public String getName() { @@ -29,10 +38,27 @@ public class Friend { this.name = name; } + public String getNick() { + return nick; + } + + public void setNick(String nick) { + this.nick = nick; + } + + // apodo si existe, si no el nombre real + public String getDisplayName() { + return (nick == null || nick.isBlank()) ? name : nick; + } + public UUID getUuid() { return uuid; } + public long getBefriendedAt() { + return befriendedAt; + } + public @Nullable Player getPlayer() { if (mc.level == null) return null; Entity entity = mc.level.getEntity(uuid); @@ -40,6 +66,11 @@ public class Friend { return player; } + public @Nullable PlayerInfo getPlayerInfo() { + if (mc.getConnection() == null) return null; + return mc.getConnection().getPlayerInfo(uuid); + } + public boolean isSearchMatch() { return searchMatch; } @@ -56,4 +87,4 @@ public class Friend { NOT_BEFRIENDED, NO_FRIENDS; // :( } -} +} \ No newline at end of file diff --git a/src/main/java/me/retucio/sputnik/friend/FriendManager.java b/src/main/java/me/retucio/sputnik/friend/FriendManager.java index 28c5e17..98322fd 100644 --- a/src/main/java/me/retucio/sputnik/friend/FriendManager.java +++ b/src/main/java/me/retucio/sputnik/friend/FriendManager.java @@ -29,6 +29,7 @@ public class FriendManager { public void add(UUID uuid) { Friend friend = new Friend(uuid); friend.setName(friend.getPlayer().getName().getString()); + friend.setNick(friend.getName()); add(friend); } @@ -61,6 +62,11 @@ public class FriendManager { return Friend.Status.SUCCESS; } + public void rename(Friend friend, String nick) { + friend.setNick(nick); + Sputnik.EVENT_BUS.post(new FriendEvent.Rename(friend)); + } + public Friend get(UUID uuid) { for (Friend friend : friends) { if (friend.getUuid().equals(uuid)) { diff --git a/src/main/java/me/retucio/sputnik/mixin/mixins/render/LevelRendererMixin.java b/src/main/java/me/retucio/sputnik/mixin/mixins/render/LevelRendererMixin.java index b9325ee..8805631 100644 --- a/src/main/java/me/retucio/sputnik/mixin/mixins/render/LevelRendererMixin.java +++ b/src/main/java/me/retucio/sputnik/mixin/mixins/render/LevelRendererMixin.java @@ -10,16 +10,25 @@ import me.retucio.sputnik.event.render.Render3DEvent; import me.retucio.sputnik.event.render.RenderBlockOutlineEvent; import me.retucio.sputnik.module.ModuleManager; import me.retucio.sputnik.module.modules.camera.Freecam; +import me.retucio.sputnik.module.modules.render.BreakingProgress; import me.retucio.sputnik.util.render.SputnikBuffers; import net.minecraft.client.DeltaTracker; +import net.minecraft.client.renderer.GameRenderer; import net.minecraft.client.renderer.LevelRenderer; +import net.minecraft.client.renderer.ShaderManager; import net.minecraft.client.renderer.SubmitNodeCollector; +import net.minecraft.client.renderer.blockentity.BlockEntityRenderDispatcher; +import net.minecraft.client.renderer.entity.EntityRenderDispatcher; import net.minecraft.client.renderer.state.level.CameraRenderState; import net.minecraft.client.renderer.state.level.LevelRenderState; +import net.minecraft.client.renderer.texture.TextureManager; +import net.minecraft.client.resources.model.ModelManager; +import net.minecraft.client.resources.model.sprite.AtlasManager; import net.minecraft.util.profiling.ProfilerFiller; import org.joml.Matrix4fc; import org.joml.Vector4f; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.*; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.invoke.arg.Args; @@ -31,6 +40,14 @@ import static me.retucio.sputnik.Sputnik.mc; @Mixin(LevelRenderer.class) public abstract class LevelRendererMixin { + @Unique + private BreakingProgress bp; + + @Inject(method = "", at = @At("TAIL")) + private void getModules(EntityRenderDispatcher entityRenderDispatcher, BlockEntityRenderDispatcher blockEntityRenderDispatcher, ModelManager modelManager, TextureManager textureManager, AtlasManager atlasManager, ShaderManager shaderManager, GameRenderer gameRenderer, int width, int height, CallbackInfo ci) { + bp = ModuleManager.INSTANCE.getModuleByClass(BreakingProgress.class); + } + @Inject(method = "render", at = @At("RETURN")) private void render(GraphicsResourceAllocator resourceAllocator, DeltaTracker dt, boolean renderOutline, CameraRenderState cameraState, Matrix4fc modelViewMatrix, GpuBufferSlice terrainFog, Vector4f fogColor, boolean shouldRenderSky, CallbackInfo ci, @Local(name = "profiler") ProfilerFiller profiler) { if (mc == null || mc.level == null) return; @@ -55,13 +72,6 @@ public abstract class LevelRendererMixin { if (freecam.isEnabled() && !freecam.blockOutlines.getValue()) ci.cancel(); } -// @Inject(method = "hasBlindnessOrDarkness(Lnet/minecraft/client/extractRenderState/Camera;)Z", at = @At("HEAD"), cancellable = true) -// private void hasBlindnessOrDarkness(Camera camera, CallbackInfoReturnable cir) { -// NoRender noRender = ModuleManager.INSTANCE.getModuleByClass(NoRender.class); -// if (!noRender.isEnabled()) return; -// if (!noRender.blindnessEffect.getValue() || !noRender.darknessEffect.getValue()) cir.setReturnValue(null); -// } - // puto mojang con sus nombres confusos @ModifyArgs(method = "submitBlockOutline", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/LevelRenderer;submitHitOutline(Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/SubmitNodeCollector;Lnet/minecraft/client/renderer/rendertype/RenderType;Lnet/minecraft/client/renderer/state/level/BlockOutlineRenderState;IFZ)V")) private void modifyBlockOutline(Args args) { @@ -72,4 +82,12 @@ public abstract class LevelRendererMixin { if (event.getLineWidth() != (float) args.get(5)) args.set(5, event.getLineWidth()); } + + @Inject(method = "submitBlockDestroyAnimation", at = @At("HEAD"), cancellable = true) + private void cancelBreakingAnim(PoseStack poseStack, SubmitNodeCollector submitNodeCollector, LevelRenderState levelRenderState, CallbackInfo ci) { + if (!bp.isEnabled()) return; + if (bp.cancelAnim.getValue()) { + ci.cancel(); + } + } } \ No newline at end of file diff --git a/src/main/java/me/retucio/sputnik/module/modules/render/BreakingProgress.java b/src/main/java/me/retucio/sputnik/module/modules/render/BreakingProgress.java index 8be9aea..b2cdeed 100644 --- a/src/main/java/me/retucio/sputnik/module/modules/render/BreakingProgress.java +++ b/src/main/java/me/retucio/sputnik/module/modules/render/BreakingProgress.java @@ -26,6 +26,12 @@ public class BreakingProgress extends Module { private final EnumSetting breakMode = sgGeneral.add(new EnumSetting<>("modo de minado", "elige si el cubo se encoge o se dilata", BreakMode.class, BreakMode.INWARDS)); + public final BooleanSetting cancelAnim = sgGeneral.add(new BooleanSetting( + "cancelar animación", + "no renderizar la anim. original", + true + )); + private final BooleanSetting outlines = sgOutlines.add(new BooleanSetting("contorno", "renderizar contorno", true)); private final ColorSetting outlineColor = sgOutlines.add(new ColorSetting("color del contorno", "color del contorno", new Color(0, 255, 0, 200), false)); diff --git a/src/main/java/me/retucio/sputnik/ui/screen/ClickGui.java b/src/main/java/me/retucio/sputnik/ui/screen/ClickGui.java index 37a8ae3..6c96285 100644 --- a/src/main/java/me/retucio/sputnik/ui/screen/ClickGui.java +++ b/src/main/java/me/retucio/sputnik/ui/screen/ClickGui.java @@ -12,11 +12,10 @@ import me.retucio.sputnik.module.Category; import me.retucio.sputnik.module.Module; import me.retucio.sputnik.module.setting.Setting; import me.retucio.sputnik.module.setting.settings.ColorSetting; -import me.retucio.sputnik.ui.widgets.buttons.FriendButton; +import me.retucio.sputnik.ui.screen.tabs.FriendsTab; import me.retucio.sputnik.ui.widgets.buttons.settings.ListButton; import me.retucio.sputnik.ui.widgets.buttons.ModuleButton; import me.retucio.sputnik.ui.widgets.buttons.SettingButton; -import me.retucio.sputnik.ui.widgets.panels.FriendsPanel; import me.retucio.sputnik.ui.widgets.panels.settings.ClientSettingsPanel; import me.retucio.sputnik.ui.widgets.panels.settings.ColorPickerPanel; import me.retucio.sputnik.ui.widgets.panels.ModulePanel; @@ -31,7 +30,6 @@ import me.retucio.sputnik.ui.widgets.misc.ScrollBarWidget; import me.retucio.sputnik.ui.widgets.misc.SearchBarWidget; import me.retucio.sputnik.ui.widgets.misc.TabBarWidget; import me.retucio.sputnik.util.Colors; -import me.retucio.sputnik.ui.widgets.panels.settings.FriendSettingsPanel; import me.retucio.sputnik.util.KeyUtil; import me.retucio.sputnik.util.MiscUtil; @@ -69,7 +67,6 @@ public class ClickGui extends Screen { private final List modulePanels = new ArrayList<>(); private final List settingsPanels = new ArrayList<>(); private final ClientSettingsPanel clientSettingsPanel = new ClientSettingsPanel(620, 280, 100, 20); - private final FriendsPanel friendsPanel = new FriendsPanel(40, 280, 100, 20); private final ScrollBarWidget scrollBar = new ScrollBarWidget(); private final SearchBarWidget searchBar = new SearchBarWidget(320, 10, 320, 20); @@ -78,6 +75,7 @@ public class ClickGui extends Screen { private final TabBarWidget tabBar = new TabBarWidget(this::onTabLeft); private final ProfilesTab profilesTab = new ProfilesTab(); private final MacrosTab macrosTab = new MacrosTab(); + private final FriendsTab friendsTab = new FriendsTab(); private static final int PLACEMENT_SEARCH_STEP = 8; @@ -99,6 +97,7 @@ public class ClickGui extends Screen { case HUD -> renderHud(gui, mouseX, mouseY); case PROFILES -> profilesTab.render(gui, mouseX, mouseY, delta); case MACROS -> macrosTab.render(gui, mouseX, mouseY, delta); + case FRIENDS -> friendsTab.render(gui, mouseX, mouseY, delta); } tabBar.render(gui, mouseX, mouseY, delta); @@ -126,7 +125,6 @@ public class ClickGui extends Screen { searchBar.updatePosition(mouseX, mouseY); // actualizar la posición de renderizado vertical de los paneles cada tick - friendsPanel.updateRenderY(scrollOffset); clientSettingsPanel.updateRenderY(scrollOffset); for (ModulePanel mp : modulePanels) { mp.updateRenderY(scrollOffset); @@ -151,9 +149,6 @@ public class ClickGui extends Screen { sp.drawTooltips(gui, mouseX, mouseY); } - friendsPanel.render(gui, mouseX, mouseY, delta); - friendsPanel.updatePosition(mouseX, mouseY); - clientSettingsPanel.render(gui, mouseX, mouseY, delta); clientSettingsPanel.updatePosition(mouseX, mouseY); @@ -193,10 +188,6 @@ public class ClickGui extends Screen { bottom = Math.max(bottom, sp.getY() + sp.getH() + sp.getTotalHeight()); } - int friendsBottom = friendsPanel.getY() + friendsPanel.getH() - + (friendsPanel.isExtended() ? friendsPanel.getTotalHeight() : 0); - bottom = Math.max(bottom, friendsBottom); - int clientBottom = clientSettingsPanel.getY() + clientSettingsPanel.getH() + (clientSettingsPanel.isExtended() ? clientSettingsPanel.getTotalHeight() : 0); bottom = Math.max(bottom, clientBottom); @@ -235,9 +226,6 @@ public class ClickGui extends Screen { 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); } @@ -257,8 +245,6 @@ public class ClickGui extends Screen { switch (tabBar.getSelected()) { case MODULES -> { miscWidgets.forEach(w -> w.mouseClicked(x, y, click.button())); - - friendsPanel.mouseClicked(x, y, click.button()); clientSettingsPanel.mouseClicked(x, y, click.button()); for (ModulePanel mp : modulePanels.reversed()) { mp.mouseClicked(x, y, click.button()); @@ -270,6 +256,7 @@ public class ClickGui extends Screen { case HUD -> HudEditor.INSTANCE.mouseClicked(x, y, click.button()); case PROFILES -> profilesTab.mouseClicked(x, y, click.button()); case MACROS -> macrosTab.mouseClicked(x, y, click.button()); + case FRIENDS -> friendsTab.mouseClicked(x, y, click.button()); } return super.mouseClicked(click, doubled); @@ -291,7 +278,6 @@ public class ClickGui extends Screen { x, y, click.button())); // registrar cuándo se suelta el clic, en cada panel respectivamente - friendsPanel.mouseReleased(x, y, click.button()); clientSettingsPanel.mouseReleased(x, y, click.button()); for (ModulePanel mp : modulePanels.reversed()) { mp.mouseReleased(x, y, click.button()); @@ -335,6 +321,7 @@ public class ClickGui extends Screen { } case PROFILES -> profilesTab.onKey(event.getKey(), event.getAction()); case MACROS -> macrosTab.onKey(event.getKey(), event.getAction()); + case FRIENDS -> friendsTab.onKey(event.getKey(), event.getAction()); } } @@ -358,7 +345,6 @@ public class ClickGui extends Screen { if (correction != 0) { modulePanels.forEach(mp -> mp.setY(mp.getY() + correction)); settingsPanels.forEach(sp -> sp.setY(sp.getY() + correction)); - friendsPanel.setY(friendsPanel.getY() + correction); clientSettingsPanel.setY(clientSettingsPanel.getY() + correction); } } @@ -427,26 +413,6 @@ public class ClickGui extends Screen { } } - for (Button b : friendsPanel.getButtons()) { - if (!(b instanceof FriendButton fb)) continue; - Friend friend = fb.getFriend(); - - if (searchInput.isEmpty()) { - friend.setSearchMatch(true); - continue; - } - - String name = MiscUtil.removeAccentMarks(friend.getName()); - String uuid = MiscUtil.removeAccentMarks(friend.getUuid().toString()); - - if (!clientSettings.matchCase.getValue()) { - name = name.toLowerCase(); - uuid = uuid.toLowerCase(); - } - - friend.setSearchMatch(name.contains(searchInput) || uuid.contains(searchInput)); - } - for (Button b : clientSettingsPanel.getButtons()) { if (!(b instanceof SettingButton sb)) continue; Setting setting = sb.getSetting(); @@ -550,33 +516,6 @@ public class ClickGui extends Screen { } } - public boolean isFriendSettingsPanelOpen(Friend friend) { - for (SettingsPanel sp : getSettingsPanels()) { - if (sp instanceof FriendSettingsPanel fsp) { - if (fsp.getFriend().getUuid().equals(friend.getUuid())) return true; - } - } - return false; - } - - public void openFriendSettingsPanel(Friend friend, int x, int y) { - FriendSettingsPanel panel = new FriendSettingsPanel(friend, x + 80, y + 5, 153, 20); - if (isFriendSettingsPanelOpen(friend)) { - closeFriendSettingsPanel(friend); - return; - } - settingsPanels.add(panel); - } - - public void closeFriendSettingsPanel(Friend friend) { - for (SettingsPanel sp : getSettingsPanels()) { - if (sp instanceof FriendSettingsPanel fsp && fsp.getFriend().getUuid().equals(friend.getUuid())) { - settingsPanels.remove(fsp); - break; - } - } - } - public void refreshListButtons() { for (SettingsPanel panel : settingsPanels) for (Button button : panel.getButtons()) @@ -597,7 +536,8 @@ public class ClickGui extends Screen { // lo miran Sputnik#onInput y el editor del hud para no tratar las teclas que se están // escribiendo como atajos de módulos public boolean isCapturingInput() { - return searchBar.isFocused() || profilesTab.isCapturingInput() || macrosTab.isCapturingInput(); + return searchBar.isFocused() || profilesTab.isCapturingInput() + || macrosTab.isCapturingInput() || friendsTab.isCapturingInput(); } public boolean isOnHudTab() { @@ -650,7 +590,6 @@ public class ClickGui extends Screen { public List getModulePanels() { return modulePanels; } public List getSettingsPanels() { return settingsPanels; } public ClientSettingsPanel getClientSettingsPanel() { return clientSettingsPanel; } - public FriendsPanel getFriendsPanel() { return friendsPanel; } public SearchBarWidget getSearchBar() { return searchBar; } public TabBarWidget getTabBar() { return tabBar; } public ScrollBarWidget getScrollBar() { return scrollBar; } diff --git a/src/main/java/me/retucio/sputnik/ui/screen/Tab.java b/src/main/java/me/retucio/sputnik/ui/screen/Tab.java index 84bd059..dfa78d3 100644 --- a/src/main/java/me/retucio/sputnik/ui/screen/Tab.java +++ b/src/main/java/me/retucio/sputnik/ui/screen/Tab.java @@ -8,7 +8,8 @@ public enum Tab { MODULES("módulos"), HUD("hud"), PROFILES("perfiles"), - MACROS("macros"); + MACROS("macros"), + FRIENDS("amigos"); private final String name; diff --git a/src/main/java/me/retucio/sputnik/ui/screen/tabs/FriendsTab.java b/src/main/java/me/retucio/sputnik/ui/screen/tabs/FriendsTab.java new file mode 100644 index 0000000..b5ba9b1 --- /dev/null +++ b/src/main/java/me/retucio/sputnik/ui/screen/tabs/FriendsTab.java @@ -0,0 +1,101 @@ +package me.retucio.sputnik.ui.screen.tabs; + +import me.retucio.sputnik.friend.Friend; +import me.retucio.sputnik.friend.FriendManager; +import me.retucio.sputnik.ui.hud.HudRenderer; +import me.retucio.sputnik.ui.widgets.misc.FriendWidget; +import me.retucio.sputnik.util.Colors; +import me.retucio.sputnik.util.I18nUtil; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.GuiGraphicsExtractor; +import net.minecraft.network.chat.Component; + +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; + + +public class FriendsTab { + + private static final Minecraft mc = Minecraft.getInstance(); + + private static final int COLUMNS = 3; + private static final int CARD_HEIGHT = 60; + private static final int MARGIN = 6; + private static final int TOP = 40; + + // uno por amigo, persistente entre frames para no perder el foco del campo de apodo mientras se edita + private final Map widgets = new LinkedHashMap<>(); + + public void render(GuiGraphicsExtractor gui, int mouseX, int mouseY, float delta) { + List friends = FriendManager.INSTANCE.getFriends(); + syncWidgets(friends); + + int screenWidth = mc.getWindow().getGuiScaledWidth(); + int cardWidth = screenWidth / COLUMNS; + + gui.centeredText(mc.font, Component.translatable("sputnik.ui.friends.title"), + screenWidth / 2, TOP - 14, Colors.mainColor.getRGB()); + + if (friends.isEmpty()) { + gui.centeredText(mc.font, Component.translatable("sputnik.ui.friends.empty"), + screenWidth / 2, TOP + 20, Colors.instructionsTextColor.getRGB()); + return; + } + + int col = 0; + int row = 0; + for (Friend friend : friends) { + FriendWidget widget = widgets.get(friend.getUuid()); + + int cx = col * cardWidth + MARGIN; + int cy = TOP + row * (CARD_HEIGHT + MARGIN); + int cw = cardWidth - MARGIN * 2; + + widget.updateBounds(cx, cy, cw, CARD_HEIGHT); + widget.render(gui, mouseX, mouseY, delta); + + col++; + if (col >= COLUMNS) { + col = 0; + row++; + } + } + } + + // añade widgets para amigos nuevos y elimina los de quienes ya no lo son + private void syncWidgets(List friends) { + widgets.keySet().removeIf(uuid -> friends.stream().noneMatch(f -> f.getUuid().equals(uuid))); + + for (Friend friend : friends) { + widgets.computeIfAbsent(friend.getUuid(), + uuid -> new FriendWidget(friend, 0, 0, 0, CARD_HEIGHT, this::remove)); + } + } + + private void remove(Friend friend) { + FriendManager.INSTANCE.remove(friend); + HudRenderer.INSTANCE.pushNotification( + I18nUtil.orElse("sputnik.ui.friends.title", "amigos"), + I18nUtil.orElse("sputnik.ui.friends.removed", "sputnik.ui.friends.removed", friend.getName())); + } + + public void mouseClicked(int mouseX, int mouseY, int button) { + for (FriendWidget widget : widgets.values()) { + if (widget.isHovered(mouseX, mouseY) || widget.isCapturingInput()) { + widget.mouseClicked(mouseX, mouseY, button); + } + } + } + + public void onKey(int key, int action) { + for (FriendWidget widget : widgets.values()) { + if (widget.isCapturingInput()) widget.onKey(key, action); + } + } + + public boolean isCapturingInput() { + return widgets.values().stream().anyMatch(FriendWidget::isCapturingInput); + } +} \ No newline at end of file diff --git a/src/main/java/me/retucio/sputnik/ui/widgets/buttons/FriendButton.java b/src/main/java/me/retucio/sputnik/ui/widgets/buttons/FriendButton.java deleted file mode 100644 index d8bad6c..0000000 --- a/src/main/java/me/retucio/sputnik/ui/widgets/buttons/FriendButton.java +++ /dev/null @@ -1,75 +0,0 @@ -package me.retucio.sputnik.ui.widgets.buttons; - -import me.retucio.sputnik.friend.Friend; -import me.retucio.sputnik.module.Module; -import me.retucio.sputnik.ui.screen.ClickGui; -import me.retucio.sputnik.ui.widgets.panels.FriendsPanel; -import me.retucio.sputnik.ui.widgets.panels.ModulePanel; -import me.retucio.sputnik.ui.widgets.Button; -import me.retucio.sputnik.util.Colors; -import net.minecraft.client.gui.GuiGraphicsExtractor; -import net.minecraft.network.chat.Component; - - -// clase para el botón para cada módulo -public class FriendButton extends Button { - - private final Friend friend; - public final int height = 18; - - public FriendButton(Friend friend, FriendsPanel parent, int offset) { - super(parent, offset); - this.friend = friend; - } - - @Override - public void render(GuiGraphicsExtractor gui, int mouseX, int mouseY, float delta) { - gui.fill( // dibujar el contorno del botón - parent.getX() + 2, parent.getRenderY() + offset + 3, - parent.getX() + parent.getW() - 2 , parent.getRenderY() + height + offset, - determineColor(mouseX, mouseY)); - - gui.text( // dibujar el nombre del amigo - mc.font, friend.getName(), - parent.getX() + 5, parent.getRenderY() + offset + (height / 2) - (mc.font.lineHeight / 2) + 2, - -1, true); - - // dibujar "tooltips" (cajas de texto) al pasar el puntero encima del botón, para mostrar su UUID - if (isHovered(mouseX, mouseY)) { - drawTooltip(gui, mouseX, mouseY); - } - } - - @Override - public void drawTooltip(GuiGraphicsExtractor gui, int mouseX, int mouseY) { - gui.setTooltipForNextFrame(Component.literal(friend.getUuid().toString()), mouseX, mouseY + 20); - } - - @Override - public void mouseClicked(int mouseX, int mouseY, int button) { - if (isHovered(mouseX, mouseY) && ClickGui.INSTANCE.trySelect(this)) { - ClickGui.INSTANCE.openFriendSettingsPanel(friend, mouseX, mouseY); - } - } - - // verifica si el puntero del ratón se encuentra sobre el botón - @Override - public boolean isHovered(int mouseX, int mouseY) { - return ClickGui.INSTANCE.canSelect(this) - && mouseX > parent.getX() - && mouseX < parent.getX() + parent.getW() - && mouseY > parent.getRenderY() + offset - && mouseY < parent.getRenderY() + height + offset; - } - - public int determineColor(double mouseX, double mouseY) { - // determina el color del botón, dependiendo de si está el puntero encima - return isHovered((int) mouseX, (int) mouseY) - ? Colors.buttonColor.brighter().getRGB() - : Colors.buttonColor.getRGB(); - } - - public Friend getFriend() { - return friend; - } -} diff --git a/src/main/java/me/retucio/sputnik/ui/widgets/misc/FriendWidget.java b/src/main/java/me/retucio/sputnik/ui/widgets/misc/FriendWidget.java new file mode 100644 index 0000000..479c8f9 --- /dev/null +++ b/src/main/java/me/retucio/sputnik/ui/widgets/misc/FriendWidget.java @@ -0,0 +1,156 @@ +package me.retucio.sputnik.ui.widgets.misc; + +import me.retucio.sputnik.friend.Friend; +import me.retucio.sputnik.friend.FriendManager; +import me.retucio.sputnik.ui.widgets.Widget; +import me.retucio.sputnik.util.Colors; +import net.minecraft.client.gui.GuiGraphicsExtractor; +import net.minecraft.client.gui.components.PlayerFaceExtractor; +import net.minecraft.client.multiplayer.PlayerInfo; +import net.minecraft.network.chat.Component; + +import java.awt.Color; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.function.Consumer; + + +public class FriendWidget extends Widget { + + private static final int PADDING = 6; + private static final int HEAD_SIZE = 28; + private static final int REMOVE_SIZE = 14; + private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("dd/MM/yyyy"); + + private final Friend friend; + private final Consumer onRemove; + private final TextFieldWidget nickField; + + public FriendWidget(Friend friend, int x, int y, int w, int h, Consumer onRemove) { + super(x, y, w, h); + this.friend = friend; + this.onRemove = onRemove; + + this.nickField = new TextFieldWidget(() -> "sputnik.ui.friends.nickplaceholder", 0, 0, 0, 14) + .maxLength(32) + .onSubmit(nick -> FriendManager.INSTANCE.rename(friend, nick)); + } + + // recalcula la posición/tamaño cada frame, para que la rejilla se adapte al ancho de pantalla + public void updateBounds(int x, int y, int w, int h) { + this.x = x; + this.y = y; + this.w = w; + this.h = h; + } + + @Override + public void render(GuiGraphicsExtractor gui, int mouseX, int mouseY, float delta) { + boolean hovered = isHovered(mouseX, mouseY); + gui.fill(x, y, x + w, y + h, hovered ? Colors.buttonColor.brighter().getRGB() : Colors.buttonColor.getRGB()); + + int headX = x + PADDING; + int headY = y + (h - HEAD_SIZE) / 2; + drawHead(gui, headX, headY); + + int textX = headX + HEAD_SIZE + 8; + int textW = x + w - REMOVE_SIZE - 10 - textX; + + gui.text(mc.font, friend.getName(), textX, y + 6, -1, true); + + int nickY = y + 6 + mc.font.lineHeight + 2; + if (nickField.isFocused()) { + nickField.setX(textX); + nickField.setY(nickY); + nickField.setW(textW); + nickField.render(gui, mouseX, mouseY, delta); + } else { + gui.text(mc.font, friend.getDisplayName(), textX, nickY, Colors.mainColor.getRGB(), true); + } + + String date = DATE_FORMAT.format(new Date(friend.getBefriendedAt())); + gui.text(mc.font, Component.translatable("sputnik.ui.friends.befriendedon", date), + textX, y + h - mc.font.lineHeight - 5, Colors.instructionsTextColor.getRGB(), true + ); + + String uuid = friend.getUuid().toString(); + gui.text(mc.font, Component.translatable("sputnik.ui.friends.uuid", uuid), + textX, y + 24 + mc.font.lineHeight, Colors.instructionsTextColor.getRGB(), true + ); + + drawRemoveButton(gui, mouseX, mouseY); + } + + private void drawHead(GuiGraphicsExtractor gui, int hx, int hy) { + PlayerInfo info = friend.getPlayerInfo(); + if (info != null) { + PlayerFaceExtractor.extractRenderState(gui, info.getSkin(), hx, hy, HEAD_SIZE, -1); + } else { + // sin conexión al jugador (offline / no en el mismo server): placeholder gris + gui.fill(hx, hy, hx + HEAD_SIZE, hy + HEAD_SIZE, Colors.panelBgColor.getRGB()); + } + } + + private void drawRemoveButton(GuiGraphicsExtractor gui, int mouseX, int mouseY) { + int rx = x + w - REMOVE_SIZE - 5; + int ry = y + 5; + boolean hovered = isRemoveHovered(mouseX, mouseY); + + gui.fill(rx, ry, rx + REMOVE_SIZE, ry + REMOVE_SIZE, + hovered ? new Color(200, 60, 60).brighter().getRGB() : new Color(150, 40, 40).getRGB()); + gui.text(mc.font, "x", rx + REMOVE_SIZE / 2 - 2, ry + REMOVE_SIZE / 2 - mc.font.lineHeight / 2, -1, true); + } + + @Override + public void mouseClicked(int mouseX, int mouseY, int button) { + if (button == 0 && isRemoveHovered(mouseX, mouseY)) { + onRemove.accept(friend); + return; + } + + if (nickField.isFocused()) { + nickField.mouseClicked(mouseX, mouseY, button); + return; + } + + if (button == 0 && isNickHovered(mouseX, mouseY)) { + nickField.setText(friend.getDisplayName()); + nickField.setFocused(true); + } + } + + @Override + public void mouseReleased(int mouseX, int mouseY, int button) { + nickField.mouseReleased(mouseX, mouseY, button); + } + + public void onKey(int key, int action) { + if (nickField.isFocused()) nickField.onKey(key, action); + } + + public boolean isCapturingInput() { + return nickField.isFocused(); + } + + private boolean isNickHovered(int mouseX, int mouseY) { + int textX = x + PADDING + HEAD_SIZE + 8; + int nickY = y + 6 + mc.font.lineHeight + 2; + return mouseX >= textX && mouseX < x + w - REMOVE_SIZE - 10 + && mouseY >= nickY && mouseY < nickY + 14; + } + + private boolean isRemoveHovered(int mouseX, int mouseY) { + int rx = x + w - REMOVE_SIZE - 5; + int ry = y + 5; + return mouseX >= rx && mouseX < rx + REMOVE_SIZE && mouseY >= ry && mouseY < ry + REMOVE_SIZE; + } + + @Override + public boolean isHovered(int mouseX, int mouseY) { + return mouseX >= x && mouseX < x + w && mouseY >= y && mouseY < y + h; + } + + public Friend getFriend() { + return friend; + } +} \ No newline at end of file diff --git a/src/main/java/me/retucio/sputnik/ui/widgets/misc/TextFieldWidget.java b/src/main/java/me/retucio/sputnik/ui/widgets/misc/TextFieldWidget.java index 3b891ef..6055b96 100644 --- a/src/main/java/me/retucio/sputnik/ui/widgets/misc/TextFieldWidget.java +++ b/src/main/java/me/retucio/sputnik/ui/widgets/misc/TextFieldWidget.java @@ -111,6 +111,11 @@ public class TextFieldWidget extends Widget { } public String getText() { return buffer.toString(); } + public void setText(String text) { + buffer.setLength(0); + buffer.append(text.length() > maxLength ? text.substring(0, maxLength) : text); + } + public void clear() { buffer.setLength(0); } public boolean isFocused() { return focused; } diff --git a/src/main/java/me/retucio/sputnik/ui/widgets/panels/FriendsPanel.java b/src/main/java/me/retucio/sputnik/ui/widgets/panels/FriendsPanel.java deleted file mode 100644 index f323f1c..0000000 --- a/src/main/java/me/retucio/sputnik/ui/widgets/panels/FriendsPanel.java +++ /dev/null @@ -1,143 +0,0 @@ -package me.retucio.sputnik.ui.widgets.panels; - -import com.github.retucio.neutrino.EventListener; -import me.retucio.sputnik.Sputnik; -import me.retucio.sputnik.event.sputnik.FriendEvent; -import me.retucio.sputnik.event.sputnik.FriendPanelEvent; -import me.retucio.sputnik.friend.Friend; -import me.retucio.sputnik.friend.FriendManager; -import me.retucio.sputnik.ui.screen.ClickGui; -import me.retucio.sputnik.ui.widgets.buttons.FriendButton; -import me.retucio.sputnik.util.Colors; -import me.retucio.sputnik.util.I18nUtil; -import net.minecraft.client.gui.GuiGraphicsExtractor; -import net.minecraft.network.chat.Component; - -import java.util.List; - - -public class FriendsPanel extends ExtendablePanel { - - private int offset; - - public FriendsPanel(int x, int y, int w, int h) { - super(() -> I18nUtil.orElse("sputnik.ui.friends.title", "amigos"), x, y, w, h); - dragging = false; - - Sputnik.EVENT_BUS.subscribe(this); - - offset = h; - for (Friend friend : FriendManager.INSTANCE.getFriends()) { - buttons.add(new FriendButton(friend, this, offset)); - offset += h; - } - } - - @Override - protected void updateWidth() { - int maxWidth = mc.font.width(getTitle()) + mc.font.width(" +"); - for (FriendButton button : buttons) { - int textWidth = mc.font.width(button.getFriend().getName()); - maxWidth = Math.max(maxWidth, textWidth); - } - this.w = maxWidth + 22; - } - - @Override - public void render(GuiGraphicsExtractor gui, int mouseX, int mouseY, float delta) { - updateWidth(); - gui.fill(x, renderY, x + w, renderY + h, Colors.mainColor.getRGB()); - - gui.text(mc.font, Component.literal(getTitle()), - x + 8, - renderY + (h / 2) - (mc.font.lineHeight / 2), - -1, true); - - drawExpandCollapse(gui, mouseX, mouseY); - - List visibleButtons = buttons.stream() - .filter(fb -> fb.getFriend().isSearchMatch()) - .toList(); - - if (extended) { - totalHeight = visibleButtons.size() * h + 3; - gui.fill(x, renderY + h + 1, x + w, renderY + h + totalHeight, Colors.panelBgColor.getRGB()); - - int buttonY = renderY + h + 1; - for (FriendButton friendButton : visibleButtons) { - friendButton.setOffset(buttonY - renderY); - friendButton.render(gui, mouseX, mouseY, delta); - buttonY += h; - } - } else { - totalHeight = 0; - } - } - - @Override - public void mouseClicked(int mouseX, int mouseY, int button) { - if (isHovered(mouseX, mouseY) && ClickGui.INSTANCE.trySelect(this)) { - if (button == 0) { - dragging = true; - dragX = mouseX - x; - dragY = mouseY - y; - } else if (button == 1) { - toggleExtended(); - Sputnik.EVENT_BUS.post(new FriendPanelEvent.Extend()); - } - } - - if (!extended) return; - - List visibleFriendButtons = buttons.stream() - .filter(fb -> fb.getFriend().isSearchMatch()) - .toList(); - - for (FriendButton friendButton : visibleFriendButtons) { - friendButton.mouseClicked(mouseX, mouseY, button); - } - } - - @Override - public void mouseReleased(int mouseX, int mouseY, int button) { - ClickGui.INSTANCE.unselect(this); - if (button == 0 && dragging) dragging = false; - - List visibleFriendButtons = buttons.stream() - .filter(fb -> fb.getFriend().isSearchMatch()) - .toList(); - - for (FriendButton friendButton : visibleFriendButtons) { - if (friendButton.isHovered(mouseX, mouseY)) - friendButton.mouseReleased(mouseX, mouseY, button); - } - - if (isHovered(mouseX, mouseY)) - Sputnik.EVENT_BUS.post(new FriendPanelEvent.Move()); - } - - public void updatePosition(double mouseX, double mouseY) { - if (dragging) { - x = (int) (mouseX - dragX); - y = (int) (mouseY - dragY); - } - } - - @EventListener - private void onAddFriend(FriendEvent.Add event) { - buttons.add(new FriendButton(event.getFriend(), this, offset)); - } - - @EventListener - private void onRemoveFriend(FriendEvent.Remove event) { - buttons.remove(getButtonOfFriend(event.getFriend())); - } - - public FriendButton getButtonOfFriend(Friend friend) { - for (FriendButton button : buttons) { - if (button.getFriend().getUuid().equals(friend.getUuid())) - return button; - } - return null; - } -} \ No newline at end of file diff --git a/src/main/java/me/retucio/sputnik/ui/widgets/panels/settings/FriendSettingsPanel.java b/src/main/java/me/retucio/sputnik/ui/widgets/panels/settings/FriendSettingsPanel.java deleted file mode 100644 index 507e0cc..0000000 --- a/src/main/java/me/retucio/sputnik/ui/widgets/panels/settings/FriendSettingsPanel.java +++ /dev/null @@ -1,102 +0,0 @@ -package me.retucio.sputnik.ui.widgets.panels.settings; - -import me.retucio.sputnik.config.ConfigManager; -import me.retucio.sputnik.friend.Friend; -import me.retucio.sputnik.friend.FriendManager; -import me.retucio.sputnik.module.Category; -import me.retucio.sputnik.module.Module; -import me.retucio.sputnik.module.ModuleManager; -import me.retucio.sputnik.module.modules.client.Friends; -import me.retucio.sputnik.module.setting.settings.StringSetting; -import me.retucio.sputnik.ui.screen.ClickGui; -import me.retucio.sputnik.ui.widgets.buttons.settings.TextButton; -import me.retucio.sputnik.ui.widgets.panels.SettingsPanel; -import me.retucio.sputnik.util.Colors; -import me.retucio.sputnik.util.I18nUtil; -import net.minecraft.client.gui.GuiGraphicsExtractor; - - -public class FriendSettingsPanel extends SettingsPanel { - - private final Friend friend; - private final StringSetting nickname; - public final Module dummyModule; - - private int removeButtonY; - - public FriendSettingsPanel(Friend friend, int x, int y, int w, int h) { - super(ModuleManager.INSTANCE.getModuleByClass(Friends.class), x, y, w, h); - - this.friend = friend; - - dummyModule = new Module(friend.getName(), - I18nUtil.orElse("sputnik.ui.friend.manage", "gestiona a " + friend.getName(), friend.getName()), - Category.CLIENT) { - @Override public void onEnable() {} - @Override public void onDisable() {} - }; - - dummyModule.getSettings().forEach(s -> s.visibility(false)); - dummyModule.shouldSaveSettings(false); - - setModule(dummyModule); - - // clave a mano: el módulo es un dummy con el nombre del jugador, así que la clave - // derivada dependería de él y no existiría nunca en el lang - nickname = new StringSetting("nombre", "con qué nombre guardar al amigo", friend.getName(), 40) - .translationKey("sputnik.setting.friend.nickname"); - dummyModule.getSgGeneral().add(nickname); - nickname.onUpdate(name -> { - friend.setName(name); - ConfigManager.INSTANCE.getConfig().friends.put(friend.getUuid().toString(), name); - ConfigManager.INSTANCE.save(); - }); - - buttons.clear(); - addButton(new TextButton(nickname, this, h)); - - setSettingGroups(dummyModule.getSgs()); - } - - @Override - public void render(GuiGraphicsExtractor gui, int mx, int my, float delta) { - super.render(gui, mx, my, delta); - - removeButtonY = renderY + h + totalHeight + PADDING; - int buttonH = h - h / 4; - - gui.fill(x, removeButtonY, x + w, removeButtonY + buttonH + PADDING, Colors.panelBgColor.getRGB()); - - int color = isRemoveButtonHovered(mx, my) - ? Colors.disabledToggleButtonColor.brighter().getRGB() - : Colors.disabledToggleButtonColor.getRGB(); - - gui.fill(x + PADDING, removeButtonY, x + w - PADDING, removeButtonY + buttonH, color); - - String label = I18nUtil.orElse("sputnik.ui.friend.remove", "eliminar amigo"); - gui.text(mc.font, label, - x + w / 2 - mc.font.width(label) / 2, - removeButtonY + (buttonH - mc.font.lineHeight) / 2, - -1, true); - } - - @Override - public void mouseClicked(int mouseX, int mouseY, int button) { - super.mouseClicked(mouseX, mouseY, button); - - if (button == 0 && isRemoveButtonHovered(mouseX, mouseY)) { - FriendManager.INSTANCE.remove(friend); - ClickGui.INSTANCE.closeSettingsPanel(dummyModule); - } - } - - private boolean isRemoveButtonHovered(int mouseX, int mouseY) { - int buttonH = h - h / 4; - return mouseX > x + PADDING && mouseX < x + w - PADDING - && mouseY > removeButtonY && mouseY < removeButtonY + buttonH; - } - - public Friend getFriend() { - return friend; - } -} \ No newline at end of file diff --git a/src/main/resources/assets/sputnik/lang/en_us.json b/src/main/resources/assets/sputnik/lang/en_us.json index 3f788c3..c2ba409 100644 --- a/src/main/resources/assets/sputnik/lang/en_us.json +++ b/src/main/resources/assets/sputnik/lang/en_us.json @@ -1665,5 +1665,10 @@ "sputnik.version.info.dev": "mod in a development state: v%s", "sputnik.version.info.uptodate": "the mod is up to date: v%s", "sputnik.version.warn.check": "could not check whether the mod is up to date: %s", - "sputnik.version.warn.metadata": "could not build gradle.properties from the metadata" + "sputnik.version.warn.metadata": "could not build gradle.properties from the metadata", + "sputnik.ui.friends.nickplaceholder": "nickname...", + "sputnik.ui.friends.befriendedon": "friends since %s", + "sputnik.ui.friends.removed": "you now hate %s", + "sputnik.ui.friends.empty": "you don't have any friends loser", + "sputnik.ui.friends.uuid": "UUID: %s" } diff --git a/src/main/resources/assets/sputnik/lang/es_es.json b/src/main/resources/assets/sputnik/lang/es_es.json index 86a07c8..4e400b8 100644 --- a/src/main/resources/assets/sputnik/lang/es_es.json +++ b/src/main/resources/assets/sputnik/lang/es_es.json @@ -1665,5 +1665,10 @@ "sputnik.version.info.dev": "mod en estado de desarrollo: v%s", "sputnik.version.info.uptodate": "el mod está al día: v%s", "sputnik.version.warn.check": "no se pudo comprobar si el mod está actualizado: %s", - "sputnik.version.warn.metadata": "no se pudo construir gradle.properties desde la metadata" + "sputnik.version.warn.metadata": "no se pudo construir gradle.properties desde la metadata", + "sputnik.ui.friends.nickplaceholder": "apodo...", + "sputnik.ui.friends.befriendedon": "amigos desde %s", + "sputnik.ui.friends.removed": "%s ya no es tu amigo", + "sputnik.ui.friends.empty": "no tienes amigos jajsjsjs", + "sputnik.ui.friends.uuid": "UUID: %s" } \ No newline at end of file