Implement command executors, dynamicproxy

This commit is contained in:
Vankka 2022-06-25 22:33:55 +03:00
parent d4975f833a
commit 83fb75d4c0
No known key found for this signature in database
GPG Key ID: 6E50CB7A29B96AD0
31 changed files with 869 additions and 9 deletions

View File

@ -36,6 +36,9 @@ 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

@ -190,7 +190,7 @@ public interface DiscordSRVApi {
ATTEMPTING_TO_CONNECT,
/**
* DiscordSRV is connected to Discord & is ready.
* DiscordSRV is connected to Discord and is ready.
* @see #isReady()
*/
CONNECTED,

View File

@ -32,7 +32,7 @@ import java.util.Optional;
/**
* A Minecraft json text component. Use {@link DiscordSRVApi#componentFactory()} to get an instance.<br/>
* <br/>
* This is designed to work with Adventure, see {@link #adventureAdapter(Class, Class)} & {@link #adventureAdapter(MinecraftComponentAdapter)}
* This is designed to work with Adventure, see {@link #adventureAdapter(Class, Class)} and {@link #adventureAdapter(MinecraftComponentAdapter)}
* but is compatible with anything able to handle Minecraft's json format.
* Legacy is <b>not supported</b>.
*/

View File

@ -83,7 +83,7 @@ public interface DiscordUser extends JDAEntity<User>, Snowflake, Mentionable {
/**
* Gets the Discord user's username followed by a {@code #} and their discriminator.
* @return the Discord user's username & discriminator in the following format {@code Username#1234}
* @return the Discord user's username and discriminator in the following format {@code Username#1234}
*/
@Placeholder("user_tag")
default String getAsTag() {

View File

@ -8,7 +8,7 @@ plugins {
version '2.0.0-SNAPSHOT'
allprojects {
subprojects {
apply plugin: 'java'
apply plugin: 'java-library'
apply plugin: 'com.github.johnrengelman.shadow'
@ -41,8 +41,8 @@ allprojects {
repositories {
// Snapshot repositories
//maven { url 'https://oss.sonatype.org/content/repositories/snapshots/' }
mavenLocal()
maven { url 'https://s01.oss.sonatype.org/content/repositories/snapshots/' }
//mavenLocal()
maven {
url 'https://nexus.scarsz.me/content/groups/public/'
@ -63,10 +63,34 @@ allprojects {
mavenCentral()
}
// Add a 'template' source set to all projects
sourceSets {
template {
java {
compileClasspath += sourceSets.main.compileClasspath
}
}
main {
java {
srcDir sourceSets.template.output.generatedSourcesDirs.getSingleFile()
}
}
}
// 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
testImplementation(libs.jupiter.api)
testRuntimeOnly(libs.jupiter.engine)
// DynamicProxy
templateAnnotationProcessor(libs.dynamicproxy)
}
test {

View File

@ -35,8 +35,9 @@ allprojects {
}
filter {
includeGroup 'com.destroystokyo.paper'
includeGroup 'io.papermc'
includeGroup 'io.papermc.paper'
includeGroup 'org.spigotmc'
includeGroup 'net.md-5'
}
}

View File

@ -20,6 +20,8 @@ package com.discordsrv.bukkit.console;
import com.discordsrv.bukkit.BukkitDiscordSRV;
import com.discordsrv.bukkit.command.game.sender.BukkitCommandSender;
import com.discordsrv.bukkit.console.executor.BukkitCommandExecutorProvider;
import com.discordsrv.common.command.game.executor.CommandExecutorProvider;
import com.discordsrv.common.console.Console;
import com.discordsrv.common.logging.NamedLogger;
import com.discordsrv.common.logging.backend.LoggingBackend;
@ -29,6 +31,7 @@ import com.discordsrv.common.logging.backend.impl.Log4JLoggerImpl;
public class BukkitConsole extends BukkitCommandSender implements Console {
private final LoggingBackend loggingBackend;
private final CommandExecutorProvider executorProvider;
public BukkitConsole(BukkitDiscordSRV discordSRV) {
super(discordSRV, discordSRV.server().getConsoleSender(), () -> discordSRV.audiences().console());
@ -45,10 +48,16 @@ public class BukkitConsole extends BukkitCommandSender implements Console {
logging = JavaLoggerImpl.getRoot();
}
this.loggingBackend = logging;
this.executorProvider = new BukkitCommandExecutorProvider(discordSRV);
}
@Override
public LoggingBackend loggingBackend() {
return loggingBackend;
}
@Override
public CommandExecutorProvider commandExecutorProvider() {
return executorProvider;
}
}

View File

@ -0,0 +1,58 @@
/*
* This file is part of DiscordSRV, licensed under the GPLv3 License
* Copyright (c) 2016-2022 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.console.executor;
import com.discordsrv.bukkit.BukkitDiscordSRV;
import com.discordsrv.common.command.game.executor.CommandExecutor;
import com.discordsrv.common.command.game.executor.CommandExecutorProvider;
import net.kyori.adventure.text.Component;
import org.bukkit.command.CommandSender;
import java.util.function.Consumer;
public class BukkitCommandExecutorProvider implements CommandExecutorProvider {
private static final boolean HAS_PAPER_FORWARDING;
static {
boolean has = false;
try {
has = PaperCommandExecutor.CREATE_COMMAND_SENDER != null;
} catch (Throwable ignored) {}
HAS_PAPER_FORWARDING = has;
}
private final BukkitDiscordSRV discordSRV;
public BukkitCommandExecutorProvider(BukkitDiscordSRV discordSRV) {
this.discordSRV = discordSRV;
}
@Override
public CommandExecutor getConsoleExecutor(Consumer<Component> componentConsumer) {
if (HAS_PAPER_FORWARDING) {
try {
return new PaperCommandExecutor(discordSRV, componentConsumer);
} catch (Throwable ignored) {}
}
CommandSender commandSender = new BukkitCommandExecutorProxy(discordSRV.server().getConsoleSender(), componentConsumer).getProxy();
return new CommandSenderExecutor(discordSRV, commandSender);
}
}

View File

@ -0,0 +1,39 @@
/*
* This file is part of DiscordSRV, licensed under the GPLv3 License
* Copyright (c) 2016-2022 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.console.executor;
import com.discordsrv.bukkit.BukkitDiscordSRV;
import com.discordsrv.common.command.game.executor.CommandExecutor;
import org.bukkit.command.CommandSender;
public class CommandSenderExecutor implements CommandExecutor {
private final BukkitDiscordSRV discordSRV;
private final CommandSender commandSender;
public CommandSenderExecutor(BukkitDiscordSRV discordSRV, CommandSender commandSender) {
this.discordSRV = discordSRV;
this.commandSender = commandSender;
}
@Override
public void runCommand(String command) {
discordSRV.scheduler().runOnMainThread(() -> discordSRV.server().dispatchCommand(commandSender, command));
}
}

View File

@ -0,0 +1,49 @@
/*
* This file is part of DiscordSRV, licensed under the GPLv3 License
* Copyright (c) 2016-2022 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.console.executor;
import com.discordsrv.bukkit.BukkitDiscordSRV;
import net.kyori.adventure.text.Component;
import org.bukkit.Server;
import org.bukkit.command.CommandSender;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.util.function.Consumer;
@SuppressWarnings("JavaLangInvokeHandleSignature") // PaperAPI that is not included at compile accessed via reflection
public class PaperCommandExecutor extends CommandSenderExecutor {
public static final MethodHandle CREATE_COMMAND_SENDER;
static {
MethodHandles.Lookup lookup = MethodHandles.lookup();
MethodHandle handle = null;
try {
MethodType methodType = MethodType.methodType(CommandSender.class, Consumer.class);
handle = lookup.findVirtual(Server.class, "createCommandSender", methodType);
} catch (Throwable ignored) {}
CREATE_COMMAND_SENDER = handle;
}
public PaperCommandExecutor(BukkitDiscordSRV discordSRV, Consumer<Component> componentConsumer) throws Throwable {
super(discordSRV, (CommandSender) CREATE_COMMAND_SENDER.invoke(componentConsumer));
}
}

View File

@ -0,0 +1,122 @@
/*
* This file is part of DiscordSRV, licensed under the GPLv3 License
* Copyright (c) 2016-2022 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.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;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.serializer.bungeecord.BungeeComponentSerializer;
import net.md_5.bungee.api.chat.BaseComponent;
import org.bukkit.command.CommandSender;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.UUID;
import java.util.function.Consumer;
@Proxy(value = CommandSender.class, className = "BukkitCommandExecutorProxy")
public abstract class BukkitCommandExecutorProxyTemplate implements CommandSender {
@Original
private final CommandSender commandSender;
private final Consumer<Component> componentConsumer;
private Spigot spigot;
public BukkitCommandExecutorProxyTemplate(CommandSender commandSender, Consumer<Component> componentConsumer) {
this.commandSender = commandSender;
this.componentConsumer = componentConsumer;
try {
spigot = new Spigot(commandSender.spigot());
} catch (Throwable ignored) {}
}
@Override
public void sendMessage(@Nullable UUID sender, @NotNull String... messages) {
forwardLegacy(String.join("\n", messages));
CallOriginal.call(sender, messages);
}
@Override
public void sendMessage(@NotNull String... messages) {
forwardLegacy(String.join("\n", messages));
CallOriginal.call((Object) messages);
}
@Override
public void sendMessage(@Nullable UUID sender, @NotNull String message) {
forwardLegacy(message);
CallOriginal.call(sender, message);
}
@Override
public void sendMessage(@NotNull String message) {
forwardLegacy(message);
CallOriginal.call(message);
}
private void forwardLegacy(String legacy) {
componentConsumer.accept(BukkitComponentSerializer.legacy().deserialize(legacy));
}
@Override
public @NotNull CommandSender.Spigot spigot() {
return spigot;
}
@SuppressWarnings("deprecation")
public class Spigot extends CommandSender.Spigot {
private final CommandSender.Spigot spigot;
Spigot(CommandSender.Spigot spigot) {
this.spigot = spigot;
}
@Override
public void sendMessage(@Nullable UUID sender, @NotNull BaseComponent component) {
spigot.sendMessage(sender, component);
forwardBungee(new BaseComponent[] {component});
}
@Override
public void sendMessage(@NotNull BaseComponent component) {
spigot.sendMessage(component);
forwardBungee(new BaseComponent[] {component});
}
@Override
public void sendMessage(@Nullable UUID sender, @NotNull BaseComponent... components) {
spigot.sendMessage(components);
forwardBungee(components);
}
@Override
public void sendMessage(@NotNull BaseComponent... components) {
spigot.sendMessage(components);
forwardBungee(components);
}
private void forwardBungee(BaseComponent[] components) {
componentConsumer.accept(BungeeComponentSerializer.get().deserialize(components));
}
}
}

View File

@ -20,6 +20,8 @@ package com.discordsrv.bungee.console;
import com.discordsrv.bungee.BungeeDiscordSRV;
import com.discordsrv.bungee.command.game.sender.BungeeCommandSender;
import com.discordsrv.bungee.console.executor.BungeeCommandExecutorProvider;
import com.discordsrv.common.command.game.executor.CommandExecutorProvider;
import com.discordsrv.common.console.Console;
import com.discordsrv.common.logging.backend.LoggingBackend;
import com.discordsrv.common.logging.backend.impl.JavaLoggerImpl;
@ -27,14 +29,21 @@ import com.discordsrv.common.logging.backend.impl.JavaLoggerImpl;
public class BungeeConsole extends BungeeCommandSender implements Console {
private final LoggingBackend loggingBackend;
private final BungeeCommandExecutorProvider executorProvider;
public BungeeConsole(BungeeDiscordSRV discordSRV) {
super(discordSRV, discordSRV.proxy().getConsole(), () -> discordSRV.audiences().console());
this.loggingBackend = JavaLoggerImpl.getRoot();
this.executorProvider = new BungeeCommandExecutorProvider(discordSRV);
}
@Override
public LoggingBackend loggingBackend() {
return loggingBackend;
}
@Override
public CommandExecutorProvider commandExecutorProvider() {
return executorProvider;
}
}

View File

@ -0,0 +1,45 @@
/*
* This file is part of DiscordSRV, licensed under the GPLv3 License
* Copyright (c) 2016-2022 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.bungee.console.executor;
import com.discordsrv.bungee.BungeeDiscordSRV;
import com.discordsrv.common.command.game.executor.CommandExecutor;
import net.kyori.adventure.text.Component;
import net.md_5.bungee.api.CommandSender;
import java.util.function.Consumer;
public class BungeeCommandExecutor implements CommandExecutor {
private final BungeeDiscordSRV discordSRV;
private final CommandSender commandSender;
public BungeeCommandExecutor(BungeeDiscordSRV discordSRV, Consumer<Component> componentConsumer) {
this.discordSRV = discordSRV;
this.commandSender = new BungeeCommandExecutorProxy(
discordSRV.proxy().getConsole(),
componentConsumer
).getProxy();
}
@Override
public void runCommand(String command) {
discordSRV.proxy().getPluginManager().dispatchCommand(commandSender, command);
}
}

View File

@ -0,0 +1,40 @@
/*
* This file is part of DiscordSRV, licensed under the GPLv3 License
* Copyright (c) 2016-2022 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.bungee.console.executor;
import com.discordsrv.bungee.BungeeDiscordSRV;
import com.discordsrv.common.command.game.executor.CommandExecutor;
import com.discordsrv.common.command.game.executor.CommandExecutorProvider;
import net.kyori.adventure.text.Component;
import java.util.function.Consumer;
public class BungeeCommandExecutorProvider implements CommandExecutorProvider {
private final BungeeDiscordSRV discordSRV;
public BungeeCommandExecutorProvider(BungeeDiscordSRV discordSRV) {
this.discordSRV = discordSRV;
}
@Override
public CommandExecutor getConsoleExecutor(Consumer<Component> componentConsumer) {
return new BungeeCommandExecutor(discordSRV, componentConsumer);
}
}

View File

@ -0,0 +1,71 @@
/*
* This file is part of DiscordSRV, licensed under the GPLv3 License
* Copyright (c) 2016-2022 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.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;
import net.kyori.adventure.text.serializer.bungeecord.BungeeComponentSerializer;
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
import net.md_5.bungee.api.CommandSender;
import net.md_5.bungee.api.chat.BaseComponent;
import java.util.function.Consumer;
@Proxy(value = CommandSender.class, className = "BungeeCommandExecutorProxy")
public abstract class BungeeCommandExecutorProxyTemplate implements CommandSender {
@Original
private final CommandSender commandSender;
private final Consumer<Component> componentConsumer;
public BungeeCommandExecutorProxyTemplate(CommandSender commandSender, Consumer<Component> componentConsumer) {
this.commandSender = commandSender;
this.componentConsumer = componentConsumer;
}
private void forwardComponent(Component component) {
this.componentConsumer.accept(component);
}
@Override
public void sendMessage(BaseComponent... message) {
CallOriginal.call((Object) message);
forwardComponent(BungeeComponentSerializer.get().deserialize(message));
}
@Override
public void sendMessage(BaseComponent message) {
CallOriginal.call(message);
forwardComponent(BungeeComponentSerializer.get().deserialize(new BaseComponent[]{message}));
}
@Override
public void sendMessage(String message) {
CallOriginal.call(message);
forwardComponent(LegacyComponentSerializer.legacySection().deserialize(message));
}
@Override
public void sendMessages(String... messages) {
CallOriginal.call((Object) messages);
forwardComponent(LegacyComponentSerializer.legacySection().deserialize(String.join("\n", messages)));
}
}

View File

@ -51,6 +51,9 @@ dependencies {
exclude group: 'com.google.errorprone', module: 'error_prone_annotations'
}
// DynamicProxy
runtimeDownloadApi(libs.dynamicproxy)
// Jackson (transitive in :api)
compileOnlyApi(libs.jackson.databind)

View File

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

View File

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

View File

@ -0,0 +1,24 @@
/*
* This file is part of DiscordSRV, licensed under the GPLv3 License
* Copyright (c) 2016-2022 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.command.game.executor;
public interface CommandExecutor {
void runCommand(String command);
}

View File

@ -0,0 +1,29 @@
/*
* This file is part of DiscordSRV, licensed under the GPLv3 License
* Copyright (c) 2016-2022 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.command.game.executor;
import net.kyori.adventure.text.Component;
import java.util.function.Consumer;
@FunctionalInterface
public interface CommandExecutorProvider {
CommandExecutor getConsoleExecutor(Consumer<Component> componentConsumer);
}

View File

@ -18,13 +18,14 @@
package com.discordsrv.common.command.game.sender;
import com.discordsrv.common.command.game.executor.CommandExecutor;
import net.kyori.adventure.audience.ForwardingAudience;
import net.kyori.adventure.audience.MessageType;
import net.kyori.adventure.identity.Identity;
import net.kyori.adventure.text.Component;
import org.jetbrains.annotations.NotNull;
public interface ICommandSender extends ForwardingAudience.Single {
public interface ICommandSender extends ForwardingAudience.Single, CommandExecutor {
/**
* Sends a message to this {@link ICommandSender} with {@link Identity#nil()}.
@ -44,6 +45,5 @@ public interface ICommandSender extends ForwardingAudience.Single {
}
boolean hasPermission(String permission);
void runCommand(String command);
}

View File

@ -18,6 +18,7 @@
package com.discordsrv.common.console;
import com.discordsrv.common.command.game.executor.CommandExecutorProvider;
import com.discordsrv.common.command.game.sender.ICommandSender;
import com.discordsrv.common.logging.backend.LoggingBackend;
@ -28,4 +29,6 @@ public interface Console extends ICommandSender {
* @return the {@link LoggingBackend}
*/
LoggingBackend loggingBackend();
CommandExecutorProvider commandExecutorProvider();
}

View File

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

View File

@ -0,0 +1,121 @@
/*
* This file is part of DiscordSRV, licensed under the GPLv3 License
* Copyright (c) 2016-2022 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.command.executor;
import dev.vankka.dynamicproxy.CallOriginal;
import dev.vankka.dynamicproxy.processor.Original;
import dev.vankka.dynamicproxy.processor.Proxy;
import net.kyori.adventure.audience.Audience;
import net.kyori.adventure.audience.MessageType;
import net.kyori.adventure.identity.Identified;
import net.kyori.adventure.identity.Identity;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.ComponentLike;
import org.jetbrains.annotations.NotNull;
import java.util.function.Consumer;
@Proxy(value = Audience.class, className = "AdventureCommandExecutorProxy")
public abstract class AdventureCommandExecutorProxyTemplate implements Audience {
@Original
private final Audience audience;
private final Consumer<Component> componentConsumer;
public AdventureCommandExecutorProxyTemplate(Audience audience, Consumer<Component> componentConsumer) {
this.audience = audience;
this.componentConsumer = componentConsumer;
}
private void forwardComponent(ComponentLike component) {
componentConsumer.accept(component.asComponent());
}
@Override
public void sendMessage(@NotNull Identified source, @NotNull ComponentLike message, @NotNull MessageType type) {
CallOriginal.call(source, message, type);
forwardComponent(message);
}
@Override
public void sendMessage(@NotNull Identity source, @NotNull ComponentLike message, @NotNull MessageType type) {
CallOriginal.call(source, message, type);
forwardComponent(message);
}
@Override
public void sendMessage(@NotNull Identified source, @NotNull Component message, @NotNull MessageType type) {
CallOriginal.call(source, message, type);
forwardComponent(message);
}
@Override
public void sendMessage(@NotNull Identity source, @NotNull Component message, @NotNull MessageType type) {
CallOriginal.call(source, message, type);
forwardComponent(message);
}
@Override
public void sendMessage(@NotNull Identified source, @NotNull ComponentLike message) {
CallOriginal.call(source, message);
forwardComponent(message);
}
@Override
public void sendMessage(@NotNull Component message) {
CallOriginal.call(message);
forwardComponent(message);
}
@Override
public void sendMessage(@NotNull ComponentLike message) {
CallOriginal.call(message);
forwardComponent(message);
}
@Override
public void sendMessage(@NotNull Identity source, @NotNull Component message) {
CallOriginal.call(source, message);
forwardComponent(message);
}
@Override
public void sendMessage(@NotNull Component message, @NotNull MessageType type) {
CallOriginal.call(message, type);
forwardComponent(message);
}
@Override
public void sendMessage(@NotNull Identified source, @NotNull Component message) {
CallOriginal.call(source, message);
forwardComponent(message);
}
@Override
public void sendMessage(@NotNull Identity source, @NotNull ComponentLike message) {
CallOriginal.call(source, message);
forwardComponent(message);
}
@Override
public void sendMessage(@NotNull ComponentLike message, @NotNull MessageType type) {
CallOriginal.call(message, type);
forwardComponent(message);
}
}

View File

@ -71,6 +71,9 @@ dependencyResolutionManagement {
reject '[3,)' // Java 11
}
// DynamicProxy
library('dynamicproxy', 'dev.vankka', 'dynamicproxy').version('1.0.0-SNAPSHOT')
// Jackson
library('jackson-databind', 'com.fasterxml.jackson.core', 'jackson-databind').version('2.10.1')
@ -131,7 +134,7 @@ dependencyResolutionManagement {
rootProject.name = 'DiscordSRV2'
[
'common', 'common:api', 'common:server', 'common:proxy', 'common:unrelocate',
'common', 'common:api', 'common:server', 'common:proxy', 'common:unrelocate', 'common:templates',
'i18n',
'api',
'bukkit', 'bukkit:loader',

View File

@ -18,23 +18,32 @@
package com.discordsrv.sponge.console;
import com.discordsrv.common.command.game.executor.CommandExecutorProvider;
import com.discordsrv.common.console.Console;
import com.discordsrv.common.logging.backend.LoggingBackend;
import com.discordsrv.common.logging.backend.impl.Log4JLoggerImpl;
import com.discordsrv.sponge.SpongeDiscordSRV;
import com.discordsrv.sponge.command.game.sender.SpongeCommandSender;
import com.discordsrv.sponge.console.executor.SpongeCommandExecutorProvider;
public class SpongeConsole extends SpongeCommandSender implements Console {
private final LoggingBackend loggingBackend;
private final SpongeCommandExecutorProvider executorProvider;
public SpongeConsole(SpongeDiscordSRV discordSRV) {
super(discordSRV, () -> discordSRV.game().systemSubject(), () -> discordSRV.game().systemSubject());
this.loggingBackend = Log4JLoggerImpl.getRoot();
this.executorProvider = new SpongeCommandExecutorProvider(discordSRV);
}
@Override
public LoggingBackend loggingBackend() {
return loggingBackend;
}
@Override
public CommandExecutorProvider commandExecutorProvider() {
return executorProvider;
}
}

View File

@ -0,0 +1,58 @@
/*
* This file is part of DiscordSRV, licensed under the GPLv3 License
* Copyright (c) 2016-2022 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.sponge.console.executor;
import com.discordsrv.common.command.executor.AdventureCommandExecutorProxy;
import com.discordsrv.common.command.game.executor.CommandExecutor;
import com.discordsrv.sponge.SpongeDiscordSRV;
import net.kyori.adventure.text.Component;
import org.spongepowered.api.SystemSubject;
import org.spongepowered.api.command.exception.CommandException;
import java.util.function.Consumer;
public class SpongeCommandExecutor implements CommandExecutor {
private final SpongeDiscordSRV discordSRV;
private final SystemSubject subject;
public SpongeCommandExecutor(SpongeDiscordSRV discordSRV, Consumer<Component> componentConsumer) {
this.discordSRV = discordSRV;
this.subject = (SystemSubject) new AdventureCommandExecutorProxy(
discordSRV.game().systemSubject(),
componentConsumer
).getProxy();
}
@Override
public void runCommand(String command) {
discordSRV.scheduler().runOnMainThread(() -> runOnMain(command));
}
private void runOnMain(String command) {
try {
discordSRV.game().server().commandManager().process(subject, command);
} catch (CommandException e) {
Component message = e.componentMessage();
if (message != null) {
subject.sendMessage(message);
}
}
}
}

View File

@ -0,0 +1,40 @@
/*
* This file is part of DiscordSRV, licensed under the GPLv3 License
* Copyright (c) 2016-2022 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.sponge.console.executor;
import com.discordsrv.common.command.game.executor.CommandExecutor;
import com.discordsrv.common.command.game.executor.CommandExecutorProvider;
import com.discordsrv.sponge.SpongeDiscordSRV;
import net.kyori.adventure.text.Component;
import java.util.function.Consumer;
public class SpongeCommandExecutorProvider implements CommandExecutorProvider {
private final SpongeDiscordSRV discordSRV;
public SpongeCommandExecutorProvider(SpongeDiscordSRV discordSRV) {
this.discordSRV = discordSRV;
}
@Override
public CommandExecutor getConsoleExecutor(Consumer<Component> componentConsumer) {
return new SpongeCommandExecutor(discordSRV, componentConsumer);
}
}

View File

@ -18,23 +18,32 @@
package com.discordsrv.velocity.console;
import com.discordsrv.common.command.game.executor.CommandExecutorProvider;
import com.discordsrv.common.console.Console;
import com.discordsrv.common.logging.backend.LoggingBackend;
import com.discordsrv.common.logging.backend.impl.Log4JLoggerImpl;
import com.discordsrv.velocity.VelocityDiscordSRV;
import com.discordsrv.velocity.command.game.sender.VelocityCommandSender;
import com.discordsrv.velocity.console.executor.VelocityCommandExecutorProvider;
public class VelocityConsole extends VelocityCommandSender implements Console {
private final LoggingBackend loggingBackend;
private final VelocityCommandExecutorProvider executorProvider;
public VelocityConsole(VelocityDiscordSRV discordSRV) {
super(discordSRV, discordSRV.proxy().getConsoleCommandSource());
this.loggingBackend = Log4JLoggerImpl.getRoot();
this.executorProvider = new VelocityCommandExecutorProvider(discordSRV);
}
@Override
public LoggingBackend loggingBackend() {
return loggingBackend;
}
@Override
public CommandExecutorProvider commandExecutorProvider() {
return executorProvider;
}
}

View File

@ -0,0 +1,46 @@
/*
* This file is part of DiscordSRV, licensed under the GPLv3 License
* Copyright (c) 2016-2022 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.velocity.console.executor;
import com.discordsrv.common.command.executor.AdventureCommandExecutorProxy;
import com.discordsrv.common.command.game.executor.CommandExecutor;
import com.discordsrv.velocity.VelocityDiscordSRV;
import com.velocitypowered.api.proxy.ConsoleCommandSource;
import net.kyori.adventure.text.Component;
import java.util.function.Consumer;
public class VelocityCommandExecutor implements CommandExecutor {
private final VelocityDiscordSRV discordSRV;
private final ConsoleCommandSource source;
public VelocityCommandExecutor(VelocityDiscordSRV discordSRV, Consumer<Component> componentConsumer) {
this.discordSRV = discordSRV;
this.source = (ConsoleCommandSource) new AdventureCommandExecutorProxy(
discordSRV.proxy().getConsoleCommandSource(),
componentConsumer
).getProxy();
}
@Override
public void runCommand(String command) {
discordSRV.proxy().getCommandManager().executeAsync(source, command);
}
}

View File

@ -0,0 +1,40 @@
/*
* This file is part of DiscordSRV, licensed under the GPLv3 License
* Copyright (c) 2016-2022 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.velocity.console.executor;
import com.discordsrv.common.command.game.executor.CommandExecutor;
import com.discordsrv.common.command.game.executor.CommandExecutorProvider;
import com.discordsrv.velocity.VelocityDiscordSRV;
import net.kyori.adventure.text.Component;
import java.util.function.Consumer;
public class VelocityCommandExecutorProvider implements CommandExecutorProvider {
private final VelocityDiscordSRV discordSRV;
public VelocityCommandExecutorProvider(VelocityDiscordSRV discordSRV) {
this.discordSRV = discordSRV;
}
@Override
public CommandExecutor getConsoleExecutor(Consumer<Component> componentConsumer) {
return new VelocityCommandExecutor(discordSRV, componentConsumer);
}
}