Skip to content

Conversation

@Jakubk15
Copy link
Member

@Jakubk15 Jakubk15 commented Jan 17, 2026

This pull request introduces comprehensive Discord integration into the ParcelLockers plugin, including support for both native Discord bots and DiscordSRV, as well as configurable messages and settings. The changes add new configuration options, message templates, and implementation classes to enable Discord account linking, notifications, and commands.

Discord Integration Features:

  • Added Discord integration support with a toggle in PluginConfig. Includes settings for enabling/disabling and specifying the Discord bot token. [1] [2]
  • Implemented Discord account linking services and repository, supporting both DiscordSRV and a fallback linking system. Includes new classes such as DiscordLinkService, DiscordFallbackLinkService, and DiscordLinkRepository. [1] [2] [3]
  • Added DiscordClientManager for managing the Discord bot client lifecycle, including login and shutdown.
  • Integrated Discord-related commands (DiscordLinkCommand, DiscordUnlinkCommand, DiscordSrvLinkCommand, DiscordSrvUnlinkCommand) and event controllers for handling parcel delivery notifications via Discord. [1] [2]

Configuration and Messaging Enhancements:

  • Extended MessageConfig with a new DiscordMessages section, allowing customization of all messages related to Discord linking, verification, and notifications, including DiscordSRV-specific messages. [1] [2]
  • Updated plugin initialization and shutdown logic to handle Discord integration setup and teardown gracefully, including disabling the plugin if required Discord settings are missing. [1] [2] [3]

General Refactoring:

  • Refactored metrics and updater service initialization for clarity.

These changes collectively enable robust Discord integration, allowing users to link their Minecraft and Discord accounts, receive notifications, and configure all related messages and settings.

@Jakubk15 Jakubk15 added the 🆕 feature New feature or request label Jan 17, 2026
@Jakubk15 Jakubk15 marked this pull request as draft January 17, 2026 14:54
Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a significant new feature: Discord integration. The implementation is comprehensive, covering configuration, commands for linking/unlinking accounts, and the necessary database persistence.

My review focuses on several key areas:

  • Critical Blocking Calls: There are several instances of blocking network and I/O calls (.block()) on the main server thread. These will cause your server to freeze and must be addressed. I've marked these as critical.
  • Code Readability: Some methods with asynchronous logic have deeply nested callbacks, which can be refactored for better readability and maintainability.
  • Configuration Defaults: The default values in the configuration should be set to be more generic for a public plugin.
  • Minor Logic Errors: I found a few minor issues, such as a duplicated condition and incorrect message targets for admin commands.

Overall, this is a great addition. Addressing the blocking calls is the highest priority before this can be safely used on a production server.

Comment on lines +29 to +31
if (this.client != null) {
this.client.logout().block();
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

Similar to initialize(), using .block() here during plugin shutdown can cause delays and potentially server hangs if the logout process takes time. It's better to use a non-blocking approach, such as .subscribe(), to ensure a swift shutdown.

Jakubk15 and others added 6 commits January 17, 2026 16:07
…/DiscordLinkRepositoryOrmLite.java

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
…/DiscordLinkRepositoryOrmLite.java

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
@Jakubk15 Jakubk15 linked an issue Jan 17, 2026 that may be closed by this pull request
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This pull request adds Discord integration to the ParcelLockers plugin, enabling players to link their Minecraft accounts with Discord for notifications. The implementation includes account linking/unlinking commands with verification flow, repository layer for persistence, and Discord client lifecycle management.

Changes:

  • Added Discord client manager with async login/logout functionality
  • Implemented account linking commands with verification code flow using Paper's Dialog API
  • Created repository layer with OrmLite for storing Discord-Minecraft account links
  • Extended configuration with Discord settings and related messages

Reviewed changes

Copilot reviewed 11 out of 12 changed files in this pull request and generated 17 comments.

Show a summary per file
File Description
build.gradle.kts Added discord4j-core dependency and invalid JUnit version
DiscordLink.java Simple record for linking Minecraft UUID to Discord ID
DiscordNotificationType.java Unused enum defining notification delivery types
DiscordClientManager.java Manages Discord client lifecycle with async initialization issues
DiscordLinkRepository*.java Repository interface, entity, and OrmLite implementation with query bug
DiscordLinkCommand.java Account linking command with verification flow and security concerns
DiscordUnlinkCommand.java Account unlinking command for self and admin operations
PluginConfig.java Discord configuration settings with hardcoded test values
MessageConfig.java Discord-related user messages with misleading error text
ParcelLockers.java Plugin initialization with race condition and null handling issues

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@Jakubk15 Jakubk15 marked this pull request as ready for review January 24, 2026 18:44
Jakubk15 and others added 8 commits January 24, 2026 19:51
…scordLinkCommand.java

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
…scordLinkCommand.java

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
…scordLinkCommand.java

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
…ementation/MessageConfig.java

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 24 out of 25 changed files in this pull request and generated 15 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 80 to 141
if (this.authCodesCache.getIfPresent(playerUuid) != null) {
this.noticeService.player(playerUuid, messages -> messages.discord.verificationAlreadyPending);
return;
}

this.validateAndLink(playerUuid, discordIdString)
.thenCompose(validationResult -> {
if (!validationResult.isValid()) {
this.noticeService.player(playerUuid, validationResult.errorMessage());
return CompletableFuture.completedFuture(null);
}

return this.sendVerification(playerUuid, discordIdString, player, validationResult.discordUser())
.toFuture();
})
.exceptionally(error -> {
this.noticeService.player(playerUuid, messages -> messages.discord.linkFailed);
return null;
});
}

@Execute
@Permission("parcellockers.admin")
void linkOther(@Context CommandSender sender, @Arg String playerName, @Arg long discordId) {
String discordIdString = String.valueOf(discordId);

this.resolvePlayerUuid(playerName)
.thenCompose(playerUuid -> {
if (playerUuid == null) {
this.noticeService.viewer(sender, messages -> messages.discord.userNotFound);
return CompletableFuture.completedFuture(null);
}

return this.validateAndLink(playerUuid, discordIdString)
.thenCompose(validationResult -> {
if (!validationResult.isValid()) {
this.noticeService.viewer(sender, validationResult.errorMessage());
return CompletableFuture.completedFuture(null);
}

return this.discordLinkService.createLink(playerUuid, discordIdString)
.thenAccept(success -> {
if (success) {
this.noticeService.viewer(sender, messages -> messages.discord.adminLinkSuccess);
this.noticeService.player(playerUuid, messages -> messages.discord.linkSuccess);
} else {
this.noticeService.viewer(sender, messages -> messages.discord.linkFailed);
}
});
});
})
.exceptionally(error -> {
this.noticeService.viewer(sender, messages -> messages.discord.linkFailed);
return null;
});
}

private Mono<Void> sendVerification(UUID playerUuid, String discordId, Player player, User discordUser) {
String code = this.generateVerificationCode();

VerificationData data = new VerificationData(discordId, code);
if (this.authCodesCache.asMap().putIfAbsent(playerUuid, data) != null) {
Copy link

Copilot AI Jan 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Race condition in cache check. The code checks if a verification is pending with getIfPresent, but then later uses putIfAbsent. Between these two calls on lines 80 and 141, another thread could insert a value, causing the putIfAbsent to fail but the code continues as if it succeeded. Consider using a single putIfAbsent check at line 80 instead of getIfPresent.

Copilot uses AI. Check for mistakes.
Jakubk15 and others added 4 commits January 24, 2026 20:35
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@Jakubk15 Jakubk15 changed the title Add Discord Integration GH-75 Add Discord Integration Jan 24, 2026
public void shutdown() {
this.logger.info("Shutting down Discord client...");
if (this.client != null) {
this.client.logout().block();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Blocking main thread?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not a problem on shutdown. We don't have to block, but then the discord bot will be shown as online for few minutes despite server shutdown

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Blocking the main thread is generally a bad idea, even during shutdown. The main thread handles all server ticks, events, and scheduled tasks. Using .block() here will freeze the server until the logout completes, which can cause delays, timeouts, or even deadlocks if the logout takes longer than expected.

A better approach is to use a non-blocking call, like .subscribe(), so the Discord logout happens in the background and the server can continue shutting down immediately. This way you avoid hanging the main thread while still performing a clean shutdown.

);

this.liteCommands = LiteBukkitFactory.builder(this.getName(), this)
var liteCommandsBuilder = LiteBukkitFactory.builder(this.getName(), this)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

?

public CompletableFuture<ValidationResult> validate(UUID playerUuid, String discordId) {
return this.discordLinkService.findLinkByPlayer(playerUuid).thenCompose(optionalLink -> {
if (optionalLink.isPresent()) {
return CompletableFuture.completedFuture(ValidationResult.invalid("alreadyLinked"));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use enum for result instead of hardcoded string for validation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🆕 feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Discord webhooks, bot, plugin integration

4 participants