Add Bukkit chat plugin integrations, make better use of DynamicProxy, consolidate some of the :common subprojects

This commit is contained in:
Vankka 2023-02-20 21:55:45 +02:00
parent eb5a8dc9a8
commit 6ff5ddb6a7
No known key found for this signature in database
GPG Key ID: 6E50CB7A29B96AD0
41 changed files with 784 additions and 104 deletions

View File

@ -36,9 +36,6 @@ java {
withJavadocJar()
}
// Fix template source set not being depended on/other tasks not depending on template source set
sourcesJar { dependsOn compileTemplateJava }
jar {
from sourceSets.ap.output
}

View File

@ -31,6 +31,8 @@ import org.jetbrains.annotations.NotNull;
*/
public interface GameChannel {
String DEFAULT_NAME = "global";
/**
* Gets the name of the plugin/mod/extension that 'owns' this game channel.
* @return the name of the owner of this game channel

View File

@ -26,4 +26,4 @@ package com.discordsrv.api.discord.entity.interaction.component;
import com.discordsrv.api.discord.entity.JDAEntity;
import net.dv8tion.jda.api.interactions.components.ItemComponent;
public interface Component<T extends ItemComponent> extends JDAEntity<T> {}
public interface DiscordComponent<T extends ItemComponent> extends JDAEntity<T> {}

View File

@ -25,5 +25,5 @@ package com.discordsrv.api.discord.entity.interaction.component;
import net.dv8tion.jda.api.interactions.components.ItemComponent;
public interface MessageComponent extends Component<ItemComponent> {
public interface MessageComponent extends DiscordComponent<ItemComponent> {
}

View File

@ -25,5 +25,5 @@ package com.discordsrv.api.discord.entity.interaction.component;
import net.dv8tion.jda.api.interactions.components.ItemComponent;
public interface ModalComponent extends Component<ItemComponent> {
public interface ModalComponent extends DiscordComponent<ItemComponent> {
}

View File

@ -24,20 +24,20 @@
package com.discordsrv.api.discord.entity.interaction.component.actionrow;
import com.discordsrv.api.discord.entity.JDAEntity;
import com.discordsrv.api.discord.entity.interaction.component.Component;
import com.discordsrv.api.discord.entity.interaction.component.DiscordComponent;
import net.dv8tion.jda.api.interactions.components.ItemComponent;
import java.util.List;
import java.util.stream.Collectors;
public interface ActionRow<T extends Component<? extends ItemComponent>> extends JDAEntity<net.dv8tion.jda.api.interactions.components.ActionRow> {
public interface ActionRow<T extends DiscordComponent<? extends ItemComponent>> extends JDAEntity<net.dv8tion.jda.api.interactions.components.ActionRow> {
List<T> components();
@Override
default net.dv8tion.jda.api.interactions.components.ActionRow asJDA() {
return net.dv8tion.jda.api.interactions.components.ActionRow.of(
components().stream().map(Component::asJDA).collect(Collectors.toList())
components().stream().map(DiscordComponent::asJDA).collect(Collectors.toList())
);
}
}

View File

@ -47,7 +47,15 @@ public class GameChannelLookupEvent implements Processable {
}
/**
* The channel name being looked up, this should be case insensitive wherever possible.
* If this is for the "default" channel.
* @return if this lookup is for the default channel
*/
public boolean isDefault() {
return GameChannel.DEFAULT_NAME.equals(channelName);
}
/**
* The channel name being looked up, this should be case-insensitive wherever possible.
* @return the channel name
*/
@NotNull
@ -75,6 +83,7 @@ public class GameChannelLookupEvent implements Processable {
/**
* Provides a {@link GameChannel} for the provided channel name ({@link #getChannelName()}).
* If this is the {@link #isDefault()} channel, any channel name is accepted.
* @param channel the channel
* @throws IllegalStateException if the event is already processed
*/
@ -88,7 +97,7 @@ public class GameChannelLookupEvent implements Processable {
}
String channelName = channel.getChannelName();
if (!channelName.equalsIgnoreCase(this.channelName)) {
if (!isDefault() && !channelName.equalsIgnoreCase(this.channelName)) {
throw new IllegalArgumentException("The provided channel is named "
+ channelName + " when it should've been: " + this.channelName);
}

View File

@ -11,6 +11,7 @@ version '3.0.0-SNAPSHOT'
subprojects {
apply plugin: 'java'
apply plugin: 'java-library'
apply plugin: 'idea'
apply plugin: 'com.github.johnrengelman.shadow'
apply plugin: 'org.cadixdev.licenser'
apply plugin: 'net.kyori.indra.git'
@ -29,7 +30,7 @@ subprojects {
compileOnlyApi.extendsFrom runtimeDownloadApi
runtimeDownloadOnly.extendsFrom runtimeDownloadApi
all {
configureEach {
resolutionStrategy.failOnDynamicVersions()
}
}
@ -63,26 +64,15 @@ subprojects {
mavenCentral()
}
// Add a 'template' source set to all projects
sourceSets {
template {
java {
compileClasspath += sourceSets.main.compileClasspath
}
}
main {
java {
srcDir sourceSets.template.output.generatedSourcesDirs.getSingleFile()
var generatedSources = sourceSets.main.output.generatedSourcesDirs
idea {
module {
generatedSources.forEach {
generatedSourceDirs.plus(it)
}
}
}
// Compile template source
compileJava { dependsOn compileTemplateJava }
// Fix template source set not being depended on/other tasks not depending on template source set
checkLicenseMain { dependsOn compileTemplateJava }
updateLicenseMain { dependsOn compileTemplateJava }
dependencies {
// Test dependencies
@ -90,14 +80,14 @@ subprojects {
testRuntimeOnly(libs.jupiter.engine)
// DynamicProxy
templateAnnotationProcessor(libs.dynamicproxy)
annotationProcessor(libs.dynamicproxy)
}
test {
useJUnitPlatform()
}
task deleteJarsDir(type: Delete) {
tasks.register('deleteJarsDir', Delete) {
delete rootProject.file('jars')
}
clean.dependsOn deleteJarsDir

View File

@ -21,7 +21,7 @@ configurations {
compileOnly.extendsFrom commodore
}
task generateResourceForCommodore(type: GenerateDependencyDownloadResourceTask) {
tasks.register('generateResourceForCommodore', GenerateDependencyDownloadResourceTask) {
var conf = configurations.commodore
configuration = conf
file = 'dependencies/' + conf.name + '.txt'
@ -48,6 +48,10 @@ allprojects {
filter {
includeGroup 'net.milkbowl.vault'
includeGroup 'me.clip'
includeGroup 'com.palmergames.bukkit'
includeGroup 'mineverse.aust1n46'
includeGroup 'ru.mrbrikster'
includeGroup 'com.github.ucchyocean.lc'
}
}
}
@ -64,7 +68,6 @@ dependencies {
// Common
compileOnly project(':common')
implementation project(':common:common-templates')
implementation project(path: ':common', configuration: 'runtimeElements')
// DependencyDownload
@ -85,6 +88,12 @@ dependencies {
// Integrations
compileOnly(libs.vaultapi)
compileOnly(libs.placeholderapi.bukkit)
// Chat Integrations
compileOnly(libs.chatty)
compileOnly(libs.lunachat)
compileOnly(libs.townychat)
compileOnly(libs.venturechat)
}
processResources {

View File

@ -9,6 +9,10 @@ api-version: 1.13
softdepend: [
# Permission + group providers
Vault, LuckPerms,
# Chat
Chatty, LunaChat, TownyChat, VentureChat,
# Other integrations
PlaceholderAPI,
# Adventure
ViaVersion
]

View File

@ -227,6 +227,12 @@ public class BukkitDiscordSRV extends ServerDiscordSRV<DiscordSRVBukkitBootstrap
registerIntegration("com.discordsrv.bukkit.integration.VaultIntegration");
registerIntegration("com.discordsrv.bukkit.integration.PlaceholderAPIIntegration");
// Chat Integrations
registerIntegration("com.discordsrv.bukkit.integration.chat.ChattyChatIntegration");
registerIntegration("com.discordsrv.bukkit.integration.chat.LunaChatIntegration");
registerIntegration("com.discordsrv.bukkit.integration.chat.TownyChatIntegration");
registerIntegration("com.discordsrv.bukkit.integration.chat.VentureChatIntegration");
super.enable();
// Connection listener

View File

@ -18,7 +18,9 @@
package com.discordsrv.bukkit.config.main;
import com.discordsrv.api.channel.GameChannel;
import com.discordsrv.common.config.main.MainConfig;
import com.discordsrv.common.config.main.PluginIntegrationConfig;
import com.discordsrv.common.config.main.channels.base.ChannelConfig;
import com.discordsrv.common.config.main.channels.base.server.ServerBaseChannelConfig;
import com.discordsrv.common.config.main.channels.base.server.ServerChannelConfig;
@ -29,7 +31,14 @@ public class BukkitConfig extends MainConfig {
public BukkitConfig() {
channels.clear();
channels.put("global", new ServerChannelConfig());
channels.put(GameChannel.DEFAULT_NAME, new ServerChannelConfig());
channels.put(ChannelConfig.DEFAULT_KEY, new ServerBaseChannelConfig());
}
public PluginIntegrationConfig integrations = new PluginIntegrationConfig();
@Override
public PluginIntegrationConfig integrations() {
return integrations;
}
}

View File

@ -18,7 +18,6 @@
package com.discordsrv.bukkit.console.executor;
import dev.vankka.dynamicproxy.CallOriginal;
import dev.vankka.dynamicproxy.processor.Original;
import dev.vankka.dynamicproxy.processor.Proxy;
import net.kyori.adventure.platform.bukkit.BukkitComponentSerializer;
@ -51,26 +50,26 @@ public abstract class BukkitCommandExecutorProxyTemplate implements CommandSende
@Override
public void sendMessage(@Nullable UUID sender, @NotNull String... messages) {
commandSender.sendMessage(sender, messages);
forwardLegacy(String.join("\n", messages));
CallOriginal.call(sender, messages);
}
@Override
public void sendMessage(@NotNull String... messages) {
commandSender.sendMessage(messages);
forwardLegacy(String.join("\n", messages));
CallOriginal.call((Object) messages);
}
@Override
public void sendMessage(@Nullable UUID sender, @NotNull String message) {
commandSender.sendMessage(sender, message);
forwardLegacy(message);
CallOriginal.call(sender, message);
}
@Override
public void sendMessage(@NotNull String message) {
commandSender.sendMessage(message);
forwardLegacy(message);
CallOriginal.call(message);
}
private void forwardLegacy(String legacy) {

View File

@ -47,6 +47,11 @@ public class PlaceholderAPIIntegration extends PluginIntegration<BukkitDiscordSR
super(discordSRV);
}
@Override
public @NotNull String getIntegrationName() {
return "PlaceholderAPI";
}
@Override
public boolean isEnabled() {
try {

View File

@ -49,6 +49,11 @@ public class VaultIntegration extends PluginIntegration<BukkitDiscordSRV> implem
super(discordSRV);
}
@Override
public @NotNull String getIntegrationName() {
return "Vault";
}
@Override
public int priority(Class<?> type) {
// Lower priority than default

View File

@ -0,0 +1,134 @@
/*
* This file is part of DiscordSRV, licensed under the GPLv3 License
* Copyright (c) 2016-2023 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 <https://www.gnu.org/licenses/>.
*/
package com.discordsrv.bukkit.integration.chat;
import com.discordsrv.api.channel.GameChannel;
import com.discordsrv.api.component.MinecraftComponent;
import com.discordsrv.api.event.bus.Subscribe;
import com.discordsrv.api.event.events.channel.GameChannelLookupEvent;
import com.discordsrv.api.event.events.message.receive.game.GameChatMessageReceiveEvent;
import com.discordsrv.bukkit.BukkitDiscordSRV;
import com.discordsrv.common.component.util.ComponentUtil;
import com.discordsrv.common.logging.NamedLogger;
import com.discordsrv.common.module.type.PluginIntegration;
import net.kyori.adventure.platform.bukkit.BukkitComponentSerializer;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.HandlerList;
import org.bukkit.event.Listener;
import org.jetbrains.annotations.NotNull;
import ru.mrbrikster.chatty.api.ChattyApi;
import ru.mrbrikster.chatty.api.chats.Chat;
import ru.mrbrikster.chatty.api.events.ChattyMessageEvent;
public class ChattyChatIntegration extends PluginIntegration<BukkitDiscordSRV> implements Listener {
public ChattyChatIntegration(BukkitDiscordSRV discordSRV) {
super(discordSRV, new NamedLogger(discordSRV, "CHATTY"));
}
@Override
public @NotNull String getIntegrationName() {
return "Chatty";
}
@Override
public boolean isEnabled() {
try {
Class.forName("ru.mrbrikster.chatty.api.ChattyApi");
} catch (ClassNotFoundException ignored) {
return false;
}
return super.isEnabled();
}
@Override
public void enable() {
discordSRV.server().getPluginManager().registerEvents(this, discordSRV.plugin());
}
@Override
public void disable() {
HandlerList.unregisterAll(this);
}
@EventHandler(priority = org.bukkit.event.EventPriority.MONITOR)
public void onChattyMessage(ChattyMessageEvent event) {
Player player = event.getPlayer();
Chat chat = event.getChat();
MinecraftComponent component = ComponentUtil.toAPI(
BukkitComponentSerializer.legacy().deserialize(event.getMessage())
);
discordSRV.scheduler().run(() -> discordSRV.eventBus().publish(
new GameChatMessageReceiveEvent(
discordSRV.playerProvider().player(player),
new ChattyChannel(chat),
component,
false
)
));
}
@Subscribe
public void onGameChannelLookup(GameChannelLookupEvent event) {
if (checkProcessor(event)) {
return;
}
ChattyApi api = ChattyApi.get();
if (api == null) {
logger().error("ChattyApi == null");
return;
}
api.getChat(event.getChannelName())
.ifPresent(value -> event.process(new ChattyChannel(value)));
}
private class ChattyChannel implements GameChannel {
private final Chat chat;
public ChattyChannel(Chat chat) {
this.chat = chat;
}
@Override
public @NotNull String getOwnerName() {
return getIntegrationName();
}
@Override
public @NotNull String getChannelName() {
return chat.getName();
}
@Override
public boolean isChat() {
return true;
}
@Override
public void sendMessage(@NotNull MinecraftComponent component) {
chat.sendMessage(BukkitComponentSerializer.legacy().serialize(ComponentUtil.fromAPI(component)));
}
}
}

View File

@ -0,0 +1,134 @@
package com.discordsrv.bukkit.integration.chat;
import com.discordsrv.api.channel.GameChannel;
import com.discordsrv.api.component.MinecraftComponent;
import com.discordsrv.api.event.bus.Subscribe;
import com.discordsrv.api.event.events.channel.GameChannelLookupEvent;
import com.discordsrv.api.event.events.message.receive.game.GameChatMessageReceiveEvent;
import com.discordsrv.bukkit.BukkitDiscordSRV;
import com.discordsrv.common.component.util.ComponentUtil;
import com.discordsrv.common.logging.NamedLogger;
import com.discordsrv.common.module.type.PluginIntegration;
import com.github.ucchyocean.lc3.LunaChatAPI;
import com.github.ucchyocean.lc3.LunaChatBukkit;
import com.github.ucchyocean.lc3.bukkit.event.LunaChatBukkitChannelChatEvent;
import com.github.ucchyocean.lc3.channel.Channel;
import com.github.ucchyocean.lc3.member.ChannelMember;
import com.github.ucchyocean.lc3.member.ChannelMemberPlayer;
import net.kyori.adventure.platform.bukkit.BukkitComponentSerializer;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.HandlerList;
import org.bukkit.event.Listener;
import org.jetbrains.annotations.NotNull;
public class LunaChatIntegration extends PluginIntegration<BukkitDiscordSRV> implements Listener {
public LunaChatIntegration(BukkitDiscordSRV discordSRV) {
super(discordSRV, new NamedLogger(discordSRV, "LUNACHAT"));
}
@Override
public @NotNull String getIntegrationName() {
return "LunaChat";
}
@Override
public boolean isEnabled() {
try {
Class.forName("com.github.ucchyocean.lc3.LunaChatAPI");
} catch (ClassNotFoundException ignored) {
return false;
}
return super.isEnabled();
}
@Override
public void enable() {
discordSRV.server().getPluginManager().registerEvents(this, discordSRV.plugin());
}
@Override
public void disable() {
HandlerList.unregisterAll(this);
}
@EventHandler(priority = org.bukkit.event.EventPriority.MONITOR)
public void onLunaChatBukkitChannelChat(LunaChatBukkitChannelChatEvent event) {
ChannelMember member = event.getMember();
if (!(member instanceof ChannelMemberPlayer)) {
return;
}
Player player = ((ChannelMemberPlayer) member).getPlayer();
Channel channel = event.getChannel();
MinecraftComponent component = ComponentUtil.toAPI(
BukkitComponentSerializer.legacy().deserialize(event.getNgMaskedMessage())
);
discordSRV.scheduler().run(() -> discordSRV.eventBus().publish(
new GameChatMessageReceiveEvent(
discordSRV.playerProvider().player(player),
new LunaChatChannel(channel),
component,
event.isCancelled()
)
));
}
@Subscribe
public void onGameChannelLookup(GameChannelLookupEvent event) {
if (checkProcessor(event)) {
return;
}
LunaChatBukkit lunaChat = LunaChatBukkit.getInstance();
if (lunaChat == null) {
logger().debug("LunaChatBukkit == null");
return;
}
LunaChatAPI api = lunaChat.getLunaChatAPI();
if (api == null) {
logger().debug("LunaChatAPI == null");
return;
}
Channel channel = api.getChannel(event.getChannelName());
if (channel != null) {
event.process(new LunaChatChannel(channel));
}
}
private class LunaChatChannel implements GameChannel {
private final Channel channel;
public LunaChatChannel(Channel channel) {
this.channel = channel;
}
@Override
public @NotNull String getOwnerName() {
return getIntegrationName();
}
@Override
public @NotNull String getChannelName() {
return channel.getName();
}
@Override
public boolean isChat() {
return true;
}
@Override
public void sendMessage(@NotNull MinecraftComponent component) {
String message = BukkitComponentSerializer.legacy().serialize(ComponentUtil.fromAPI(component));
channel.chatFromOtherSource("Discord", null, message);
}
}
}

View File

@ -0,0 +1,155 @@
/*
* This file is part of DiscordSRV, licensed under the GPLv3 License
* Copyright (c) 2016-2023 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 <https://www.gnu.org/licenses/>.
*/
package com.discordsrv.bukkit.integration.chat;
import com.discordsrv.api.channel.GameChannel;
import com.discordsrv.api.component.MinecraftComponent;
import com.discordsrv.api.event.bus.Subscribe;
import com.discordsrv.api.event.events.channel.GameChannelLookupEvent;
import com.discordsrv.api.event.events.message.receive.game.GameChatMessageReceiveEvent;
import com.discordsrv.bukkit.BukkitDiscordSRV;
import com.discordsrv.bukkit.player.BukkitPlayer;
import com.discordsrv.common.component.util.ComponentUtil;
import com.discordsrv.common.logging.NamedLogger;
import com.discordsrv.common.module.type.PluginIntegration;
import com.palmergames.bukkit.TownyChat.Chat;
import com.palmergames.bukkit.TownyChat.channels.Channel;
import com.palmergames.bukkit.TownyChat.events.AsyncChatHookEvent;
import net.kyori.adventure.platform.bukkit.BukkitComponentSerializer;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.HandlerList;
import org.bukkit.event.Listener;
import org.jetbrains.annotations.NotNull;
public class TownyChatIntegration extends PluginIntegration<BukkitDiscordSRV> implements Listener {
public TownyChatIntegration(BukkitDiscordSRV discordSRV) {
super(discordSRV, new NamedLogger(discordSRV, "TOWNYCHAT"));
}
@Override
public @NotNull String getIntegrationName() {
return "TownyChat";
}
@Override
public boolean isEnabled() {
try {
Class.forName("com.palmergames.bukkit.TownyChat.Chat");
} catch (ClassNotFoundException ignored) {
return false;
}
return super.isEnabled();
}
@Override
public void enable() {
discordSRV.server().getPluginManager().registerEvents(this, discordSRV.plugin());
}
@Override
public void disable() {
HandlerList.unregisterAll(this);
}
@EventHandler(priority = org.bukkit.event.EventPriority.MONITOR)
public void onAsyncChatHook(AsyncChatHookEvent event) {
Player player = event.getPlayer();
Channel channel = event.getChannel();
MinecraftComponent component = ComponentUtil.toAPI(
BukkitComponentSerializer.legacy().deserialize(event.getMessage())
);
discordSRV.scheduler().run(() -> discordSRV.eventBus().publish(
new GameChatMessageReceiveEvent(
discordSRV.playerProvider().player(player),
new TownyChatChannel(channel),
component,
event.isCancelled()
)
));
}
@Subscribe
public void onGameChannelLookup(GameChannelLookupEvent event) {
if (checkProcessor(event)) {
return;
}
Chat chat = (Chat) Bukkit.getPluginManager().getPlugin("TownyChat");
if (chat == null) {
logger().debug("TownyChat main class == null");
return;
}
Channel channel;
if (event.isDefault()) {
channel = chat.getChannelsHandler().getDefaultChannel();
} else {
channel = chat.getChannelsHandler().getChannel(event.getChannelName());
}
if (channel != null) {
event.process(new TownyChatChannel(channel));
}
}
private class TownyChatChannel implements GameChannel {
private final Channel channel;
public TownyChatChannel(Channel channel) {
this.channel = channel;
}
@Override
public @NotNull String getOwnerName() {
return getIntegrationName();
}
@Override
public @NotNull String getChannelName() {
return channel.getName();
}
@Override
public boolean isChat() {
return true;
}
@Override
public void sendMessage(@NotNull MinecraftComponent component) {
for (BukkitPlayer player : discordSRV.playerProvider().allPlayers()) {
if (!channel.isPresent(player.username())) {
continue;
}
String permission = channel.getPermission();
if (permission != null && !player.hasPermission(permission)) {
continue;
}
player.sendMessage(ComponentUtil.fromAPI(component));
}
}
}
}

View File

@ -0,0 +1,170 @@
/*
* This file is part of DiscordSRV, licensed under the GPLv3 License
* Copyright (c) 2016-2023 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 <https://www.gnu.org/licenses/>.
*/
package com.discordsrv.bukkit.integration.chat;
import com.discordsrv.api.channel.GameChannel;
import com.discordsrv.api.component.MinecraftComponent;
import com.discordsrv.api.event.bus.Subscribe;
import com.discordsrv.api.event.events.channel.GameChannelLookupEvent;
import com.discordsrv.api.event.events.message.receive.game.GameChatMessageReceiveEvent;
import com.discordsrv.bukkit.BukkitDiscordSRV;
import com.discordsrv.common.component.util.ComponentUtil;
import com.discordsrv.common.logging.NamedLogger;
import com.discordsrv.common.module.type.PluginIntegration;
import mineverse.Aust1n46.chat.api.MineverseChatAPI;
import mineverse.Aust1n46.chat.api.MineverseChatPlayer;
import mineverse.Aust1n46.chat.api.events.VentureChatEvent;
import mineverse.Aust1n46.chat.channel.ChatChannel;
import mineverse.Aust1n46.chat.utilities.Format;
import net.kyori.adventure.platform.bukkit.BukkitComponentSerializer;
import net.kyori.adventure.text.Component;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.HandlerList;
import org.bukkit.event.Listener;
import org.jetbrains.annotations.NotNull;
public class VentureChatIntegration extends PluginIntegration<BukkitDiscordSRV> implements Listener {
public VentureChatIntegration(BukkitDiscordSRV discordSRV) {
super(discordSRV, new NamedLogger(discordSRV, "VENTURECHAT"));
}
@Override
public @NotNull String getIntegrationName() {
return "VentureChat";
}
@Override
public boolean isEnabled() {
try {
Class.forName("mineverse.Aust1n46.chat.api.events.VentureChatEvent");
} catch (ClassNotFoundException ignored) {
return false;
}
return super.isEnabled();
}
@Override
public void enable() {
discordSRV.server().getPluginManager().registerEvents(this, discordSRV.plugin());
}
@Override
public void disable() {
HandlerList.unregisterAll(this);
}
@EventHandler(priority = org.bukkit.event.EventPriority.MONITOR)
public void onAsyncChatHook(VentureChatEvent event) {
MineverseChatPlayer chatPlayer = event.getMineverseChatPlayer();
Player player = chatPlayer.getPlayer();
if (player == null) {
logger().debug("Bukkit player == null for " + chatPlayer.getName());
return;
}
ChatChannel channel = event.getChannel();
MinecraftComponent component = ComponentUtil.toAPI(
BukkitComponentSerializer.legacy().deserialize(event.getChat())
);
discordSRV.scheduler().run(() -> discordSRV.eventBus().publish(
new GameChatMessageReceiveEvent(
discordSRV.playerProvider().player(player),
new VentureChatChannel(channel),
component,
false
)
));
}
@Subscribe
public void onGameChannelLookup(GameChannelLookupEvent event) {
if (checkProcessor(event)) {
return;
}
ChatChannel channel;
if (event.isDefault()) {
channel = ChatChannel.getDefaultChannel();
} else {
channel = ChatChannel.getChannel(event.getChannelName());
}
if (channel != null) {
event.process(new VentureChatChannel(channel));
}
}
private class VentureChatChannel implements GameChannel {
private final ChatChannel channel;
public VentureChatChannel(ChatChannel channel) {
this.channel = channel;
}
@Override
public @NotNull String getOwnerName() {
return getIntegrationName();
}
@Override
public @NotNull String getChannelName() {
return channel.getName();
}
@Override
public boolean isChat() {
return true;
}
@Override
public void sendMessage(@NotNull MinecraftComponent component) {
Component comp = ComponentUtil.fromAPI(component);
for (MineverseChatPlayer player : MineverseChatAPI.getMineverseChatPlayers()) {
if (!player.isListening(channel.getName())) {
continue;
}
Player bukkitPlayer = player.getPlayer();
if (bukkitPlayer == null) {
continue;
}
if (channel.hasPermission() && !bukkitPlayer.hasPermission(channel.getPermission())) {
continue;
}
if (player.hasFilter() && channel.isFiltered()) {
comp = BukkitComponentSerializer.legacy().deserialize(
Format.FilterChat(
BukkitComponentSerializer.legacy().serialize(comp)
)
);
}
discordSRV.playerProvider().player(bukkitPlayer).sendMessage(comp);
}
}
}
}

View File

@ -22,7 +22,7 @@ import com.discordsrv.api.component.MinecraftComponent;
import com.discordsrv.api.event.events.message.receive.game.GameChatMessageReceiveEvent;
import com.discordsrv.bukkit.BukkitDiscordSRV;
import com.discordsrv.bukkit.component.PaperComponentHandle;
import com.discordsrv.common.channel.DefaultGlobalChannel;
import com.discordsrv.common.channel.GlobalChannel;
import com.discordsrv.common.component.util.ComponentUtil;
import io.papermc.paper.event.player.AsyncChatEvent;
import net.kyori.adventure.platform.bukkit.BukkitComponentSerializer;
@ -53,7 +53,7 @@ public abstract class BukkitChatListener implements Listener {
discordSRV.scheduler().run(() -> discordSRV.eventBus().publish(
new GameChatMessageReceiveEvent(
discordSRV.playerProvider().player(player),
new DefaultGlobalChannel(discordSRV),
new GlobalChannel(discordSRV),
component,
cancelled
)

View File

@ -37,7 +37,6 @@ dependencies {
// Common
implementation project(':common')
implementation project(':common:common-templates')
// DependencyDownload
implementation(libs.mcdependencydownload.bungee.bootstrap)

View File

@ -18,7 +18,6 @@
package com.discordsrv.bungee.console.executor;
import dev.vankka.dynamicproxy.CallOriginal;
import dev.vankka.dynamicproxy.processor.Original;
import dev.vankka.dynamicproxy.processor.Proxy;
import net.kyori.adventure.text.Component;
@ -47,27 +46,27 @@ public abstract class BungeeCommandExecutorProxyTemplate implements CommandSende
@Override
public void sendMessage(BaseComponent... message) {
CallOriginal.call((Object) message);
commandSender.sendMessage(message);
forwardComponent(BungeeComponentSerializer.get().deserialize(message));
}
@Override
public void sendMessage(BaseComponent message) {
CallOriginal.call(message);
commandSender.sendMessage(message);
forwardComponent(BungeeComponentSerializer.get().deserialize(new BaseComponent[]{message}));
}
@Override
@SuppressWarnings({"deprecation", "RedundantSuppression"})
public void sendMessage(String message) {
CallOriginal.call(message);
commandSender.sendMessage(message);
forwardComponent(LegacyComponentSerializer.legacySection().deserialize(message));
}
@Override
@SuppressWarnings({"deprecation", "RedundantSuppression"})
public void sendMessages(String... messages) {
CallOriginal.call((Object) messages);
commandSender.sendMessages(messages);
forwardComponent(LegacyComponentSerializer.legacySection().deserialize(String.join("\n", messages)));
}
}

View File

@ -9,22 +9,22 @@ configurations {
testRuntimeOnly.extendsFrom runtimeDownloadOnly
}
task generateResourceForHikari(type: GenerateDependencyDownloadResourceTask) {
tasks.register('generateResourceForHikari', GenerateDependencyDownloadResourceTask) {
var conf = configurations.hikari
configuration = conf
file = 'dependencies/' + conf.name + '.txt'
}
task generateResourceForH2Driver(type: GenerateDependencyDownloadResourceTask) {
tasks.register('generateResourceForH2Driver', GenerateDependencyDownloadResourceTask) {
var conf = configurations.h2Driver
configuration = conf
file = 'dependencies/' + conf.name + '.txt'
}
task generateResourceForMySQLDriver(type: GenerateDependencyDownloadResourceTask) {
tasks.register('generateResourceForMySQLDriver', GenerateDependencyDownloadResourceTask) {
var conf = configurations.mysqlDriver
configuration = conf
file = 'dependencies/' + conf.name + '.txt'
}
task generateResourceForMCAuthLib(type: GenerateDependencyDownloadResourceTask) {
tasks.register('generateResourceForMCAuthLib', GenerateDependencyDownloadResourceTask) {
var conf = configurations.mcAuthLib
configuration = conf
file = 'dependencies/' + conf.name + '.txt'
@ -65,7 +65,6 @@ dependencies {
runtimeDownloadApi(libs.configurate.hocon)
// Logging
compileOnlyApi project(':common:common-unrelocate')
compileOnly(libs.log4j.core)
// Adventure, MCDiscordReserializer, EnhancedLegacyText

View File

@ -44,6 +44,22 @@ public class ChannelUpdaterModule extends AbstractModule<DiscordSRV> {
super(discordSRV, new NamedLogger(discordSRV, "CHANNEL_UPDATER"));
}
@Override
public boolean isEnabled() {
boolean any = false;
for (ChannelUpdaterConfig channelUpdater : discordSRV.config().channelUpdaters) {
if (!channelUpdater.channelIds.isEmpty()) {
any = true;
break;
}
}
if (!any) {
return false;
}
return super.isEnabled();
}
@Override
public void reloadNoResult() {
futures.forEach(future -> future.cancel(false));
@ -64,7 +80,9 @@ public class ChannelUpdaterModule extends AbstractModule<DiscordSRV> {
try {
// Wait a moment in case we're (re)connecting at the time
discordSRV.waitForStatus(DiscordSRV.Status.CONNECTED, 15, TimeUnit.SECONDS);
} catch (InterruptedException ignored) {}
} catch (InterruptedException ignored) {
Thread.currentThread().interrupt();
}
JDA jda = discordSRV.jda();
if (jda == null) {

View File

@ -1,21 +1,3 @@
/*
* This file is part of DiscordSRV, licensed under the GPLv3 License
* Copyright (c) 2016-2023 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 <https://www.gnu.org/licenses/>.
*/
package com.discordsrv.common.channel;
import com.discordsrv.api.channel.GameChannel;
@ -26,11 +8,11 @@ import com.discordsrv.common.player.IPlayer;
import net.kyori.adventure.text.Component;
import org.jetbrains.annotations.NotNull;
public class DefaultGlobalChannel implements GameChannel {
public class GlobalChannel implements GameChannel {
private final DiscordSRV discordSRV;
public DefaultGlobalChannel(DiscordSRV discordSRV) {
public GlobalChannel(DiscordSRV discordSRV) {
this.discordSRV = discordSRV;
}

View File

@ -26,11 +26,8 @@ import com.discordsrv.common.module.type.AbstractModule;
public class GlobalChannelLookupModule extends AbstractModule<DiscordSRV> {
private final DefaultGlobalChannel defaultGlobalChannel;
public GlobalChannelLookupModule(DiscordSRV discordSRV) {
super(discordSRV);
defaultGlobalChannel = new DefaultGlobalChannel(discordSRV);
}
@Subscribe(priority = EventPriority.LATE)
@ -40,7 +37,7 @@ public class GlobalChannelLookupModule extends AbstractModule<DiscordSRV> {
return;
}
event.process(defaultGlobalChannel);
event.process(new GlobalChannel(discordSRV));
}
}
}

View File

@ -16,9 +16,8 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.discordsrv.common.command.executor;
package com.discordsrv.common.command.game.executor;
import dev.vankka.dynamicproxy.CallOriginal;
import dev.vankka.dynamicproxy.processor.Original;
import dev.vankka.dynamicproxy.processor.Proxy;
import net.kyori.adventure.audience.Audience;
@ -49,73 +48,73 @@ public abstract class AdventureCommandExecutorProxyTemplate implements Audience
@Override
public void sendMessage(@NotNull Identified source, @NotNull ComponentLike message, @NotNull MessageType type) {
CallOriginal.call(source, message, type);
audience.sendMessage(source, message, type);
forwardComponent(message);
}
@Override
public void sendMessage(@NotNull Identity source, @NotNull ComponentLike message, @NotNull MessageType type) {
CallOriginal.call(source, message, type);
audience.sendMessage(source, message, type);
forwardComponent(message);
}
@Override
public void sendMessage(@NotNull Identified source, @NotNull Component message, @NotNull MessageType type) {
CallOriginal.call(source, message, type);
audience.sendMessage(source, message, type);
forwardComponent(message);
}
@Override
public void sendMessage(@NotNull Identity source, @NotNull Component message, @NotNull MessageType type) {
CallOriginal.call(source, message, type);
audience.sendMessage(source, message, type);
forwardComponent(message);
}
@Override
public void sendMessage(@NotNull Identified source, @NotNull ComponentLike message) {
CallOriginal.call(source, message);
audience.sendMessage(source, message);
forwardComponent(message);
}
@Override
public void sendMessage(@NotNull Component message) {
CallOriginal.call(message);
audience.sendMessage(message);
forwardComponent(message);
}
@Override
public void sendMessage(@NotNull ComponentLike message) {
CallOriginal.call(message);
audience.sendMessage(message);
forwardComponent(message);
}
@Override
public void sendMessage(@NotNull Identity source, @NotNull Component message) {
CallOriginal.call(source, message);
audience.sendMessage(source, message);
forwardComponent(message);
}
@Override
public void sendMessage(@NotNull Component message, @NotNull MessageType type) {
CallOriginal.call(message, type);
audience.sendMessage(message, type);
forwardComponent(message);
}
@Override
public void sendMessage(@NotNull Identified source, @NotNull Component message) {
CallOriginal.call(source, message);
audience.sendMessage(source, message);
forwardComponent(message);
}
@Override
public void sendMessage(@NotNull Identity source, @NotNull ComponentLike message) {
CallOriginal.call(source, message);
audience.sendMessage(source, message);
forwardComponent(message);
}
@Override
public void sendMessage(@NotNull ComponentLike message, @NotNull MessageType type) {
CallOriginal.call(message, type);
audience.sendMessage(message, type);
forwardComponent(message);
}
}

View File

@ -1,3 +1,21 @@
/*
* This file is part of DiscordSRV, licensed under the GPLv3 License
* Copyright (c) 2016-2023 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 <https://www.gnu.org/licenses/>.
*/
package com.discordsrv.common.config.connection;
import org.spongepowered.configurate.objectmapping.ConfigSerializable;

View File

@ -18,6 +18,7 @@
package com.discordsrv.common.config.main;
import com.discordsrv.api.channel.GameChannel;
import com.discordsrv.common.config.Config;
import com.discordsrv.common.config.annotation.DefaultOnly;
import com.discordsrv.common.config.main.channels.base.BaseChannelConfig;
@ -28,7 +29,7 @@ import org.spongepowered.configurate.objectmapping.meta.Comment;
import java.util.*;
@ConfigSerializable
public class MainConfig implements Config {
public abstract class MainConfig implements Config {
public static final String FILE_NAME = "config.yaml";
@ -37,9 +38,9 @@ public class MainConfig implements Config {
return FILE_NAME;
}
@DefaultOnly("default")
@DefaultOnly(ChannelConfig.DEFAULT_KEY)
public Map<String, BaseChannelConfig> channels = new LinkedHashMap<String, BaseChannelConfig>() {{
put("global", new ChannelConfig());
put(GameChannel.DEFAULT_NAME, new ChannelConfig());
put(ChannelConfig.DEFAULT_KEY, new BaseChannelConfig());
}};
@ -57,4 +58,6 @@ public class MainConfig implements Config {
@Comment("Configuration for the %discord_invite% placeholder. The below options will be attempted in the order they are in")
public DiscordInviteConfig invite = new DiscordInviteConfig();
public abstract PluginIntegrationConfig integrations();
}

View File

@ -0,0 +1,14 @@
package com.discordsrv.common.config.main;
import org.spongepowered.configurate.objectmapping.ConfigSerializable;
import org.spongepowered.configurate.objectmapping.meta.Comment;
import java.util.ArrayList;
import java.util.List;
@ConfigSerializable
public class PluginIntegrationConfig {
@Comment("Plugin integrations that should be disabled. Specify the names or ids of plugins to disable integrations for")
public List<String> disabledIntegrations = new ArrayList<>();
}

View File

@ -68,6 +68,22 @@ public class GroupSyncModule extends AbstractModule<DiscordSRV> {
.build();
}
@Override
public boolean isEnabled() {
boolean any = false;
for (GroupSyncConfig.PairConfig pair : discordSRV.config().groupSync.pairs) {
if (pair.roleId != 0 && StringUtils.isNotEmpty(pair.groupName)) {
any = true;
break;
}
}
if (!any) {
return false;
}
return super.isEnabled();
}
@Override
public void reloadNoResult() {
synchronized (pairs) {

View File

@ -65,6 +65,11 @@ public class LuckPermsIntegration extends PluginIntegration<DiscordSRV> implemen
super(discordSRV);
}
@Override
public @NotNull String getIntegrationName() {
return "LuckPerms";
}
@Override
public boolean isEnabled() {
try {

View File

@ -20,6 +20,7 @@ package com.discordsrv.common.module.type;
import com.discordsrv.common.DiscordSRV;
import com.discordsrv.common.logging.Logger;
import org.jetbrains.annotations.NotNull;
import javax.annotation.OverridingMethodsMustInvokeSuper;
@ -33,9 +34,15 @@ public abstract class PluginIntegration<DT extends DiscordSRV> extends AbstractM
super(discordSRV, logger);
}
@NotNull
public abstract String getIntegrationName();
@Override
@OverridingMethodsMustInvokeSuper
public boolean isEnabled() {
if (discordSRV.config().integrations().disabledIntegrations.contains(getIntegrationName())) {
return false;
}
return super.isEnabled();
}
}

View File

@ -1,3 +0,0 @@
dependencies {
api project(':common')
}

View File

@ -1,3 +0,0 @@
dependencies {
api(libs.slf4j.api)
}

View File

@ -101,6 +101,10 @@ dependencyResolutionManagement {
library('luckperms', 'net.luckperms', 'api').version('5.4')
library('vaultapi', 'net.milkbowl.vault', 'VaultAPI').version('1.7')
library('placeholderapi-bukkit', 'me.clip', 'placeholderapi').version('2.11.1')
library('townychat', 'com.palmergames.bukkit', 'TownyChat').version('0.45')
library('venturechat', 'mineverse.aust1n46', 'venturechat').version('3.5.0')
library('chatty', 'ru.mrbrikster', 'chatty-api').version('2.19.13')
library('lunachat', 'com.github.ucchyocean.lc', 'LunaChat').version('3.0.16')
// Logging
library('slf4j-api', 'org.slf4j', 'slf4j-api').version('1.7.36')
@ -134,7 +138,7 @@ dependencyResolutionManagement {
rootProject.name = 'DiscordSRV2'
[
'common', 'common:api', 'common:unrelocate', 'common:templates',
'common', 'common:api',
'i18n',
'api',
'bukkit', 'bukkit:loader',

View File

@ -31,7 +31,6 @@ dependencies {
// Common
implementation project(':common')
implementation project(':common:common-templates')
// Dependency Download
implementation(libs.dependencydownload.jarinjar.bootstrap)

View File

@ -18,7 +18,7 @@
package com.discordsrv.sponge.console.executor;
import com.discordsrv.common.command.executor.AdventureCommandExecutorProxy;
import com.discordsrv.common.command.game.executor.AdventureCommandExecutorProxy;
import com.discordsrv.common.command.game.executor.CommandExecutor;
import com.discordsrv.sponge.SpongeDiscordSRV;
import net.kyori.adventure.text.Component;

View File

@ -25,7 +25,6 @@ dependencies {
// Common
implementation project(':common')
implementation project(':common:common-templates')
// Platform
annotationProcessor(libs.velocity)

View File

@ -18,7 +18,7 @@
package com.discordsrv.velocity.console.executor;
import com.discordsrv.common.command.executor.AdventureCommandExecutorProxy;
import com.discordsrv.common.command.game.executor.AdventureCommandExecutorProxy;
import com.discordsrv.common.command.game.executor.CommandExecutor;
import com.discordsrv.velocity.VelocityDiscordSRV;
import com.velocitypowered.api.proxy.ConsoleCommandSource;