From 409a08a8dda833301ce4bfc8017f1ebbf243a1f5 Mon Sep 17 00:00:00 2001 From: Edouard127 <46357922+Edouard127@users.noreply.github.com> Date: Wed, 27 Nov 2024 14:04:16 -0500 Subject: [PATCH 01/12] Create ClickFriend.kt --- .../module/modules/player/ClickFriend.kt | 100 ++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100644 common/src/main/kotlin/com/lambda/module/modules/player/ClickFriend.kt diff --git a/common/src/main/kotlin/com/lambda/module/modules/player/ClickFriend.kt b/common/src/main/kotlin/com/lambda/module/modules/player/ClickFriend.kt new file mode 100644 index 000000000..b8b5163c6 --- /dev/null +++ b/common/src/main/kotlin/com/lambda/module/modules/player/ClickFriend.kt @@ -0,0 +1,100 @@ +/* + * Copyright 2024 Lambda + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lambda.module.modules.player + +import com.lambda.event.events.MouseEvent +import com.lambda.event.listener.SafeListener.Companion.listener +import com.lambda.friend.FriendManager.befriend +import com.lambda.friend.FriendManager.isFriend +import com.lambda.friend.FriendManager.unfriend +import com.lambda.module.Module +import com.lambda.module.modules.client.ClickGui +import com.lambda.module.tag.ModuleTag +import com.lambda.util.Communication.info +import com.lambda.util.Mouse +import com.lambda.util.text.buildText +import com.lambda.util.text.color +import com.lambda.util.text.literal +import com.lambda.util.text.text +import com.lambda.util.world.raycast.RayCastUtils.entityResult +import net.minecraft.client.network.OtherClientPlayerEntity +import org.lwjgl.glfw.GLFW.GLFW_MOD_ALT +import org.lwjgl.glfw.GLFW.GLFW_MOD_CONTROL +import org.lwjgl.glfw.GLFW.GLFW_MOD_SHIFT +import org.lwjgl.glfw.GLFW.GLFW_MOD_SUPER +import java.awt.Color + +object ClickFriend : Module( + name = "ClickFriend", + description = "Add or remove friends with a single click", + defaultTags = setOf(ModuleTag.PLAYER) +) { + private val friendButton by setting("Friend Button", Mouse.Button.Right, description = "Button to press to friend a player") + private val friendAction by setting("Action", Mouse.Action.Release, description = "What mouse action should add or remove the player") + private val comboUnfriend by setting("Combo Unfriend", false, description = "Press a key and right click a player to unfriend") + private val modUnfriend by setting("Combo Key", MouseMod.Shift, description = "The key to press to activate the unfriend combo") { comboUnfriend } + + init { + listener { + if (it.button != friendButton || + it.action != friendAction || + mc.currentScreen != null + ) return@listener + + val target = mc.crosshairTarget?.entityResult?.entity as? OtherClientPlayerEntity + ?: return@listener + + if ((modUnfriend.flagsPresent(it.modifiers) || !comboUnfriend) && target.isFriend) { + target.unfriend() + info(buildText { + color(Color.RED) { + literal("Removed ") + color(Color.CYAN) { + text(target.name) + color(Color.WHITE) { literal(" from your friend list") } + } + } + }) + } + + if (!modUnfriend.flagsPresent(it.modifiers) && !target.isFriend) { + target.befriend() + info(buildText { + color(Color.GREEN) { + literal("Added ") + color(Color.CYAN) { + text(target.name) + color(Color.WHITE) { + literal(" to your friend list") + } + } + } + }) + } + } + } + + private enum class MouseMod(val modifiers: Int) { + Shift(GLFW_MOD_SHIFT), + Control(GLFW_MOD_CONTROL), + Alt(GLFW_MOD_ALT), + Super(GLFW_MOD_SUPER); + + fun flagsPresent(flags: Int) = flags and modifiers == modifiers + } +} From 683fd1661795d1d72bf9d8eb8051d0168cfeea2c Mon Sep 17 00:00:00 2001 From: Edouard127 <46357922+Edouard127@users.noreply.github.com> Date: Wed, 27 Nov 2024 14:08:10 -0500 Subject: [PATCH 02/12] indentation --- .../kotlin/com/lambda/module/modules/player/ClickFriend.kt | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/common/src/main/kotlin/com/lambda/module/modules/player/ClickFriend.kt b/common/src/main/kotlin/com/lambda/module/modules/player/ClickFriend.kt index b8b5163c6..44b1a106d 100644 --- a/common/src/main/kotlin/com/lambda/module/modules/player/ClickFriend.kt +++ b/common/src/main/kotlin/com/lambda/module/modules/player/ClickFriend.kt @@ -79,9 +79,7 @@ object ClickFriend : Module( literal("Added ") color(Color.CYAN) { text(target.name) - color(Color.WHITE) { - literal(" to your friend list") - } + color(Color.WHITE) { literal(" to your friend list") } } } }) From f07796e9e1e6922141cc02a32d24c169e3a275f7 Mon Sep 17 00:00:00 2001 From: Edouard127 <46357922+Edouard127@users.noreply.github.com> Date: Thu, 28 Nov 2024 14:01:20 -0500 Subject: [PATCH 03/12] Create FriendCommand.kt --- .../lambda/command/commands/FriendCommand.kt | 133 ++++++++++++++++++ 1 file changed, 133 insertions(+) create mode 100644 common/src/main/kotlin/com/lambda/command/commands/FriendCommand.kt diff --git a/common/src/main/kotlin/com/lambda/command/commands/FriendCommand.kt b/common/src/main/kotlin/com/lambda/command/commands/FriendCommand.kt new file mode 100644 index 000000000..0eb7ec44f --- /dev/null +++ b/common/src/main/kotlin/com/lambda/command/commands/FriendCommand.kt @@ -0,0 +1,133 @@ +/* + * Copyright 2024 Lambda + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lambda.command.commands + +import com.lambda.Lambda.mc +import com.lambda.brigadier.CommandResult.Companion.failure +import com.lambda.brigadier.CommandResult.Companion.success +import com.lambda.brigadier.argument.literal +import com.lambda.brigadier.argument.string +import com.lambda.brigadier.argument.value +import com.lambda.brigadier.execute +import com.lambda.brigadier.executeWithResult +import com.lambda.brigadier.required +import com.lambda.command.LambdaCommand +import com.lambda.config.configurations.FriendConfig +import com.lambda.friend.FriendManager +import com.lambda.util.Communication.info +import com.lambda.util.extension.CommandBuilder +import com.lambda.util.text.ClickEvents +import com.lambda.util.text.buildText +import com.lambda.util.text.color +import com.lambda.util.text.literal +import com.lambda.util.text.styled +import java.awt.Color + +object FriendCommand : LambdaCommand( + name = "friend", + usage = "friend [add/remove] [name]", + description = "Add or remove a friend" +) { + override fun CommandBuilder.create() { + execute { + this@FriendCommand.info( + buildText { + styled( + color = Color.CYAN, + underlined = true, + clickEvent = ClickEvents.openFile(FriendConfig.primary.absolutePath), + ) { + literal("Click to open your friend list") + } + } + ) + } + + required(literal("add")) { + required(string("player name")) { player -> + suggests { _, builder -> + mc.networkHandler + ?.playerList + ?.filter { it.profile != mc.gameProfile } + ?.map { it.profile.name } + ?.forEach { builder.suggest(it) } + + builder.buildFuture() + } + + executeWithResult { + val name = player().value() + if (FriendManager.contains(name)) + return@executeWithResult failure("This player is already in your friend list") + + val id = mc.networkHandler + ?.playerList + ?.firstOrNull { + it.profile.name == name && + it.profile != mc.gameProfile + } ?: return@executeWithResult failure("Could not find the player in the server") + + FriendManager.add(id.profile) + + this@FriendCommand.info(buildText { + color(Color.GREEN) { + literal("Added ") + color(Color.CYAN) { + literal(name) + color(Color.WHITE) { literal(" to your friend list") } + } + } + }) + + return@executeWithResult success() + } + } + } + + required(literal("remove")) { + required(string("player name")) { player -> + suggests { _, builder -> + FriendManager.friends.map { it.name } + .forEach { builder.suggest(it) } + + builder.buildFuture() + } + + executeWithResult { + val name = player().value() + val profile = FriendManager.get(name) + ?: return@executeWithResult failure("This player is not in your friend list") + + FriendManager.remove(profile) + + this@FriendCommand.info(buildText { + color(Color.RED) { + literal("Removed ") + color(Color.CYAN) { + literal(profile.name) + color(Color.WHITE) { literal(" from your friend list") } + } + } + }) + + return@executeWithResult success() + } + } + } + } +} From abd7dc075632b570c95e776efc51dcbaad527e2f Mon Sep 17 00:00:00 2001 From: Edouard127 <46357922+Edouard127@users.noreply.github.com> Date: Thu, 28 Nov 2024 14:01:51 -0500 Subject: [PATCH 04/12] fix later --- common/src/main/kotlin/com/lambda/friend/FriendManager.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/src/main/kotlin/com/lambda/friend/FriendManager.kt b/common/src/main/kotlin/com/lambda/friend/FriendManager.kt index 306b1e310..1760c6c05 100644 --- a/common/src/main/kotlin/com/lambda/friend/FriendManager.kt +++ b/common/src/main/kotlin/com/lambda/friend/FriendManager.kt @@ -30,7 +30,7 @@ object FriendManager : Configurable(FriendConfig), Loadable { fun add(profile: GameProfile) { if (!contains(profile)) friends.add(profile) } - fun remove(profile: GameProfile) { friends.remove(profile) } + fun remove(profile: GameProfile) = friends.remove(profile) // FixMe: For some reasons you can't remove friends fun get(name: String) = friends.firstOrNull { it.name == name } fun get(uuid: UUID) = friends.firstOrNull { it.id == uuid } From 8683549759886622b55edb9ce1fb3234758848a7 Mon Sep 17 00:00:00 2001 From: Constructor Date: Sat, 7 Dec 2024 01:23:47 +0100 Subject: [PATCH 05/12] Fix saving friends and safer management --- .../lambda/command/commands/ConfigCommand.kt | 2 +- .../lambda/command/commands/FriendCommand.kt | 6 ++-- .../lambda/command/commands/ReplayCommand.kt | 2 +- .../command/commands/TransferCommand.kt | 2 +- .../kotlin/com/lambda/friend/FriendManager.kt | 10 +++--- .../module/modules/player/ClickFriend.kt | 35 ++++++++----------- .../kotlin/com/lambda/util/text/TextDsl.kt | 13 +++++++ 7 files changed, 38 insertions(+), 32 deletions(-) diff --git a/common/src/main/kotlin/com/lambda/command/commands/ConfigCommand.kt b/common/src/main/kotlin/com/lambda/command/commands/ConfigCommand.kt index c5c456648..68ac65dd0 100644 --- a/common/src/main/kotlin/com/lambda/command/commands/ConfigCommand.kt +++ b/common/src/main/kotlin/com/lambda/command/commands/ConfigCommand.kt @@ -29,7 +29,7 @@ import com.lambda.util.extension.CommandBuilder object ConfigCommand : LambdaCommand( name = "config", aliases = setOf("cfg"), - usage = "config ", + usage = "config ", description = "Save or load the configuration files" ) { override fun CommandBuilder.create() { diff --git a/common/src/main/kotlin/com/lambda/command/commands/FriendCommand.kt b/common/src/main/kotlin/com/lambda/command/commands/FriendCommand.kt index 0eb7ec44f..0c17c90fd 100644 --- a/common/src/main/kotlin/com/lambda/command/commands/FriendCommand.kt +++ b/common/src/main/kotlin/com/lambda/command/commands/FriendCommand.kt @@ -40,7 +40,7 @@ import java.awt.Color object FriendCommand : LambdaCommand( name = "friend", - usage = "friend [add/remove] [name]", + usage = "friend ", description = "Add or remove a friend" ) { override fun CommandBuilder.create() { @@ -80,7 +80,7 @@ object FriendCommand : LambdaCommand( ?.firstOrNull { it.profile.name == name && it.profile != mc.gameProfile - } ?: return@executeWithResult failure("Could not find the player in the server") + } ?: return@executeWithResult failure("Could not find the player on the server") FriendManager.add(id.profile) @@ -110,7 +110,7 @@ object FriendCommand : LambdaCommand( executeWithResult { val name = player().value() - val profile = FriendManager.get(name) + val profile = FriendManager.gameProfile(name) ?: return@executeWithResult failure("This player is not in your friend list") FriendManager.remove(profile) diff --git a/common/src/main/kotlin/com/lambda/command/commands/ReplayCommand.kt b/common/src/main/kotlin/com/lambda/command/commands/ReplayCommand.kt index 29f3fbea2..f5610f997 100644 --- a/common/src/main/kotlin/com/lambda/command/commands/ReplayCommand.kt +++ b/common/src/main/kotlin/com/lambda/command/commands/ReplayCommand.kt @@ -33,7 +33,7 @@ import com.lambda.util.extension.CommandBuilder object ReplayCommand : LambdaCommand( name = "replay", - usage = "replay ", + usage = "replay ", description = "Play, load, save, or prune a replay" ) { override fun CommandBuilder.create() { diff --git a/common/src/main/kotlin/com/lambda/command/commands/TransferCommand.kt b/common/src/main/kotlin/com/lambda/command/commands/TransferCommand.kt index 67a4b932b..4ab9ab51f 100644 --- a/common/src/main/kotlin/com/lambda/command/commands/TransferCommand.kt +++ b/common/src/main/kotlin/com/lambda/command/commands/TransferCommand.kt @@ -32,7 +32,7 @@ import com.lambda.util.extension.CommandBuilder object TransferCommand : LambdaCommand( name = "transfer", - usage = "transfer ", + usage = "transfer ", description = "Transfer items from anywhere to anywhere", ) { private var lastTransfer: TransferResult.Transfer? = null diff --git a/common/src/main/kotlin/com/lambda/friend/FriendManager.kt b/common/src/main/kotlin/com/lambda/friend/FriendManager.kt index 1760c6c05..a65507da0 100644 --- a/common/src/main/kotlin/com/lambda/friend/FriendManager.kt +++ b/common/src/main/kotlin/com/lambda/friend/FriendManager.kt @@ -26,14 +26,14 @@ import java.util.* object FriendManager : Configurable(FriendConfig), Loadable { override val name = "friends" - val friends by setting("friends", listOf(), hackDelegates = true) + val friends by setting("friends", setOf()) - fun add(profile: GameProfile) { if (!contains(profile)) friends.add(profile) } + fun add(profile: GameProfile) = friends.add(profile) - fun remove(profile: GameProfile) = friends.remove(profile) // FixMe: For some reasons you can't remove friends + fun remove(profile: GameProfile): Boolean = friends.remove(profile) - fun get(name: String) = friends.firstOrNull { it.name == name } - fun get(uuid: UUID) = friends.firstOrNull { it.id == uuid } + fun gameProfile(name: String) = friends.firstOrNull { it.name == name } + fun gameProfile(uuid: UUID) = friends.firstOrNull { it.id == uuid } fun contains(profile: GameProfile) = friends.contains(profile) fun contains(name: String) = friends.any { it.name == name } diff --git a/common/src/main/kotlin/com/lambda/module/modules/player/ClickFriend.kt b/common/src/main/kotlin/com/lambda/module/modules/player/ClickFriend.kt index 44b1a106d..e73755d55 100644 --- a/common/src/main/kotlin/com/lambda/module/modules/player/ClickFriend.kt +++ b/common/src/main/kotlin/com/lambda/module/modules/player/ClickFriend.kt @@ -44,7 +44,7 @@ object ClickFriend : Module( description = "Add or remove friends with a single click", defaultTags = setOf(ModuleTag.PLAYER) ) { - private val friendButton by setting("Friend Button", Mouse.Button.Right, description = "Button to press to friend a player") + private val friendButton by setting("Friend Button", Mouse.Button.Middle, description = "Button to press to befriend a player") private val friendAction by setting("Action", Mouse.Action.Release, description = "What mouse action should add or remove the player") private val comboUnfriend by setting("Combo Unfriend", false, description = "Press a key and right click a player to unfriend") private val modUnfriend by setting("Combo Key", MouseMod.Shift, description = "The key to press to activate the unfriend combo") { comboUnfriend } @@ -59,30 +59,23 @@ object ClickFriend : Module( val target = mc.crosshairTarget?.entityResult?.entity as? OtherClientPlayerEntity ?: return@listener - if ((modUnfriend.flagsPresent(it.modifiers) || !comboUnfriend) && target.isFriend) { - target.unfriend() - info(buildText { - color(Color.RED) { - literal("Removed ") - color(Color.CYAN) { + if (modUnfriend.flagsPresent(it.modifiers) || !comboUnfriend) { + when { + target.isFriend && target.unfriend() -> { + this@ClickFriend.info(buildText { + literal(Color.RED, "Removed ") text(target.name) - color(Color.WHITE) { literal(" from your friend list") } - } + literal(Color.WHITE, " from your friend list") + }) } - }) - } - - if (!modUnfriend.flagsPresent(it.modifiers) && !target.isFriend) { - target.befriend() - info(buildText { - color(Color.GREEN) { - literal("Added ") - color(Color.CYAN) { + !target.isFriend && target.befriend() -> { + this@ClickFriend.info(buildText { + literal(Color.GREEN, "Added ") text(target.name) - color(Color.WHITE) { literal(" to your friend list") } - } + literal(Color.WHITE, " to your friend list") + }) } - }) + } } } } diff --git a/common/src/main/kotlin/com/lambda/util/text/TextDsl.kt b/common/src/main/kotlin/com/lambda/util/text/TextDsl.kt index f2f4bbcf6..58c04eee9 100644 --- a/common/src/main/kotlin/com/lambda/util/text/TextDsl.kt +++ b/common/src/main/kotlin/com/lambda/util/text/TextDsl.kt @@ -113,6 +113,19 @@ fun TextBuilder.literal(value: String) { styleAndAppend(Text.literal(value)) } +/** + * Adds a literal text. + * + * @param value The text. + * @see StyleBuilder for action + */ +@TextDsl +fun TextBuilder.literal(color: Color, value: String) { + color(color) { + literal(value) + } +} + /** * Adds a mutable key bind text. * From 3b7c8102504515543463a0f22e4d97d6a4024864 Mon Sep 17 00:00:00 2001 From: Constructor Date: Sat, 7 Dec 2024 02:15:22 +0100 Subject: [PATCH 06/12] Better friend command handling --- .../lambda/command/commands/FriendCommand.kt | 86 ++++++++++++------- .../kotlin/com/lambda/friend/FriendManager.kt | 42 +++++++-- .../module/modules/player/ClickFriend.kt | 13 +-- .../kotlin/com/lambda/util/text/TextDsl.kt | 2 +- 4 files changed, 92 insertions(+), 51 deletions(-) diff --git a/common/src/main/kotlin/com/lambda/command/commands/FriendCommand.kt b/common/src/main/kotlin/com/lambda/command/commands/FriendCommand.kt index 0c17c90fd..c97fbac69 100644 --- a/common/src/main/kotlin/com/lambda/command/commands/FriendCommand.kt +++ b/common/src/main/kotlin/com/lambda/command/commands/FriendCommand.kt @@ -22,6 +22,7 @@ import com.lambda.brigadier.CommandResult.Companion.failure import com.lambda.brigadier.CommandResult.Companion.success import com.lambda.brigadier.argument.literal import com.lambda.brigadier.argument.string +import com.lambda.brigadier.argument.uuid import com.lambda.brigadier.argument.value import com.lambda.brigadier.execute import com.lambda.brigadier.executeWithResult @@ -33,26 +34,36 @@ import com.lambda.util.Communication.info import com.lambda.util.extension.CommandBuilder import com.lambda.util.text.ClickEvents import com.lambda.util.text.buildText -import com.lambda.util.text.color import com.lambda.util.text.literal import com.lambda.util.text.styled import java.awt.Color object FriendCommand : LambdaCommand( - name = "friend", - usage = "friend ", + name = "friends", + usage = "friends ", description = "Add or remove a friend" ) { override fun CommandBuilder.create() { execute { this@FriendCommand.info( buildText { + if (FriendManager.friends.isEmpty()) { + literal("You have no friends yet. Go make some! :3\n") + } else { + literal("Your friends (${FriendManager.friends.size}):\n") + + FriendManager.friends.forEachIndexed { index, gameProfile -> + literal(" ${index + 1}. ${gameProfile.name}\n") + } + } + + literal("\n") styled( color = Color.CYAN, underlined = true, - clickEvent = ClickEvents.openFile(FriendConfig.primary.absolutePath), + clickEvent = ClickEvents.openFile(FriendConfig.primary.path), ) { - literal("Click to open your friend list") + literal("Click to open your friends list as a file") } } ) @@ -72,9 +83,6 @@ object FriendCommand : LambdaCommand( executeWithResult { val name = player().value() - if (FriendManager.contains(name)) - return@executeWithResult failure("This player is already in your friend list") - val id = mc.networkHandler ?.playerList ?.firstOrNull { @@ -82,19 +90,40 @@ object FriendCommand : LambdaCommand( it.profile != mc.gameProfile } ?: return@executeWithResult failure("Could not find the player on the server") - FriendManager.add(id.profile) + return@executeWithResult if (FriendManager.befriend(id.profile)) { + this@FriendCommand.info(FriendManager.befriendedText(id.profile.name)) + success() + } else { + failure("This player is already in your friend list") + } + } + } - this@FriendCommand.info(buildText { - color(Color.GREEN) { - literal("Added ") - color(Color.CYAN) { - literal(name) - color(Color.WHITE) { literal(" to your friend list") } - } - } - }) + required(uuid("player uuid")) { player -> + suggests { _, builder -> + mc.networkHandler + ?.playerList + ?.filter { it.profile != mc.gameProfile } + ?.map { it.profile.id } + ?.forEach { builder.suggest(it.toString()) } - return@executeWithResult success() + builder.buildFuture() + } + + executeWithResult { + val uuid = player().value() + val id = mc.networkHandler + ?.playerList + ?.firstOrNull { + it.profile.id == uuid && it.profile != mc.gameProfile + } ?: return@executeWithResult failure("Could not find the player on the server") + + return@executeWithResult if (FriendManager.befriend(id.profile)) { + this@FriendCommand.info(FriendManager.befriendedText(id.profile.name)) + success() + } else { + failure("This player is already in your friend list") + } } } } @@ -113,19 +142,12 @@ object FriendCommand : LambdaCommand( val profile = FriendManager.gameProfile(name) ?: return@executeWithResult failure("This player is not in your friend list") - FriendManager.remove(profile) - - this@FriendCommand.info(buildText { - color(Color.RED) { - literal("Removed ") - color(Color.CYAN) { - literal(profile.name) - color(Color.WHITE) { literal(" from your friend list") } - } - } - }) - - return@executeWithResult success() + return@executeWithResult if (FriendManager.unfriend(profile)) { + this@FriendCommand.info(FriendManager.unfriendedText(name)) + success() + } else { + failure("This player is not in your friend list") + } } } } diff --git a/common/src/main/kotlin/com/lambda/friend/FriendManager.kt b/common/src/main/kotlin/com/lambda/friend/FriendManager.kt index a65507da0..9442b1b2a 100644 --- a/common/src/main/kotlin/com/lambda/friend/FriendManager.kt +++ b/common/src/main/kotlin/com/lambda/friend/FriendManager.kt @@ -20,35 +20,61 @@ package com.lambda.friend import com.lambda.config.Configurable import com.lambda.config.configurations.FriendConfig import com.lambda.core.Loadable +import com.lambda.util.text.buildText +import com.lambda.util.text.literal +import com.lambda.util.text.text import com.mojang.authlib.GameProfile import net.minecraft.client.network.OtherClientPlayerEntity +import net.minecraft.text.Text +import java.awt.Color import java.util.* +// ToDo: +// - Allow adding of offline players by name or uuid. +// - Should store the data until the player was seen. +// Either no UUID but with name or no name but with uuid or both. +// -> Should update the record if the player was seen again. +// - Handle player changing names. +// - Improve save file structure. object FriendManager : Configurable(FriendConfig), Loadable { override val name = "friends" val friends by setting("friends", setOf()) - fun add(profile: GameProfile) = friends.add(profile) + fun befriend(profile: GameProfile) = friends.add(profile) - fun remove(profile: GameProfile): Boolean = friends.remove(profile) + fun unfriend(profile: GameProfile): Boolean = friends.remove(profile) fun gameProfile(name: String) = friends.firstOrNull { it.name == name } fun gameProfile(uuid: UUID) = friends.firstOrNull { it.id == uuid } - fun contains(profile: GameProfile) = friends.contains(profile) - fun contains(name: String) = friends.any { it.name == name } - fun contains(uuid: UUID) = friends.any { it.id == uuid } + fun isFriend(profile: GameProfile) = friends.contains(profile) + fun isFriend(name: String) = friends.any { it.name == name } + fun isFriend(uuid: UUID) = friends.any { it.id == uuid } fun clear() = friends.clear() val OtherClientPlayerEntity.isFriend: Boolean - get() = contains(gameProfile) + get() = isFriend(gameProfile) - fun OtherClientPlayerEntity.befriend() = add(gameProfile) - fun OtherClientPlayerEntity.unfriend() = remove(gameProfile) + fun OtherClientPlayerEntity.befriend() = befriend(gameProfile) + fun OtherClientPlayerEntity.unfriend() = unfriend(gameProfile) override fun load(): String { // TODO: Because the settings are loaded after the property and the loadables, the friend list is empty at that point return "Loaded ${friends.size} friends" } + + fun befriendedText(name: String): Text = befriendedText(Text.of(name)) + fun befriendedText(name: Text) = buildText { + literal(Color.GREEN, "Added ") + text(name) + literal(" to your friend list") + } + + fun unfriendedText(name: String): Text = unfriendedText(Text.of(name)) + fun unfriendedText(name: Text) = buildText { + literal(Color.RED, "Removed ") + text(name) + literal(" from your friend list") + } } diff --git a/common/src/main/kotlin/com/lambda/module/modules/player/ClickFriend.kt b/common/src/main/kotlin/com/lambda/module/modules/player/ClickFriend.kt index e73755d55..51431063b 100644 --- a/common/src/main/kotlin/com/lambda/module/modules/player/ClickFriend.kt +++ b/common/src/main/kotlin/com/lambda/module/modules/player/ClickFriend.kt @@ -19,6 +19,7 @@ package com.lambda.module.modules.player import com.lambda.event.events.MouseEvent import com.lambda.event.listener.SafeListener.Companion.listener +import com.lambda.friend.FriendManager import com.lambda.friend.FriendManager.befriend import com.lambda.friend.FriendManager.isFriend import com.lambda.friend.FriendManager.unfriend @@ -62,18 +63,10 @@ object ClickFriend : Module( if (modUnfriend.flagsPresent(it.modifiers) || !comboUnfriend) { when { target.isFriend && target.unfriend() -> { - this@ClickFriend.info(buildText { - literal(Color.RED, "Removed ") - text(target.name) - literal(Color.WHITE, " from your friend list") - }) + this@ClickFriend.info(FriendManager.unfriendedText(target.name)) } !target.isFriend && target.befriend() -> { - this@ClickFriend.info(buildText { - literal(Color.GREEN, "Added ") - text(target.name) - literal(Color.WHITE, " to your friend list") - }) + this@ClickFriend.info(FriendManager.befriendedText(target.name)) } } } diff --git a/common/src/main/kotlin/com/lambda/util/text/TextDsl.kt b/common/src/main/kotlin/com/lambda/util/text/TextDsl.kt index 58c04eee9..b611d7dfc 100644 --- a/common/src/main/kotlin/com/lambda/util/text/TextDsl.kt +++ b/common/src/main/kotlin/com/lambda/util/text/TextDsl.kt @@ -120,7 +120,7 @@ fun TextBuilder.literal(value: String) { * @see StyleBuilder for action */ @TextDsl -fun TextBuilder.literal(color: Color, value: String) { +fun TextBuilder.literal(color: Color = Color.WHITE, value: String) { color(color) { literal(value) } From 3aeeedcc9e8a1c0990a840aa444469e42061c850 Mon Sep 17 00:00:00 2001 From: Constructor Date: Sat, 7 Dec 2024 02:15:35 +0100 Subject: [PATCH 07/12] Remove hack delegates --- .../kotlin/com/lambda/config/Configurable.kt | 3 --- .../config/settings/collections/SetSetting.kt | 20 ++----------------- 2 files changed, 2 insertions(+), 21 deletions(-) diff --git a/common/src/main/kotlin/com/lambda/config/Configurable.kt b/common/src/main/kotlin/com/lambda/config/Configurable.kt index 4f388e91d..3a5c38429 100644 --- a/common/src/main/kotlin/com/lambda/config/Configurable.kt +++ b/common/src/main/kotlin/com/lambda/config/Configurable.kt @@ -248,7 +248,6 @@ abstract class Configurable( * @param name The unique identifier for the setting. * @param defaultValue The default [Set] value of type [T] for the setting. * @param description A brief explanation of the setting's purpose and behavior. - * @param hackDelegates A flag that determines whether the setting should be serialized with the default value. * @param visibility A lambda expression that determines the visibility status of the setting. * * ```kotlin @@ -262,14 +261,12 @@ abstract class Configurable( name: String, defaultValue: Set, description: String = "", - hackDelegates: Boolean = false, noinline visibility: () -> Boolean = { true }, ) = SetSetting( name, defaultValue.toMutableSet(), TypeToken.getParameterized(MutableSet::class.java, T::class.java).type, description, - hackDelegates, visibility, ).also { settings.add(it) diff --git a/common/src/main/kotlin/com/lambda/config/settings/collections/SetSetting.kt b/common/src/main/kotlin/com/lambda/config/settings/collections/SetSetting.kt index eec3047d0..160256c1b 100644 --- a/common/src/main/kotlin/com/lambda/config/settings/collections/SetSetting.kt +++ b/common/src/main/kotlin/com/lambda/config/settings/collections/SetSetting.kt @@ -17,8 +17,6 @@ package com.lambda.config.settings.collections -import com.google.gson.JsonElement -import com.lambda.Lambda.gson import com.lambda.config.AbstractSetting import java.lang.reflect.Type @@ -27,27 +25,13 @@ import java.lang.reflect.Type */ class SetSetting( override val name: String, - private val defaultValue: MutableSet, + defaultValue: MutableSet, type: Type, description: String, - private val hackDelegates: Boolean, visibility: () -> Boolean, ) : AbstractSetting>( defaultValue, type, description, visibility -) { - override fun toJson(): JsonElement { - return if (hackDelegates) gson.toJsonTree(defaultValue, type) - else super.toJson() - } - - override fun loadFromJson(serialized: JsonElement) { - if (hackDelegates) { - defaultValue.addAll(gson.fromJson(serialized, type)) - setValue(this, ::value, defaultValue.distinct().toMutableSet()) - } - else super.loadFromJson(serialized) - } -} +) From 7574cd33287fea17c8277f0d4a0b361f15edeab9 Mon Sep 17 00:00:00 2001 From: Constructor Date: Sat, 7 Dec 2024 02:15:57 +0100 Subject: [PATCH 08/12] Show unbound not -1 in command preview --- common/src/main/kotlin/com/lambda/util/Communication.kt | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/common/src/main/kotlin/com/lambda/util/Communication.kt b/common/src/main/kotlin/com/lambda/util/Communication.kt index fdb49c774..8a9a55053 100644 --- a/common/src/main/kotlin/com/lambda/util/Communication.kt +++ b/common/src/main/kotlin/com/lambda/util/Communication.kt @@ -151,7 +151,12 @@ object Communication { literal("\n") literal("Keybind: ") color(GuiSettings.primaryColor) { - literal(module.keybind.keyCode.toString()) + if (module.keybind.keyCode != -1) { + literal(module.keybind.keyCode.toString()) + } else { + literal("Unbound") + } + } literal("\n") literal("Default tags: ") From 06ba51601a89f1c047a65873efd6536252860219 Mon Sep 17 00:00:00 2001 From: Constructor Date: Sat, 7 Dec 2024 02:23:38 +0100 Subject: [PATCH 09/12] Undo friends action --- .../kotlin/com/lambda/friend/FriendManager.kt | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/common/src/main/kotlin/com/lambda/friend/FriendManager.kt b/common/src/main/kotlin/com/lambda/friend/FriendManager.kt index 9442b1b2a..34608be0d 100644 --- a/common/src/main/kotlin/com/lambda/friend/FriendManager.kt +++ b/common/src/main/kotlin/com/lambda/friend/FriendManager.kt @@ -20,9 +20,7 @@ package com.lambda.friend import com.lambda.config.Configurable import com.lambda.config.configurations.FriendConfig import com.lambda.core.Loadable -import com.lambda.util.text.buildText -import com.lambda.util.text.literal -import com.lambda.util.text.text +import com.lambda.util.text.* import com.mojang.authlib.GameProfile import net.minecraft.client.network.OtherClientPlayerEntity import net.minecraft.text.Text @@ -68,13 +66,23 @@ object FriendManager : Configurable(FriendConfig), Loadable { fun befriendedText(name: Text) = buildText { literal(Color.GREEN, "Added ") text(name) - literal(" to your friend list") + literal(" to your friend list ") + clickEvent(ClickEvents.suggestCommand(";friends remove ${name.string}")) { + styled(underlined = true, color = Color.LIGHT_GRAY) { + literal("[Click to undo]") + } + } } fun unfriendedText(name: String): Text = unfriendedText(Text.of(name)) fun unfriendedText(name: Text) = buildText { literal(Color.RED, "Removed ") text(name) - literal(" from your friend list") + literal(" from your friend list ") + clickEvent(ClickEvents.suggestCommand(";friends add ${name.string}")) { + styled(underlined = true, color = Color.LIGHT_GRAY) { + literal("[Click to undo]") + } + } } } From 96c408cb5af9a107b4131b08ec35e50e871adfff Mon Sep 17 00:00:00 2001 From: Constructor Date: Sat, 7 Dec 2024 03:04:03 +0100 Subject: [PATCH 10/12] Shorter undo message --- common/src/main/kotlin/com/lambda/friend/FriendManager.kt | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/common/src/main/kotlin/com/lambda/friend/FriendManager.kt b/common/src/main/kotlin/com/lambda/friend/FriendManager.kt index 34608be0d..aa57de7a6 100644 --- a/common/src/main/kotlin/com/lambda/friend/FriendManager.kt +++ b/common/src/main/kotlin/com/lambda/friend/FriendManager.kt @@ -39,7 +39,6 @@ object FriendManager : Configurable(FriendConfig), Loadable { val friends by setting("friends", setOf()) fun befriend(profile: GameProfile) = friends.add(profile) - fun unfriend(profile: GameProfile): Boolean = friends.remove(profile) fun gameProfile(name: String) = friends.firstOrNull { it.name == name } @@ -69,7 +68,7 @@ object FriendManager : Configurable(FriendConfig), Loadable { literal(" to your friend list ") clickEvent(ClickEvents.suggestCommand(";friends remove ${name.string}")) { styled(underlined = true, color = Color.LIGHT_GRAY) { - literal("[Click to undo]") + literal("[Undo]") } } } @@ -81,7 +80,7 @@ object FriendManager : Configurable(FriendConfig), Loadable { literal(" from your friend list ") clickEvent(ClickEvents.suggestCommand(";friends add ${name.string}")) { styled(underlined = true, color = Color.LIGHT_GRAY) { - literal("[Click to undo]") + literal("[Undo]") } } } From 79d2c837d673fedbbdb1c899364c7be079eeff37 Mon Sep 17 00:00:00 2001 From: Constructor Date: Sat, 7 Dec 2024 17:54:21 +0100 Subject: [PATCH 11/12] Resolve merge conflicts --- .../lambda/module/modules/player/ClickFriend.kt | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/common/src/main/kotlin/com/lambda/module/modules/player/ClickFriend.kt b/common/src/main/kotlin/com/lambda/module/modules/player/ClickFriend.kt index 51431063b..6de55cb8d 100644 --- a/common/src/main/kotlin/com/lambda/module/modules/player/ClickFriend.kt +++ b/common/src/main/kotlin/com/lambda/module/modules/player/ClickFriend.kt @@ -18,27 +18,21 @@ package com.lambda.module.modules.player import com.lambda.event.events.MouseEvent -import com.lambda.event.listener.SafeListener.Companion.listener +import com.lambda.event.listener.SafeListener.Companion.listen import com.lambda.friend.FriendManager import com.lambda.friend.FriendManager.befriend import com.lambda.friend.FriendManager.isFriend import com.lambda.friend.FriendManager.unfriend import com.lambda.module.Module -import com.lambda.module.modules.client.ClickGui import com.lambda.module.tag.ModuleTag import com.lambda.util.Communication.info import com.lambda.util.Mouse -import com.lambda.util.text.buildText -import com.lambda.util.text.color -import com.lambda.util.text.literal -import com.lambda.util.text.text import com.lambda.util.world.raycast.RayCastUtils.entityResult import net.minecraft.client.network.OtherClientPlayerEntity import org.lwjgl.glfw.GLFW.GLFW_MOD_ALT import org.lwjgl.glfw.GLFW.GLFW_MOD_CONTROL import org.lwjgl.glfw.GLFW.GLFW_MOD_SHIFT import org.lwjgl.glfw.GLFW.GLFW_MOD_SUPER -import java.awt.Color object ClickFriend : Module( name = "ClickFriend", @@ -51,14 +45,14 @@ object ClickFriend : Module( private val modUnfriend by setting("Combo Key", MouseMod.Shift, description = "The key to press to activate the unfriend combo") { comboUnfriend } init { - listener { + listen { if (it.button != friendButton || it.action != friendAction || mc.currentScreen != null - ) return@listener + ) return@listen val target = mc.crosshairTarget?.entityResult?.entity as? OtherClientPlayerEntity - ?: return@listener + ?: return@listen if (modUnfriend.flagsPresent(it.modifiers) || !comboUnfriend) { when { From 6d746cad14bf4f9d9f7164559818d45cd0db4741 Mon Sep 17 00:00:00 2001 From: Constructor Date: Sat, 7 Dec 2024 17:56:25 +0100 Subject: [PATCH 12/12] Notice for value changes --- common/src/main/kotlin/com/lambda/config/AbstractSetting.kt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/common/src/main/kotlin/com/lambda/config/AbstractSetting.kt b/common/src/main/kotlin/com/lambda/config/AbstractSetting.kt index 1950dc46c..e54586340 100644 --- a/common/src/main/kotlin/com/lambda/config/AbstractSetting.kt +++ b/common/src/main/kotlin/com/lambda/config/AbstractSetting.kt @@ -100,6 +100,10 @@ abstract class AbstractSetting( value = gson.fromJson(serialized, type) } + /** + * Will only register changes of the variable, not the content of the variable! + * E.g., if the variable is a list, it will only register if the list reference changes, not if the content of the list changes. + */ fun onValueChange(block: SafeContext.(from: T, to: T) -> Unit) { listeners.add(ValueListener(true) { from, to -> runSafe {