From 0e73f80d4030ea25954dbaa9a3fd8dbc8b073fa0 Mon Sep 17 00:00:00 2001 From: Vankka Date: Fri, 24 Dec 2021 01:21:14 +0200 Subject: [PATCH] Join, leave, server switch messages. Fixed dependency logging, added config option ordering annotation, fixed some issues with translation/configuration --- .github/workflows/crowdin-download.yaml | 4 +- .github/workflows/crowdin-upload.yaml | 4 +- .../java/com/discordsrv/api/color/Color.java | 2 +- .../entity/message/DiscordMessageEmbed.java | 2 +- .../impl/SendableDiscordMessageImpl.java | 8 +- .../events}/DiscordMessageReceivedEvent.java | 2 +- .../discordsrv/api/event/bus/EventBus.java | 3 + ... => DiscordChatMessageForwardedEvent.java} | 4 +- .../game/DeathMessageForwardedEvent.java} | 12 +- .../game/GameChatMessageForwardedEvent.java} | 12 +- ...nt.java => JoinMessageForwardedEvent.java} | 4 +- .../LeaveMessageForwardedEvent.java} | 12 +- .../ServerSwitchMessageForwardedEvent.java | 11 ++ ...=> DiscordChatMessageProcessingEvent.java} | 7 +- .../game/AbstractGameMessageReceiveEvent.java | 22 +-- .../game/DeathMessageReceiveEvent.java | 60 ++++++ ....java => GameChatMessageReceiveEvent.java} | 21 +- .../receive/game/JoinMessageReceiveEvent.java | 61 ++++++ .../game/LeaveMessageReceiveEvent.java | 61 ++++++ .../game/ServerSwitchMessageReceiveEvent.java | 19 ++ .../api/placeholder/mapper/ResultMappers.java | 22 +-- .../api/player/DiscordSRVPlayer.java | 4 +- build.gradle | 2 +- buildscript/relocations.gradle | 11 +- .../discordsrv/bukkit/BukkitDiscordSRV.java | 6 +- .../bukkit/DiscordSRVBukkitBootstrap.java | 4 +- .../component/util/PaperComponentUtil.java | 82 ++++++++ .../bukkit/config/main/BukkitConfig.java | 9 + .../config/manager/BukkitConfigManager.java | 4 +- .../bukkit/console/BukkitConsole.java | 6 +- .../bukkit/listener/BukkitChatListener.java | 52 +---- .../bukkit/listener/BukkitDeathListener.java | 48 +++++ .../listener/BukkitStatusMessageListener.java | 64 ++++++ .../bukkit/player/BukkitOfflinePlayer.java | 2 +- .../bukkit/player/BukkitPlayer.java | 2 +- .../discordsrv/bungee/BungeeDiscordSRV.java | 4 +- .../bungee/DiscordSRVBungeeBootstrap.java | 4 +- .../bungee/console/BungeeConsole.java | 4 +- .../bungee/player/BungeePlayer.java | 4 +- common/api/build.gradle | 3 +- .../logging}/LogAppender.java | 3 +- .../{ => common}/logging/LogLevel.java | 2 +- .../adapter/DependencyLoggerAdapter.java | 6 +- .../slf4j/impl/DiscordSRVLoggerFactory.java | 5 +- common/build.gradle | 7 + .../com/discordsrv/proxy/ProxyDiscordSRV.java | 41 ++++ .../channels/ServerSwitchMessageConfig.java | 25 +++ .../channels/base/ProxyBaseChannelConfig.java | 31 +++ .../channels/base/ProxyChannelConfig.java | 22 +++ .../config/manager/ProxyConfigManager.java | 21 ++ .../discordsrv/proxy/config/package-info.java | 1 + .../modules/ServerSwitchMessageModule.java | 51 +++++ .../common/server/ServerDiscordSRV.java | 15 ++ .../config/channels/DeathMessageConfig.java | 41 ++++ .../base/ServerBaseChannelConfig.java | 31 +++ .../channels/base/ServerChannelConfig.java} | 32 +-- .../config/manager/ServerConfigManager.java | 39 ++++ .../server/modules/DeathMessageModule.java | 69 +++++++ common/slf4j-hack/build.gradle | 3 + .../java/com/discordsrv/x/slf4j/Logger.java | 28 +++ .../discordsrv/common/AbstractDiscordSRV.java | 40 ++-- .../com/discordsrv/common/DiscordSRV.java | 9 +- .../common/channel/ChannelConfigHelper.java | 91 +++++---- .../renderer/DiscordSRVMinecraftRenderer.java | 10 +- .../common/component/util/ComponentUtil.java | 19 ++ .../common/config/annotation/Order.java | 35 ++++ .../OrderedFieldDiscovererProxy.java | 92 +++++++++ .../common/config/main/MainConfig.java | 11 +- .../DiscordToMinecraftChatConfig.java | 22 ++- .../main/channels/JoinMessageConfig.java | 39 ++++ .../main/channels/LeaveMessageConfig.java | 39 ++++ .../MinecraftToDiscordChatConfig.java | 7 +- .../main/channels/base/BaseChannelConfig.java | 40 ++++ .../ChannelConfig.java} | 30 ++- .../main/channels/base/IChannelConfig.java | 52 +++++ .../loader/YamlConfigLoaderProvider.java | 5 - .../manager/ConfigurateConfigManager.java | 47 ++++- .../manager/TranslatedConfigManager.java | 17 +- .../config/serializer/ColorSerializer.java | 2 +- .../DiscordMessageEmbedSerializer.java | 12 +- .../discordsrv/common/console/Console.java | 2 +- .../dependency/InitialDependencyLoader.java | 2 +- .../common/discord/api/DiscordAPIImpl.java | 10 +- .../api/guild/DiscordGuildMemberImpl.java | 19 +- .../message/ReceivedDiscordMessageImpl.java | 36 ++-- .../discordsrv/common}/logging/Logger.java | 2 +- .../common}/logging/backend/LogFilter.java | 4 +- .../logging/backend/LoggingBackend.java | 4 +- .../DependencyLoggingHandler.java | 10 +- .../common}/logging/impl/JavaLoggerImpl.java | 12 +- .../common}/logging/impl/Log4JLoggerImpl.java | 12 +- .../common}/logging/impl/SLF4JLoggerImpl.java | 10 +- .../module/ModuleInitializationFunction.java} | 12 +- .../common/module/ModuleManager.java | 28 +-- .../module/modules/DiscordAPIEventModule.java | 6 +- .../modules/GlobalChannelLookupModule.java | 7 +- .../integration/LuckPermsIntegration.java | 82 ++++++++ .../message/AbstractGameMessageModule.java | 143 ++++++++++++++ .../DiscordToMinecraftChatModule.java} | 48 +++-- .../modules/message/JoinMessageModule.java | 66 +++++++ .../modules/message/LeaveMessageModule.java | 66 +++++++ .../MinecraftToDiscordChatModule.java} | 109 ++++++----- .../{Module.java => type/AbstractModule.java} | 14 +- .../discordsrv/common/module/type/Module.java | 34 ++++ .../module/type/PermissionDataProvider.java | 28 +++ .../module/type/PluginIntegration.java} | 11 +- .../ComponentResultStringifier.java | 2 +- .../provider/util/PlaceholderMethodUtil.java | 1 + .../common/player/IOfflinePlayer.java | 4 +- .../com/discordsrv/common/player/IPlayer.java | 22 +-- .../provider/AbstractPlayerProvider.java | 2 +- .../common/scheduler/Scheduler.java | 8 +- .../common/scheduler/StandardScheduler.java | 43 ++-- .../com/discordsrv/common/MockDiscordSRV.java | 4 +- i18n/build.gradle | 11 +- .../config/DiscordSRVTranslation.java | 113 +++++++---- .../com/discordsrv/config/MockDiscordSRV.java | 184 ++++++++++++++++++ .../config/TranslationConfigManagerProxy.java | 59 ++++++ settings.gradle | 2 +- .../sponge/DiscordSRVSpongeBootstrap.java | 4 +- .../discordsrv/sponge/SpongeDiscordSRV.java | 2 +- .../sponge/console/SpongeConsole.java | 4 +- .../sponge/player/SpongeOfflinePlayer.java | 2 +- .../sponge/player/SpongePlayer.java | 2 +- .../velocity/DiscordSRVVelocityBootstrap.java | 6 +- .../velocity/VelocityDiscordSRV.java | 4 +- .../velocity/console/VelocityConsole.java | 4 +- .../velocity/player/VelocityPlayer.java | 4 +- 128 files changed, 2523 insertions(+), 501 deletions(-) rename api/src/main/java/com/discordsrv/api/{event/events/discord => discord/events}/DiscordMessageReceivedEvent.java (98%) rename api/src/main/java/com/discordsrv/api/event/events/message/forward/discord/{DiscordMessageForwardedEvent.java => DiscordChatMessageForwardedEvent.java} (91%) rename api/src/main/java/com/discordsrv/api/event/events/message/{receive/package-info.java => forward/game/DeathMessageForwardedEvent.java} (75%) rename api/src/main/java/com/discordsrv/api/event/events/message/{package-info.java => forward/game/GameChatMessageForwardedEvent.java} (75%) rename api/src/main/java/com/discordsrv/api/event/events/message/forward/game/{ChatMessageForwardedEvent.java => JoinMessageForwardedEvent.java} (92%) rename api/src/main/java/com/discordsrv/api/event/events/message/forward/{package-info.java => game/LeaveMessageForwardedEvent.java} (75%) create mode 100644 api/src/main/java/com/discordsrv/api/event/events/message/forward/game/ServerSwitchMessageForwardedEvent.java rename api/src/main/java/com/discordsrv/api/event/events/message/receive/discord/{DiscordMessageProcessingEvent.java => DiscordChatMessageProcessingEvent.java} (89%) create mode 100644 api/src/main/java/com/discordsrv/api/event/events/message/receive/game/DeathMessageReceiveEvent.java rename api/src/main/java/com/discordsrv/api/event/events/message/receive/game/{ChatMessageProcessingEvent.java => GameChatMessageReceiveEvent.java} (72%) create mode 100644 api/src/main/java/com/discordsrv/api/event/events/message/receive/game/JoinMessageReceiveEvent.java create mode 100644 api/src/main/java/com/discordsrv/api/event/events/message/receive/game/LeaveMessageReceiveEvent.java create mode 100644 api/src/main/java/com/discordsrv/api/event/events/message/receive/game/ServerSwitchMessageReceiveEvent.java create mode 100644 bukkit/src/main/java/com/discordsrv/bukkit/component/util/PaperComponentUtil.java create mode 100644 bukkit/src/main/java/com/discordsrv/bukkit/listener/BukkitDeathListener.java create mode 100644 bukkit/src/main/java/com/discordsrv/bukkit/listener/BukkitStatusMessageListener.java rename common/api/src/main/java/com/discordsrv/{logging/backend => common/logging}/LogAppender.java (93%) rename common/api/src/main/java/com/discordsrv/{ => common}/logging/LogLevel.java (97%) rename common/api/src/main/java/com/discordsrv/{ => common}/logging/adapter/DependencyLoggerAdapter.java (97%) create mode 100644 common/proxy/src/main/java/com/discordsrv/proxy/ProxyDiscordSRV.java create mode 100644 common/proxy/src/main/java/com/discordsrv/proxy/config/channels/ServerSwitchMessageConfig.java create mode 100644 common/proxy/src/main/java/com/discordsrv/proxy/config/channels/base/ProxyBaseChannelConfig.java create mode 100644 common/proxy/src/main/java/com/discordsrv/proxy/config/channels/base/ProxyChannelConfig.java create mode 100644 common/proxy/src/main/java/com/discordsrv/proxy/config/manager/ProxyConfigManager.java create mode 100644 common/proxy/src/main/java/com/discordsrv/proxy/config/package-info.java create mode 100644 common/proxy/src/main/java/com/discordsrv/proxy/modules/ServerSwitchMessageModule.java create mode 100644 common/server/src/main/java/com/discordsrv/common/server/config/channels/DeathMessageConfig.java create mode 100644 common/server/src/main/java/com/discordsrv/common/server/config/channels/base/ServerBaseChannelConfig.java rename common/{src/main/java/com/discordsrv/common/config/main/channels/ChannelConfig.java => server/src/main/java/com/discordsrv/common/server/config/channels/base/ServerChannelConfig.java} (53%) create mode 100644 common/server/src/main/java/com/discordsrv/common/server/config/manager/ServerConfigManager.java create mode 100644 common/server/src/main/java/com/discordsrv/common/server/modules/DeathMessageModule.java create mode 100644 common/slf4j-hack/build.gradle create mode 100644 common/slf4j-hack/src/main/java/com/discordsrv/x/slf4j/Logger.java create mode 100644 common/src/main/java/com/discordsrv/common/config/annotation/Order.java create mode 100644 common/src/main/java/com/discordsrv/common/config/fielddiscoverer/OrderedFieldDiscovererProxy.java create mode 100644 common/src/main/java/com/discordsrv/common/config/main/channels/JoinMessageConfig.java create mode 100644 common/src/main/java/com/discordsrv/common/config/main/channels/LeaveMessageConfig.java create mode 100644 common/src/main/java/com/discordsrv/common/config/main/channels/base/BaseChannelConfig.java rename common/src/main/java/com/discordsrv/common/config/main/channels/{BaseChannelConfig.java => base/ChannelConfig.java} (72%) create mode 100644 common/src/main/java/com/discordsrv/common/config/main/channels/base/IChannelConfig.java rename common/{api/src/main/java/com/discordsrv => src/main/java/com/discordsrv/common}/logging/Logger.java (98%) rename common/{api/src/main/java/com/discordsrv => src/main/java/com/discordsrv/common}/logging/backend/LogFilter.java (92%) rename common/{api/src/main/java/com/discordsrv => src/main/java/com/discordsrv/common}/logging/backend/LoggingBackend.java (91%) rename common/src/main/java/com/discordsrv/common/logging/{ => dependency}/DependencyLoggingHandler.java (93%) rename common/{api/src/main/java/com/discordsrv => src/main/java/com/discordsrv/common}/logging/impl/JavaLoggerImpl.java (94%) rename common/{api/src/main/java/com/discordsrv => src/main/java/com/discordsrv/common}/logging/impl/Log4JLoggerImpl.java (96%) rename common/{api/src/main/java/com/discordsrv => src/main/java/com/discordsrv/common}/logging/impl/SLF4JLoggerImpl.java (88%) rename common/{proxy/src/main/java/com/discordsrv/common/proxy/ProxyDiscordSRV.java => src/main/java/com/discordsrv/common/module/ModuleInitializationFunction.java} (71%) create mode 100644 common/src/main/java/com/discordsrv/common/module/modules/integration/LuckPermsIntegration.java create mode 100644 common/src/main/java/com/discordsrv/common/module/modules/message/AbstractGameMessageModule.java rename common/src/main/java/com/discordsrv/common/module/modules/{DiscordToMinecraftModule.java => message/DiscordToMinecraftChatModule.java} (78%) create mode 100644 common/src/main/java/com/discordsrv/common/module/modules/message/JoinMessageModule.java create mode 100644 common/src/main/java/com/discordsrv/common/module/modules/message/LeaveMessageModule.java rename common/src/main/java/com/discordsrv/common/module/modules/{MinecraftToDiscordModule.java => message/MinecraftToDiscordChatModule.java} (79%) rename common/src/main/java/com/discordsrv/common/module/{Module.java => type/AbstractModule.java} (86%) create mode 100644 common/src/main/java/com/discordsrv/common/module/type/Module.java create mode 100644 common/src/main/java/com/discordsrv/common/module/type/PermissionDataProvider.java rename common/{proxy/src/main/java/com/discordsrv/common/package-info.java => src/main/java/com/discordsrv/common/module/type/PluginIntegration.java} (77%) create mode 100644 i18n/src/main/java/com/discordsrv/config/MockDiscordSRV.java create mode 100644 i18n/src/main/java/com/discordsrv/config/TranslationConfigManagerProxy.java diff --git a/.github/workflows/crowdin-download.yaml b/.github/workflows/crowdin-download.yaml index 2b306431..99d86c14 100644 --- a/.github/workflows/crowdin-download.yaml +++ b/.github/workflows/crowdin-download.yaml @@ -19,8 +19,8 @@ jobs: create_pull_request: true pull_request_title: "New Crowdin translations" pull_request_body: "" - source: "source.yml" - translation: "/%original_path%/src/main/resources/translations/%three_letters_code%.yml" + source: "source.yaml" + translation: "/%original_path%/src/main/resources/translations/%three_letters_code%.yaml" project_id: ${{ secrets.CROWDIN_PROJECT_ID }} token: ${{ secrets.CROWDIN_PERSONAL_TOKEN }} env: diff --git a/.github/workflows/crowdin-upload.yaml b/.github/workflows/crowdin-upload.yaml index a4d75aeb..a379c053 100644 --- a/.github/workflows/crowdin-upload.yaml +++ b/.github/workflows/crowdin-upload.yaml @@ -27,8 +27,8 @@ jobs: upload_translations: true download_translations: false localization_branch_name: i18n - source: "source.yml" - translation: "/%original_path%/src/main/resources/translations/%three_letters_code%.yml" + source: "source.yaml" + translation: "/%original_path%/src/main/resources/translations/%three_letters_code%.yaml" project_id: ${{ secrets.CROWDIN_PROJECT_ID }} token: ${{ secrets.CROWDIN_PERSONAL_TOKEN }} env: diff --git a/api/src/main/java/com/discordsrv/api/color/Color.java b/api/src/main/java/com/discordsrv/api/color/Color.java index 48ed7532..3ff0979d 100644 --- a/api/src/main/java/com/discordsrv/api/color/Color.java +++ b/api/src/main/java/com/discordsrv/api/color/Color.java @@ -67,7 +67,7 @@ public class Color { } public String hex() { - return Integer.toHexString(rgb); + return Integer.toHexString(0xF000000 | rgb).substring(1); } public int red() { diff --git a/api/src/main/java/com/discordsrv/api/discord/api/entity/message/DiscordMessageEmbed.java b/api/src/main/java/com/discordsrv/api/discord/api/entity/message/DiscordMessageEmbed.java index 76afac2a..202b2a31 100644 --- a/api/src/main/java/com/discordsrv/api/discord/api/entity/message/DiscordMessageEmbed.java +++ b/api/src/main/java/com/discordsrv/api/discord/api/entity/message/DiscordMessageEmbed.java @@ -429,7 +429,7 @@ public class DiscordMessageEmbed { @NotNull public Builder setFooter(@Nullable CharSequence footer, @Nullable CharSequence footerImageUrl) { this.footer = footer != null ? footer.toString() : null; - this.footerImageUrl = footerImageUrl != null ? footerImageUrl.toString() : null; + this.footerImageUrl = footerImageUrl != null && footerImageUrl.length() != 0 ? footerImageUrl.toString() : null; return this; } diff --git a/api/src/main/java/com/discordsrv/api/discord/api/entity/message/impl/SendableDiscordMessageImpl.java b/api/src/main/java/com/discordsrv/api/discord/api/entity/message/impl/SendableDiscordMessageImpl.java index bbff2b29..4d1f9b75 100644 --- a/api/src/main/java/com/discordsrv/api/discord/api/entity/message/impl/SendableDiscordMessageImpl.java +++ b/api/src/main/java/com/discordsrv/api/discord/api/entity/message/impl/SendableDiscordMessageImpl.java @@ -209,7 +209,7 @@ public class SendableDiscordMessageImpl implements SendableDiscordMessage { @Override public @NotNull Formatter applyPlaceholderService() { - DiscordSRVApi api = DiscordSRVApiProvider.optional().orElse(null); + DiscordSRVApi api = DiscordSRVApiProvider.get(); if (api == null) { throw new IllegalStateException("DiscordSRVApi not available"); } @@ -221,7 +221,7 @@ public class SendableDiscordMessageImpl implements SendableDiscordMessage { private Function wrapFunction(Function function) { return matcher -> { Object result = function.apply(matcher); - if (result instanceof FormattedText) { + if (result instanceof FormattedText || ResultMappers.isPlainContext()) { // Process as regular text return result.toString(); } else if (result instanceof CharSequence) { @@ -258,7 +258,7 @@ public class SendableDiscordMessageImpl implements SendableDiscordMessage { DiscordMessageEmbed.Builder embedBuilder = embed.toBuilder(); // TODO: check which parts allow formatting more thoroughly - ResultMappers.runInPlainComponentContext(() -> { + ResultMappers.runInPlainContext(() -> { embedBuilder.setAuthor( placeholders.apply( embedBuilder.getAuthorName()), @@ -307,7 +307,7 @@ public class SendableDiscordMessageImpl implements SendableDiscordMessage { builder.addEmbed(embedBuilder.build()); } - ResultMappers.runInPlainComponentContext(() -> { + ResultMappers.runInPlainContext(() -> { builder.setWebhookUsername(placeholders.apply(builder.getWebhookUsername())); builder.setWebhookAvatarUrl(placeholders.apply(builder.getWebhookAvatarUrl())); }); diff --git a/api/src/main/java/com/discordsrv/api/event/events/discord/DiscordMessageReceivedEvent.java b/api/src/main/java/com/discordsrv/api/discord/events/DiscordMessageReceivedEvent.java similarity index 98% rename from api/src/main/java/com/discordsrv/api/event/events/discord/DiscordMessageReceivedEvent.java rename to api/src/main/java/com/discordsrv/api/discord/events/DiscordMessageReceivedEvent.java index 1675830d..3fd3133d 100644 --- a/api/src/main/java/com/discordsrv/api/event/events/discord/DiscordMessageReceivedEvent.java +++ b/api/src/main/java/com/discordsrv/api/discord/events/DiscordMessageReceivedEvent.java @@ -21,7 +21,7 @@ * SOFTWARE. */ -package com.discordsrv.api.event.events.discord; +package com.discordsrv.api.discord.events; import com.discordsrv.api.discord.api.entity.channel.DiscordDMChannel; import com.discordsrv.api.discord.api.entity.channel.DiscordMessageChannel; diff --git a/api/src/main/java/com/discordsrv/api/event/bus/EventBus.java b/api/src/main/java/com/discordsrv/api/event/bus/EventBus.java index 8d9dfae5..55e0ba08 100644 --- a/api/src/main/java/com/discordsrv/api/event/bus/EventBus.java +++ b/api/src/main/java/com/discordsrv/api/event/bus/EventBus.java @@ -25,6 +25,7 @@ package com.discordsrv.api.event.bus; import com.discordsrv.api.event.events.Event; import net.dv8tion.jda.api.events.GenericEvent; +import org.jetbrains.annotations.Blocking; import org.jetbrains.annotations.NotNull; /** @@ -52,6 +53,7 @@ public interface EventBus { * * @param event the event */ + @Blocking void publish(@NotNull Event event); /** @@ -59,6 +61,7 @@ public interface EventBus { * * @param event the event */ + @Blocking void publish(@NotNull GenericEvent event); } diff --git a/api/src/main/java/com/discordsrv/api/event/events/message/forward/discord/DiscordMessageForwardedEvent.java b/api/src/main/java/com/discordsrv/api/event/events/message/forward/discord/DiscordChatMessageForwardedEvent.java similarity index 91% rename from api/src/main/java/com/discordsrv/api/event/events/message/forward/discord/DiscordMessageForwardedEvent.java rename to api/src/main/java/com/discordsrv/api/event/events/message/forward/discord/DiscordChatMessageForwardedEvent.java index cda6573b..3e1b714c 100644 --- a/api/src/main/java/com/discordsrv/api/event/events/message/forward/discord/DiscordMessageForwardedEvent.java +++ b/api/src/main/java/com/discordsrv/api/event/events/message/forward/discord/DiscordChatMessageForwardedEvent.java @@ -28,12 +28,12 @@ import com.discordsrv.api.component.MinecraftComponent; import com.discordsrv.api.event.events.Event; import org.jetbrains.annotations.NotNull; -public class DiscordMessageForwardedEvent implements Event { +public class DiscordChatMessageForwardedEvent implements Event { private final MinecraftComponent message; private final GameChannel channel; - public DiscordMessageForwardedEvent(@NotNull MinecraftComponent message, @NotNull GameChannel channel) { + public DiscordChatMessageForwardedEvent(@NotNull MinecraftComponent message, @NotNull GameChannel channel) { this.message = message; this.channel = channel; } diff --git a/api/src/main/java/com/discordsrv/api/event/events/message/receive/package-info.java b/api/src/main/java/com/discordsrv/api/event/events/message/forward/game/DeathMessageForwardedEvent.java similarity index 75% rename from api/src/main/java/com/discordsrv/api/event/events/message/receive/package-info.java rename to api/src/main/java/com/discordsrv/api/event/events/message/forward/game/DeathMessageForwardedEvent.java index fcb50edc..e7be4001 100644 --- a/api/src/main/java/com/discordsrv/api/event/events/message/receive/package-info.java +++ b/api/src/main/java/com/discordsrv/api/event/events/message/forward/game/DeathMessageForwardedEvent.java @@ -21,4 +21,14 @@ * SOFTWARE. */ -package com.discordsrv.api.event.events.message.receive; +package com.discordsrv.api.event.events.message.forward.game; + +import com.discordsrv.api.discord.api.entity.message.ReceivedDiscordMessageCluster; +import org.jetbrains.annotations.NotNull; + +public class DeathMessageForwardedEvent extends AbstractGameMessageForwardedEvent { + + public DeathMessageForwardedEvent(@NotNull ReceivedDiscordMessageCluster discordMessage) { + super(discordMessage); + } +} diff --git a/api/src/main/java/com/discordsrv/api/event/events/message/package-info.java b/api/src/main/java/com/discordsrv/api/event/events/message/forward/game/GameChatMessageForwardedEvent.java similarity index 75% rename from api/src/main/java/com/discordsrv/api/event/events/message/package-info.java rename to api/src/main/java/com/discordsrv/api/event/events/message/forward/game/GameChatMessageForwardedEvent.java index 4f6aa53c..4046e74b 100644 --- a/api/src/main/java/com/discordsrv/api/event/events/message/package-info.java +++ b/api/src/main/java/com/discordsrv/api/event/events/message/forward/game/GameChatMessageForwardedEvent.java @@ -21,4 +21,14 @@ * SOFTWARE. */ -package com.discordsrv.api.event.events.message; +package com.discordsrv.api.event.events.message.forward.game; + +import com.discordsrv.api.discord.api.entity.message.ReceivedDiscordMessageCluster; +import org.jetbrains.annotations.NotNull; + +public class GameChatMessageForwardedEvent extends AbstractGameMessageForwardedEvent { + + public GameChatMessageForwardedEvent(@NotNull ReceivedDiscordMessageCluster discordMessage) { + super(discordMessage); + } +} diff --git a/api/src/main/java/com/discordsrv/api/event/events/message/forward/game/ChatMessageForwardedEvent.java b/api/src/main/java/com/discordsrv/api/event/events/message/forward/game/JoinMessageForwardedEvent.java similarity index 92% rename from api/src/main/java/com/discordsrv/api/event/events/message/forward/game/ChatMessageForwardedEvent.java rename to api/src/main/java/com/discordsrv/api/event/events/message/forward/game/JoinMessageForwardedEvent.java index c5b05f6d..16f0d542 100644 --- a/api/src/main/java/com/discordsrv/api/event/events/message/forward/game/ChatMessageForwardedEvent.java +++ b/api/src/main/java/com/discordsrv/api/event/events/message/forward/game/JoinMessageForwardedEvent.java @@ -26,9 +26,9 @@ package com.discordsrv.api.event.events.message.forward.game; import com.discordsrv.api.discord.api.entity.message.ReceivedDiscordMessageCluster; import org.jetbrains.annotations.NotNull; -public class ChatMessageForwardedEvent extends AbstractGameMessageForwardedEvent { +public class JoinMessageForwardedEvent extends AbstractGameMessageForwardedEvent { - public ChatMessageForwardedEvent(@NotNull ReceivedDiscordMessageCluster discordMessage) { + public JoinMessageForwardedEvent(@NotNull ReceivedDiscordMessageCluster discordMessage) { super(discordMessage); } } diff --git a/api/src/main/java/com/discordsrv/api/event/events/message/forward/package-info.java b/api/src/main/java/com/discordsrv/api/event/events/message/forward/game/LeaveMessageForwardedEvent.java similarity index 75% rename from api/src/main/java/com/discordsrv/api/event/events/message/forward/package-info.java rename to api/src/main/java/com/discordsrv/api/event/events/message/forward/game/LeaveMessageForwardedEvent.java index ab779473..0125ea63 100644 --- a/api/src/main/java/com/discordsrv/api/event/events/message/forward/package-info.java +++ b/api/src/main/java/com/discordsrv/api/event/events/message/forward/game/LeaveMessageForwardedEvent.java @@ -21,4 +21,14 @@ * SOFTWARE. */ -package com.discordsrv.api.event.events.message.forward; +package com.discordsrv.api.event.events.message.forward.game; + +import com.discordsrv.api.discord.api.entity.message.ReceivedDiscordMessageCluster; +import org.jetbrains.annotations.NotNull; + +public class LeaveMessageForwardedEvent extends AbstractGameMessageForwardedEvent { + + public LeaveMessageForwardedEvent(@NotNull ReceivedDiscordMessageCluster discordMessage) { + super(discordMessage); + } +} diff --git a/api/src/main/java/com/discordsrv/api/event/events/message/forward/game/ServerSwitchMessageForwardedEvent.java b/api/src/main/java/com/discordsrv/api/event/events/message/forward/game/ServerSwitchMessageForwardedEvent.java new file mode 100644 index 00000000..b5f9d587 --- /dev/null +++ b/api/src/main/java/com/discordsrv/api/event/events/message/forward/game/ServerSwitchMessageForwardedEvent.java @@ -0,0 +1,11 @@ +package com.discordsrv.api.event.events.message.forward.game; + +import com.discordsrv.api.discord.api.entity.message.ReceivedDiscordMessageCluster; +import org.jetbrains.annotations.NotNull; + +public class ServerSwitchMessageForwardedEvent extends AbstractGameMessageForwardedEvent { + + public ServerSwitchMessageForwardedEvent(@NotNull ReceivedDiscordMessageCluster discordMessage) { + super(discordMessage); + } +} diff --git a/api/src/main/java/com/discordsrv/api/event/events/message/receive/discord/DiscordMessageProcessingEvent.java b/api/src/main/java/com/discordsrv/api/event/events/message/receive/discord/DiscordChatMessageProcessingEvent.java similarity index 89% rename from api/src/main/java/com/discordsrv/api/event/events/message/receive/discord/DiscordMessageProcessingEvent.java rename to api/src/main/java/com/discordsrv/api/event/events/message/receive/discord/DiscordChatMessageProcessingEvent.java index 105281ef..b7e98c33 100644 --- a/api/src/main/java/com/discordsrv/api/event/events/message/receive/discord/DiscordMessageProcessingEvent.java +++ b/api/src/main/java/com/discordsrv/api/event/events/message/receive/discord/DiscordChatMessageProcessingEvent.java @@ -30,7 +30,7 @@ import com.discordsrv.api.event.events.Cancellable; import com.discordsrv.api.event.events.Processable; import org.jetbrains.annotations.NotNull; -public class DiscordMessageProcessingEvent implements Cancellable, Processable { +public class DiscordChatMessageProcessingEvent implements Cancellable, Processable { private final ReceivedDiscordMessage discordMessage; private String messageContent; @@ -38,7 +38,7 @@ public class DiscordMessageProcessingEvent implements Cancellable, Processable { private boolean cancelled; private boolean processed; - public DiscordMessageProcessingEvent(@NotNull ReceivedDiscordMessage discordMessage, @NotNull DiscordTextChannel channel) { + public DiscordChatMessageProcessingEvent(@NotNull ReceivedDiscordMessage discordMessage, @NotNull DiscordTextChannel channel) { this.discordMessage = discordMessage; this.messageContent = discordMessage.getContent().orElse(null); this.channel = channel; @@ -81,6 +81,9 @@ public class DiscordMessageProcessingEvent implements Cancellable, Processable { @Override public void markAsProcessed() { + if (isCancelled()) { + throw new IllegalStateException("Cannot process cancelled event"); + } this.processed = true; } diff --git a/api/src/main/java/com/discordsrv/api/event/events/message/receive/game/AbstractGameMessageReceiveEvent.java b/api/src/main/java/com/discordsrv/api/event/events/message/receive/game/AbstractGameMessageReceiveEvent.java index c00f64f9..22498989 100644 --- a/api/src/main/java/com/discordsrv/api/event/events/message/receive/game/AbstractGameMessageReceiveEvent.java +++ b/api/src/main/java/com/discordsrv/api/event/events/message/receive/game/AbstractGameMessageReceiveEvent.java @@ -23,7 +23,6 @@ package com.discordsrv.api.event.events.message.receive.game; -import com.discordsrv.api.channel.GameChannel; import com.discordsrv.api.component.MinecraftComponent; import com.discordsrv.api.event.events.Cancellable; import com.discordsrv.api.event.events.Processable; @@ -32,30 +31,22 @@ import org.jetbrains.annotations.NotNull; public abstract class AbstractGameMessageReceiveEvent implements Processable, Cancellable { private final MinecraftComponent message; - private GameChannel gameChannel; private boolean cancelled; private boolean processed; - public AbstractGameMessageReceiveEvent(@NotNull MinecraftComponent message, @NotNull GameChannel gameChannel, boolean cancelled) { + public AbstractGameMessageReceiveEvent( + @NotNull MinecraftComponent message, + boolean cancelled + ) { this.message = message; - this.gameChannel = gameChannel; this.cancelled = cancelled; } @NotNull - public MinecraftComponent message() { + public MinecraftComponent getMessage() { return message; } - @NotNull - public GameChannel getGameChannel() { - return gameChannel; - } - - public void setGameChannel(@NotNull GameChannel gameChannel) { - this.gameChannel = gameChannel; - } - @Override public boolean isCancelled() { return cancelled; @@ -73,6 +64,9 @@ public abstract class AbstractGameMessageReceiveEvent implements Processable, Ca @Override public void markAsProcessed() { + if (isCancelled()) { + throw new IllegalStateException("Cannot process cancelled event"); + } this.processed = true; } } diff --git a/api/src/main/java/com/discordsrv/api/event/events/message/receive/game/DeathMessageReceiveEvent.java b/api/src/main/java/com/discordsrv/api/event/events/message/receive/game/DeathMessageReceiveEvent.java new file mode 100644 index 00000000..cc367cda --- /dev/null +++ b/api/src/main/java/com/discordsrv/api/event/events/message/receive/game/DeathMessageReceiveEvent.java @@ -0,0 +1,60 @@ +/* + * This file is part of the DiscordSRV API, licensed under the MIT License + * Copyright (c) 2016-2021 Austin "Scarsz" Shapiro, Henri "Vankka" Schubin and DiscordSRV contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package com.discordsrv.api.event.events.message.receive.game; + +import com.discordsrv.api.channel.GameChannel; +import com.discordsrv.api.component.MinecraftComponent; +import com.discordsrv.api.player.DiscordSRVPlayer; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class DeathMessageReceiveEvent extends AbstractGameMessageReceiveEvent { + + private final DiscordSRVPlayer player; + private GameChannel gameChannel; + + public DeathMessageReceiveEvent( + @NotNull DiscordSRVPlayer player, + @Nullable GameChannel gameChannel, + @NotNull MinecraftComponent message, + boolean cancelled) { + super(message, cancelled); + this.player = player; + this.gameChannel = gameChannel; + } + + @NotNull + public DiscordSRVPlayer getPlayer() { + return player; + } + + @Nullable + public GameChannel getGameChannel() { + return gameChannel; + } + + public void setGameChannel(@Nullable GameChannel gameChannel) { + this.gameChannel = gameChannel; + } +} diff --git a/api/src/main/java/com/discordsrv/api/event/events/message/receive/game/ChatMessageProcessingEvent.java b/api/src/main/java/com/discordsrv/api/event/events/message/receive/game/GameChatMessageReceiveEvent.java similarity index 72% rename from api/src/main/java/com/discordsrv/api/event/events/message/receive/game/ChatMessageProcessingEvent.java rename to api/src/main/java/com/discordsrv/api/event/events/message/receive/game/GameChatMessageReceiveEvent.java index 5258ae80..243effc4 100644 --- a/api/src/main/java/com/discordsrv/api/event/events/message/receive/game/ChatMessageProcessingEvent.java +++ b/api/src/main/java/com/discordsrv/api/event/events/message/receive/game/GameChatMessageReceiveEvent.java @@ -27,14 +27,29 @@ import com.discordsrv.api.channel.GameChannel; import com.discordsrv.api.component.MinecraftComponent; import com.discordsrv.api.event.events.PlayerEvent; import com.discordsrv.api.player.DiscordSRVPlayer; +import org.jetbrains.annotations.NotNull; -public class ChatMessageProcessingEvent extends AbstractGameMessageReceiveEvent implements PlayerEvent { +public class GameChatMessageReceiveEvent extends AbstractGameMessageReceiveEvent implements PlayerEvent { private final DiscordSRVPlayer player; + private GameChannel gameChannel; - public ChatMessageProcessingEvent(DiscordSRVPlayer player, MinecraftComponent message, GameChannel gameChannel, boolean cancelled) { - super(message, gameChannel, cancelled); + public GameChatMessageReceiveEvent( + @NotNull DiscordSRVPlayer player, + @NotNull GameChannel gameChannel, + @NotNull MinecraftComponent message, + boolean cancelled) { + super(message, cancelled); this.player = player; + this.gameChannel = gameChannel; + } + + public GameChannel getGameChannel() { + return gameChannel; + } + + public void setGameChannel(GameChannel gameChannel) { + this.gameChannel = gameChannel; } @Override diff --git a/api/src/main/java/com/discordsrv/api/event/events/message/receive/game/JoinMessageReceiveEvent.java b/api/src/main/java/com/discordsrv/api/event/events/message/receive/game/JoinMessageReceiveEvent.java new file mode 100644 index 00000000..7020b2b6 --- /dev/null +++ b/api/src/main/java/com/discordsrv/api/event/events/message/receive/game/JoinMessageReceiveEvent.java @@ -0,0 +1,61 @@ +/* + * This file is part of the DiscordSRV API, licensed under the MIT License + * Copyright (c) 2016-2021 Austin "Scarsz" Shapiro, Henri "Vankka" Schubin and DiscordSRV contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package com.discordsrv.api.event.events.message.receive.game; + +import com.discordsrv.api.channel.GameChannel; +import com.discordsrv.api.component.MinecraftComponent; +import com.discordsrv.api.player.DiscordSRVPlayer; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class JoinMessageReceiveEvent extends AbstractGameMessageReceiveEvent { + + private final DiscordSRVPlayer player; + private GameChannel gameChannel; + + public JoinMessageReceiveEvent( + @NotNull DiscordSRVPlayer player, + @Nullable GameChannel gameChannel, + @NotNull MinecraftComponent message, + boolean cancelled) { + super(message, cancelled); + this.player = player; + this.gameChannel = gameChannel; + } + + @NotNull + public DiscordSRVPlayer getPlayer() { + return player; + } + + @Nullable + public GameChannel getGameChannel() { + return gameChannel; + } + + public void setGameChannel(@Nullable GameChannel gameChannel) { + this.gameChannel = gameChannel; + } + +} diff --git a/api/src/main/java/com/discordsrv/api/event/events/message/receive/game/LeaveMessageReceiveEvent.java b/api/src/main/java/com/discordsrv/api/event/events/message/receive/game/LeaveMessageReceiveEvent.java new file mode 100644 index 00000000..b789c63b --- /dev/null +++ b/api/src/main/java/com/discordsrv/api/event/events/message/receive/game/LeaveMessageReceiveEvent.java @@ -0,0 +1,61 @@ +/* + * This file is part of the DiscordSRV API, licensed under the MIT License + * Copyright (c) 2016-2021 Austin "Scarsz" Shapiro, Henri "Vankka" Schubin and DiscordSRV contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package com.discordsrv.api.event.events.message.receive.game; + +import com.discordsrv.api.channel.GameChannel; +import com.discordsrv.api.component.MinecraftComponent; +import com.discordsrv.api.player.DiscordSRVPlayer; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class LeaveMessageReceiveEvent extends AbstractGameMessageReceiveEvent { + + private final DiscordSRVPlayer player; + private GameChannel gameChannel; + + public LeaveMessageReceiveEvent( + @NotNull DiscordSRVPlayer player, + @Nullable GameChannel gameChannel, + @NotNull MinecraftComponent message, + boolean cancelled) { + super(message, cancelled); + this.player = player; + this.gameChannel = gameChannel; + } + + @NotNull + public DiscordSRVPlayer getPlayer() { + return player; + } + + @Nullable + public GameChannel getGameChannel() { + return gameChannel; + } + + public void setGameChannel(@Nullable GameChannel gameChannel) { + this.gameChannel = gameChannel; + } + +} diff --git a/api/src/main/java/com/discordsrv/api/event/events/message/receive/game/ServerSwitchMessageReceiveEvent.java b/api/src/main/java/com/discordsrv/api/event/events/message/receive/game/ServerSwitchMessageReceiveEvent.java new file mode 100644 index 00000000..f943735f --- /dev/null +++ b/api/src/main/java/com/discordsrv/api/event/events/message/receive/game/ServerSwitchMessageReceiveEvent.java @@ -0,0 +1,19 @@ +package com.discordsrv.api.event.events.message.receive.game; + +import com.discordsrv.api.component.MinecraftComponent; +import com.discordsrv.api.player.DiscordSRVPlayer; +import org.jetbrains.annotations.NotNull; + +public class ServerSwitchMessageReceiveEvent extends AbstractGameMessageReceiveEvent { + + private final DiscordSRVPlayer player; + + public ServerSwitchMessageReceiveEvent(DiscordSRVPlayer player, @NotNull MinecraftComponent message, boolean cancelled) { + super(message, cancelled); + this.player = player; + } + + public DiscordSRVPlayer getPlayer() { + return player; + } +} diff --git a/api/src/main/java/com/discordsrv/api/placeholder/mapper/ResultMappers.java b/api/src/main/java/com/discordsrv/api/placeholder/mapper/ResultMappers.java index d840b7bb..0e9bcac7 100644 --- a/api/src/main/java/com/discordsrv/api/placeholder/mapper/ResultMappers.java +++ b/api/src/main/java/com/discordsrv/api/placeholder/mapper/ResultMappers.java @@ -29,22 +29,21 @@ import java.util.function.Supplier; public final class ResultMappers { - private static final ThreadLocal PLAIN_COMPONENTS = ThreadLocal.withInitial(() -> false); + private static final ThreadLocal PLAIN = ThreadLocal.withInitial(() -> false); private ResultMappers() {} - public static boolean isPlainComponentContext() { - return PLAIN_COMPONENTS.get(); + public static boolean isPlainContext() { + return PLAIN.get(); } /** * Utility method to run the provided {@link Runnable} where {@link PlaceholderService}s - * will replace {@link com.discordsrv.api.component.MinecraftComponent}s - * as plain without formatting (instead of converting to Discord formatting). + * will use plain text without Discord formatting (instead of converting to Discord formatting). * @param runnable a task that will be executed immediately */ - public static void runInPlainComponentContext(Runnable runnable) { - getInPlainComponentContext(() -> { + public static void runInPlainContext(Runnable runnable) { + getInPlainContext(() -> { runnable.run(); return null; }); @@ -52,15 +51,14 @@ public final class ResultMappers { /** * Utility method to run the provided {@link Runnable} where {@link PlaceholderService}s - * will replace {@link com.discordsrv.api.component.MinecraftComponent}s - * as plain without formatting (instead of converting to Discord formatting). + * will use plain text without Discord formatting (instead of converting to Discord formatting). * @param supplier a supplier that will be executed immediately * @return the output of the supplier provided as parameter */ - public static T getInPlainComponentContext(Supplier supplier) { - PLAIN_COMPONENTS.set(true); + public static T getInPlainContext(Supplier supplier) { + PLAIN.set(true); T output = supplier.get(); - PLAIN_COMPONENTS.set(false); + PLAIN.set(false); return output; } } diff --git a/api/src/main/java/com/discordsrv/api/player/DiscordSRVPlayer.java b/api/src/main/java/com/discordsrv/api/player/DiscordSRVPlayer.java index dcbda690..2a95a4e6 100644 --- a/api/src/main/java/com/discordsrv/api/player/DiscordSRVPlayer.java +++ b/api/src/main/java/com/discordsrv/api/player/DiscordSRVPlayer.java @@ -39,7 +39,7 @@ public interface DiscordSRVPlayer { */ @Placeholder("player_name") @NotNull - String getUsername(); + String username(); /** * The {@link UUID} of the player. @@ -47,6 +47,6 @@ public interface DiscordSRVPlayer { */ @Placeholder("player_uuid") @NotNull - UUID getUniqueId(); + UUID uniqueId(); } diff --git a/build.gradle b/build.gradle index ce2cee6b..6aa4b360 100644 --- a/build.gradle +++ b/build.gradle @@ -1,5 +1,5 @@ plugins { - id 'com.github.johnrengelman.shadow' version '7.0.0' apply false + id 'com.github.johnrengelman.shadow' version '7.1.1' apply false id 'org.cadixdev.licenser' version '0.6.0' apply false id 'io.freefair.lombok' version '5.3.3.3' apply false id 'net.kyori.blossom' version '1.2.0' apply false diff --git a/buildscript/relocations.gradle b/buildscript/relocations.gradle index 559545a3..0f9b3938 100644 --- a/buildscript/relocations.gradle +++ b/buildscript/relocations.gradle @@ -40,6 +40,9 @@ shadowJar { // Commons 'org.apache.commons', + // SLF4J + 'org.slf4j', + // Checker Framework 'org.checkerframework', @@ -54,10 +57,6 @@ shadowJar { relocate it, 'com.discordsrv.dependencies.' + it } - // SLF4J - relocate('org.slf4j', 'com.discordsrv.dependencies.org.slf4j') { - include('*') - exclude('com.discordsrv.logging.impl.SLF4JLoggerImpl') - exclude('com.discordsrv.velocity.DiscordSRVVelocityBootstrap') - } + // SLF4J hack + relocate('com.discordsrv.x.slf4j', 'org.slf4j') } diff --git a/bukkit/src/main/java/com/discordsrv/bukkit/BukkitDiscordSRV.java b/bukkit/src/main/java/com/discordsrv/bukkit/BukkitDiscordSRV.java index ff09e967..59b4bc2b 100644 --- a/bukkit/src/main/java/com/discordsrv/bukkit/BukkitDiscordSRV.java +++ b/bukkit/src/main/java/com/discordsrv/bukkit/BukkitDiscordSRV.java @@ -25,11 +25,13 @@ import com.discordsrv.bukkit.config.manager.BukkitConfigManager; import com.discordsrv.bukkit.config.manager.BukkitConnectionConfigManager; import com.discordsrv.bukkit.console.BukkitConsole; import com.discordsrv.bukkit.listener.BukkitChatListener; +import com.discordsrv.bukkit.listener.BukkitDeathListener; +import com.discordsrv.bukkit.listener.BukkitStatusMessageListener; import com.discordsrv.bukkit.player.BukkitPlayerProvider; import com.discordsrv.bukkit.scheduler.BukkitScheduler; import com.discordsrv.common.config.manager.ConnectionConfigManager; import com.discordsrv.common.config.manager.MainConfigManager; -import com.discordsrv.logging.Logger; +import com.discordsrv.common.logging.Logger; import com.discordsrv.common.server.ServerDiscordSRV; import net.kyori.adventure.platform.bukkit.BukkitAudiences; import org.bukkit.Server; @@ -133,5 +135,7 @@ public class BukkitDiscordSRV extends ServerDiscordSRV. + */ + +package com.discordsrv.bukkit.component.util; + +import com.discordsrv.api.component.MinecraftComponent; +import com.discordsrv.common.DiscordSRV; +import com.discordsrv.common.component.util.ComponentUtil; +import net.kyori.adventure.platform.bukkit.BukkitComponentSerializer; +import org.bukkit.event.Event; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.function.Function; + +public final class PaperComponentUtil { + + public static final boolean IS_PAPER_ADVENTURE; + + static { + boolean isPaperAdventure = false; + try { + Class.forName("io.papermc.paper.event.player.AsyncChatEvent"); + isPaperAdventure = true; + } catch (ClassNotFoundException ignored) {} + IS_PAPER_ADVENTURE = isPaperAdventure; + } + + private PaperComponentUtil() {} + + public static MinecraftComponent getComponent( + DiscordSRV discordSRV, T source, String methodName, Function legacy) { + if (!IS_PAPER_ADVENTURE) { + return getLegacy(legacy.apply(source)); + } + + return getComponent(discordSRV, source, methodName); + } + + private static MinecraftComponent getLegacy(String legacy) { + return ComponentUtil.toAPI(BukkitComponentSerializer.legacy().deserialize(legacy)); + } + + public static MinecraftComponent getComponent(DiscordSRV discordSRV, Object source, String methodName) { + if (!IS_PAPER_ADVENTURE) { + return null; + } + + Class eventClass = source.getClass(); + Object unrelocated; + try { + Method method = eventClass.getMethod(methodName); + unrelocated = method.invoke(source); + } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) { + throw new IllegalStateException("Failed to invoke method reflectively", e); + } + + MinecraftComponent component = discordSRV.componentFactory().empty(); + MinecraftComponent.Adapter adapter = component.unrelocatedAdapter().orElse(null); + if (adapter == null) { + throw new IllegalStateException("Unrelocated adventure unavailable"); + } + + adapter.setComponent(unrelocated); + return component; + } +} diff --git a/bukkit/src/main/java/com/discordsrv/bukkit/config/main/BukkitConfig.java b/bukkit/src/main/java/com/discordsrv/bukkit/config/main/BukkitConfig.java index 866be166..a04fcadf 100644 --- a/bukkit/src/main/java/com/discordsrv/bukkit/config/main/BukkitConfig.java +++ b/bukkit/src/main/java/com/discordsrv/bukkit/config/main/BukkitConfig.java @@ -19,8 +19,17 @@ package com.discordsrv.bukkit.config.main; import com.discordsrv.common.config.main.MainConfig; +import com.discordsrv.common.config.main.channels.base.ChannelConfig; +import com.discordsrv.common.server.config.channels.base.ServerBaseChannelConfig; +import com.discordsrv.common.server.config.channels.base.ServerChannelConfig; import org.spongepowered.configurate.objectmapping.ConfigSerializable; @ConfigSerializable public class BukkitConfig extends MainConfig { + + public BukkitConfig() { + channels.clear(); + channels.put("global", new ServerChannelConfig()); + channels.put(ChannelConfig.DEFAULT_KEY, new ServerBaseChannelConfig()); + } } diff --git a/bukkit/src/main/java/com/discordsrv/bukkit/config/manager/BukkitConfigManager.java b/bukkit/src/main/java/com/discordsrv/bukkit/config/manager/BukkitConfigManager.java index 341c4f74..9587d071 100644 --- a/bukkit/src/main/java/com/discordsrv/bukkit/config/manager/BukkitConfigManager.java +++ b/bukkit/src/main/java/com/discordsrv/bukkit/config/manager/BukkitConfigManager.java @@ -20,9 +20,9 @@ package com.discordsrv.bukkit.config.manager; import com.discordsrv.bukkit.config.main.BukkitConfig; import com.discordsrv.common.DiscordSRV; -import com.discordsrv.common.config.manager.MainConfigManager; +import com.discordsrv.common.server.config.manager.ServerConfigManager; -public class BukkitConfigManager extends MainConfigManager { +public class BukkitConfigManager extends ServerConfigManager { public BukkitConfigManager(DiscordSRV discordSRV) { super(discordSRV); diff --git a/bukkit/src/main/java/com/discordsrv/bukkit/console/BukkitConsole.java b/bukkit/src/main/java/com/discordsrv/bukkit/console/BukkitConsole.java index 0eed3bf1..ccdda638 100644 --- a/bukkit/src/main/java/com/discordsrv/bukkit/console/BukkitConsole.java +++ b/bukkit/src/main/java/com/discordsrv/bukkit/console/BukkitConsole.java @@ -20,9 +20,9 @@ package com.discordsrv.bukkit.console; import com.discordsrv.bukkit.BukkitDiscordSRV; import com.discordsrv.common.console.Console; -import com.discordsrv.logging.backend.LoggingBackend; -import com.discordsrv.logging.impl.JavaLoggerImpl; -import com.discordsrv.logging.impl.Log4JLoggerImpl; +import com.discordsrv.common.logging.backend.LoggingBackend; +import com.discordsrv.common.logging.impl.JavaLoggerImpl; +import com.discordsrv.common.logging.impl.Log4JLoggerImpl; import net.kyori.adventure.identity.Identity; import net.kyori.adventure.text.Component; import org.jetbrains.annotations.NotNull; diff --git a/bukkit/src/main/java/com/discordsrv/bukkit/listener/BukkitChatListener.java b/bukkit/src/main/java/com/discordsrv/bukkit/listener/BukkitChatListener.java index f4aabf59..adb7c6b8 100644 --- a/bukkit/src/main/java/com/discordsrv/bukkit/listener/BukkitChatListener.java +++ b/bukkit/src/main/java/com/discordsrv/bukkit/listener/BukkitChatListener.java @@ -19,8 +19,9 @@ package com.discordsrv.bukkit.listener; import com.discordsrv.api.component.MinecraftComponent; -import com.discordsrv.api.event.events.message.receive.game.ChatMessageProcessingEvent; +import com.discordsrv.api.event.events.message.receive.game.GameChatMessageReceiveEvent; import com.discordsrv.bukkit.BukkitDiscordSRV; +import com.discordsrv.bukkit.component.util.PaperComponentUtil; import com.discordsrv.common.channel.DefaultGlobalChannel; import com.discordsrv.common.component.util.ComponentUtil; import io.papermc.paper.event.player.AsyncChatEvent; @@ -30,20 +31,13 @@ import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; - public abstract class BukkitChatListener implements Listener { public static BukkitChatListener get(BukkitDiscordSRV discordSRV) { - // TODO: config option - //noinspection ConstantConditions - if (1 == 2) { - try { - Class.forName("io.papermc.paper.event.player.AsyncChatEvent"); - return new Paper(discordSRV); - } catch (ClassNotFoundException ignored) {} + //noinspection ConstantConditions,PointlessBooleanExpression + if (1 == 2 && PaperComponentUtil.IS_PAPER_ADVENTURE) { + return new Paper(discordSRV); } return new Bukkit(discordSRV); @@ -56,14 +50,14 @@ public abstract class BukkitChatListener implements Listener { } protected void publishEvent(Player player, MinecraftComponent component, boolean cancelled) { - discordSRV.eventBus().publish( - new ChatMessageProcessingEvent( + discordSRV.scheduler().run(() -> discordSRV.eventBus().publish( + new GameChatMessageReceiveEvent( discordSRV.playerProvider().player(player), - component, new DefaultGlobalChannel(discordSRV), + component, cancelled ) - ); + )); } static class Bukkit extends BukkitChatListener { @@ -84,39 +78,13 @@ public abstract class BukkitChatListener implements Listener { static class Paper extends BukkitChatListener { - private static final Method MESSAGE_METHOD; - - static { - try { - MESSAGE_METHOD = AsyncChatEvent.class.getMethod("message"); - } catch (NoSuchMethodException e) { - throw new ExceptionInInitializerError(e); - } - } - public Paper(BukkitDiscordSRV discordSRV) { super(discordSRV); } @EventHandler(priority = EventPriority.MONITOR) public void onAsyncChat(AsyncChatEvent event) { - MinecraftComponent component = discordSRV.componentFactory().empty(); - - Object unrelocated; - try { - unrelocated = MESSAGE_METHOD.invoke(event); - } catch (IllegalAccessException | InvocationTargetException e) { - discordSRV.logger().error("Failed to get message from Paper AsyncChatEvent", e); - return; - } - - MinecraftComponent.Adapter adapter = component.unrelocatedAdapter().orElse(null); - if (adapter == null) { - discordSRV.logger().error("Failed to get unrelocated adventure adapter for Paper AsyncChatEvent listener"); - return; - } - - adapter.setComponent(unrelocated); + MinecraftComponent component = PaperComponentUtil.getComponent(discordSRV, event, "message"); publishEvent( event.getPlayer(), component, diff --git a/bukkit/src/main/java/com/discordsrv/bukkit/listener/BukkitDeathListener.java b/bukkit/src/main/java/com/discordsrv/bukkit/listener/BukkitDeathListener.java new file mode 100644 index 00000000..94ac7608 --- /dev/null +++ b/bukkit/src/main/java/com/discordsrv/bukkit/listener/BukkitDeathListener.java @@ -0,0 +1,48 @@ +/* + * This file is part of DiscordSRV, licensed under the GPLv3 License + * Copyright (c) 2016-2021 Austin "Scarsz" Shapiro, Henri "Vankka" Schubin and DiscordSRV contributors + * + * 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.discordsrv.bukkit.listener; + +import com.discordsrv.api.component.MinecraftComponent; +import com.discordsrv.api.event.events.message.receive.game.DeathMessageReceiveEvent; +import com.discordsrv.api.player.DiscordSRVPlayer; +import com.discordsrv.bukkit.BukkitDiscordSRV; +import com.discordsrv.bukkit.component.util.PaperComponentUtil; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.entity.PlayerDeathEvent; + +public class BukkitDeathListener implements Listener { + + private final BukkitDiscordSRV discordSRV; + + public BukkitDeathListener(BukkitDiscordSRV discordSRV) { + this.discordSRV = discordSRV; + } + + @SuppressWarnings("deprecation") // Paper + @EventHandler(priority = EventPriority.MONITOR) + public void onPlayerDeath(PlayerDeathEvent event) { + DiscordSRVPlayer player = discordSRV.playerProvider().player(event.getEntity()); + MinecraftComponent component = PaperComponentUtil.getComponent(discordSRV, event, "deathMessage", PlayerDeathEvent::getDeathMessage); + + discordSRV.scheduler().run(() -> discordSRV.eventBus().publish( + new DeathMessageReceiveEvent(player, null, component, event.isCancelled()))); + } +} diff --git a/bukkit/src/main/java/com/discordsrv/bukkit/listener/BukkitStatusMessageListener.java b/bukkit/src/main/java/com/discordsrv/bukkit/listener/BukkitStatusMessageListener.java new file mode 100644 index 00000000..ae744765 --- /dev/null +++ b/bukkit/src/main/java/com/discordsrv/bukkit/listener/BukkitStatusMessageListener.java @@ -0,0 +1,64 @@ +/* + * This file is part of DiscordSRV, licensed under the GPLv3 License + * Copyright (c) 2016-2021 Austin "Scarsz" Shapiro, Henri "Vankka" Schubin and DiscordSRV contributors + * + * 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.discordsrv.bukkit.listener; + +import com.discordsrv.api.component.MinecraftComponent; +import com.discordsrv.api.event.events.message.receive.game.JoinMessageReceiveEvent; +import com.discordsrv.api.event.events.message.receive.game.LeaveMessageReceiveEvent; +import com.discordsrv.api.player.DiscordSRVPlayer; +import com.discordsrv.bukkit.BukkitDiscordSRV; +import com.discordsrv.bukkit.component.util.PaperComponentUtil; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerJoinEvent; +import org.bukkit.event.player.PlayerQuitEvent; + +public class BukkitStatusMessageListener implements Listener { + + private final BukkitDiscordSRV discordSRV; + + public BukkitStatusMessageListener(BukkitDiscordSRV discordSRV) { + this.discordSRV = discordSRV; + } + + @SuppressWarnings("deprecation") // Paper + @EventHandler(priority = EventPriority.MONITOR) + public void onPlayerJoin(PlayerJoinEvent event) { + DiscordSRVPlayer player = discordSRV.playerProvider().player(event.getPlayer()); + MinecraftComponent component = PaperComponentUtil.getComponent( + discordSRV, event, "joinMessage", PlayerJoinEvent::getJoinMessage); + + discordSRV.scheduler().run(() -> discordSRV.eventBus().publish( + new JoinMessageReceiveEvent(player, null, component, false) + )); + } + + @SuppressWarnings("deprecation") // Paper + @EventHandler(priority = EventPriority.HIGH) + public void onPlayerQuit(PlayerQuitEvent event) { + DiscordSRVPlayer player = discordSRV.playerProvider().player(event.getPlayer()); + MinecraftComponent component = PaperComponentUtil.getComponent( + discordSRV, event, "quitMessage", PlayerQuitEvent::getQuitMessage); + + discordSRV.scheduler().run(() -> discordSRV.eventBus().publish( + new LeaveMessageReceiveEvent(player, null, component, false) + )); + } +} diff --git a/bukkit/src/main/java/com/discordsrv/bukkit/player/BukkitOfflinePlayer.java b/bukkit/src/main/java/com/discordsrv/bukkit/player/BukkitOfflinePlayer.java index c6cabcbf..8ae9453f 100644 --- a/bukkit/src/main/java/com/discordsrv/bukkit/player/BukkitOfflinePlayer.java +++ b/bukkit/src/main/java/com/discordsrv/bukkit/player/BukkitOfflinePlayer.java @@ -38,7 +38,7 @@ public class BukkitOfflinePlayer implements IOfflinePlayer { @SuppressWarnings("NullabilityProblems") @Override - public String getUsername() { + public String username() { return offlinePlayer.getName(); } diff --git a/bukkit/src/main/java/com/discordsrv/bukkit/player/BukkitPlayer.java b/bukkit/src/main/java/com/discordsrv/bukkit/player/BukkitPlayer.java index f3e9e529..76c49e2a 100644 --- a/bukkit/src/main/java/com/discordsrv/bukkit/player/BukkitPlayer.java +++ b/bukkit/src/main/java/com/discordsrv/bukkit/player/BukkitPlayer.java @@ -82,7 +82,7 @@ public class BukkitPlayer extends BukkitOfflinePlayer implements IPlayer { @SuppressWarnings("deprecation") // Paper @Override - public @NotNull Component getDisplayName() { + public @NotNull Component displayName() { if (DISPLAY_NAME_METHOD != null) { try { return ComponentUtil.fromUnrelocated(DISPLAY_NAME_METHOD.invoke(player)); diff --git a/bungee/src/main/java/com/discordsrv/bungee/BungeeDiscordSRV.java b/bungee/src/main/java/com/discordsrv/bungee/BungeeDiscordSRV.java index 7a0f808f..628798f3 100644 --- a/bungee/src/main/java/com/discordsrv/bungee/BungeeDiscordSRV.java +++ b/bungee/src/main/java/com/discordsrv/bungee/BungeeDiscordSRV.java @@ -24,8 +24,8 @@ import com.discordsrv.common.config.connection.ConnectionConfig; import com.discordsrv.common.config.main.MainConfig; import com.discordsrv.common.config.manager.ConnectionConfigManager; import com.discordsrv.common.config.manager.MainConfigManager; -import com.discordsrv.logging.Logger; -import com.discordsrv.common.proxy.ProxyDiscordSRV; +import com.discordsrv.common.logging.Logger; +import com.discordsrv.proxy.ProxyDiscordSRV; import com.discordsrv.common.scheduler.StandardScheduler; import net.kyori.adventure.platform.bungeecord.BungeeAudiences; import net.md_5.bungee.api.ProxyServer; diff --git a/bungee/src/main/java/com/discordsrv/bungee/DiscordSRVBungeeBootstrap.java b/bungee/src/main/java/com/discordsrv/bungee/DiscordSRVBungeeBootstrap.java index db0df28a..ac8adc21 100644 --- a/bungee/src/main/java/com/discordsrv/bungee/DiscordSRVBungeeBootstrap.java +++ b/bungee/src/main/java/com/discordsrv/bungee/DiscordSRVBungeeBootstrap.java @@ -19,8 +19,8 @@ package com.discordsrv.bungee; import com.discordsrv.common.dependency.InitialDependencyLoader; -import com.discordsrv.logging.Logger; -import com.discordsrv.logging.impl.JavaLoggerImpl; +import com.discordsrv.common.logging.Logger; +import com.discordsrv.common.logging.impl.JavaLoggerImpl; import dev.vankka.mcdependencydownload.bungee.bootstrap.BungeeBootstrap; import dev.vankka.mcdependencydownload.classloader.JarInJarClassLoader; import net.md_5.bungee.api.plugin.Plugin; diff --git a/bungee/src/main/java/com/discordsrv/bungee/console/BungeeConsole.java b/bungee/src/main/java/com/discordsrv/bungee/console/BungeeConsole.java index 6b83a3c7..2c4feee7 100644 --- a/bungee/src/main/java/com/discordsrv/bungee/console/BungeeConsole.java +++ b/bungee/src/main/java/com/discordsrv/bungee/console/BungeeConsole.java @@ -20,8 +20,8 @@ package com.discordsrv.bungee.console; import com.discordsrv.bungee.BungeeDiscordSRV; import com.discordsrv.common.console.Console; -import com.discordsrv.logging.backend.LoggingBackend; -import com.discordsrv.logging.impl.JavaLoggerImpl; +import com.discordsrv.common.logging.backend.LoggingBackend; +import com.discordsrv.common.logging.impl.JavaLoggerImpl; import net.kyori.adventure.identity.Identity; import net.kyori.adventure.text.Component; import org.jetbrains.annotations.NotNull; diff --git a/bungee/src/main/java/com/discordsrv/bungee/player/BungeePlayer.java b/bungee/src/main/java/com/discordsrv/bungee/player/BungeePlayer.java index 6befe497..e849b8ca 100644 --- a/bungee/src/main/java/com/discordsrv/bungee/player/BungeePlayer.java +++ b/bungee/src/main/java/com/discordsrv/bungee/player/BungeePlayer.java @@ -65,7 +65,7 @@ public class BungeePlayer implements IPlayer { } @Override - public @NotNull String getUsername() { + public @NotNull String username() { return player.getName(); } @@ -75,7 +75,7 @@ public class BungeePlayer implements IPlayer { } @Override - public @NotNull Component getDisplayName() { + public @NotNull Component displayName() { return BungeeComponentUtil.fromLegacy(player.getDisplayName()); } } diff --git a/common/api/build.gradle b/common/api/build.gradle index 4bacae88..ee9bd10a 100644 --- a/common/api/build.gradle +++ b/common/api/build.gradle @@ -3,6 +3,5 @@ dependencies { api project(':api') // Logging - api 'org.slf4j:slf4j-api:1.6.99' - compileOnly 'org.apache.logging.log4j:log4j-core:2.0-beta9' + api 'org.slf4j:slf4j-api:1.7.32' } diff --git a/common/api/src/main/java/com/discordsrv/logging/backend/LogAppender.java b/common/api/src/main/java/com/discordsrv/common/logging/LogAppender.java similarity index 93% rename from common/api/src/main/java/com/discordsrv/logging/backend/LogAppender.java rename to common/api/src/main/java/com/discordsrv/common/logging/LogAppender.java index c853ec37..ba25d169 100644 --- a/common/api/src/main/java/com/discordsrv/logging/backend/LogAppender.java +++ b/common/api/src/main/java/com/discordsrv/common/logging/LogAppender.java @@ -16,9 +16,8 @@ * along with this program. If not, see . */ -package com.discordsrv.logging.backend; +package com.discordsrv.common.logging; -import com.discordsrv.logging.LogLevel; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; diff --git a/common/api/src/main/java/com/discordsrv/logging/LogLevel.java b/common/api/src/main/java/com/discordsrv/common/logging/LogLevel.java similarity index 97% rename from common/api/src/main/java/com/discordsrv/logging/LogLevel.java rename to common/api/src/main/java/com/discordsrv/common/logging/LogLevel.java index e5abf64e..959d57bc 100644 --- a/common/api/src/main/java/com/discordsrv/logging/LogLevel.java +++ b/common/api/src/main/java/com/discordsrv/common/logging/LogLevel.java @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.discordsrv.logging; +package com.discordsrv.common.logging; public interface LogLevel { diff --git a/common/api/src/main/java/com/discordsrv/logging/adapter/DependencyLoggerAdapter.java b/common/api/src/main/java/com/discordsrv/common/logging/adapter/DependencyLoggerAdapter.java similarity index 97% rename from common/api/src/main/java/com/discordsrv/logging/adapter/DependencyLoggerAdapter.java rename to common/api/src/main/java/com/discordsrv/common/logging/adapter/DependencyLoggerAdapter.java index 2d10757e..ae0a00cf 100644 --- a/common/api/src/main/java/com/discordsrv/logging/adapter/DependencyLoggerAdapter.java +++ b/common/api/src/main/java/com/discordsrv/common/logging/adapter/DependencyLoggerAdapter.java @@ -16,10 +16,10 @@ * along with this program. If not, see . */ -package com.discordsrv.logging.adapter; +package com.discordsrv.common.logging.adapter; -import com.discordsrv.logging.LogLevel; -import com.discordsrv.logging.backend.LogAppender; +import com.discordsrv.common.logging.LogAppender; +import com.discordsrv.common.logging.LogLevel; import org.slf4j.Marker; import org.slf4j.helpers.MarkerIgnoringBase; import org.slf4j.spi.LocationAwareLogger; diff --git a/common/api/src/main/java/org/slf4j/impl/DiscordSRVLoggerFactory.java b/common/api/src/main/java/org/slf4j/impl/DiscordSRVLoggerFactory.java index 1ccbdef1..79364bac 100644 --- a/common/api/src/main/java/org/slf4j/impl/DiscordSRVLoggerFactory.java +++ b/common/api/src/main/java/org/slf4j/impl/DiscordSRVLoggerFactory.java @@ -18,11 +18,10 @@ package org.slf4j.impl; -import com.discordsrv.logging.adapter.DependencyLoggerAdapter; +import com.discordsrv.common.logging.adapter.DependencyLoggerAdapter; import org.slf4j.ILoggerFactory; import org.slf4j.Logger; -import java.util.Locale; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; @@ -32,6 +31,6 @@ public class DiscordSRVLoggerFactory implements ILoggerFactory { @Override public Logger getLogger(String s) { - return loggerMap.computeIfAbsent(s.toLowerCase(Locale.ROOT), DependencyLoggerAdapter::new); + return loggerMap.computeIfAbsent(s, DependencyLoggerAdapter::new); } } diff --git a/common/build.gradle b/common/build.gradle index 36d6e686..3207dff1 100644 --- a/common/build.gradle +++ b/common/build.gradle @@ -40,6 +40,10 @@ dependencies { runtimeDownloadApi 'org.spongepowered:configurate-yaml:' + rootProject.configurateVersion runtimeDownloadApi 'org.spongepowered:configurate-hocon:' + rootProject.configurateVersion + // Logging + compileOnlyApi project(':common:common-slf4j-hack') + compileOnly 'org.apache.logging.log4j:log4j-core:2.0-beta9' + // Adventure, MCDiscordReserializer, EnhancedLegacyText runtimeDownloadApi 'net.kyori:adventure-api:' + rootProject.adventureVersion runtimeDownloadApi 'net.kyori:adventure-text-serializer-plain:' + rootProject.adventureVersion @@ -51,6 +55,9 @@ dependencies { // Database Drivers h2Driver 'com.h2database:h2:1.4.200' mysqlDriver 'mysql:mysql-connector-java:8.0.25' + + // Integrations + compileOnlyApi 'net.luckperms:api:5.3' } processResources { diff --git a/common/proxy/src/main/java/com/discordsrv/proxy/ProxyDiscordSRV.java b/common/proxy/src/main/java/com/discordsrv/proxy/ProxyDiscordSRV.java new file mode 100644 index 00000000..fcbaf434 --- /dev/null +++ b/common/proxy/src/main/java/com/discordsrv/proxy/ProxyDiscordSRV.java @@ -0,0 +1,41 @@ +/* + * This file is part of DiscordSRV, licensed under the GPLv3 License + * Copyright (c) 2016-2021 Austin "Scarsz" Shapiro, Henri "Vankka" Schubin and DiscordSRV contributors + * + * 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.discordsrv.proxy; + +import com.discordsrv.common.AbstractDiscordSRV; +import com.discordsrv.common.config.connection.ConnectionConfig; +import com.discordsrv.common.config.main.MainConfig; +import com.discordsrv.common.module.ModuleInitializationFunction; +import com.discordsrv.proxy.modules.ServerSwitchMessageModule; + +public abstract class ProxyDiscordSRV extends AbstractDiscordSRV { + + @Override + protected void enable() throws Throwable { + super.enable(); + + for (ModuleInitializationFunction function : new ModuleInitializationFunction[]{ + ServerSwitchMessageModule::new + }) { + try { + registerModule(function.initialize(this)); + } catch (Throwable ignored) {} + } + } +} diff --git a/common/proxy/src/main/java/com/discordsrv/proxy/config/channels/ServerSwitchMessageConfig.java b/common/proxy/src/main/java/com/discordsrv/proxy/config/channels/ServerSwitchMessageConfig.java new file mode 100644 index 00000000..412de1a1 --- /dev/null +++ b/common/proxy/src/main/java/com/discordsrv/proxy/config/channels/ServerSwitchMessageConfig.java @@ -0,0 +1,25 @@ +package com.discordsrv.proxy.config.channels; + +import com.discordsrv.api.discord.api.entity.message.DiscordMessageEmbed; +import com.discordsrv.api.discord.api.entity.message.SendableDiscordMessage; +import com.discordsrv.common.config.annotation.Untranslated; +import org.spongepowered.configurate.objectmapping.ConfigSerializable; + +@ConfigSerializable +public class ServerSwitchMessageConfig { + + public boolean enabled = true; + + @Untranslated(Untranslated.Type.VALUE) + public SendableDiscordMessage.Builder format = SendableDiscordMessage.builder() + .addEmbed( + DiscordMessageEmbed.builder() + .setAuthor( + "%player_display_name% switched from %from_server% to %to_server%", + null, + "%player_avatar_url%" + ) + .setColor(0x5555FF) + .build() + ); +} diff --git a/common/proxy/src/main/java/com/discordsrv/proxy/config/channels/base/ProxyBaseChannelConfig.java b/common/proxy/src/main/java/com/discordsrv/proxy/config/channels/base/ProxyBaseChannelConfig.java new file mode 100644 index 00000000..2c20fe45 --- /dev/null +++ b/common/proxy/src/main/java/com/discordsrv/proxy/config/channels/base/ProxyBaseChannelConfig.java @@ -0,0 +1,31 @@ +/* + * This file is part of DiscordSRV, licensed under the GPLv3 License + * Copyright (c) 2016-2021 Austin "Scarsz" Shapiro, Henri "Vankka" Schubin and DiscordSRV contributors + * + * 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.discordsrv.proxy.config.channels.base; + +import com.discordsrv.common.config.annotation.Order; +import com.discordsrv.common.config.main.channels.base.BaseChannelConfig; +import com.discordsrv.proxy.config.channels.ServerSwitchMessageConfig; +import org.spongepowered.configurate.objectmapping.ConfigSerializable; + +@ConfigSerializable +public class ProxyBaseChannelConfig extends BaseChannelConfig { + + @Order(1) + public ServerSwitchMessageConfig serverSwitchMessages = new ServerSwitchMessageConfig(); +} diff --git a/common/proxy/src/main/java/com/discordsrv/proxy/config/channels/base/ProxyChannelConfig.java b/common/proxy/src/main/java/com/discordsrv/proxy/config/channels/base/ProxyChannelConfig.java new file mode 100644 index 00000000..353d2cc3 --- /dev/null +++ b/common/proxy/src/main/java/com/discordsrv/proxy/config/channels/base/ProxyChannelConfig.java @@ -0,0 +1,22 @@ +package com.discordsrv.proxy.config.channels.base; + +import com.discordsrv.common.config.main.channels.base.IChannelConfig; +import org.spongepowered.configurate.objectmapping.meta.Comment; + +import java.util.ArrayList; +import java.util.List; + +public class ProxyChannelConfig extends ProxyBaseChannelConfig implements IChannelConfig { + + public ProxyChannelConfig() { + initialize(); + } + + @Comment(CHANNEL_IDS_COMMENT) + public List channelIds = new ArrayList<>(); + + @Override + public List ids() { + return channelIds; + } +} diff --git a/common/proxy/src/main/java/com/discordsrv/proxy/config/manager/ProxyConfigManager.java b/common/proxy/src/main/java/com/discordsrv/proxy/config/manager/ProxyConfigManager.java new file mode 100644 index 00000000..8a359bf2 --- /dev/null +++ b/common/proxy/src/main/java/com/discordsrv/proxy/config/manager/ProxyConfigManager.java @@ -0,0 +1,21 @@ +package com.discordsrv.proxy.config.manager; + +import com.discordsrv.common.DiscordSRV; +import com.discordsrv.common.config.main.MainConfig; +import com.discordsrv.common.config.main.channels.base.ChannelConfig; +import com.discordsrv.common.config.manager.MainConfigManager; +import com.discordsrv.proxy.config.channels.base.ProxyBaseChannelConfig; +import com.discordsrv.proxy.config.channels.base.ProxyChannelConfig; +import org.spongepowered.configurate.objectmapping.ObjectMapper; + +public abstract class ProxyConfigManager extends MainConfigManager { + + public ProxyConfigManager(DiscordSRV discordSRV) { + super(discordSRV); + } + + @Override + public ChannelConfig.Serializer getChannelConfigSerializer(ObjectMapper.Factory mapperFactory) { + return new ChannelConfig.Serializer(mapperFactory, ProxyBaseChannelConfig.class, ProxyChannelConfig.class); + } +} diff --git a/common/proxy/src/main/java/com/discordsrv/proxy/config/package-info.java b/common/proxy/src/main/java/com/discordsrv/proxy/config/package-info.java new file mode 100644 index 00000000..a90e56f8 --- /dev/null +++ b/common/proxy/src/main/java/com/discordsrv/proxy/config/package-info.java @@ -0,0 +1 @@ +package com.discordsrv.proxy.config; diff --git a/common/proxy/src/main/java/com/discordsrv/proxy/modules/ServerSwitchMessageModule.java b/common/proxy/src/main/java/com/discordsrv/proxy/modules/ServerSwitchMessageModule.java new file mode 100644 index 00000000..d37297f4 --- /dev/null +++ b/common/proxy/src/main/java/com/discordsrv/proxy/modules/ServerSwitchMessageModule.java @@ -0,0 +1,51 @@ +package com.discordsrv.proxy.modules; + +import com.discordsrv.api.discord.api.entity.message.ReceivedDiscordMessageCluster; +import com.discordsrv.api.discord.api.entity.message.SendableDiscordMessage; +import com.discordsrv.api.event.bus.EventPriority; +import com.discordsrv.api.event.bus.Subscribe; +import com.discordsrv.api.event.events.message.forward.game.ServerSwitchMessageForwardedEvent; +import com.discordsrv.api.event.events.message.receive.game.ServerSwitchMessageReceiveEvent; +import com.discordsrv.common.DiscordSRV; +import com.discordsrv.common.config.main.channels.base.BaseChannelConfig; +import com.discordsrv.common.function.OrDefault; +import com.discordsrv.common.module.modules.message.AbstractGameMessageModule; +import com.discordsrv.proxy.config.channels.ServerSwitchMessageConfig; +import com.discordsrv.proxy.config.channels.base.ProxyBaseChannelConfig; + +public class ServerSwitchMessageModule extends AbstractGameMessageModule { + + public ServerSwitchMessageModule(DiscordSRV discordSRV) { + super(discordSRV); + } + + @Subscribe(priority = EventPriority.LAST) + public void onServerSwitchReceive(ServerSwitchMessageReceiveEvent event) { + if (checkCancellation(event) || checkProcessor(event)) { + return; + } + + process(event, event.getPlayer(), null); + event.markAsProcessed(); + } + + @Override + public OrDefault mapConfig(OrDefault channelConfig) { + return channelConfig.map(cfg -> ((ProxyBaseChannelConfig) cfg).serverSwitchMessages); + } + + @Override + public boolean isEnabled(OrDefault config) { + return config.get(cfg -> cfg.enabled, false); + } + + @Override + public SendableDiscordMessage.Builder getFormat(OrDefault config) { + return config.get(cfg -> cfg.format); + } + + @Override + public void postClusterToEventBus(ReceivedDiscordMessageCluster cluster) { + discordSRV.eventBus().publish(new ServerSwitchMessageForwardedEvent(cluster)); + } +} diff --git a/common/server/src/main/java/com/discordsrv/common/server/ServerDiscordSRV.java b/common/server/src/main/java/com/discordsrv/common/server/ServerDiscordSRV.java index 81277a86..c6b6a1c1 100644 --- a/common/server/src/main/java/com/discordsrv/common/server/ServerDiscordSRV.java +++ b/common/server/src/main/java/com/discordsrv/common/server/ServerDiscordSRV.java @@ -21,6 +21,8 @@ package com.discordsrv.common.server; import com.discordsrv.common.AbstractDiscordSRV; import com.discordsrv.common.config.connection.ConnectionConfig; import com.discordsrv.common.config.main.MainConfig; +import com.discordsrv.common.module.ModuleInitializationFunction; +import com.discordsrv.common.server.modules.DeathMessageModule; import com.discordsrv.common.server.player.ServerPlayerProvider; import com.discordsrv.common.server.scheduler.ServerScheduler; import org.jetbrains.annotations.NotNull; @@ -36,6 +38,19 @@ public abstract class ServerDiscordSRV playerProvider(); + @Override + protected void enable() throws Throwable { + super.enable(); + + for (ModuleInitializationFunction function : new ModuleInitializationFunction[]{ + DeathMessageModule::new + }) { + try { + registerModule(function.initialize(this)); + } catch (Throwable ignored) {} + } + } + public final CompletableFuture invokeServerStarted() { return invokeLifecycle(this::serverStarted, "Failed to enable", true); } diff --git a/common/server/src/main/java/com/discordsrv/common/server/config/channels/DeathMessageConfig.java b/common/server/src/main/java/com/discordsrv/common/server/config/channels/DeathMessageConfig.java new file mode 100644 index 00000000..356a834b --- /dev/null +++ b/common/server/src/main/java/com/discordsrv/common/server/config/channels/DeathMessageConfig.java @@ -0,0 +1,41 @@ +/* + * This file is part of DiscordSRV, licensed under the GPLv3 License + * Copyright (c) 2016-2021 Austin "Scarsz" Shapiro, Henri "Vankka" Schubin and DiscordSRV contributors + * + * 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.discordsrv.common.server.config.channels; + +import com.discordsrv.api.discord.api.entity.message.DiscordMessageEmbed; +import com.discordsrv.api.discord.api.entity.message.SendableDiscordMessage; +import com.discordsrv.common.config.annotation.Untranslated; +import org.spongepowered.configurate.objectmapping.ConfigSerializable; +import org.spongepowered.configurate.objectmapping.meta.Comment; + +@ConfigSerializable +public class DeathMessageConfig { + + @Comment("Enable death message forwarding") + public boolean enabled = true; + + @Untranslated(Untranslated.Type.VALUE) + public SendableDiscordMessage.Builder format = SendableDiscordMessage.builder() + .addEmbed( + DiscordMessageEmbed.builder() + .setAuthor("%message%", null, "%player_avatar_url%") + .setColor(1) + .build() + ); +} diff --git a/common/server/src/main/java/com/discordsrv/common/server/config/channels/base/ServerBaseChannelConfig.java b/common/server/src/main/java/com/discordsrv/common/server/config/channels/base/ServerBaseChannelConfig.java new file mode 100644 index 00000000..419a68a3 --- /dev/null +++ b/common/server/src/main/java/com/discordsrv/common/server/config/channels/base/ServerBaseChannelConfig.java @@ -0,0 +1,31 @@ +/* + * This file is part of DiscordSRV, licensed under the GPLv3 License + * Copyright (c) 2016-2021 Austin "Scarsz" Shapiro, Henri "Vankka" Schubin and DiscordSRV contributors + * + * 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.discordsrv.common.server.config.channels.base; + +import com.discordsrv.common.config.annotation.Order; +import com.discordsrv.common.server.config.channels.DeathMessageConfig; +import com.discordsrv.common.config.main.channels.base.BaseChannelConfig; +import org.spongepowered.configurate.objectmapping.ConfigSerializable; + +@ConfigSerializable +public class ServerBaseChannelConfig extends BaseChannelConfig { + + @Order(1) + public DeathMessageConfig deathMessages = new DeathMessageConfig(); +} diff --git a/common/src/main/java/com/discordsrv/common/config/main/channels/ChannelConfig.java b/common/server/src/main/java/com/discordsrv/common/server/config/channels/base/ServerChannelConfig.java similarity index 53% rename from common/src/main/java/com/discordsrv/common/config/main/channels/ChannelConfig.java rename to common/server/src/main/java/com/discordsrv/common/server/config/channels/base/ServerChannelConfig.java index b8d8d135..40f4db58 100644 --- a/common/src/main/java/com/discordsrv/common/config/main/channels/ChannelConfig.java +++ b/common/server/src/main/java/com/discordsrv/common/server/config/channels/base/ServerChannelConfig.java @@ -16,39 +16,27 @@ * along with this program. If not, see . */ -package com.discordsrv.common.config.main.channels; +package com.discordsrv.common.server.config.channels.base; +import com.discordsrv.common.config.main.channels.base.IChannelConfig; import org.spongepowered.configurate.objectmapping.ConfigSerializable; import org.spongepowered.configurate.objectmapping.meta.Comment; -import java.lang.reflect.Field; -import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.List; @ConfigSerializable -public class ChannelConfig extends BaseChannelConfig { +public class ServerChannelConfig extends ServerBaseChannelConfig implements IChannelConfig { - public static final String DEFAULT_KEY = "default"; - - public ChannelConfig() { - // Clear everything besides channelIds by default (these will be filled back in by Configurate if they are in the config itself) - for (Field field : getClass().getFields()) { - int modifiers = field.getModifiers(); - if (!Modifier.isPublic(modifiers) || Modifier.isFinal(modifiers) || Modifier.isStatic(modifiers)) { - continue; - } - if (field.getName().equals("channelIds")) { - continue; - } - - try { - field.set(this, null); - } catch (IllegalAccessException ignored) {} - } + public ServerChannelConfig() { + initialize(); } - @Comment("The channels this in-game channel will forward to in Discord") + @Comment(CHANNEL_IDS_COMMENT) public List channelIds = new ArrayList<>(); + @Override + public List ids() { + return channelIds; + } } diff --git a/common/server/src/main/java/com/discordsrv/common/server/config/manager/ServerConfigManager.java b/common/server/src/main/java/com/discordsrv/common/server/config/manager/ServerConfigManager.java new file mode 100644 index 00000000..f3ab5995 --- /dev/null +++ b/common/server/src/main/java/com/discordsrv/common/server/config/manager/ServerConfigManager.java @@ -0,0 +1,39 @@ +/* + * This file is part of DiscordSRV, licensed under the GPLv3 License + * Copyright (c) 2016-2021 Austin "Scarsz" Shapiro, Henri "Vankka" Schubin and DiscordSRV contributors + * + * 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.discordsrv.common.server.config.manager; + +import com.discordsrv.common.DiscordSRV; +import com.discordsrv.common.config.main.MainConfig; +import com.discordsrv.common.config.main.channels.base.ChannelConfig; +import com.discordsrv.common.config.manager.MainConfigManager; +import com.discordsrv.common.server.config.channels.base.ServerBaseChannelConfig; +import com.discordsrv.common.server.config.channels.base.ServerChannelConfig; +import org.spongepowered.configurate.objectmapping.ObjectMapper; + +public abstract class ServerConfigManager extends MainConfigManager { + + public ServerConfigManager(DiscordSRV discordSRV) { + super(discordSRV); + } + + @Override + public ChannelConfig.Serializer getChannelConfigSerializer(ObjectMapper.Factory mapperFactory) { + return new ChannelConfig.Serializer(mapperFactory, ServerBaseChannelConfig.class, ServerChannelConfig.class); + } +} diff --git a/common/server/src/main/java/com/discordsrv/common/server/modules/DeathMessageModule.java b/common/server/src/main/java/com/discordsrv/common/server/modules/DeathMessageModule.java new file mode 100644 index 00000000..b13bd6f8 --- /dev/null +++ b/common/server/src/main/java/com/discordsrv/common/server/modules/DeathMessageModule.java @@ -0,0 +1,69 @@ +/* + * This file is part of DiscordSRV, licensed under the GPLv3 License + * Copyright (c) 2016-2021 Austin "Scarsz" Shapiro, Henri "Vankka" Schubin and DiscordSRV contributors + * + * 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.discordsrv.common.server.modules; + +import com.discordsrv.api.discord.api.entity.message.ReceivedDiscordMessageCluster; +import com.discordsrv.api.discord.api.entity.message.SendableDiscordMessage; +import com.discordsrv.api.event.bus.EventPriority; +import com.discordsrv.api.event.bus.Subscribe; +import com.discordsrv.api.event.events.message.forward.game.DeathMessageForwardedEvent; +import com.discordsrv.api.event.events.message.receive.game.DeathMessageReceiveEvent; +import com.discordsrv.common.DiscordSRV; +import com.discordsrv.common.config.main.channels.base.BaseChannelConfig; +import com.discordsrv.common.server.config.channels.DeathMessageConfig; +import com.discordsrv.common.function.OrDefault; +import com.discordsrv.common.module.modules.message.AbstractGameMessageModule; +import com.discordsrv.common.server.config.channels.base.ServerBaseChannelConfig; + +public class DeathMessageModule extends AbstractGameMessageModule { + + public DeathMessageModule(DiscordSRV discordSRV) { + super(discordSRV); + } + + @Subscribe(priority = EventPriority.LAST) + public void onDeathReceive(DeathMessageReceiveEvent event) { + if (checkCancellation(event) || checkProcessor(event)) { + return; + } + + process(event, event.getPlayer(), event.getGameChannel()); + event.markAsProcessed(); + } + + @Override + public OrDefault mapConfig(OrDefault channelConfig) { + return channelConfig.map(cfg -> ((ServerBaseChannelConfig) cfg).deathMessages); + } + + @Override + public boolean isEnabled(OrDefault config) { + return config.get(cfg -> cfg.enabled, true); + } + + @Override + public SendableDiscordMessage.Builder getFormat(OrDefault config) { + return config.get(cfg -> cfg.format); + } + + @Override + public void postClusterToEventBus(ReceivedDiscordMessageCluster cluster) { + discordSRV.eventBus().publish(new DeathMessageForwardedEvent(cluster)); + } +} diff --git a/common/slf4j-hack/build.gradle b/common/slf4j-hack/build.gradle new file mode 100644 index 00000000..ec42264e --- /dev/null +++ b/common/slf4j-hack/build.gradle @@ -0,0 +1,3 @@ +dependencies { + api 'org.slf4j:slf4j-api:1.7.32' +} diff --git a/common/slf4j-hack/src/main/java/com/discordsrv/x/slf4j/Logger.java b/common/slf4j-hack/src/main/java/com/discordsrv/x/slf4j/Logger.java new file mode 100644 index 00000000..aeb69759 --- /dev/null +++ b/common/slf4j-hack/src/main/java/com/discordsrv/x/slf4j/Logger.java @@ -0,0 +1,28 @@ +/* + * This file is part of DiscordSRV, licensed under the GPLv3 License + * Copyright (c) 2016-2021 Austin "Scarsz" Shapiro, Henri "Vankka" Schubin and DiscordSRV contributors + * + * 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.discordsrv.x.slf4j; + +/** + * A fake org.slf4j.Logger that is compileOnly scoped and relocated back to the real org.slf4j package. + * This is required as we want to relocate 'org.slf4j' + * but we also need the non-relocated version for Velocity's logging. + * + * Could be fixed by https://github.com/johnrengelman/shadow/issues/727 + */ +public interface Logger extends org.slf4j.Logger {} diff --git a/common/src/main/java/com/discordsrv/common/AbstractDiscordSRV.java b/common/src/main/java/com/discordsrv/common/AbstractDiscordSRV.java index ca1bde50..e600ae76 100644 --- a/common/src/main/java/com/discordsrv/common/AbstractDiscordSRV.java +++ b/common/src/main/java/com/discordsrv/common/AbstractDiscordSRV.java @@ -35,22 +35,26 @@ import com.discordsrv.common.discord.connection.jda.JDAConnectionManager; import com.discordsrv.common.discord.details.DiscordConnectionDetailsImpl; import com.discordsrv.common.event.bus.EventBusImpl; import com.discordsrv.common.function.CheckedRunnable; -import com.discordsrv.common.logging.DependencyLoggingHandler; -import com.discordsrv.common.module.Module; +import com.discordsrv.common.logging.dependency.DependencyLoggingHandler; +import com.discordsrv.common.module.modules.message.JoinMessageModule; +import com.discordsrv.common.module.modules.message.LeaveMessageModule; +import com.discordsrv.common.module.type.AbstractModule; +import com.discordsrv.common.module.type.Module; +import com.discordsrv.common.module.ModuleInitializationFunction; import com.discordsrv.common.module.ModuleManager; import com.discordsrv.common.module.modules.DiscordAPIEventModule; -import com.discordsrv.common.module.modules.DiscordToMinecraftModule; +import com.discordsrv.common.module.modules.message.DiscordToMinecraftChatModule; import com.discordsrv.common.module.modules.GlobalChannelLookupModule; -import com.discordsrv.common.module.modules.MinecraftToDiscordModule; +import com.discordsrv.common.module.modules.message.MinecraftToDiscordChatModule; +import com.discordsrv.common.module.modules.integration.LuckPermsIntegration; import com.discordsrv.common.placeholder.ComponentResultStringifier; import com.discordsrv.common.placeholder.PlaceholderServiceImpl; import com.discordsrv.common.placeholder.context.GlobalTextHandlingContext; -import com.discordsrv.logging.adapter.DependencyLoggerAdapter; +import com.discordsrv.common.logging.adapter.DependencyLoggerAdapter; import net.dv8tion.jda.api.JDA; import org.jetbrains.annotations.NotNull; import javax.annotation.OverridingMethodsMustInvokeSuper; -import java.util.Arrays; import java.util.Locale; import java.util.Optional; import java.util.concurrent.CompletableFuture; @@ -167,12 +171,12 @@ public abstract class AbstractDiscordSRV T getModule(Class moduleType); - void registerModule(Module module); - void unregisterModule(Module module); + void registerModule(AbstractModule module); + void unregisterModule(AbstractModule module); Locale locale(); void setStatus(Status status); diff --git a/common/src/main/java/com/discordsrv/common/channel/ChannelConfigHelper.java b/common/src/main/java/com/discordsrv/common/channel/ChannelConfigHelper.java index 8367265f..ab6f2fe0 100644 --- a/common/src/main/java/com/discordsrv/common/channel/ChannelConfigHelper.java +++ b/common/src/main/java/com/discordsrv/common/channel/ChannelConfigHelper.java @@ -24,17 +24,16 @@ import com.discordsrv.api.event.bus.Subscribe; import com.discordsrv.api.event.events.channel.GameChannelLookupEvent; import com.discordsrv.api.event.events.lifecycle.DiscordSRVReloadEvent; import com.discordsrv.common.DiscordSRV; -import com.discordsrv.common.config.main.channels.BaseChannelConfig; -import com.discordsrv.common.config.main.channels.ChannelConfig; +import com.discordsrv.common.config.main.channels.base.BaseChannelConfig; +import com.discordsrv.common.config.main.channels.base.ChannelConfig; +import com.discordsrv.common.config.main.channels.base.IChannelConfig; import com.discordsrv.common.function.OrDefault; import com.github.benmanes.caffeine.cache.CacheLoader; import com.github.benmanes.caffeine.cache.LoadingCache; -import org.apache.commons.lang3.tuple.Pair; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; -import java.util.HashMap; -import java.util.Map; +import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.TimeUnit; @@ -42,7 +41,7 @@ public class ChannelConfigHelper { private final DiscordSRV discordSRV; private final LoadingCache nameToChannelCache; - private final Map> discordToConfigMap; + private final Map> discordToConfigMap; public ChannelConfigHelper(DiscordSRV discordSRV) { this.discordSRV = discordSRV; @@ -74,14 +73,15 @@ public class ChannelConfigHelper { return; } - Map> newMap = new HashMap<>(); + Map> newMap = new HashMap<>(); for (Map.Entry entry : channels().entrySet()) { String channelName = entry.getKey(); BaseChannelConfig value = entry.getValue(); - if (value instanceof ChannelConfig) { - ChannelConfig channelConfig = (ChannelConfig) value; - for (long channelId : channelConfig.channelIds) { - newMap.put(channelId, Pair.of(channelName, channelConfig)); + if (value instanceof IChannelConfig) { + IChannelConfig channelConfig = (IChannelConfig) value; + for (long channelId : channelConfig.ids()) { + newMap.computeIfAbsent(channelId, key -> new LinkedHashMap<>()) + .put(channelName, value); } } } @@ -96,22 +96,27 @@ public class ChannelConfigHelper { return discordSRV.config().channels; } + private BaseChannelConfig getDefault() { + return channels().computeIfAbsent(ChannelConfig.DEFAULT_KEY, key -> new BaseChannelConfig()); + } + + public Set> getAllChannels() { + BaseChannelConfig defaultConfig = getDefault(); + + Set> channelConfigs = new HashSet<>(); + for (Map.Entry entry : channels().entrySet()) { + if (entry.getKey().equals(ChannelConfig.DEFAULT_KEY)) { + continue; + } + channelConfigs.add(new OrDefault<>(entry.getValue(), defaultConfig)); + } + return channelConfigs; + } + public OrDefault orDefault(GameChannel gameChannel) { return orDefault(gameChannel.getOwnerName(), gameChannel.getChannelName()); } - public OrDefault> orDefault(DiscordTextChannel discordTextChannel) { - return new OrDefault<>( - getDiscordResolved(discordTextChannel), - Pair.of(null, getDefault()) - ); - } - - private BaseChannelConfig getDefault() { - return channels().computeIfAbsent( - "default", key -> new BaseChannelConfig()); - } - public OrDefault orDefault(String ownerName, String channelName) { BaseChannelConfig defaultConfig = getDefault(); @@ -144,21 +149,39 @@ public class ChannelConfigHelper { return gameChannel != null ? get(gameChannel) : null; } - public Pair getDiscordResolved(DiscordTextChannel channel) { - Pair pair = getDiscord(channel); - if (pair == null) { - return null; - } + public Map> orDefault(DiscordTextChannel discordTextChannel) { + BaseChannelConfig defaultConfig = getDefault(); - GameChannel gameChannel = nameToChannelCache.get(pair.getKey()); - if (gameChannel == null) { - return null; + Map> channels = new HashMap<>(); + for (Map.Entry entry : getDiscordResolved(discordTextChannel).entrySet()) { + channels.put( + entry.getKey(), + new OrDefault<>(entry.getValue(), defaultConfig) + ); } - - return Pair.of(gameChannel, pair.getValue()); + return channels; } - public Pair getDiscord(DiscordTextChannel channel) { + public Map getDiscordResolved(DiscordTextChannel channel) { + Map pairs = getDiscord(channel); + if (pairs == null) { + return Collections.emptyMap(); + } + + Map channels = new LinkedHashMap<>(); + for (Map.Entry entry : pairs.entrySet()) { + GameChannel gameChannel = nameToChannelCache.get(entry.getKey()); + if (gameChannel == null) { + continue; + } + + channels.put(gameChannel, entry.getValue()); + } + + return channels; + } + + public Map getDiscord(DiscordTextChannel channel) { synchronized (discordToConfigMap) { return discordToConfigMap.get(channel.getId()); } diff --git a/common/src/main/java/com/discordsrv/common/component/renderer/DiscordSRVMinecraftRenderer.java b/common/src/main/java/com/discordsrv/common/component/renderer/DiscordSRVMinecraftRenderer.java index 41ca24a3..470d9315 100644 --- a/common/src/main/java/com/discordsrv/common/component/renderer/DiscordSRVMinecraftRenderer.java +++ b/common/src/main/java/com/discordsrv/common/component/renderer/DiscordSRVMinecraftRenderer.java @@ -23,7 +23,7 @@ import com.discordsrv.api.discord.api.entity.DiscordUser; import com.discordsrv.api.discord.api.entity.guild.DiscordGuild; import com.discordsrv.api.discord.api.entity.guild.DiscordGuildMember; import com.discordsrv.api.discord.api.entity.guild.DiscordRole; -import com.discordsrv.api.event.events.message.receive.discord.DiscordMessageProcessingEvent; +import com.discordsrv.api.event.events.message.receive.discord.DiscordChatMessageProcessingEvent; import com.discordsrv.common.DiscordSRV; import com.discordsrv.common.component.util.ComponentUtil; import com.discordsrv.common.config.main.channels.DiscordToMinecraftChatConfig; @@ -47,7 +47,7 @@ public class DiscordSRVMinecraftRenderer extends DefaultMinecraftRenderer { } public static void runInContext( - DiscordMessageProcessingEvent event, + DiscordChatMessageProcessingEvent event, OrDefault config, Runnable runnable ) { @@ -58,7 +58,7 @@ public class DiscordSRVMinecraftRenderer extends DefaultMinecraftRenderer { } public static T getWithContext( - DiscordMessageProcessingEvent event, + DiscordChatMessageProcessingEvent event, OrDefault config, Supplier supplier ) { @@ -149,10 +149,10 @@ public class DiscordSRVMinecraftRenderer extends DefaultMinecraftRenderer { private static class Context { - private final DiscordMessageProcessingEvent event; + private final DiscordChatMessageProcessingEvent event; private final OrDefault config; - public Context(DiscordMessageProcessingEvent event, OrDefault config) { + public Context(DiscordChatMessageProcessingEvent event, OrDefault config) { this.event = event; this.config = config; } diff --git a/common/src/main/java/com/discordsrv/common/component/util/ComponentUtil.java b/common/src/main/java/com/discordsrv/common/component/util/ComponentUtil.java index a13049da..7c7909b2 100644 --- a/common/src/main/java/com/discordsrv/common/component/util/ComponentUtil.java +++ b/common/src/main/java/com/discordsrv/common/component/util/ComponentUtil.java @@ -22,9 +22,13 @@ import com.discordsrv.api.component.MinecraftComponent; import com.discordsrv.api.component.MinecraftComponentAdapter; import com.discordsrv.common.component.MinecraftComponentImpl; import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.ComponentLike; +import net.kyori.adventure.text.TextComponent; import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer; import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer; +import java.util.Collection; + /** * An util class for {@link Component}s and {@link MinecraftComponent}s. */ @@ -65,4 +69,19 @@ public final class ComponentUtil { .setComponent(unrelocatedAdventure); return fromAPI(component); } + + public static Component join(Component delimiter, Collection components) { + return join(delimiter, components.toArray(new ComponentLike[0])); + } + + public static Component join(Component delimiter, ComponentLike[] components) { + TextComponent.Builder builder = Component.text(); + for (int i = 0; i < components.length; i++) { + builder.append(components[i]); + if (i < components.length - 1) { + builder.append(delimiter); + } + } + return builder.build(); + } } diff --git a/common/src/main/java/com/discordsrv/common/config/annotation/Order.java b/common/src/main/java/com/discordsrv/common/config/annotation/Order.java new file mode 100644 index 00000000..2f5c84bd --- /dev/null +++ b/common/src/main/java/com/discordsrv/common/config/annotation/Order.java @@ -0,0 +1,35 @@ +/* + * This file is part of DiscordSRV, licensed under the GPLv3 License + * Copyright (c) 2016-2021 Austin "Scarsz" Shapiro, Henri "Vankka" Schubin and DiscordSRV contributors + * + * 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.discordsrv.common.config.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Manually determines the position of the option in the config, everything is ordered {@code 0} by default, + * and will go in the order they are defined. + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.FIELD) +public @interface Order { + + int value(); +} diff --git a/common/src/main/java/com/discordsrv/common/config/fielddiscoverer/OrderedFieldDiscovererProxy.java b/common/src/main/java/com/discordsrv/common/config/fielddiscoverer/OrderedFieldDiscovererProxy.java new file mode 100644 index 00000000..cc6e9b27 --- /dev/null +++ b/common/src/main/java/com/discordsrv/common/config/fielddiscoverer/OrderedFieldDiscovererProxy.java @@ -0,0 +1,92 @@ +/* + * This file is part of DiscordSRV, licensed under the GPLv3 License + * Copyright (c) 2016-2021 Austin "Scarsz" Shapiro, Henri "Vankka" Schubin and DiscordSRV contributors + * + * 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.discordsrv.common.config.fielddiscoverer; + +import org.checkerframework.checker.nullness.qual.Nullable; +import org.spongepowered.configurate.objectmapping.FieldData; +import org.spongepowered.configurate.objectmapping.FieldDiscoverer; +import org.spongepowered.configurate.serialize.SerializationException; +import org.spongepowered.configurate.util.CheckedFunction; + +import java.lang.reflect.AnnotatedElement; +import java.lang.reflect.AnnotatedType; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; + +public class OrderedFieldDiscovererProxy implements FieldDiscoverer { + + private final FieldDiscoverer fieldDiscoverer; + private final Comparator> order; + + public OrderedFieldDiscovererProxy(FieldDiscoverer fieldDiscoverer, Comparator> order) { + this.fieldDiscoverer = fieldDiscoverer; + this.order = order; + } + + @Override + public @Nullable InstanceFactory discover(AnnotatedType target, FieldCollector collector) throws SerializationException { + List> data = new ArrayList<>(); + FieldCollector fieldCollector = (name, type, annotations, deserializer, serializer) -> + data.add(new FieldCollectorData<>(name, type, annotations, deserializer, serializer)); + + InstanceFactory instanceFactory = fieldDiscoverer.discover(target, fieldCollector); + if (instanceFactory == null) { + return null; + } + + data.sort(order); + for (FieldCollectorData field : data) { + collector.accept(field.name, field.type, field.annotations, field.deserializer, field.serializer); + } + + return instanceFactory; + } + + public static class FieldCollectorData { + + private final String name; + private final AnnotatedType type; + private final AnnotatedElement annotations; + private final FieldData.Deserializer deserializer; + private final CheckedFunction serializer; + + public FieldCollectorData(String name, AnnotatedType type, AnnotatedElement annotations, + FieldData.Deserializer deserializer, + CheckedFunction serializer) { + this.name = name; + this.type = type; + this.annotations = annotations; + this.deserializer = deserializer; + this.serializer = serializer; + } + + public String name() { + return name; + } + + public AnnotatedType type() { + return type; + } + + public AnnotatedElement annotations() { + return annotations; + } + } +} diff --git a/common/src/main/java/com/discordsrv/common/config/main/MainConfig.java b/common/src/main/java/com/discordsrv/common/config/main/MainConfig.java index a38d59c4..8fbf9286 100644 --- a/common/src/main/java/com/discordsrv/common/config/main/MainConfig.java +++ b/common/src/main/java/com/discordsrv/common/config/main/MainConfig.java @@ -20,12 +20,11 @@ package com.discordsrv.common.config.main; import com.discordsrv.common.config.Config; import com.discordsrv.common.config.annotation.DefaultOnly; -import com.discordsrv.common.config.main.channels.BaseChannelConfig; -import com.discordsrv.common.config.main.channels.ChannelConfig; +import com.discordsrv.common.config.main.channels.base.BaseChannelConfig; +import com.discordsrv.common.config.main.channels.base.ChannelConfig; import org.spongepowered.configurate.objectmapping.ConfigSerializable; -import java.util.LinkedHashMap; -import java.util.Map; +import java.util.*; @ConfigSerializable public class MainConfig implements Config { @@ -40,6 +39,8 @@ public class MainConfig implements Config { @DefaultOnly("default") public Map channels = new LinkedHashMap() {{ put("global", new ChannelConfig()); - put("default", new BaseChannelConfig()); + put(ChannelConfig.DEFAULT_KEY, new BaseChannelConfig()); }}; + + public List channelUpdaters = new ArrayList<>(Collections.singletonList(new ChannelUpdaterConfig())); } diff --git a/common/src/main/java/com/discordsrv/common/config/main/channels/DiscordToMinecraftChatConfig.java b/common/src/main/java/com/discordsrv/common/config/main/channels/DiscordToMinecraftChatConfig.java index 72d254ae..eb944e2b 100644 --- a/common/src/main/java/com/discordsrv/common/config/main/channels/DiscordToMinecraftChatConfig.java +++ b/common/src/main/java/com/discordsrv/common/config/main/channels/DiscordToMinecraftChatConfig.java @@ -18,6 +18,7 @@ package com.discordsrv.common.config.main.channels; +import com.discordsrv.common.config.annotation.Untranslated; import org.spongepowered.configurate.objectmapping.ConfigSerializable; import org.spongepowered.configurate.objectmapping.meta.Comment; @@ -30,14 +31,24 @@ import java.util.regex.Pattern; @ConfigSerializable public class DiscordToMinecraftChatConfig { - @Comment("The Discord to Minecraft message format for regular users") - public String format = "[ᛩF2Discord&r] [hover:show_text:Tag: %user_tag%&r\nRoles: %user_roles_, |text_&7&oNone%]%user_color%%user_effective_name%&r » %message% %message_attachments%"; + @Comment("Is Discord to Minecraft chat forwarding enabled") + public boolean enabled = true; + + @Comment("The Discord to Minecraft message format for regular users and bots") + @Untranslated(Untranslated.Type.VALUE) + public String format = "[ᛩF2Discord&r] [hover:show_text:Tag: %user_tag%&r\nRoles: %user_roles_, |text_&7&oNone%]%user_color%%user_effective_name%&r » %message%%message_attachments%"; @Comment("The Discord to Minecraft message format for webhook messages (if enabled)") - public String webhookFormat = "[ᛩF2Discord&r] [hover:show_text:Webhook message]%user_name%&r » %message% %message_attachments%"; + @Untranslated(Untranslated.Type.VALUE) + public String webhookFormat = "[ᛩF2Discord&r] [hover:show_text:Webhook message]%user_name%&r » %message%%message_attachments_ %"; + + @Comment("Attachment format") + @Untranslated(Untranslated.Type.VALUE) + public String attachmentFormat = "[hover:show_text:Open %file_name% in browser][click:open_url:%file_url%]&a[&f%file_name%&a]&r"; // TODO: more info on regex pairs (String#replaceAll) @Comment("Regex filters for Discord message contents (this is the %message% part of the \"format\" option)") + @Untranslated(Untranslated.Type.VALUE) public Map contentRegexFilters = new LinkedHashMap<>(); @Comment("Users, bots and webhooks to ignore") @@ -56,7 +67,7 @@ public class DiscordToMinecraftChatConfig { public boolean bots = false; @Comment("If webhooks should be ignored") - public boolean webhooks = false; + public boolean webhooks = true; @ConfigSerializable public static class IDs { @@ -82,11 +93,14 @@ public class DiscordToMinecraftChatConfig { public static class Format { @Comment("The format shown in-game") + @Untranslated(Untranslated.Type.VALUE) public String format = ""; @Comment("The format when the entity is deleted or can't be looked up") + @Untranslated(Untranslated.Type.VALUE) public String unknownFormat = ""; + @SuppressWarnings("unused") // Configurate public Format() {} public Format(String format, String unknownFormat) { diff --git a/common/src/main/java/com/discordsrv/common/config/main/channels/JoinMessageConfig.java b/common/src/main/java/com/discordsrv/common/config/main/channels/JoinMessageConfig.java new file mode 100644 index 00000000..fef74e5c --- /dev/null +++ b/common/src/main/java/com/discordsrv/common/config/main/channels/JoinMessageConfig.java @@ -0,0 +1,39 @@ +/* + * This file is part of DiscordSRV, licensed under the GPLv3 License + * Copyright (c) 2016-2021 Austin "Scarsz" Shapiro, Henri "Vankka" Schubin and DiscordSRV contributors + * + * 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.discordsrv.common.config.main.channels; + +import com.discordsrv.api.discord.api.entity.message.DiscordMessageEmbed; +import com.discordsrv.api.discord.api.entity.message.SendableDiscordMessage; +import com.discordsrv.common.config.annotation.Untranslated; +import org.spongepowered.configurate.objectmapping.ConfigSerializable; + +@ConfigSerializable +public class JoinMessageConfig { + + public boolean enabled = true; + + @Untranslated(Untranslated.Type.VALUE) + public SendableDiscordMessage.Builder format = SendableDiscordMessage.builder() + .addEmbed( + DiscordMessageEmbed.builder() + .setAuthor("%player_display_name% joined", null, "%player_avatar_url%") + .setColor(0x55FF55) + .build() + ); +} diff --git a/common/src/main/java/com/discordsrv/common/config/main/channels/LeaveMessageConfig.java b/common/src/main/java/com/discordsrv/common/config/main/channels/LeaveMessageConfig.java new file mode 100644 index 00000000..f12169a2 --- /dev/null +++ b/common/src/main/java/com/discordsrv/common/config/main/channels/LeaveMessageConfig.java @@ -0,0 +1,39 @@ +/* + * This file is part of DiscordSRV, licensed under the GPLv3 License + * Copyright (c) 2016-2021 Austin "Scarsz" Shapiro, Henri "Vankka" Schubin and DiscordSRV contributors + * + * 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.discordsrv.common.config.main.channels; + +import com.discordsrv.api.discord.api.entity.message.DiscordMessageEmbed; +import com.discordsrv.api.discord.api.entity.message.SendableDiscordMessage; +import com.discordsrv.common.config.annotation.Untranslated; +import org.spongepowered.configurate.objectmapping.ConfigSerializable; + +@ConfigSerializable +public class LeaveMessageConfig { + + public boolean enabled = true; + + @Untranslated(Untranslated.Type.VALUE) + public SendableDiscordMessage.Builder format = SendableDiscordMessage.builder() + .addEmbed( + DiscordMessageEmbed.builder() + .setAuthor("%player_display_name% left", null, "%player_avatar_url%") + .setColor(0xFF5555) + .build() + ); +} diff --git a/common/src/main/java/com/discordsrv/common/config/main/channels/MinecraftToDiscordChatConfig.java b/common/src/main/java/com/discordsrv/common/config/main/channels/MinecraftToDiscordChatConfig.java index a72c515b..a9cb4653 100644 --- a/common/src/main/java/com/discordsrv/common/config/main/channels/MinecraftToDiscordChatConfig.java +++ b/common/src/main/java/com/discordsrv/common/config/main/channels/MinecraftToDiscordChatConfig.java @@ -19,6 +19,7 @@ package com.discordsrv.common.config.main.channels; import com.discordsrv.api.discord.api.entity.message.SendableDiscordMessage; +import com.discordsrv.common.config.annotation.Untranslated; import org.spongepowered.configurate.objectmapping.ConfigSerializable; import org.spongepowered.configurate.objectmapping.meta.Comment; @@ -29,10 +30,14 @@ import java.util.regex.Pattern; @ConfigSerializable public class MinecraftToDiscordChatConfig { + @Comment("Is Minecraft to Discord chat forwarding enabled") + public boolean enabled = true; + + @Untranslated(Untranslated.Type.VALUE) public SendableDiscordMessage.Builder format = SendableDiscordMessage.builder() .setWebhookUsername("%player_display_name%") .setWebhookAvatarUrl("%player_avatar_url%") - .setContent("%message%");// TODO + .setContent("%message%"); // TODO: more info on regex pairs (String#replaceAll) @Comment("Regex filters for Minecraft message contents (this is the %message% part of the \"format\" option)") diff --git a/common/src/main/java/com/discordsrv/common/config/main/channels/base/BaseChannelConfig.java b/common/src/main/java/com/discordsrv/common/config/main/channels/base/BaseChannelConfig.java new file mode 100644 index 00000000..9b3cefec --- /dev/null +++ b/common/src/main/java/com/discordsrv/common/config/main/channels/base/BaseChannelConfig.java @@ -0,0 +1,40 @@ +/* + * This file is part of DiscordSRV, licensed under the GPLv3 License + * Copyright (c) 2016-2021 Austin "Scarsz" Shapiro, Henri "Vankka" Schubin and DiscordSRV contributors + * + * 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.discordsrv.common.config.main.channels.base; + +import com.discordsrv.common.config.annotation.Order; +import com.discordsrv.common.config.annotation.Untranslated; +import com.discordsrv.common.config.main.channels.DiscordToMinecraftChatConfig; +import com.discordsrv.common.config.main.channels.JoinMessageConfig; +import com.discordsrv.common.config.main.channels.LeaveMessageConfig; +import com.discordsrv.common.config.main.channels.MinecraftToDiscordChatConfig; +import org.spongepowered.configurate.objectmapping.ConfigSerializable; + +@ConfigSerializable +public class BaseChannelConfig { + + public MinecraftToDiscordChatConfig minecraftToDiscord = new MinecraftToDiscordChatConfig(); + public DiscordToMinecraftChatConfig discordToMinecraft = new DiscordToMinecraftChatConfig(); + public JoinMessageConfig joinMessages = new JoinMessageConfig(); + public LeaveMessageConfig leaveMessages = new LeaveMessageConfig(); + + @Untranslated(Untranslated.Type.VALUE) + @Order(5) + public String avatarUrlProvider = "https://heads.discordsrv.com/head.png?texture=%texture%&uuid=%uuid%&name=%username%&overlay"; +} diff --git a/common/src/main/java/com/discordsrv/common/config/main/channels/BaseChannelConfig.java b/common/src/main/java/com/discordsrv/common/config/main/channels/base/ChannelConfig.java similarity index 72% rename from common/src/main/java/com/discordsrv/common/config/main/channels/BaseChannelConfig.java rename to common/src/main/java/com/discordsrv/common/config/main/channels/base/ChannelConfig.java index e4256b02..48904840 100644 --- a/common/src/main/java/com/discordsrv/common/config/main/channels/BaseChannelConfig.java +++ b/common/src/main/java/com/discordsrv/common/config/main/channels/base/ChannelConfig.java @@ -16,38 +16,52 @@ * along with this program. If not, see . */ -package com.discordsrv.common.config.main.channels; +package com.discordsrv.common.config.main.channels.base; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.configurate.ConfigurationNode; import org.spongepowered.configurate.objectmapping.ConfigSerializable; import org.spongepowered.configurate.objectmapping.ObjectMapper; +import org.spongepowered.configurate.objectmapping.meta.Comment; import org.spongepowered.configurate.serialize.SerializationException; import org.spongepowered.configurate.serialize.TypeSerializer; import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.List; @ConfigSerializable -public class BaseChannelConfig { +public class ChannelConfig extends BaseChannelConfig implements IChannelConfig { - public MinecraftToDiscordChatConfig minecraftToDiscord = new MinecraftToDiscordChatConfig(); - public DiscordToMinecraftChatConfig discordToMinecraft = new DiscordToMinecraftChatConfig(); + public ChannelConfig() { + initialize(); + } - public String avatarUrlProvider = "https://heads.discordsrv.com/head.png?texture=%texture%&uuid=%uuid%&name=%username%&overlay"; + @Comment(CHANNEL_IDS_COMMENT) + public List channelIds = new ArrayList<>(); + + @Override + public List ids() { + return channelIds; + } public static class Serializer implements TypeSerializer { private final ObjectMapper.Factory mapperFactory; + private final Class baseConfigClass; + private final Class configClass; - public Serializer(ObjectMapper.Factory mapperFactory) { + public Serializer(ObjectMapper.Factory mapperFactory, Class baseConfigClass, Class configClass) { this.mapperFactory = mapperFactory; + this.baseConfigClass = baseConfigClass; + this.configClass = configClass; } @Override public BaseChannelConfig deserialize(Type type, ConfigurationNode node) throws SerializationException { return (BaseChannelConfig) mapperFactory.asTypeSerializer() .deserialize( - ChannelConfig.DEFAULT_KEY.equals(node.key()) ? BaseChannelConfig.class : ChannelConfig.class, + ChannelConfig.DEFAULT_KEY.equals(node.key()) ? baseConfigClass : configClass, node ); } @@ -60,7 +74,7 @@ public class BaseChannelConfig { } mapperFactory.asTypeSerializer().serialize( - ChannelConfig.DEFAULT_KEY.equals(node.key()) ? BaseChannelConfig.class : ChannelConfig.class, + ChannelConfig.DEFAULT_KEY.equals(node.key()) ? baseConfigClass : configClass, obj, node ); diff --git a/common/src/main/java/com/discordsrv/common/config/main/channels/base/IChannelConfig.java b/common/src/main/java/com/discordsrv/common/config/main/channels/base/IChannelConfig.java new file mode 100644 index 00000000..192e5b67 --- /dev/null +++ b/common/src/main/java/com/discordsrv/common/config/main/channels/base/IChannelConfig.java @@ -0,0 +1,52 @@ +/* + * This file is part of DiscordSRV, licensed under the GPLv3 License + * Copyright (c) 2016-2021 Austin "Scarsz" Shapiro, Henri "Vankka" Schubin and DiscordSRV contributors + * + * 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.discordsrv.common.config.main.channels.base; + +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.util.List; + +public interface IChannelConfig { + + String DEFAULT_KEY = "default"; + String CHANNEL_IDS_COMMENT = "The channels this in-game channel will forward to in Discord"; + + default void initialize() { + // Clear everything besides channelIds by default (these will be filled back in by Configurate if they are in the config itself) + Class clazz = getClass(); + while (clazz != null) { + for (Field field : clazz.getFields()) { + int modifiers = field.getModifiers(); + if (!Modifier.isPublic(modifiers) || Modifier.isFinal(modifiers) || Modifier.isStatic(modifiers)) { + continue; + } + if (field.getName().equals("channelIds")) { + continue; + } + + try { + field.set(this, null); + } catch (IllegalAccessException ignored) {} + } + clazz = clazz.getSuperclass(); + } + } + + List ids(); +} diff --git a/common/src/main/java/com/discordsrv/common/config/manager/loader/YamlConfigLoaderProvider.java b/common/src/main/java/com/discordsrv/common/config/manager/loader/YamlConfigLoaderProvider.java index b00e2021..b01d39f9 100644 --- a/common/src/main/java/com/discordsrv/common/config/manager/loader/YamlConfigLoaderProvider.java +++ b/common/src/main/java/com/discordsrv/common/config/manager/loader/YamlConfigLoaderProvider.java @@ -19,17 +19,12 @@ package com.discordsrv.common.config.manager.loader; import org.jetbrains.annotations.ApiStatus; -import org.spongepowered.configurate.ConfigurationOptions; import org.spongepowered.configurate.loader.AbstractConfigurationLoader; import org.spongepowered.configurate.yaml.NodeStyle; import org.spongepowered.configurate.yaml.YamlConfigurationLoader; public interface YamlConfigLoaderProvider extends ConfigLoaderProvider { - default ConfigurationOptions defaultOptions() { - return ConfigurationOptions.defaults(); - } - default NodeStyle nodeStyle() { return NodeStyle.BLOCK; } diff --git a/common/src/main/java/com/discordsrv/common/config/manager/manager/ConfigurateConfigManager.java b/common/src/main/java/com/discordsrv/common/config/manager/manager/ConfigurateConfigManager.java index 26a024e0..9298f4ae 100644 --- a/common/src/main/java/com/discordsrv/common/config/manager/manager/ConfigurateConfigManager.java +++ b/common/src/main/java/com/discordsrv/common/config/manager/manager/ConfigurateConfigManager.java @@ -23,7 +23,10 @@ import com.discordsrv.api.discord.api.entity.message.DiscordMessageEmbed; import com.discordsrv.api.discord.api.entity.message.SendableDiscordMessage; import com.discordsrv.common.DiscordSRV; import com.discordsrv.common.config.annotation.DefaultOnly; -import com.discordsrv.common.config.main.channels.BaseChannelConfig; +import com.discordsrv.common.config.annotation.Order; +import com.discordsrv.common.config.fielddiscoverer.OrderedFieldDiscovererProxy; +import com.discordsrv.common.config.main.channels.base.BaseChannelConfig; +import com.discordsrv.common.config.main.channels.base.ChannelConfig; import com.discordsrv.common.config.manager.loader.ConfigLoaderProvider; import com.discordsrv.common.config.serializer.ColorSerializer; import com.discordsrv.common.config.serializer.DiscordMessageEmbedSerializer; @@ -37,6 +40,7 @@ import org.spongepowered.configurate.ConfigurationNode; import org.spongepowered.configurate.ConfigurationOptions; import org.spongepowered.configurate.loader.AbstractConfigurationLoader; import org.spongepowered.configurate.objectmapping.ConfigSerializable; +import org.spongepowered.configurate.objectmapping.FieldDiscoverer; import org.spongepowered.configurate.objectmapping.ObjectMapper; import org.spongepowered.configurate.serialize.SerializationException; import org.spongepowered.configurate.util.NamingScheme; @@ -44,6 +48,7 @@ import org.spongepowered.configurate.util.NamingSchemes; import java.nio.file.Path; import java.util.Arrays; +import java.util.Comparator; import java.util.List; import java.util.Map; import java.util.regex.Pattern; @@ -88,18 +93,30 @@ public abstract class ConfigurateConfigManager { ObjectMapper.Factory objectMapper = configObjectMapper(); + builder.register(BaseChannelConfig.class, getChannelConfigSerializer(objectMapper)); builder.register(Color.class, new ColorSerializer()); builder.register(Pattern.class, new PatternSerializer()); - builder.register(BaseChannelConfig.class, new BaseChannelConfig.Serializer(objectMapper)); builder.register(DiscordMessageEmbed.Builder.class, new DiscordMessageEmbedSerializer(NAMING_SCHEME)); builder.register(DiscordMessageEmbed.Field.class, new DiscordMessageEmbedSerializer.FieldSerializer(NAMING_SCHEME)); builder.register(SendableDiscordMessage.Builder.class, new SendableDiscordMessageSerializer(NAMING_SCHEME)); + + // give Configurate' serializers the ObjectMapper mapper + builder.register(type -> { + String typeName = type.getTypeName(); + return typeName.startsWith("com.discordsrv") + && !typeName.startsWith("com.discordsrv.dependencies") + && !typeName.contains(".serializer"); + }, objectMapper.asTypeSerializer()); }); } @@ -111,12 +128,20 @@ public abstract class ConfigurateConfigManager> fieldOrder = Comparator.comparingInt(data -> { + Order order = data.annotations().getAnnotation(Order.class); + return order != null ? order.value() : 0; + }); + return ObjectMapper.factoryBuilder() - .defaultNamingScheme(NAMING_SCHEME); + .defaultNamingScheme(NAMING_SCHEME) + .addDiscoverer(new OrderedFieldDiscovererProxy<>((FieldDiscoverer) FieldDiscoverer.emptyConstructorObject(), fieldOrder)) + .addDiscoverer(new OrderedFieldDiscovererProxy<>((FieldDiscoverer) FieldDiscoverer.record(), fieldOrder)); } - protected ObjectMapper.Factory.Builder configObjectMapperBuilder() { + public ObjectMapper.Factory.Builder configObjectMapperBuilder() { return objectMapperBuilder(); } @@ -164,9 +189,13 @@ public abstract class ConfigurateConfigManager) defaultConfig.getClass()).save(defaultConfig, node); return node; } @@ -175,6 +204,10 @@ public abstract class ConfigurateConfigManager> extends ConfigurateConfigManager { @@ -64,17 +67,18 @@ public abstract class TranslatedConfigManager) config.getClass(), node); - //node.set(config); - translateNode(node, translation, translation.node("_comments")); + translateNode(node, translation, comments); } catch (ConfigurateException e) { throw new ConfigException(e); } @@ -96,13 +100,14 @@ public abstract class TranslatedConfigManager path = new ArrayList<>(Arrays.asList(node.path().array())); String translation = translations.node(path).getString(); if (translation != null) { node.set(translation); } + path.add("_comment"); String commentTranslation = commentTranslations.node(path).getString(); if (commentTranslation != null) { node.comment(commentTranslation); diff --git a/common/src/main/java/com/discordsrv/common/config/serializer/ColorSerializer.java b/common/src/main/java/com/discordsrv/common/config/serializer/ColorSerializer.java index dfe09e99..d94f8356 100644 --- a/common/src/main/java/com/discordsrv/common/config/serializer/ColorSerializer.java +++ b/common/src/main/java/com/discordsrv/common/config/serializer/ColorSerializer.java @@ -54,6 +54,6 @@ public class ColorSerializer implements TypeSerializer { if (obj == null) { return; } - node.set(obj.hex()); + node.set("#" + obj.hex()); } } diff --git a/common/src/main/java/com/discordsrv/common/config/serializer/DiscordMessageEmbedSerializer.java b/common/src/main/java/com/discordsrv/common/config/serializer/DiscordMessageEmbedSerializer.java index 46d08067..5561c1d4 100644 --- a/common/src/main/java/com/discordsrv/common/config/serializer/DiscordMessageEmbedSerializer.java +++ b/common/src/main/java/com/discordsrv/common/config/serializer/DiscordMessageEmbedSerializer.java @@ -29,6 +29,7 @@ import org.spongepowered.configurate.util.NamingScheme; import java.lang.reflect.Type; import java.util.Collections; +import java.util.List; public class DiscordMessageEmbedSerializer implements TypeSerializer { @@ -53,7 +54,7 @@ public class DiscordMessageEmbedSerializer implements TypeSerializer fields = obj.getFields(); + ConfigurationNode fieldsNode = node.node(map("Fields")); + fieldsNode.setList(DiscordMessageEmbed.Field.class, fields.isEmpty() ? null : obj.getFields()); node.node(map("ThumbnailUrl")).set(obj.getThumbnailUrl()); node.node(map("ImageUrl")).set(obj.getImageUrl()); diff --git a/common/src/main/java/com/discordsrv/common/console/Console.java b/common/src/main/java/com/discordsrv/common/console/Console.java index 54b4720f..7115f430 100644 --- a/common/src/main/java/com/discordsrv/common/console/Console.java +++ b/common/src/main/java/com/discordsrv/common/console/Console.java @@ -19,7 +19,7 @@ package com.discordsrv.common.console; import com.discordsrv.common.command.game.sender.ICommandSender; -import com.discordsrv.logging.backend.LoggingBackend; +import com.discordsrv.common.logging.backend.LoggingBackend; public interface Console extends ICommandSender { diff --git a/common/src/main/java/com/discordsrv/common/dependency/InitialDependencyLoader.java b/common/src/main/java/com/discordsrv/common/dependency/InitialDependencyLoader.java index f803a957..382d5e78 100644 --- a/common/src/main/java/com/discordsrv/common/dependency/InitialDependencyLoader.java +++ b/common/src/main/java/com/discordsrv/common/dependency/InitialDependencyLoader.java @@ -18,7 +18,7 @@ package com.discordsrv.common.dependency; -import com.discordsrv.logging.Logger; +import com.discordsrv.common.logging.Logger; import com.discordsrv.common.scheduler.threadfactory.CountingForkJoinWorkerThreadFactory; import dev.vankka.dependencydownload.classpath.ClasspathAppender; diff --git a/common/src/main/java/com/discordsrv/common/discord/api/DiscordAPIImpl.java b/common/src/main/java/com/discordsrv/common/discord/api/DiscordAPIImpl.java index 2f180de1..a231e967 100644 --- a/common/src/main/java/com/discordsrv/common/discord/api/DiscordAPIImpl.java +++ b/common/src/main/java/com/discordsrv/common/discord/api/DiscordAPIImpl.java @@ -30,8 +30,8 @@ import com.discordsrv.api.discord.api.entity.guild.DiscordRole; import com.discordsrv.api.discord.api.exception.NotReadyException; import com.discordsrv.api.discord.api.exception.RestErrorResponseException; import com.discordsrv.common.DiscordSRV; -import com.discordsrv.common.config.main.channels.BaseChannelConfig; -import com.discordsrv.common.config.main.channels.ChannelConfig; +import com.discordsrv.common.config.main.channels.base.BaseChannelConfig; +import com.discordsrv.common.config.main.channels.base.IChannelConfig; import com.discordsrv.common.discord.api.channel.DiscordDMChannelImpl; import com.discordsrv.common.discord.api.channel.DiscordTextChannelImpl; import com.discordsrv.common.discord.api.guild.DiscordGuildImpl; @@ -208,7 +208,7 @@ public class DiscordAPIImpl implements DiscordAPI { }).thenApply(webhook -> WebhookClientBuilder.fromJDA(webhook) .setHttpClient(jda.getHttpClient()) - .setExecutorService(discordSRV.scheduler().executor()) + .setExecutorService(discordSRV.scheduler().scheduledExecutor()) .build() ); } @@ -218,8 +218,8 @@ public class DiscordAPIImpl implements DiscordAPI { private boolean isConfiguredChannel(Long channelId) { for (BaseChannelConfig config : discordSRV.config().channels.values()) { - if (config instanceof ChannelConfig - && ((ChannelConfig) config).channelIds.contains(channelId)) { + if (config instanceof IChannelConfig + && ((IChannelConfig) config).ids().contains(channelId)) { return true; } } diff --git a/common/src/main/java/com/discordsrv/common/discord/api/guild/DiscordGuildMemberImpl.java b/common/src/main/java/com/discordsrv/common/discord/api/guild/DiscordGuildMemberImpl.java index e84679dd..0e138223 100644 --- a/common/src/main/java/com/discordsrv/common/discord/api/guild/DiscordGuildMemberImpl.java +++ b/common/src/main/java/com/discordsrv/common/discord/api/guild/DiscordGuildMemberImpl.java @@ -25,12 +25,12 @@ import com.discordsrv.api.discord.api.entity.guild.DiscordRole; import com.discordsrv.api.placeholder.annotation.Placeholder; import com.discordsrv.api.placeholder.annotation.PlaceholderRemainder; import com.discordsrv.common.DiscordSRV; +import com.discordsrv.common.component.util.ComponentUtil; import com.discordsrv.common.discord.api.DiscordUserImpl; import net.dv8tion.jda.api.entities.Member; import net.dv8tion.jda.api.entities.Role; import net.dv8tion.jda.api.entities.User; import net.kyori.adventure.text.Component; -import net.kyori.adventure.text.TextComponent; import net.kyori.adventure.text.format.TextColor; import org.jetbrains.annotations.NotNull; @@ -107,20 +107,19 @@ public class DiscordGuildMemberImpl extends DiscordUserImpl implements DiscordGu return null; } - @Placeholder("user_roles_") + @Placeholder("user_roles") public Component _allRoles(@PlaceholderRemainder String suffix) { + if (suffix.startsWith("_")) { + suffix = suffix.substring(1); + } else if (!suffix.isEmpty()) { + return null; + } + List components = new ArrayList<>(); for (DiscordRole role : getRoles()) { components.add(Component.text(role.getName()).color(TextColor.color(role.getColor().rgb()))); } - TextComponent.Builder builder = Component.text(); - for (int i = 0; i < components.size(); i++) { - builder.append(components.get(i)); - if (i < components.size() - 1) { - builder.append(Component.text(suffix)); - } - } - return builder.build(); + return ComponentUtil.join(Component.text(suffix), components); } } diff --git a/common/src/main/java/com/discordsrv/common/discord/api/message/ReceivedDiscordMessageImpl.java b/common/src/main/java/com/discordsrv/common/discord/api/message/ReceivedDiscordMessageImpl.java index 157ee6a1..b19ee73d 100644 --- a/common/src/main/java/com/discordsrv/common/discord/api/message/ReceivedDiscordMessageImpl.java +++ b/common/src/main/java/com/discordsrv/common/discord/api/message/ReceivedDiscordMessageImpl.java @@ -36,18 +36,20 @@ import com.discordsrv.api.discord.api.entity.message.SendableDiscordMessage; import com.discordsrv.api.discord.api.entity.message.impl.SendableDiscordMessageImpl; import com.discordsrv.api.discord.api.exception.RestErrorResponseException; import com.discordsrv.api.placeholder.annotation.Placeholder; +import com.discordsrv.api.placeholder.annotation.PlaceholderRemainder; import com.discordsrv.common.DiscordSRV; +import com.discordsrv.common.component.util.ComponentUtil; +import com.discordsrv.common.config.main.channels.base.BaseChannelConfig; import com.discordsrv.common.discord.api.DiscordUserImpl; import com.discordsrv.common.discord.api.channel.DiscordMessageChannelImpl; import com.discordsrv.common.discord.api.guild.DiscordGuildMemberImpl; +import com.discordsrv.common.function.OrDefault; import net.dv8tion.jda.api.entities.Member; import net.dv8tion.jda.api.entities.Message; import net.dv8tion.jda.api.entities.MessageEmbed; import net.dv8tion.jda.api.entities.User; import net.dv8tion.jda.api.requests.ErrorResponse; import net.kyori.adventure.text.Component; -import net.kyori.adventure.text.TextComponent; -import net.kyori.adventure.text.event.ClickEvent; import org.jetbrains.annotations.NotNull; import java.util.ArrayList; @@ -287,18 +289,24 @@ public class ReceivedDiscordMessageImpl extends SendableDiscordMessageImpl imple // @Placeholder("message_attachments") - public Component _attachments() { - // TODO: customizable - - TextComponent.Builder builder = Component.text(); - for (Attachment attachment : attachments) { - builder.append( - Component.text() - .content("[" + attachment.fileName() + "]") - .clickEvent(ClickEvent.openUrl(attachment.url())) - ) - .append(Component.text(" ")); + public Component _attachments(OrDefault config, @PlaceholderRemainder String suffix) { + if (suffix.startsWith("_")) { + suffix = suffix.substring(1); + } else if (!suffix.isEmpty()) { + return null; } - return builder.build(); + + String attachmentFormat = config.map(cfg -> cfg.discordToMinecraft).get(cfg -> cfg.attachmentFormat); + List components = new ArrayList<>(); + for (Attachment attachment : attachments) { + components.add(ComponentUtil.fromAPI( + discordSRV.componentFactory().enhancedBuilder(attachmentFormat) + .addReplacement("%file_name%", attachment.fileName()) + .addReplacement("%file_url%", attachment.url()) + .build() + )); + } + + return ComponentUtil.join(Component.text(suffix), components); } } diff --git a/common/api/src/main/java/com/discordsrv/logging/Logger.java b/common/src/main/java/com/discordsrv/common/logging/Logger.java similarity index 98% rename from common/api/src/main/java/com/discordsrv/logging/Logger.java rename to common/src/main/java/com/discordsrv/common/logging/Logger.java index eb924e35..aad54594 100644 --- a/common/api/src/main/java/com/discordsrv/logging/Logger.java +++ b/common/src/main/java/com/discordsrv/common/logging/Logger.java @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.discordsrv.logging; +package com.discordsrv.common.logging; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; diff --git a/common/api/src/main/java/com/discordsrv/logging/backend/LogFilter.java b/common/src/main/java/com/discordsrv/common/logging/backend/LogFilter.java similarity index 92% rename from common/api/src/main/java/com/discordsrv/logging/backend/LogFilter.java rename to common/src/main/java/com/discordsrv/common/logging/backend/LogFilter.java index fa9a638b..ef2d94c8 100644 --- a/common/api/src/main/java/com/discordsrv/logging/backend/LogFilter.java +++ b/common/src/main/java/com/discordsrv/common/logging/backend/LogFilter.java @@ -16,9 +16,9 @@ * along with this program. If not, see . */ -package com.discordsrv.logging.backend; +package com.discordsrv.common.logging.backend; -import com.discordsrv.logging.LogLevel; +import com.discordsrv.common.logging.LogLevel; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; diff --git a/common/api/src/main/java/com/discordsrv/logging/backend/LoggingBackend.java b/common/src/main/java/com/discordsrv/common/logging/backend/LoggingBackend.java similarity index 91% rename from common/api/src/main/java/com/discordsrv/logging/backend/LoggingBackend.java rename to common/src/main/java/com/discordsrv/common/logging/backend/LoggingBackend.java index 04fc2a9e..ea615671 100644 --- a/common/api/src/main/java/com/discordsrv/logging/backend/LoggingBackend.java +++ b/common/src/main/java/com/discordsrv/common/logging/backend/LoggingBackend.java @@ -16,7 +16,9 @@ * along with this program. If not, see . */ -package com.discordsrv.logging.backend; +package com.discordsrv.common.logging.backend; + +import com.discordsrv.common.logging.LogAppender; public interface LoggingBackend { diff --git a/common/src/main/java/com/discordsrv/common/logging/DependencyLoggingHandler.java b/common/src/main/java/com/discordsrv/common/logging/dependency/DependencyLoggingHandler.java similarity index 93% rename from common/src/main/java/com/discordsrv/common/logging/DependencyLoggingHandler.java rename to common/src/main/java/com/discordsrv/common/logging/dependency/DependencyLoggingHandler.java index b9fd1359..9c5eca45 100644 --- a/common/src/main/java/com/discordsrv/common/logging/DependencyLoggingHandler.java +++ b/common/src/main/java/com/discordsrv/common/logging/dependency/DependencyLoggingHandler.java @@ -16,11 +16,11 @@ * along with this program. If not, see . */ -package com.discordsrv.common.logging; +package com.discordsrv.common.logging.dependency; import com.discordsrv.common.DiscordSRV; -import com.discordsrv.logging.LogLevel; -import com.discordsrv.logging.backend.LogAppender; +import com.discordsrv.common.logging.LogLevel; +import com.discordsrv.common.logging.LogAppender; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -53,8 +53,8 @@ public class DependencyLoggingHandler implements LogAppender { @Override public void append(@Nullable String loggerName, @NotNull LogLevel logLevel, @Nullable String message, @Nullable Throwable throwable) { - if (loggerName == null || !loggerName.startsWith("com.discordsrv.dependencies")) { - return; + if (loggerName == null) { + loggerName = "null"; } if (message != null) { diff --git a/common/api/src/main/java/com/discordsrv/logging/impl/JavaLoggerImpl.java b/common/src/main/java/com/discordsrv/common/logging/impl/JavaLoggerImpl.java similarity index 94% rename from common/api/src/main/java/com/discordsrv/logging/impl/JavaLoggerImpl.java rename to common/src/main/java/com/discordsrv/common/logging/impl/JavaLoggerImpl.java index fcd718fe..1a633ed3 100644 --- a/common/api/src/main/java/com/discordsrv/logging/impl/JavaLoggerImpl.java +++ b/common/src/main/java/com/discordsrv/common/logging/impl/JavaLoggerImpl.java @@ -16,13 +16,13 @@ * along with this program. If not, see . */ -package com.discordsrv.logging.impl; +package com.discordsrv.common.logging.impl; -import com.discordsrv.logging.LogLevel; -import com.discordsrv.logging.Logger; -import com.discordsrv.logging.backend.LogAppender; -import com.discordsrv.logging.backend.LogFilter; -import com.discordsrv.logging.backend.LoggingBackend; +import com.discordsrv.common.logging.LogLevel; +import com.discordsrv.common.logging.Logger; +import com.discordsrv.common.logging.LogAppender; +import com.discordsrv.common.logging.backend.LogFilter; +import com.discordsrv.common.logging.backend.LoggingBackend; import org.apache.commons.collections4.bidimap.DualHashBidiMap; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; diff --git a/common/api/src/main/java/com/discordsrv/logging/impl/Log4JLoggerImpl.java b/common/src/main/java/com/discordsrv/common/logging/impl/Log4JLoggerImpl.java similarity index 96% rename from common/api/src/main/java/com/discordsrv/logging/impl/Log4JLoggerImpl.java rename to common/src/main/java/com/discordsrv/common/logging/impl/Log4JLoggerImpl.java index ca23a6da..2ea28447 100644 --- a/common/api/src/main/java/com/discordsrv/logging/impl/Log4JLoggerImpl.java +++ b/common/src/main/java/com/discordsrv/common/logging/impl/Log4JLoggerImpl.java @@ -16,13 +16,13 @@ * along with this program. If not, see . */ -package com.discordsrv.logging.impl; +package com.discordsrv.common.logging.impl; -import com.discordsrv.logging.LogLevel; -import com.discordsrv.logging.backend.LogAppender; -import com.discordsrv.logging.backend.LogFilter; -import com.discordsrv.logging.backend.LoggingBackend; -import com.discordsrv.logging.Logger; +import com.discordsrv.common.logging.LogLevel; +import com.discordsrv.common.logging.LogAppender; +import com.discordsrv.common.logging.backend.LogFilter; +import com.discordsrv.common.logging.backend.LoggingBackend; +import com.discordsrv.common.logging.Logger; import org.apache.commons.collections4.bidimap.DualHashBidiMap; import org.apache.logging.log4j.Level; import org.apache.logging.log4j.LogManager; diff --git a/common/api/src/main/java/com/discordsrv/logging/impl/SLF4JLoggerImpl.java b/common/src/main/java/com/discordsrv/common/logging/impl/SLF4JLoggerImpl.java similarity index 88% rename from common/api/src/main/java/com/discordsrv/logging/impl/SLF4JLoggerImpl.java rename to common/src/main/java/com/discordsrv/common/logging/impl/SLF4JLoggerImpl.java index bac0445e..9c11dcbc 100644 --- a/common/api/src/main/java/com/discordsrv/logging/impl/SLF4JLoggerImpl.java +++ b/common/src/main/java/com/discordsrv/common/logging/impl/SLF4JLoggerImpl.java @@ -16,18 +16,18 @@ * along with this program. If not, see . */ -package com.discordsrv.logging.impl; +package com.discordsrv.common.logging.impl; -import com.discordsrv.logging.LogLevel; -import com.discordsrv.logging.Logger; +import com.discordsrv.common.logging.LogLevel; +import com.discordsrv.common.logging.Logger; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; public class SLF4JLoggerImpl implements Logger { - private final org.slf4j.Logger logger; + private final com.discordsrv.x.slf4j.Logger logger; - public SLF4JLoggerImpl(org.slf4j.Logger logger) { + public SLF4JLoggerImpl(com.discordsrv.x.slf4j.Logger logger) { this.logger = logger; } diff --git a/common/proxy/src/main/java/com/discordsrv/common/proxy/ProxyDiscordSRV.java b/common/src/main/java/com/discordsrv/common/module/ModuleInitializationFunction.java similarity index 71% rename from common/proxy/src/main/java/com/discordsrv/common/proxy/ProxyDiscordSRV.java rename to common/src/main/java/com/discordsrv/common/module/ModuleInitializationFunction.java index b874d88c..f51b64e1 100644 --- a/common/proxy/src/main/java/com/discordsrv/common/proxy/ProxyDiscordSRV.java +++ b/common/src/main/java/com/discordsrv/common/module/ModuleInitializationFunction.java @@ -16,12 +16,14 @@ * along with this program. If not, see . */ -package com.discordsrv.common.proxy; +package com.discordsrv.common.module; -import com.discordsrv.common.AbstractDiscordSRV; -import com.discordsrv.common.config.connection.ConnectionConfig; -import com.discordsrv.common.config.main.MainConfig; +import com.discordsrv.common.DiscordSRV; +import com.discordsrv.common.module.type.AbstractModule; -public abstract class ProxyDiscordSRV extends AbstractDiscordSRV { +@FunctionalInterface +public interface ModuleInitializationFunction { + + AbstractModule initialize(DiscordSRV discordSRV) throws Throwable; } diff --git a/common/src/main/java/com/discordsrv/common/module/ModuleManager.java b/common/src/main/java/com/discordsrv/common/module/ModuleManager.java index 4257866b..b29dcb3e 100644 --- a/common/src/main/java/com/discordsrv/common/module/ModuleManager.java +++ b/common/src/main/java/com/discordsrv/common/module/ModuleManager.java @@ -23,6 +23,8 @@ import com.discordsrv.api.event.bus.Subscribe; import com.discordsrv.api.event.events.lifecycle.DiscordSRVReloadEvent; import com.discordsrv.api.event.events.lifecycle.DiscordSRVShuttingDownEvent; import com.discordsrv.common.DiscordSRV; +import com.discordsrv.common.module.type.AbstractModule; +import com.discordsrv.common.module.type.Module; import java.util.Map; import java.util.Set; @@ -31,8 +33,8 @@ import java.util.concurrent.CopyOnWriteArraySet; public class ModuleManager { - private final Set modules = new CopyOnWriteArraySet<>(); - private final Map moduleLookupTable = new ConcurrentHashMap<>(); + private final Set modules = new CopyOnWriteArraySet<>(); + private final Map moduleLookupTable = new ConcurrentHashMap<>(); private final DiscordSRV discordSRV; public ModuleManager(DiscordSRV discordSRV) { @@ -42,23 +44,25 @@ public class ModuleManager { @SuppressWarnings("unchecked") public T getModule(Class moduleType) { return (T) moduleLookupTable.computeIfAbsent(moduleType.getName(), key -> { - for (Module module : modules) { - if (moduleType.isAssignableFrom(module.getClass())) { - return module; + AbstractModule bestCandidate = null; + for (AbstractModule module : modules) { + if (moduleType.isAssignableFrom(module.getClass()) + && (bestCandidate == null || module.priority() > bestCandidate.priority())) { + bestCandidate = module; } } - return null; + return bestCandidate; }); } - public void register(Module module) { + public void register(AbstractModule module) { this.modules.add(module); this.moduleLookupTable.put(module.getClass().getName(), module); enable(module); } - private void enable(Module module) { + private void enable(AbstractModule module) { try { module.enableModule(); } catch (Throwable t) { @@ -66,14 +70,14 @@ public class ModuleManager { } } - public void unregister(Module module) { + public void unregister(AbstractModule module) { this.modules.remove(module); this.moduleLookupTable.values().removeIf(mod -> mod == module); disable(module); } - private void disable(Module module) { + private void disable(AbstractModule module) { try { module.disable(); } catch (Throwable t) { @@ -83,14 +87,14 @@ public class ModuleManager { @Subscribe(priority = EventPriority.EARLY) public void onShuttingDown(DiscordSRVShuttingDownEvent event) { - for (Module module : modules) { + for (AbstractModule module : modules) { unregister(module); } } @Subscribe(priority = EventPriority.EARLY) public void onReload(DiscordSRVReloadEvent event) { - for (Module module : modules) { + for (AbstractModule module : modules) { // Check if the module needs to be enabled due to reload enable(module); diff --git a/common/src/main/java/com/discordsrv/common/module/modules/DiscordAPIEventModule.java b/common/src/main/java/com/discordsrv/common/module/modules/DiscordAPIEventModule.java index b88b3bfa..39749445 100644 --- a/common/src/main/java/com/discordsrv/common/module/modules/DiscordAPIEventModule.java +++ b/common/src/main/java/com/discordsrv/common/module/modules/DiscordAPIEventModule.java @@ -19,14 +19,14 @@ package com.discordsrv.common.module.modules; import com.discordsrv.api.event.bus.Subscribe; -import com.discordsrv.api.event.events.discord.DiscordMessageReceivedEvent; +import com.discordsrv.api.discord.events.DiscordMessageReceivedEvent; import com.discordsrv.common.DiscordSRV; import com.discordsrv.common.discord.api.channel.DiscordMessageChannelImpl; import com.discordsrv.common.discord.api.message.ReceivedDiscordMessageImpl; -import com.discordsrv.common.module.Module; +import com.discordsrv.common.module.type.AbstractModule; import net.dv8tion.jda.api.events.message.MessageReceivedEvent; -public class DiscordAPIEventModule extends Module { +public class DiscordAPIEventModule extends AbstractModule { public DiscordAPIEventModule(DiscordSRV discordSRV) { super(discordSRV); diff --git a/common/src/main/java/com/discordsrv/common/module/modules/GlobalChannelLookupModule.java b/common/src/main/java/com/discordsrv/common/module/modules/GlobalChannelLookupModule.java index b7fd2291..c7ff5016 100644 --- a/common/src/main/java/com/discordsrv/common/module/modules/GlobalChannelLookupModule.java +++ b/common/src/main/java/com/discordsrv/common/module/modules/GlobalChannelLookupModule.java @@ -23,10 +23,9 @@ import com.discordsrv.api.event.bus.Subscribe; import com.discordsrv.api.event.events.channel.GameChannelLookupEvent; import com.discordsrv.common.DiscordSRV; import com.discordsrv.common.channel.DefaultGlobalChannel; -import com.discordsrv.common.event.util.EventUtil; -import com.discordsrv.common.module.Module; +import com.discordsrv.common.module.type.AbstractModule; -public class GlobalChannelLookupModule extends Module { +public class GlobalChannelLookupModule extends AbstractModule { private final DefaultGlobalChannel defaultGlobalChannel; @@ -37,7 +36,7 @@ public class GlobalChannelLookupModule extends Module { @Subscribe(priority = EventPriority.LATE) public void onGameChannelLookup(GameChannelLookupEvent event) { - if (EventUtil.checkProcessor(discordSRV, event)) { + if (checkProcessor(event)) { return; } diff --git a/common/src/main/java/com/discordsrv/common/module/modules/integration/LuckPermsIntegration.java b/common/src/main/java/com/discordsrv/common/module/modules/integration/LuckPermsIntegration.java new file mode 100644 index 00000000..40232d26 --- /dev/null +++ b/common/src/main/java/com/discordsrv/common/module/modules/integration/LuckPermsIntegration.java @@ -0,0 +1,82 @@ +/* + * This file is part of DiscordSRV, licensed under the GPLv3 License + * Copyright (c) 2016-2021 Austin "Scarsz" Shapiro, Henri "Vankka" Schubin and DiscordSRV contributors + * + * 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.discordsrv.common.module.modules.integration; + +import com.discordsrv.common.DiscordSRV; +import com.discordsrv.common.module.type.PermissionDataProvider; +import com.discordsrv.common.module.type.PluginIntegration; +import net.luckperms.api.LuckPerms; +import net.luckperms.api.LuckPermsProvider; +import net.luckperms.api.model.group.Group; +import net.luckperms.api.model.user.User; +import net.luckperms.api.query.QueryOptions; + +import java.util.Collection; +import java.util.UUID; + +public class LuckPermsIntegration extends PluginIntegration implements PermissionDataProvider { + + private LuckPerms luckPerms; + + public LuckPermsIntegration(DiscordSRV discordSRV) { + super(discordSRV); + } + + @Override + public boolean isEnabled() { + try { + Class.forName("net.luckperms.api.LuckPerms"); + } catch (ClassNotFoundException e) { + return false; + } + + return true; + } + + @Override + public void enable() { + luckPerms = LuckPermsProvider.get(); + } + + @Override + public void disable() { + luckPerms = null; + } + + @Override + public boolean hasGroup(UUID player, String groupName) { + User user = luckPerms.getUserManager().getUser(player); + if (user == null) { + return false; + } + + Collection groups = user.getInheritedGroups(QueryOptions.defaultContextualOptions()); + return groups.stream().anyMatch(group -> group.getName().equalsIgnoreCase(groupName)); + } + + @Override + public void addGroup(UUID player, String groupName) { + + } + + @Override + public void removeGroup(UUID player, String groupName) { + + } +} diff --git a/common/src/main/java/com/discordsrv/common/module/modules/message/AbstractGameMessageModule.java b/common/src/main/java/com/discordsrv/common/module/modules/message/AbstractGameMessageModule.java new file mode 100644 index 00000000..6c922742 --- /dev/null +++ b/common/src/main/java/com/discordsrv/common/module/modules/message/AbstractGameMessageModule.java @@ -0,0 +1,143 @@ +/* + * This file is part of DiscordSRV, licensed under the GPLv3 License + * Copyright (c) 2016-2021 Austin "Scarsz" Shapiro, Henri "Vankka" Schubin and DiscordSRV contributors + * + * 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.discordsrv.common.module.modules.message; + +import com.discordsrv.api.channel.GameChannel; +import com.discordsrv.api.discord.api.entity.message.ReceivedDiscordMessage; +import com.discordsrv.api.discord.api.entity.message.ReceivedDiscordMessageCluster; +import com.discordsrv.api.discord.api.entity.message.SendableDiscordMessage; +import com.discordsrv.api.discord.api.util.DiscordFormattingUtil; +import com.discordsrv.api.event.events.message.receive.game.AbstractGameMessageReceiveEvent; +import com.discordsrv.api.placeholder.FormattedText; +import com.discordsrv.api.player.DiscordSRVPlayer; +import com.discordsrv.common.DiscordSRV; +import com.discordsrv.common.component.util.ComponentUtil; +import com.discordsrv.common.config.main.channels.base.BaseChannelConfig; +import com.discordsrv.common.config.main.channels.base.IChannelConfig; +import com.discordsrv.common.discord.api.message.ReceivedDiscordMessageClusterImpl; +import com.discordsrv.common.function.OrDefault; +import com.discordsrv.common.module.type.AbstractModule; +import net.kyori.adventure.text.Component; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.CompletableFuture; + +public abstract class AbstractGameMessageModule extends AbstractModule { + + public AbstractGameMessageModule(DiscordSRV discordSRV) { + super(discordSRV); + } + + public abstract OrDefault mapConfig(OrDefault channelConfig); + public abstract boolean isEnabled(OrDefault config); + public abstract SendableDiscordMessage.Builder getFormat(OrDefault config); + public abstract void postClusterToEventBus(ReceivedDiscordMessageCluster cluster); + + public final void process( + @NotNull AbstractGameMessageReceiveEvent event, + @NotNull DiscordSRVPlayer player, + @Nullable GameChannel channel + ) { + if (channel == null) { + // Send to all channels due to lack of specified channel + for (OrDefault channelConfig : discordSRV.channelConfig().getAllChannels()) { + forwardToChannel(event, player, channelConfig); + } + return; + } + + OrDefault channelConfig = discordSRV.channelConfig().orDefault(channel); + forwardToChannel(event, player, channelConfig); + } + + private void forwardToChannel( + @NotNull AbstractGameMessageReceiveEvent event, + @NotNull DiscordSRVPlayer player, + @NotNull OrDefault channelConfig + ) { + OrDefault config = mapConfig(channelConfig); + if (!isEnabled(config)) { + return; + } + + List channelIds = channelConfig.get(cfg -> cfg instanceof IChannelConfig ? ((IChannelConfig) cfg).ids() : null); + if (channelIds == null || channelIds.isEmpty()) { + return; + } + + SendableDiscordMessage.Builder format = getFormat(config); + if (format == null) { + return; + } + + String message = convertMessage(config, ComponentUtil.fromAPI(event.getMessage())); + List> futures = sendMessageToChannels( + config, format, channelIds, message, + // Context + channelConfig, player + ); + + CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])) + .whenComplete((v, t) -> { + if (t != null) { + discordSRV.logger().error("Failed to deliver message to Discord", t); + return; + } + + List messages = new ArrayList<>(); + for (CompletableFuture future : futures) { + // They are all done + messages.add(future.join()); + } + + postClusterToEventBus(new ReceivedDiscordMessageClusterImpl(messages)); + }); + } + + public String convertMessage(OrDefault config, Component component) { + return DiscordFormattingUtil.escapeContent( + discordSRV.componentFactory().discordSerializer().serialize(component) + ); + } + + public List> sendMessageToChannels( + OrDefault config, + SendableDiscordMessage.Builder format, + List channelIds, + String message, + Object... context + ) { + SendableDiscordMessage discordMessage = format.toFormatter() + .addContext(context) + .addReplacement("%message%", new FormattedText(message)) + .applyPlaceholderService() + .build(); + + List> futures = new ArrayList<>(); + for (Long channelId : channelIds) { + discordSRV.discordAPI().getTextChannelById(channelId) + .ifPresent(channel -> futures.add(channel.sendMessage(discordMessage))); + } + + return futures; + } +} diff --git a/common/src/main/java/com/discordsrv/common/module/modules/DiscordToMinecraftModule.java b/common/src/main/java/com/discordsrv/common/module/modules/message/DiscordToMinecraftChatModule.java similarity index 78% rename from common/src/main/java/com/discordsrv/common/module/modules/DiscordToMinecraftModule.java rename to common/src/main/java/com/discordsrv/common/module/modules/message/DiscordToMinecraftChatModule.java index ddfa54d0..dcb08ddc 100644 --- a/common/src/main/java/com/discordsrv/common/module/modules/DiscordToMinecraftModule.java +++ b/common/src/main/java/com/discordsrv/common/module/modules/message/DiscordToMinecraftChatModule.java @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.discordsrv.common.module.modules; +package com.discordsrv.common.module.modules.message; import com.discordsrv.api.channel.GameChannel; import com.discordsrv.api.component.EnhancedTextBuilder; @@ -25,25 +25,25 @@ import com.discordsrv.api.discord.api.entity.DiscordUser; import com.discordsrv.api.discord.api.entity.channel.DiscordTextChannel; import com.discordsrv.api.discord.api.entity.guild.DiscordGuildMember; import com.discordsrv.api.discord.api.entity.message.ReceivedDiscordMessage; +import com.discordsrv.api.discord.events.DiscordMessageReceivedEvent; import com.discordsrv.api.event.bus.Subscribe; -import com.discordsrv.api.event.events.discord.DiscordMessageReceivedEvent; -import com.discordsrv.api.event.events.message.receive.discord.DiscordMessageProcessingEvent; +import com.discordsrv.api.event.events.message.receive.discord.DiscordChatMessageProcessingEvent; import com.discordsrv.api.placeholder.util.Placeholders; import com.discordsrv.common.DiscordSRV; import com.discordsrv.common.component.renderer.DiscordSRVMinecraftRenderer; import com.discordsrv.common.component.util.ComponentUtil; -import com.discordsrv.common.config.main.channels.BaseChannelConfig; +import com.discordsrv.common.config.main.channels.base.BaseChannelConfig; import com.discordsrv.common.config.main.channels.DiscordToMinecraftChatConfig; import com.discordsrv.common.function.OrDefault; -import com.discordsrv.common.module.Module; +import com.discordsrv.common.module.type.AbstractModule; import net.kyori.adventure.text.Component; -import org.apache.commons.lang3.tuple.Pair; +import java.util.Map; import java.util.Optional; -public class DiscordToMinecraftModule extends Module { +public class DiscordToMinecraftChatModule extends AbstractModule { - public DiscordToMinecraftModule(DiscordSRV discordSRV) { + public DiscordToMinecraftChatModule(DiscordSRV discordSRV) { super(discordSRV); } @@ -54,30 +54,38 @@ public class DiscordToMinecraftModule extends Module { return; } - discordSRV.eventBus().publish(new DiscordMessageProcessingEvent(event.getMessage(), channel)); + discordSRV.eventBus().publish(new DiscordChatMessageProcessingEvent(event.getMessage(), channel)); } @Subscribe - public void onDiscordMessageReceive(DiscordMessageProcessingEvent event) { + public void onDiscordMessageReceive(DiscordChatMessageProcessingEvent event) { if (checkCancellation(event) || checkProcessor(event)) { return; } + Map> channels = discordSRV.channelConfig().orDefault(event.getChannel()); + if (channels == null || channels.isEmpty()) { + return; + } + + for (Map.Entry> entry : channels.entrySet()) { + process(event, entry.getKey(), entry.getValue()); + } + event.markAsProcessed(); + } + + private void process(DiscordChatMessageProcessingEvent event, GameChannel gameChannel, OrDefault channelConfig) { + OrDefault chatConfig = channelConfig.map(cfg -> cfg.discordToMinecraft); + if (!chatConfig.get(cfg -> cfg.enabled, true)) { + return; + } + DiscordTextChannel channel = event.getChannel(); ReceivedDiscordMessage discordMessage = event.getDiscordMessage(); DiscordUser author = discordMessage.getAuthor(); Optional member = discordMessage.getMember(); boolean webhookMessage = discordMessage.isWebhookMessage(); - OrDefault> channelPair = discordSRV.channelConfig().orDefault(channel); - GameChannel gameChannel = channelPair.get(Pair::getKey); - if (gameChannel == null) { - return; - } - - OrDefault channelConfig = channelPair.map(Pair::getValue); - OrDefault chatConfig = channelConfig.map(cfg -> cfg.discordToMinecraft); - DiscordToMinecraftChatConfig.Ignores ignores = chatConfig.get(cfg -> cfg.ignores); if (ignores != null) { if (ignores.webhooks && webhookMessage) { @@ -116,7 +124,7 @@ public class DiscordToMinecraftModule extends Module { EnhancedTextBuilder componentBuilder = discordSRV.componentFactory() .enhancedBuilder(format) - .addContext(discordMessage, author) + .addContext(discordMessage, author, channel, channelConfig) .addReplacement("%message%", messageComponent); member.ifPresent(componentBuilder::addContext); diff --git a/common/src/main/java/com/discordsrv/common/module/modules/message/JoinMessageModule.java b/common/src/main/java/com/discordsrv/common/module/modules/message/JoinMessageModule.java new file mode 100644 index 00000000..a9172842 --- /dev/null +++ b/common/src/main/java/com/discordsrv/common/module/modules/message/JoinMessageModule.java @@ -0,0 +1,66 @@ +/* + * This file is part of DiscordSRV, licensed under the GPLv3 License + * Copyright (c) 2016-2021 Austin "Scarsz" Shapiro, Henri "Vankka" Schubin and DiscordSRV contributors + * + * 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.discordsrv.common.module.modules.message; + +import com.discordsrv.api.discord.api.entity.message.ReceivedDiscordMessageCluster; +import com.discordsrv.api.discord.api.entity.message.SendableDiscordMessage; +import com.discordsrv.api.event.bus.EventPriority; +import com.discordsrv.api.event.bus.Subscribe; +import com.discordsrv.api.event.events.message.forward.game.JoinMessageForwardedEvent; +import com.discordsrv.api.event.events.message.receive.game.JoinMessageReceiveEvent; +import com.discordsrv.common.DiscordSRV; +import com.discordsrv.common.config.main.channels.JoinMessageConfig; +import com.discordsrv.common.config.main.channels.base.BaseChannelConfig; +import com.discordsrv.common.function.OrDefault; + +public class JoinMessageModule extends AbstractGameMessageModule { + + public JoinMessageModule(DiscordSRV discordSRV) { + super(discordSRV); + } + + @Override + public OrDefault mapConfig(OrDefault channelConfig) { + return channelConfig.map(cfg -> cfg.joinMessages); + } + + @Override + public boolean isEnabled(OrDefault config) { + return config.get(cfg -> cfg.enabled, true); + } + + @Override + public SendableDiscordMessage.Builder getFormat(OrDefault config) { + return config.get(cfg -> cfg.format); + } + + @Override + public void postClusterToEventBus(ReceivedDiscordMessageCluster cluster) { + discordSRV.eventBus().publish(new JoinMessageForwardedEvent(cluster)); + } + + @Subscribe(priority = EventPriority.LAST) + public void onStatusMessageReceive(JoinMessageReceiveEvent event) { + if (checkCancellation(event) || checkProcessor(event)) { + return; + } + + process(event, event.getPlayer(), event.getGameChannel()); + } +} diff --git a/common/src/main/java/com/discordsrv/common/module/modules/message/LeaveMessageModule.java b/common/src/main/java/com/discordsrv/common/module/modules/message/LeaveMessageModule.java new file mode 100644 index 00000000..4148005e --- /dev/null +++ b/common/src/main/java/com/discordsrv/common/module/modules/message/LeaveMessageModule.java @@ -0,0 +1,66 @@ +/* + * This file is part of DiscordSRV, licensed under the GPLv3 License + * Copyright (c) 2016-2021 Austin "Scarsz" Shapiro, Henri "Vankka" Schubin and DiscordSRV contributors + * + * 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.discordsrv.common.module.modules.message; + +import com.discordsrv.api.discord.api.entity.message.ReceivedDiscordMessageCluster; +import com.discordsrv.api.discord.api.entity.message.SendableDiscordMessage; +import com.discordsrv.api.event.bus.EventPriority; +import com.discordsrv.api.event.bus.Subscribe; +import com.discordsrv.api.event.events.message.forward.game.LeaveMessageForwardedEvent; +import com.discordsrv.api.event.events.message.receive.game.LeaveMessageReceiveEvent; +import com.discordsrv.common.DiscordSRV; +import com.discordsrv.common.config.main.channels.LeaveMessageConfig; +import com.discordsrv.common.config.main.channels.base.BaseChannelConfig; +import com.discordsrv.common.function.OrDefault; + +public class LeaveMessageModule extends AbstractGameMessageModule { + + public LeaveMessageModule(DiscordSRV discordSRV) { + super(discordSRV); + } + + @Override + public OrDefault mapConfig(OrDefault channelConfig) { + return channelConfig.map(cfg -> cfg.leaveMessages); + } + + @Override + public boolean isEnabled(OrDefault config) { + return config.get(cfg -> cfg.enabled, true); + } + + @Override + public SendableDiscordMessage.Builder getFormat(OrDefault config) { + return config.get(cfg -> cfg.format); + } + + @Override + public void postClusterToEventBus(ReceivedDiscordMessageCluster cluster) { + discordSRV.eventBus().publish(new LeaveMessageForwardedEvent(cluster)); + } + + @Subscribe(priority = EventPriority.LAST) + public void onStatusMessageReceive(LeaveMessageReceiveEvent event) { + if (checkCancellation(event) || checkProcessor(event)) { + return; + } + + process(event, event.getPlayer(), event.getGameChannel()); + } +} diff --git a/common/src/main/java/com/discordsrv/common/module/modules/MinecraftToDiscordModule.java b/common/src/main/java/com/discordsrv/common/module/modules/message/MinecraftToDiscordChatModule.java similarity index 79% rename from common/src/main/java/com/discordsrv/common/module/modules/MinecraftToDiscordModule.java rename to common/src/main/java/com/discordsrv/common/module/modules/message/MinecraftToDiscordChatModule.java index 13b94483..06d83613 100644 --- a/common/src/main/java/com/discordsrv/common/module/modules/MinecraftToDiscordModule.java +++ b/common/src/main/java/com/discordsrv/common/module/modules/message/MinecraftToDiscordChatModule.java @@ -16,28 +16,25 @@ * along with this program. If not, see . */ -package com.discordsrv.common.module.modules; +package com.discordsrv.common.module.modules.message; import com.discordsrv.api.channel.GameChannel; import com.discordsrv.api.discord.api.entity.channel.DiscordTextChannel; import com.discordsrv.api.discord.api.entity.guild.DiscordGuild; import com.discordsrv.api.discord.api.entity.message.ReceivedDiscordMessage; +import com.discordsrv.api.discord.api.entity.message.ReceivedDiscordMessageCluster; import com.discordsrv.api.discord.api.entity.message.SendableDiscordMessage; import com.discordsrv.api.discord.api.util.DiscordFormattingUtil; import com.discordsrv.api.event.bus.EventPriority; import com.discordsrv.api.event.bus.Subscribe; -import com.discordsrv.api.event.events.message.forward.game.ChatMessageForwardedEvent; -import com.discordsrv.api.event.events.message.receive.game.ChatMessageProcessingEvent; +import com.discordsrv.api.event.events.message.forward.game.GameChatMessageForwardedEvent; +import com.discordsrv.api.event.events.message.receive.game.GameChatMessageReceiveEvent; import com.discordsrv.api.placeholder.FormattedText; import com.discordsrv.api.placeholder.util.Placeholders; import com.discordsrv.common.DiscordSRV; -import com.discordsrv.common.component.util.ComponentUtil; -import com.discordsrv.common.config.main.channels.BaseChannelConfig; -import com.discordsrv.common.config.main.channels.ChannelConfig; import com.discordsrv.common.config.main.channels.MinecraftToDiscordChatConfig; -import com.discordsrv.common.discord.api.message.ReceivedDiscordMessageClusterImpl; +import com.discordsrv.common.config.main.channels.base.BaseChannelConfig; import com.discordsrv.common.function.OrDefault; -import com.discordsrv.common.module.Module; import net.dv8tion.jda.api.entities.Guild; import net.dv8tion.jda.api.entities.GuildChannel; import net.dv8tion.jda.api.entities.Member; @@ -45,6 +42,7 @@ import net.dv8tion.jda.api.entities.Role; import net.dv8tion.jda.api.events.channel.ChannelCreateEvent; import net.dv8tion.jda.api.events.channel.ChannelDeleteEvent; import net.dv8tion.jda.api.events.channel.update.ChannelUpdateNameEvent; +import net.dv8tion.jda.api.events.guild.GuildLeaveEvent; import net.dv8tion.jda.api.events.guild.member.GuildMemberJoinEvent; import net.dv8tion.jda.api.events.guild.member.GuildMemberRemoveEvent; import net.dv8tion.jda.api.events.guild.member.update.GuildMemberUpdateNicknameEvent; @@ -58,43 +56,70 @@ import java.util.concurrent.CompletableFuture; import java.util.concurrent.ConcurrentHashMap; import java.util.regex.Pattern; -public class MinecraftToDiscordModule extends Module { +public class MinecraftToDiscordChatModule extends AbstractGameMessageModule { private final Map> memberMentions = new ConcurrentHashMap<>(); private final Map> roleMentions = new ConcurrentHashMap<>(); private final Map> channelMentions = new ConcurrentHashMap<>(); - public MinecraftToDiscordModule(DiscordSRV discordSRV) { + public MinecraftToDiscordChatModule(DiscordSRV discordSRV) { super(discordSRV); } + @Override + public void disable() { + memberMentions.clear(); + roleMentions.clear(); + channelMentions.clear(); + } + @Subscribe(priority = EventPriority.LAST) - public void onChatReceive(ChatMessageProcessingEvent event) { + public void onChatReceive(GameChatMessageReceiveEvent event) { if (checkProcessor(event) || checkCancellation(event) || !discordSRV.isReady()) { return; } GameChannel gameChannel = event.getGameChannel(); + process(event, event.getPlayer(), gameChannel); + event.markAsProcessed(); + } + @Override + public OrDefault mapConfig(OrDefault channelConfig) { + return channelConfig.map(cfg -> cfg.minecraftToDiscord); + } - OrDefault channelConfig = discordSRV.channelConfig().orDefault(gameChannel); - OrDefault chatConfig = channelConfig.map(cfg -> cfg.minecraftToDiscord); + @Override + public boolean isEnabled(OrDefault config) { + return config.get(cfg -> cfg.enabled, true); + } - SendableDiscordMessage.Builder builder = chatConfig.get(cfg -> cfg.format); - if (builder == null) { - return; - } + @Override + public SendableDiscordMessage.Builder getFormat(OrDefault config) { + return config.get(cfg -> cfg.format); + } - List channelIds = channelConfig.get(cfg -> cfg instanceof ChannelConfig ? ((ChannelConfig) cfg).channelIds : null); - if (channelIds == null || channelIds.isEmpty()) { - return; - } + @Override + public void postClusterToEventBus(ReceivedDiscordMessageCluster cluster) { + discordSRV.eventBus().publish(new GameChatMessageForwardedEvent(cluster)); + } - Component message = ComponentUtil.fromAPI(event.message()); - Placeholders messagePlaceholders = new Placeholders(discordSRV.componentFactory().discordSerializer().serialize(message)); - - chatConfig.opt(cfg -> cfg.contentRegexFilters) + @Override + public String convertMessage(OrDefault config, Component component) { + Placeholders messagePlaceholders = new Placeholders(discordSRV.componentFactory().discordSerializer().serialize(component)); + config.opt(cfg -> cfg.contentRegexFilters) .ifPresent(patterns -> patterns.forEach(messagePlaceholders::replaceAll)); + return DiscordFormattingUtil.escapeContent(messagePlaceholders.toString()); + } + + @Override + public List> sendMessageToChannels( + OrDefault config, + SendableDiscordMessage.Builder format, + List channelIds, + String message, + Object... context + ) { Map> channels = new LinkedHashMap<>(); for (Long channelId : channelIds) { discordSRV.discordAPI().getTextChannelById(channelId) @@ -103,15 +128,14 @@ public class MinecraftToDiscordModule extends Module { .add(textChannel)); } - String serializedMessage = DiscordFormattingUtil.escapeContent(messagePlaceholders.toString()); List> futures = new ArrayList<>(); - OrDefault mentionConfig = chatConfig.map(cfg -> cfg.mentions); + OrDefault mentionConfig = config.map(cfg -> cfg.mentions); // Format messages per-Guild for (Map.Entry> entry : channels.entrySet()) { Guild guild = entry.getKey().getAsJDAGuild(); - Placeholders channelMessagePlaceholders = new Placeholders(serializedMessage); + Placeholders channelMessagePlaceholders = new Placeholders(message); List mentions = new ArrayList<>(); if (mentionConfig.get(cfg -> cfg.roles, false)) { mentions.addAll(getRoleMentions(guild).values()); @@ -128,8 +152,8 @@ public class MinecraftToDiscordModule extends Module { .sorted(Comparator.comparingInt(mention -> ((CachedMention) mention).searchLength).reversed()) .forEachOrdered(mention -> channelMessagePlaceholders.replaceAll(mention.search, mention.mention)); - SendableDiscordMessage discordMessage = builder.toFormatter() - .addContext(event.getPlayer(), gameChannel) + SendableDiscordMessage discordMessage = format.toFormatter() + .addContext(context) .addReplacement("%message%", new FormattedText(channelMessagePlaceholders.toString())) .applyPlaceholderService() .build(); @@ -139,28 +163,21 @@ public class MinecraftToDiscordModule extends Module { } } - CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])) - .whenComplete((v, t) -> { - if (t != null) { - discordSRV.logger().error("Failed to deliver message to Discord", t); - return; - } - - List messages = new ArrayList<>(); - for (CompletableFuture future : futures) { - messages.add(future.join()); - } - - discordSRV.eventBus().publish( - new ChatMessageForwardedEvent( - new ReceivedDiscordMessageClusterImpl(messages))); - }); + return futures; } // // Mention caching // + @Subscribe + public void onGuildDelete(GuildLeaveEvent event) { + long guildId = event.getGuild().getIdLong(); + memberMentions.remove(guildId); + roleMentions.remove(guildId); + channelMentions.remove(guildId); + } + private Map getRoleMentions(Guild guild) { return roleMentions.computeIfAbsent(guild.getIdLong(), key -> { Map mentions = new LinkedHashMap<>(); diff --git a/common/src/main/java/com/discordsrv/common/module/Module.java b/common/src/main/java/com/discordsrv/common/module/type/AbstractModule.java similarity index 86% rename from common/src/main/java/com/discordsrv/common/module/Module.java rename to common/src/main/java/com/discordsrv/common/module/type/AbstractModule.java index 21267646..c6aa31c1 100644 --- a/common/src/main/java/com/discordsrv/common/module/Module.java +++ b/common/src/main/java/com/discordsrv/common/module/type/AbstractModule.java @@ -16,30 +16,22 @@ * along with this program. If not, see . */ -package com.discordsrv.common.module; +package com.discordsrv.common.module.type; import com.discordsrv.api.event.events.Cancellable; import com.discordsrv.api.event.events.Processable; import com.discordsrv.common.DiscordSRV; import com.discordsrv.common.event.util.EventUtil; -public abstract class Module { +public abstract class AbstractModule implements Module { protected final DiscordSRV discordSRV; private boolean hasBeenEnabled = false; - public Module(DiscordSRV discordSRV) { + public AbstractModule(DiscordSRV discordSRV) { this.discordSRV = discordSRV; } - protected boolean isEnabled() { - return true; - } - - protected void enable() {} - protected void disable() {} - protected void reload() {} - public final void enableModule() { if (hasBeenEnabled || !isEnabled()) { return; diff --git a/common/src/main/java/com/discordsrv/common/module/type/Module.java b/common/src/main/java/com/discordsrv/common/module/type/Module.java new file mode 100644 index 00000000..e6441e4c --- /dev/null +++ b/common/src/main/java/com/discordsrv/common/module/type/Module.java @@ -0,0 +1,34 @@ +/* + * This file is part of DiscordSRV, licensed under the GPLv3 License + * Copyright (c) 2016-2021 Austin "Scarsz" Shapiro, Henri "Vankka" Schubin and DiscordSRV contributors + * + * 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.discordsrv.common.module.type; + +public interface Module { + + default boolean isEnabled() { + return true; + } + + default int priority() { + return 0; + } + + default void enable() {} + default void disable() {} + default void reload() {} +} diff --git a/common/src/main/java/com/discordsrv/common/module/type/PermissionDataProvider.java b/common/src/main/java/com/discordsrv/common/module/type/PermissionDataProvider.java new file mode 100644 index 00000000..f9cac11d --- /dev/null +++ b/common/src/main/java/com/discordsrv/common/module/type/PermissionDataProvider.java @@ -0,0 +1,28 @@ +/* + * This file is part of DiscordSRV, licensed under the GPLv3 License + * Copyright (c) 2016-2021 Austin "Scarsz" Shapiro, Henri "Vankka" Schubin and DiscordSRV contributors + * + * 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.discordsrv.common.module.type; + +import java.util.UUID; + +public interface PermissionDataProvider extends Module { + + boolean hasGroup(UUID player, String groupName); + void addGroup(UUID player, String groupName); + void removeGroup(UUID player, String groupName); +} diff --git a/common/proxy/src/main/java/com/discordsrv/common/package-info.java b/common/src/main/java/com/discordsrv/common/module/type/PluginIntegration.java similarity index 77% rename from common/proxy/src/main/java/com/discordsrv/common/package-info.java rename to common/src/main/java/com/discordsrv/common/module/type/PluginIntegration.java index b4396cc2..9d5b1df6 100644 --- a/common/proxy/src/main/java/com/discordsrv/common/package-info.java +++ b/common/src/main/java/com/discordsrv/common/module/type/PluginIntegration.java @@ -16,4 +16,13 @@ * along with this program. If not, see . */ -package com.discordsrv.common; +package com.discordsrv.common.module.type; + +import com.discordsrv.common.DiscordSRV; + +public abstract class PluginIntegration extends AbstractModule { + + public PluginIntegration(DiscordSRV discordSRV) { + super(discordSRV); + } +} diff --git a/common/src/main/java/com/discordsrv/common/placeholder/ComponentResultStringifier.java b/common/src/main/java/com/discordsrv/common/placeholder/ComponentResultStringifier.java index 9bb866b1..2d9bd9bc 100644 --- a/common/src/main/java/com/discordsrv/common/placeholder/ComponentResultStringifier.java +++ b/common/src/main/java/com/discordsrv/common/placeholder/ComponentResultStringifier.java @@ -42,7 +42,7 @@ public class ComponentResultStringifier implements PlaceholderResultMapper { } if (result instanceof Component) { Component component = (Component) result; - if (ResultMappers.isPlainComponentContext()) { + if (ResultMappers.isPlainContext()) { return PlainTextComponentSerializer.plainText().serialize(component); } else { return discordSRV.componentFactory().discordSerializer().serialize(component); diff --git a/common/src/main/java/com/discordsrv/common/placeholder/provider/util/PlaceholderMethodUtil.java b/common/src/main/java/com/discordsrv/common/placeholder/provider/util/PlaceholderMethodUtil.java index 7c296b89..9f4a62b1 100644 --- a/common/src/main/java/com/discordsrv/common/placeholder/provider/util/PlaceholderMethodUtil.java +++ b/common/src/main/java/com/discordsrv/common/placeholder/provider/util/PlaceholderMethodUtil.java @@ -49,6 +49,7 @@ public final class PlaceholderMethodUtil { for (Object o : context) { Class objectType = o.getClass(); apply(parameters, (parameter, i) -> { + Class type = parameter.getType(); if (parameter.getType().isAssignableFrom(objectType)) { parameters[i] = null; parameterValues[i] = o; diff --git a/common/src/main/java/com/discordsrv/common/player/IOfflinePlayer.java b/common/src/main/java/com/discordsrv/common/player/IOfflinePlayer.java index f3ab6b81..8a072500 100644 --- a/common/src/main/java/com/discordsrv/common/player/IOfflinePlayer.java +++ b/common/src/main/java/com/discordsrv/common/player/IOfflinePlayer.java @@ -30,12 +30,12 @@ public interface IOfflinePlayer extends Identified { @Placeholder("player_name") @Nullable - String getUsername(); + String username(); @ApiStatus.NonExtendable @Placeholder("player_uuid") @NotNull - default UUID getUniqueId() { + default UUID uniqueId() { return identity().uuid(); } } diff --git a/common/src/main/java/com/discordsrv/common/player/IPlayer.java b/common/src/main/java/com/discordsrv/common/player/IPlayer.java index 13aeabe0..4ecbbd72 100644 --- a/common/src/main/java/com/discordsrv/common/player/IPlayer.java +++ b/common/src/main/java/com/discordsrv/common/player/IPlayer.java @@ -18,12 +18,13 @@ package com.discordsrv.common.player; -import com.discordsrv.api.channel.GameChannel; import com.discordsrv.api.placeholder.annotation.Placeholder; import com.discordsrv.api.placeholder.util.Placeholders; import com.discordsrv.api.player.DiscordSRVPlayer; import com.discordsrv.common.DiscordSRV; import com.discordsrv.common.command.game.sender.ICommandSender; +import com.discordsrv.common.config.main.channels.base.BaseChannelConfig; +import com.discordsrv.common.function.OrDefault; import net.kyori.adventure.text.Component; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; @@ -37,30 +38,29 @@ public interface IPlayer extends DiscordSRVPlayer, IOfflinePlayer, ICommandSende @Override @NotNull - String getUsername(); + String username(); @Override @ApiStatus.NonExtendable - default @NotNull UUID getUniqueId() { + default @NotNull UUID uniqueId() { return identity().uuid(); } @NotNull @Placeholder("player_display_name") - Component getDisplayName(); + Component displayName(); @Nullable @Placeholder("player_avatar_url") - default String getAvatarUrl(GameChannel gameChannel) { - String avatarUrl = discordSRV().channelConfig().orDefault(gameChannel) - .get(cfg -> cfg.avatarUrlProvider); - if (avatarUrl == null) { + default String getAvatarUrl(OrDefault config) { + String avatarUrlProvider = config.get(cfg -> cfg.avatarUrlProvider); + if (avatarUrlProvider == null) { return null; } - return new Placeholders(avatarUrl) - .replace("%uuid%", getUniqueId().toString()) - .replace("%username%", getUsername()) + return new Placeholders(avatarUrlProvider) + .replace("%uuid%", uniqueId().toString()) + .replace("%username%", username()) .replace("%texture%", "") // TODO .toString(); } diff --git a/common/src/main/java/com/discordsrv/common/player/provider/AbstractPlayerProvider.java b/common/src/main/java/com/discordsrv/common/player/provider/AbstractPlayerProvider.java index 83f9259f..6e935256 100644 --- a/common/src/main/java/com/discordsrv/common/player/provider/AbstractPlayerProvider.java +++ b/common/src/main/java/com/discordsrv/common/player/provider/AbstractPlayerProvider.java @@ -52,7 +52,7 @@ public abstract class AbstractPlayerProvider implements Playe @Override public final @NotNull Optional player(@NotNull String username) { for (T value : allPlayers) { - if (value.getUsername().equalsIgnoreCase(username)) { + if (value.username().equalsIgnoreCase(username)) { return Optional.of(value); } } diff --git a/common/src/main/java/com/discordsrv/common/scheduler/Scheduler.java b/common/src/main/java/com/discordsrv/common/scheduler/Scheduler.java index 6b2d9b23..4f11ca62 100644 --- a/common/src/main/java/com/discordsrv/common/scheduler/Scheduler.java +++ b/common/src/main/java/com/discordsrv/common/scheduler/Scheduler.java @@ -31,11 +31,17 @@ public interface Scheduler { */ String THREAD_NAME_PREFIX = "DiscordSRV Async "; + /** + * Returns the {@link ExecutorService} being used. + * @return the {@link ExecutorService} + */ + ExecutorService executor(); + /** * Returns the {@link ScheduledExecutorService} being used. * @return the {@link ScheduledExecutorService} */ - ScheduledExecutorService executor(); + ScheduledExecutorService scheduledExecutor(); /** * Returns the {@link ForkJoinPool} being used. diff --git a/common/src/main/java/com/discordsrv/common/scheduler/StandardScheduler.java b/common/src/main/java/com/discordsrv/common/scheduler/StandardScheduler.java index ce592b33..2652de44 100644 --- a/common/src/main/java/com/discordsrv/common/scheduler/StandardScheduler.java +++ b/common/src/main/java/com/discordsrv/common/scheduler/StandardScheduler.java @@ -31,15 +31,23 @@ import java.util.concurrent.*; public class StandardScheduler implements Scheduler { private final DiscordSRV discordSRV; - private final ScheduledThreadPoolExecutor executorService; + private final ThreadPoolExecutor executor; + private final ScheduledThreadPoolExecutor scheduledExecutor; private final ForkJoinPool forkJoinPool; public StandardScheduler(DiscordSRV discordSRV) { this( discordSRV, + new ThreadPoolExecutor( + 4, /* Core pool size */ + 16, /* Max pool size */ + 60, TimeUnit.SECONDS, /* Timeout */ + new SynchronousQueue<>(), + new CountingThreadFactory(Scheduler.THREAD_NAME_PREFIX + "Scheduled Executor #%s") + ), new ScheduledThreadPoolExecutor( - 8, /* Core pool size */ - new CountingThreadFactory(Scheduler.THREAD_NAME_PREFIX + "Executor #%s") + 2, /* Core pool size */ + new CountingThreadFactory(Scheduler.THREAD_NAME_PREFIX + "Scheduled Executor #%s") ), new ForkJoinPool( Math.max(1, Runtime.getRuntime().availableProcessors() - 1), /* Parallelism - not core pool size */ @@ -50,15 +58,23 @@ public class StandardScheduler implements Scheduler { ); } - private StandardScheduler(DiscordSRV discordSRV, ScheduledThreadPoolExecutor executorService, ForkJoinPool forkJoinPool) { + private StandardScheduler( + DiscordSRV discordSRV, + ThreadPoolExecutor executor, + ScheduledThreadPoolExecutor scheduledExecutor, + ForkJoinPool forkJoinPool + ) { this.discordSRV = discordSRV; - this.executorService = executorService; + this.executor = executor; + this.scheduledExecutor = scheduledExecutor; this.forkJoinPool = forkJoinPool; } @Subscribe(priority = EventPriority.LAST) public void onShuttingDown(DiscordSRVShuttingDownEvent event) { - executorService.shutdownNow(); + executor.shutdownNow(); + scheduledExecutor.shutdownNow(); + forkJoinPool.shutdownNow(); } private Runnable wrap(Runnable runnable) { @@ -72,8 +88,13 @@ public class StandardScheduler implements Scheduler { } @Override - public ScheduledExecutorService executor() { - return executorService; + public ExecutorService executor() { + return executor; + } + + @Override + public ScheduledExecutorService scheduledExecutor() { + return scheduledExecutor; } @Override @@ -83,7 +104,7 @@ public class StandardScheduler implements Scheduler { @Override public Future run(@NotNull Runnable task) { - return executorService.submit(wrap(task)); + return executor.submit(wrap(task)); } @Override @@ -93,12 +114,12 @@ public class StandardScheduler implements Scheduler { @Override public ScheduledFuture runLater(Runnable task, long timeMillis) { - return executorService.schedule(wrap(task), timeMillis, TimeUnit.MILLISECONDS); + return scheduledExecutor.schedule(wrap(task), timeMillis, TimeUnit.MILLISECONDS); } @Override public ScheduledFuture runAtFixedRate(@NotNull Runnable task, long initialDelayMillis, long rateMillis) { - return executorService.scheduleAtFixedRate(wrap(task), initialDelayMillis, rateMillis, TimeUnit.MILLISECONDS); + return scheduledExecutor.scheduleAtFixedRate(wrap(task), initialDelayMillis, rateMillis, TimeUnit.MILLISECONDS); } } diff --git a/common/src/test/java/com/discordsrv/common/MockDiscordSRV.java b/common/src/test/java/com/discordsrv/common/MockDiscordSRV.java index f988ec7c..83bde787 100644 --- a/common/src/test/java/com/discordsrv/common/MockDiscordSRV.java +++ b/common/src/test/java/com/discordsrv/common/MockDiscordSRV.java @@ -23,8 +23,8 @@ import com.discordsrv.common.config.main.MainConfig; import com.discordsrv.common.config.manager.ConnectionConfigManager; import com.discordsrv.common.config.manager.MainConfigManager; import com.discordsrv.common.console.Console; -import com.discordsrv.logging.Logger; -import com.discordsrv.logging.impl.JavaLoggerImpl; +import com.discordsrv.common.logging.Logger; +import com.discordsrv.common.logging.impl.JavaLoggerImpl; import com.discordsrv.common.player.provider.AbstractPlayerProvider; import com.discordsrv.common.scheduler.Scheduler; import com.discordsrv.common.scheduler.StandardScheduler; diff --git a/i18n/build.gradle b/i18n/build.gradle index 3814f87c..9ed958a7 100644 --- a/i18n/build.gradle +++ b/i18n/build.gradle @@ -11,15 +11,18 @@ repositories { version = null dependencies { - implementation(project(':common')) + implementation(project(':common:common-api')) + implementation(project(':common:common-server')) + implementation(project(':common:common-proxy')) // Depend on all platforms for configs implementation(project(':bukkit')) { transitive = false } - implementation(project(':bungee')) { transitive = false } - implementation(project(':sponge')) { transitive = false } - implementation(project(':velocity')) { transitive = false } + //implementation(project(':bungee')) { transitive = false } + //implementation(project(':sponge')) { transitive = false } + //implementation(project(':velocity')) { transitive = false } api 'org.spongepowered:configurate-yaml:' + rootProject.configurateVersion + api 'org.spongepowered:configurate-hocon:' + rootProject.configurateVersion } application { diff --git a/i18n/src/main/java/com/discordsrv/config/DiscordSRVTranslation.java b/i18n/src/main/java/com/discordsrv/config/DiscordSRVTranslation.java index 46a250db..d9e5f46e 100644 --- a/i18n/src/main/java/com/discordsrv/config/DiscordSRVTranslation.java +++ b/i18n/src/main/java/com/discordsrv/config/DiscordSRVTranslation.java @@ -18,16 +18,18 @@ package com.discordsrv.config; -import com.discordsrv.bukkit.config.connection.BukkitConnectionConfig; -import com.discordsrv.bukkit.config.main.BukkitConfig; +import com.discordsrv.bukkit.config.manager.BukkitConfigManager; +import com.discordsrv.bukkit.config.manager.BukkitConnectionConfigManager; +import com.discordsrv.common.DiscordSRV; import com.discordsrv.common.config.Config; import com.discordsrv.common.config.annotation.Untranslated; -import com.discordsrv.common.config.main.channels.BaseChannelConfig; +import com.discordsrv.common.config.manager.manager.ConfigurateConfigManager; +import com.discordsrv.common.config.manager.manager.TranslatedConfigManager; import org.spongepowered.configurate.CommentedConfigurationNode; import org.spongepowered.configurate.ConfigurateException; import org.spongepowered.configurate.ConfigurationNode; -import org.spongepowered.configurate.ConfigurationOptions; import org.spongepowered.configurate.objectmapping.ObjectMapper; +import org.spongepowered.configurate.objectmapping.meta.Processor; import org.spongepowered.configurate.serialize.SerializationException; import org.spongepowered.configurate.yaml.YamlConfigurationLoader; @@ -35,15 +37,17 @@ import java.io.File; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.Map; /** * A java application to generate a translation file that has comments as options. */ public final class DiscordSRVTranslation { - public static final List CONFIG_INSTANCES = Arrays.asList( - new BukkitConfig(), - new BukkitConnectionConfig() + private static final DiscordSRV discordSRV = new MockDiscordSRV(); + private static final List> CONFIGS = Arrays.asList( + new BukkitConfigManager(discordSRV), + new BukkitConnectionConfigManager(discordSRV) ); public static void main(String[] args) throws ConfigurateException { @@ -52,58 +56,83 @@ public final class DiscordSRVTranslation { private DiscordSRVTranslation() {} - @SuppressWarnings("unchecked") public void run() throws ConfigurateException { - ObjectMapper.Factory objectMapper = ObjectMapper.factoryBuilder() - .addProcessor(Untranslated.class, (data, value) -> (value1, destination) -> { - try { - Untranslated.Type type = data.value(); - if (type.isValue()) { - if (type.isComment()) { - destination.set(null); - } else { - destination.set(""); - } - } else if (type.isComment() && destination instanceof CommentedConfigurationNode) { - ((CommentedConfigurationNode) destination).comment(null); - } - } catch (SerializationException e) { - e.printStackTrace(); - System.exit(1); + Processor.Factory untranslatedProcessorFactory = (data, v1) -> (v2, destination) -> { + try { + Untranslated.Type type = data.value(); + if (type.isValue()) { + Object value = destination.get(Object.class); + if (type.isComment()/* || !(value instanceof String)*/) { + destination.set(null); + } else { + destination.set(""); } - }) - .build(); + } else if (type.isComment() && destination instanceof CommentedConfigurationNode) { + ((CommentedConfigurationNode) destination).comment(null); + } + } catch (SerializationException e) { + e.printStackTrace(); + System.exit(1); + } + }; + CommentedConfigurationNode node = CommentedConfigurationNode.root(); + for (ConfigurateConfigManager configManager : CONFIGS) { + Config config = (Config) configManager.createConfiguration(); + String fileIdentifier = config.getFileName(); + ConfigurationNode commentSection = node.node(fileIdentifier + "_comments"); - BaseChannelConfig.Serializer channelSerializer = new BaseChannelConfig.Serializer(objectMapper); - CommentedConfigurationNode node = CommentedConfigurationNode.root(ConfigurationOptions.defaults() - .serializers(builder -> builder.register(BaseChannelConfig.class, channelSerializer))); - for (Config config : CONFIG_INSTANCES) { - ConfigurationNode section = node.node(config.getFileName()); - ConfigurationNode configSection = section.copy(); + ObjectMapper.Factory mapperFactory = configManager.configObjectMapperBuilder() + .addProcessor(Untranslated.class, untranslatedProcessorFactory) + .build(); - ObjectMapper mapper = objectMapper.get((Class) config.getClass()); - mapper.save(config, configSection); - convertCommentsToOptions(configSection, configSection); + TranslationConfigManagerProxy configManagerProxy = new TranslationConfigManagerProxy<>(discordSRV, mapperFactory, configManager); + CommentedConfigurationNode configurationNode = configManagerProxy.getDefaultNode(mapperFactory); + convertCommentsToOptions(configurationNode, commentSection); + + processUnwantedValues(configurationNode); + ConfigurationNode section = node.node(fileIdentifier); + ConfigurationNode configSection = section.set(configurationNode); section.set(configSection); } YamlConfigurationLoader.builder() - .file(new File("i18n", "source.yml")) + .file(new File("i18n", "source.yaml")) .build() .save(node); } - public void convertCommentsToOptions(ConfigurationNode node, ConfigurationNode parent) throws SerializationException { + public void processUnwantedValues(ConfigurationNode node) throws SerializationException { + Map children = node.childrenMap(); + Object value; + if (children.isEmpty() && (!((value = node.get(Object.class)) instanceof String) || ((String) value).isEmpty())) { + node.set(null); + return; + } + + boolean allChildrenEmpty = true; + for (ConfigurationNode child : children.values()) { + processUnwantedValues(child); + + if (child.virtual() || child.isNull() || child.empty()) { + allChildrenEmpty = false; + break; + } + } + if (!allChildrenEmpty) { + node.set(null); + } + } + + public void convertCommentsToOptions(ConfigurationNode node, ConfigurationNode commentParent) throws SerializationException { if (node instanceof CommentedConfigurationNode) { CommentedConfigurationNode commentedNode = (CommentedConfigurationNode) node; String comment = commentedNode.comment(); if (comment != null) { - List arr = new ArrayList<>(); - arr.add("_comments"); - arr.addAll(Arrays.asList(commentedNode.path().array())); - parent.node(arr).set(comment); + List path = new ArrayList<>(Arrays.asList(commentedNode.path().array())); + path.add("_comment"); + commentParent.node(path).set(comment); } } if (node.empty()) { @@ -111,7 +140,7 @@ public final class DiscordSRVTranslation { return; } for (ConfigurationNode value : node.childrenMap().values()) { - convertCommentsToOptions(value, parent); + convertCommentsToOptions(value, commentParent); } } } diff --git a/i18n/src/main/java/com/discordsrv/config/MockDiscordSRV.java b/i18n/src/main/java/com/discordsrv/config/MockDiscordSRV.java new file mode 100644 index 00000000..97f5049e --- /dev/null +++ b/i18n/src/main/java/com/discordsrv/config/MockDiscordSRV.java @@ -0,0 +1,184 @@ +/* + * This file is part of DiscordSRV, licensed under the GPLv3 License + * Copyright (c) 2016-2021 Austin "Scarsz" Shapiro, Henri "Vankka" Schubin and DiscordSRV contributors + * + * 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.discordsrv.config; + +import com.discordsrv.api.discord.connection.DiscordConnectionDetails; +import com.discordsrv.api.event.bus.EventBus; +import com.discordsrv.common.DiscordSRV; +import com.discordsrv.common.channel.ChannelConfigHelper; +import com.discordsrv.common.component.ComponentFactory; +import com.discordsrv.common.config.connection.ConnectionConfig; +import com.discordsrv.common.config.main.MainConfig; +import com.discordsrv.common.config.manager.ConnectionConfigManager; +import com.discordsrv.common.config.manager.MainConfigManager; +import com.discordsrv.common.console.Console; +import com.discordsrv.common.discord.api.DiscordAPIImpl; +import com.discordsrv.common.discord.connection.DiscordConnectionManager; +import com.discordsrv.common.module.type.AbstractModule; +import com.discordsrv.common.module.type.Module; +import com.discordsrv.common.placeholder.PlaceholderServiceImpl; +import com.discordsrv.common.player.provider.AbstractPlayerProvider; +import com.discordsrv.common.scheduler.Scheduler; +import com.discordsrv.common.logging.Logger; +import net.dv8tion.jda.api.JDA; +import org.jetbrains.annotations.NotNull; + +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Locale; +import java.util.Optional; +import java.util.concurrent.CompletableFuture; + +public class MockDiscordSRV implements DiscordSRV { + + @Override + public @NotNull Status status() { + return null; + } + + @Override + public @NotNull EventBus eventBus() { + return null; + } + + @Override + public @NotNull Optional jda() { + return Optional.empty(); + } + + @Override + public @NotNull DiscordConnectionDetails discordConnectionDetails() { + return null; + } + + @Override + public Logger logger() { + return null; + } + + @Override + public Path dataDirectory() { + return Paths.get(""); + } + + @Override + public Scheduler scheduler() { + return null; + } + + @Override + public Console console() { + return null; + } + + @Override + public String version() { + return null; + } + + @Override + public @NotNull ComponentFactory componentFactory() { + return null; + } + + @Override + public @NotNull PlaceholderServiceImpl placeholderService() { + return null; + } + + @Override + public @NotNull AbstractPlayerProvider playerProvider() { + return null; + } + + @Override + public @NotNull DiscordAPIImpl discordAPI() { + return null; + } + + @Override + public ConnectionConfigManager connectionConfigManager() { + return null; + } + + @Override + public ConnectionConfig connectionConfig() { + return null; + } + + @Override + public MainConfigManager configManager() { + return null; + } + + @Override + public MainConfig config() { + return null; + } + + @Override + public ChannelConfigHelper channelConfig() { + return null; + } + + @Override + public DiscordConnectionManager discordConnectionManager() { + return null; + } + + @Override + public T getModule(Class moduleType) { + return null; + } + + @Override + public void registerModule(AbstractModule module) { + + } + + @Override + public void unregisterModule(AbstractModule module) { + + } + + @Override + public Locale locale() { + return null; + } + + @Override + public void setStatus(Status status) { + + } + + @Override + public CompletableFuture invokeEnable() { + return null; + } + + @Override + public CompletableFuture invokeDisable() { + return null; + } + + @Override + public CompletableFuture invokeReload() { + return null; + } +} diff --git a/i18n/src/main/java/com/discordsrv/config/TranslationConfigManagerProxy.java b/i18n/src/main/java/com/discordsrv/config/TranslationConfigManagerProxy.java new file mode 100644 index 00000000..d16f9f23 --- /dev/null +++ b/i18n/src/main/java/com/discordsrv/config/TranslationConfigManagerProxy.java @@ -0,0 +1,59 @@ +/* + * This file is part of DiscordSRV, licensed under the GPLv3 License + * Copyright (c) 2016-2021 Austin "Scarsz" Shapiro, Henri "Vankka" Schubin and DiscordSRV contributors + * + * 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.discordsrv.config; + +import com.discordsrv.common.DiscordSRV; +import com.discordsrv.common.config.manager.loader.YamlConfigLoaderProvider; +import com.discordsrv.common.config.manager.manager.ConfigurateConfigManager; +import org.spongepowered.configurate.objectmapping.ObjectMapper; +import org.spongepowered.configurate.yaml.YamlConfigurationLoader; + +public class TranslationConfigManagerProxy + extends ConfigurateConfigManager + implements YamlConfigLoaderProvider { + + private final ObjectMapper.Factory objectMapper; + private final ConfigurateConfigManager configManager; + + public TranslationConfigManagerProxy(DiscordSRV discordSRV, ObjectMapper.Factory objectMapper, ConfigurateConfigManager configManager) { + super(discordSRV); + this.objectMapper = objectMapper; + this.configManager = configManager; + } + + @Override + public ObjectMapper.Factory configObjectMapper() { + return objectMapper != null ? objectMapper : super.configObjectMapper(); + } + + @Override + public ObjectMapper.Factory defaultObjectMapper() { + return objectMapper != null ? objectMapper : super.defaultObjectMapper(); + } + + @Override + protected String fileName() { + return "none"; + } + + @Override + public C createConfiguration() { + return configManager.createConfiguration(); + } +} diff --git a/settings.gradle b/settings.gradle index d71438f5..32ef62f7 100644 --- a/settings.gradle +++ b/settings.gradle @@ -9,7 +9,7 @@ pluginManagement { rootProject.name = 'DiscordSRV2' [ - 'common', 'common:api', 'common:server', 'common:proxy', + 'common', 'common:api', 'common:server', 'common:proxy', 'common:slf4j-hack', 'i18n', 'api', 'bukkit', 'bukkit:loader', diff --git a/sponge/src/main/java/com/discordsrv/sponge/DiscordSRVSpongeBootstrap.java b/sponge/src/main/java/com/discordsrv/sponge/DiscordSRVSpongeBootstrap.java index 1ad9df3b..e8537f15 100644 --- a/sponge/src/main/java/com/discordsrv/sponge/DiscordSRVSpongeBootstrap.java +++ b/sponge/src/main/java/com/discordsrv/sponge/DiscordSRVSpongeBootstrap.java @@ -19,8 +19,8 @@ package com.discordsrv.sponge; import com.discordsrv.common.dependency.InitialDependencyLoader; -import com.discordsrv.logging.Logger; -import com.discordsrv.logging.impl.Log4JLoggerImpl; +import com.discordsrv.common.logging.Logger; +import com.discordsrv.common.logging.impl.Log4JLoggerImpl; import com.discordsrv.sponge.bootstrap.ISpongeBootstrap; import dev.vankka.mcdependencydownload.bootstrap.AbstractBootstrap; import dev.vankka.mcdependencydownload.bootstrap.classpath.JarInJarClasspathAppender; diff --git a/sponge/src/main/java/com/discordsrv/sponge/SpongeDiscordSRV.java b/sponge/src/main/java/com/discordsrv/sponge/SpongeDiscordSRV.java index a5b063a8..b910d229 100644 --- a/sponge/src/main/java/com/discordsrv/sponge/SpongeDiscordSRV.java +++ b/sponge/src/main/java/com/discordsrv/sponge/SpongeDiscordSRV.java @@ -23,7 +23,7 @@ import com.discordsrv.common.config.connection.ConnectionConfig; import com.discordsrv.common.config.main.MainConfig; import com.discordsrv.common.config.manager.ConnectionConfigManager; import com.discordsrv.common.config.manager.MainConfigManager; -import com.discordsrv.logging.Logger; +import com.discordsrv.common.logging.Logger; import com.discordsrv.common.server.ServerDiscordSRV; import com.discordsrv.sponge.console.SpongeConsole; import com.discordsrv.sponge.player.SpongePlayerProvider; diff --git a/sponge/src/main/java/com/discordsrv/sponge/console/SpongeConsole.java b/sponge/src/main/java/com/discordsrv/sponge/console/SpongeConsole.java index 23e6bcdb..78bfe1d0 100644 --- a/sponge/src/main/java/com/discordsrv/sponge/console/SpongeConsole.java +++ b/sponge/src/main/java/com/discordsrv/sponge/console/SpongeConsole.java @@ -19,8 +19,8 @@ package com.discordsrv.sponge.console; import com.discordsrv.common.console.Console; -import com.discordsrv.logging.backend.LoggingBackend; -import com.discordsrv.logging.impl.Log4JLoggerImpl; +import com.discordsrv.common.logging.backend.LoggingBackend; +import com.discordsrv.common.logging.impl.Log4JLoggerImpl; import com.discordsrv.sponge.SpongeDiscordSRV; import net.kyori.adventure.identity.Identity; import net.kyori.adventure.text.Component; diff --git a/sponge/src/main/java/com/discordsrv/sponge/player/SpongeOfflinePlayer.java b/sponge/src/main/java/com/discordsrv/sponge/player/SpongeOfflinePlayer.java index 65ef5a62..d965846b 100644 --- a/sponge/src/main/java/com/discordsrv/sponge/player/SpongeOfflinePlayer.java +++ b/sponge/src/main/java/com/discordsrv/sponge/player/SpongeOfflinePlayer.java @@ -32,7 +32,7 @@ public class SpongeOfflinePlayer implements IOfflinePlayer { } @Override - public @NotNull String getUsername() { + public @NotNull String username() { return user.name(); } diff --git a/sponge/src/main/java/com/discordsrv/sponge/player/SpongePlayer.java b/sponge/src/main/java/com/discordsrv/sponge/player/SpongePlayer.java index 7f5c11e2..8bf8c3f1 100644 --- a/sponge/src/main/java/com/discordsrv/sponge/player/SpongePlayer.java +++ b/sponge/src/main/java/com/discordsrv/sponge/player/SpongePlayer.java @@ -63,7 +63,7 @@ public class SpongePlayer extends SpongeOfflinePlayer implements IPlayer { } @Override - public @NotNull Component getDisplayName() { + public @NotNull Component displayName() { return player.displayName().get(); } } diff --git a/velocity/src/main/java/com/discordsrv/velocity/DiscordSRVVelocityBootstrap.java b/velocity/src/main/java/com/discordsrv/velocity/DiscordSRVVelocityBootstrap.java index dd3a0215..4257666d 100644 --- a/velocity/src/main/java/com/discordsrv/velocity/DiscordSRVVelocityBootstrap.java +++ b/velocity/src/main/java/com/discordsrv/velocity/DiscordSRVVelocityBootstrap.java @@ -19,8 +19,8 @@ package com.discordsrv.velocity; import com.discordsrv.common.dependency.InitialDependencyLoader; -import com.discordsrv.logging.Logger; -import com.discordsrv.logging.impl.SLF4JLoggerImpl; +import com.discordsrv.common.logging.Logger; +import com.discordsrv.common.logging.impl.SLF4JLoggerImpl; import com.google.inject.Inject; import com.velocitypowered.api.event.Subscribe; import com.velocitypowered.api.event.proxy.ProxyInitializeEvent; @@ -53,7 +53,7 @@ public class DiscordSRVVelocityBootstrap { private VelocityDiscordSRV discordSRV; @Inject - public DiscordSRVVelocityBootstrap(org.slf4j.Logger logger, ProxyServer proxyServer, PluginContainer pluginContainer, @DataDirectory Path dataDirectory) throws IOException { + public DiscordSRVVelocityBootstrap(com.discordsrv.x.slf4j.Logger logger, ProxyServer proxyServer, PluginContainer pluginContainer, @DataDirectory Path dataDirectory) throws IOException { this.logger = new SLF4JLoggerImpl(logger); this.dependencies = new InitialDependencyLoader( this.logger, diff --git a/velocity/src/main/java/com/discordsrv/velocity/VelocityDiscordSRV.java b/velocity/src/main/java/com/discordsrv/velocity/VelocityDiscordSRV.java index 08e8d1c0..870f0d95 100644 --- a/velocity/src/main/java/com/discordsrv/velocity/VelocityDiscordSRV.java +++ b/velocity/src/main/java/com/discordsrv/velocity/VelocityDiscordSRV.java @@ -22,8 +22,8 @@ import com.discordsrv.common.config.connection.ConnectionConfig; import com.discordsrv.common.config.main.MainConfig; import com.discordsrv.common.config.manager.ConnectionConfigManager; import com.discordsrv.common.config.manager.MainConfigManager; -import com.discordsrv.logging.Logger; -import com.discordsrv.common.proxy.ProxyDiscordSRV; +import com.discordsrv.common.logging.Logger; +import com.discordsrv.proxy.ProxyDiscordSRV; import com.discordsrv.common.scheduler.StandardScheduler; import com.discordsrv.velocity.console.VelocityConsole; import com.discordsrv.velocity.player.VelocityPlayerProvider; diff --git a/velocity/src/main/java/com/discordsrv/velocity/console/VelocityConsole.java b/velocity/src/main/java/com/discordsrv/velocity/console/VelocityConsole.java index 53cb82be..1a4c33dd 100644 --- a/velocity/src/main/java/com/discordsrv/velocity/console/VelocityConsole.java +++ b/velocity/src/main/java/com/discordsrv/velocity/console/VelocityConsole.java @@ -19,8 +19,8 @@ package com.discordsrv.velocity.console; import com.discordsrv.common.console.Console; -import com.discordsrv.logging.backend.LoggingBackend; -import com.discordsrv.logging.impl.Log4JLoggerImpl; +import com.discordsrv.common.logging.backend.LoggingBackend; +import com.discordsrv.common.logging.impl.Log4JLoggerImpl; import com.discordsrv.velocity.VelocityDiscordSRV; import net.kyori.adventure.identity.Identity; import net.kyori.adventure.text.Component; diff --git a/velocity/src/main/java/com/discordsrv/velocity/player/VelocityPlayer.java b/velocity/src/main/java/com/discordsrv/velocity/player/VelocityPlayer.java index 37086d77..c20aaf69 100644 --- a/velocity/src/main/java/com/discordsrv/velocity/player/VelocityPlayer.java +++ b/velocity/src/main/java/com/discordsrv/velocity/player/VelocityPlayer.java @@ -59,7 +59,7 @@ public class VelocityPlayer implements IPlayer { } @Override - public @NotNull String getUsername() { + public @NotNull String username() { return player.getUsername(); } @@ -69,7 +69,7 @@ public class VelocityPlayer implements IPlayer { } @Override - public @NotNull Component getDisplayName() { + public @NotNull Component displayName() { // Use Adventure's Pointer, otherwise username return player.getOrDefaultFrom( Identity.DISPLAY_NAME,