-
-
Notifications
You must be signed in to change notification settings - Fork 21
GH-1296 feat(helpop): add helpop reply functionality and related events #1296
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
996bd1a
76bf7ab
32303c8
1496a3c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| package com.eternalcode.core.feature.helpop; | ||
|
|
||
| import java.util.UUID; | ||
| import org.jetbrains.annotations.NotNull; | ||
|
|
||
| /** | ||
| * Service responsible for managing helpop functionality. | ||
| */ | ||
| public interface HelpOpService { | ||
|
|
||
| /** | ||
| * Marks a player as having sent a helpop request. | ||
| * | ||
| * <p>This allows administrators to reply to the player's request | ||
| * using the helpop reply command. | ||
| * | ||
| * @param playerUuid the UUID of the player who sent the helpop request | ||
| */ | ||
| void markSender(@NotNull UUID playerUuid); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. markHelpOp |
||
|
|
||
| /** | ||
| * Checks if a player has sent a helpop request. | ||
| * | ||
| * <p>Helpop requests expire after a configured duration (default: 1 hour). | ||
| * | ||
| * @param playerUuid the UUID of the player to check | ||
| * @return {@code true} if the player has an active helpop request, {@code false} otherwise | ||
| */ | ||
| boolean hasSentHelpOp(@NotNull UUID playerUuid); | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,92 @@ | ||
| package com.eternalcode.core.feature.helpop.event; | ||
|
|
||
| import org.bukkit.entity.Player; | ||
| import org.bukkit.event.Cancellable; | ||
| import org.bukkit.event.Event; | ||
| import org.bukkit.event.HandlerList; | ||
| import org.jetbrains.annotations.NotNull; | ||
|
|
||
| /** | ||
| * Event called when an administrator replies to a player's helpop request. | ||
| * | ||
| * <p>This event is triggered before the reply message is actually sent to the player. | ||
| * Plugins can cancel this event to prevent the reply from being sent, or modify | ||
| * the reply content before it's delivered. | ||
| */ | ||
| public class HelpOpReplyEvent extends Event implements Cancellable { | ||
|
|
||
| private static final HandlerList HANDLER_LIST = new HandlerList(); | ||
|
|
||
| private final Player admin; | ||
| private final Player target; | ||
| private String content; | ||
| private boolean cancelled; | ||
|
|
||
| public HelpOpReplyEvent(@NotNull Player admin, @NotNull Player target, @NotNull String content) { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why not the Jspecify?????????????????????
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. applies for the whole class |
||
| super(false); | ||
|
|
||
| this.admin = admin; | ||
| this.target = target; | ||
| this.content = content; | ||
| } | ||
|
|
||
| /** | ||
| * Gets the administrator who is replying. | ||
| * | ||
| * @return the admin player | ||
| */ | ||
| @NotNull | ||
| public Player getAdmin() { | ||
| return this.admin; | ||
| } | ||
|
|
||
| /** | ||
| * Gets the player who originally sent the helpop request. | ||
| * | ||
| * @return the target player | ||
| */ | ||
| @NotNull | ||
| public Player getTarget() { | ||
| return this.target; | ||
| } | ||
|
|
||
| /** | ||
| * Gets the reply message content. | ||
| * | ||
| * @return the reply content | ||
| */ | ||
| @NotNull | ||
| public String getContent() { | ||
| return this.content; | ||
| } | ||
|
|
||
| /** | ||
| * Sets the reply message content. | ||
| * | ||
| * @param content the new reply content | ||
| */ | ||
| public void setContent(@NotNull String content) { | ||
| this.content = content; | ||
| } | ||
|
|
||
| @Override | ||
| public boolean isCancelled() { | ||
| return this.cancelled; | ||
| } | ||
|
|
||
| @Override | ||
| public void setCancelled(boolean cancel) { | ||
| this.cancelled = cancel; | ||
| } | ||
|
|
||
| @Override | ||
| @NotNull | ||
| public HandlerList getHandlers() { | ||
| return HANDLER_LIST; | ||
| } | ||
|
|
||
| @NotNull | ||
| public static HandlerList getHandlerList() { | ||
| return HANDLER_LIST; | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,76 @@ | ||
| package com.eternalcode.core.feature.helpop; | ||
|
|
||
| import com.eternalcode.annotations.scan.command.DescriptionDocs; | ||
| import com.eternalcode.annotations.scan.permission.PermissionDocs; | ||
| import com.eternalcode.core.event.EventCaller; | ||
| import com.eternalcode.core.feature.helpop.event.HelpOpReplyEvent; | ||
| import com.eternalcode.core.injector.annotations.Inject; | ||
| import com.eternalcode.core.notice.NoticeService; | ||
| import dev.rollczi.litecommands.annotations.argument.Arg; | ||
| import dev.rollczi.litecommands.annotations.command.Command; | ||
| import dev.rollczi.litecommands.annotations.context.Sender; | ||
| import dev.rollczi.litecommands.annotations.execute.Execute; | ||
| import dev.rollczi.litecommands.annotations.join.Join; | ||
| import dev.rollczi.litecommands.annotations.permission.Permission; | ||
| import net.kyori.adventure.text.minimessage.MiniMessage; | ||
| import org.bukkit.entity.Player; | ||
|
|
||
| @Command(name = "helpopreply") | ||
|
Comment on lines
+17
to
+18
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. maybe add alias "hr"
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. if someone wants to use no standard aliases, then the user can add it to the commands configuration |
||
| @Permission("eternalcore.helpop.reply") | ||
| @PermissionDocs( | ||
| name = "HelpOp Reply", | ||
| description = "Allows administrator to reply to a player's helpop request", | ||
| permission = "eternalcore.helpop.reply" | ||
| ) | ||
| class HelpOpReplyCommand { | ||
|
|
||
| private final NoticeService noticeService; | ||
| private final HelpOpService helpOpService; | ||
| private final EventCaller eventCaller; | ||
|
|
||
| @Inject | ||
| HelpOpReplyCommand(NoticeService noticeService, HelpOpService helpOpService, EventCaller eventCaller) { | ||
| this.noticeService = noticeService; | ||
| this.helpOpService = helpOpService; | ||
| this.eventCaller = eventCaller; | ||
| } | ||
|
|
||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. maybe add default execute - when player is not provided - then admin replays to the last helpop message |
||
| @Execute | ||
| @DescriptionDocs(description = "Reply to a player's helpop request", arguments = "<player> <message>") | ||
| void execute(@Sender Player admin, @Arg Player target, @Join String message) { | ||
| if (!this.helpOpService.hasSentHelpOp(target.getUniqueId())) { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ten if jest do wywalenia, nie ma potrzeby utrudniać pracy adminowi. Jeśli bardzo chce napisać do jakieś osoby na helpop pierwszy to nie ma po co mu tego zabraniać |
||
| this.noticeService.create() | ||
| .player(admin.getUniqueId()) | ||
| .notice(translation -> translation.helpOp().playerNotSentHelpOp()) | ||
| .placeholder("{PLAYER}", target.getName()) | ||
| .send(); | ||
|
|
||
| return; | ||
| } | ||
|
|
||
| HelpOpReplyEvent event = new HelpOpReplyEvent(admin, target, message); | ||
| this.eventCaller.callEvent(event); | ||
|
|
||
| if (event.isCancelled()) { | ||
| return; | ||
| } | ||
|
|
||
| String escapedMessage = MiniMessage.miniMessage().escapeTags(event.getContent()); | ||
|
|
||
| this.noticeService.create() | ||
| .console() | ||
| .player(target.getUniqueId()) | ||
| .onlinePlayers(HelpOpCommand.HELPOP_SPY) | ||
| .notice(translation -> translation.helpOp().adminReply()) | ||
| .placeholder("{ADMIN}", admin.getName()) | ||
| .placeholder("{PLAYER}", target.getName()) | ||
| .placeholder("{TEXT}", escapedMessage) | ||
| .send(); | ||
|
|
||
| this.noticeService.create() | ||
| .player(admin.getUniqueId()) | ||
| .notice(translation -> translation.helpOp().adminReplySend()) | ||
| .placeholder("{PLAYER}", target.getName()) | ||
| .send(); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,26 @@ | ||||||
| package com.eternalcode.core.feature.helpop; | ||||||
|
|
||||||
| import com.eternalcode.core.injector.annotations.component.Service; | ||||||
| import com.google.common.cache.Cache; | ||||||
| import com.google.common.cache.CacheBuilder; | ||||||
| import java.time.Duration; | ||||||
| import java.util.UUID; | ||||||
| import org.jspecify.annotations.NonNull; | ||||||
|
|
||||||
| @Service | ||||||
| class HelpOpServiceImpl implements HelpOpService { | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why though?? So we should add the |
||||||
|
|
||||||
| private final Cache<UUID, Boolean> helpOpSenders = CacheBuilder.newBuilder() | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Question, do we plan to manually invalidate this cache? The current implementation just allows the administrators to reply to a single HelpOp request infinite times in the given time period. |
||||||
| .expireAfterWrite(Duration.ofHours(1)) | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The cache expiration is hardcoded to 1 hour. The Javadoc for
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Agreed with Gemini here; it won't hurt us if we make this configurable.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. imo too much
Suggested change
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's make this configurable |
||||||
| .build(); | ||||||
|
|
||||||
| @Override | ||||||
| public void markSender(@NonNull UUID playerUuid) { | ||||||
| this.helpOpSenders.put(playerUuid, true); | ||||||
| } | ||||||
|
|
||||||
| @Override | ||||||
| public boolean hasSentHelpOp(@NonNull UUID playerUuid) { | ||||||
| return this.helpOpSenders.getIfPresent(playerUuid) != null; | ||||||
| } | ||||||
| } | ||||||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -1,18 +1,34 @@ | ||||||
| package com.eternalcode.core.feature.helpop.messages; | ||||||
|
|
||||||
| import com.eternalcode.multification.bukkit.notice.BukkitNotice; | ||||||
| import com.eternalcode.multification.notice.Notice; | ||||||
| import eu.okaeri.configs.OkaeriConfig; | ||||||
| import eu.okaeri.configs.annotation.Comment; | ||||||
| import lombok.Getter; | ||||||
| import lombok.experimental.Accessors; | ||||||
| import org.bukkit.Sound; | ||||||
|
|
||||||
| @Getter | ||||||
| @Accessors(fluent = true) | ||||||
| public class ENHelpOpMessages extends OkaeriConfig implements HelpOpSection { | ||||||
| @Comment("# {PLAYER} - Player who send message on /helpop, {TEXT} - message") | ||||||
| Notice format = Notice.chat("<dark_gray>[<color:#9d6eef>HelpOp<dark_gray>] <white>{PLAYER}<dark_gray>: <white>{TEXT}"); | ||||||
|
|
||||||
| @Comment(" ") | ||||||
| Notice send = Notice.chat("<color:#9d6eef>► <white>This message has been successfully sent to administration"); | ||||||
|
|
||||||
| @Comment("# {TIME} - Time to next use (cooldown)") | ||||||
| Notice helpOpDelay = Notice.chat("<red>✘ <dark_red>You can use this command for: <red>{TIME}"); | ||||||
|
|
||||||
| @Comment("# {ADMIN} - Admin who replied, {PLAYER} - Player who received the reply, {TEXT} - Reply message") | ||||||
| Notice adminReply = BukkitNotice.builder() | ||||||
| .chat("<dark_gray>[<color:#9d6eef>HelpOp<dark_gray>] <white>{ADMIN} <dark_gray>-> <white>{PLAYER}<dark_gray>: <white>{TEXT}") | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
| .sound(Sound.ENTITY_EXPERIENCE_ORB_PICKUP, 1.0f, 1.0f) | ||||||
| .build(); | ||||||
|
|
||||||
| @Comment(" ") | ||||||
| Notice adminReplySend = Notice.chat("<color:#9d6eef>► <white>Reply has been sent to player <color:#9d6eef>{PLAYER}"); | ||||||
|
|
||||||
| @Comment("# {PLAYER} - Player name") | ||||||
| Notice playerNotSentHelpOp = Notice.chat("<red>✘ <dark_red>Player <red>{PLAYER} <dark_red>has not sent any helpop request"); | ||||||
| } | ||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
jak bardzo chcemy żeby tu był serwis od helpop to faktycznie przenieśmy tutaj logię, delay etc. I zamiast markSender. dodajmy tutaj
.report(SENDER, MESSAGE)
.getLastReporters(): List - może się dla admina przydać do tab complete
.replay(SENDER, TARGET, MESSAGE)
.replayToLastReporter()