Initial commit

This commit is contained in:
Vankka 2021-07-29 04:14:29 +03:00
commit 9d26da6b4a
No known key found for this signature in database
GPG Key ID: 6E50CB7A29B96AD0
179 changed files with 11997 additions and 0 deletions

27
.github/workflows/crowdin-download.yaml vendored Normal file
View File

@ -0,0 +1,27 @@
name: Crowdin translation download
on:
push:
branches: [dev]
jobs:
synchronize-with-crowdin:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Download translations from Crowdin
uses: crowdin/github-action@1.1.0
with:
upload_translations: false
download_translations: true
localization_branch_name: i18n
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"
project_id: ${{ secrets.CROWDIN_PROJECT_ID }}
token: ${{ secrets.CROWDIN_PERSONAL_TOKEN }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

35
.github/workflows/crowdin-upload.yaml vendored Normal file
View File

@ -0,0 +1,35 @@
name: Crowdin translation upload
on:
push:
branches: [dev]
jobs:
synchronize-with-crowdin:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Java
uses: actions/setup-java@v2
with:
distribution: "adopt"
java-version: "11"
- name: Make gradlew execuable
run: "sudo chmod +x gradlew"
- name: Build i18n application
run: "./gradlew i18n:build"
- name: Generate translation source
run: "java -jar i18n/build/libs/i18n-all.jar"
- name: Upload translations to Crowdin
uses: crowdin/github-action@1.1.0
with:
upload_translations: true
download_translations: false
localization_branch_name: i18n
source: "source.yml"
translation: "/%original_path%/src/main/resources/translations/%three_letters_code%.yml"
project_id: ${{ secrets.CROWDIN_PROJECT_ID }}
token: ${{ secrets.CROWDIN_PERSONAL_TOKEN }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

39
.gitignore vendored Normal file
View File

@ -0,0 +1,39 @@
# Gradle
.gradle
**/build/
!src/**/build/
# Ignore Gradle GUI config
gradle-app.setting
# IntelliJ
.idea/
*.iml
out/
# Compiled class file
*.class
# Log file
*.log
# BlueJ files
*.ctxt
# Mobile Tools for Java (J2ME)
.mtj.tmp/
# Package Files #
*.jar
*.war
*.nar
*.ear
*.zip
*.tar.gz
*.rar
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)
!gradle-wrapper.jar

7
LICENSE.txt Normal file
View File

@ -0,0 +1,7 @@
DiscordSRV is dual licensed
The `api`-module is licensed under the MIT License.
Everything else is licensed under GPLv3 or later, unless otherwise noted.
You may view these licenses in the `licenses` directory.

36
api/build.gradle Normal file
View File

@ -0,0 +1,36 @@
apply from: rootProject.file('buildscript/relocations.gradle')
dependencies {
// Annotations
compileOnlyApi 'org.jetbrains:annotations:21.0.1'
compileOnlyApi 'com.google.code.findbugs:jsr305:3.0.2'
// JDA
api('net.dv8tion:JDA:' + rootProject.jdaVersion) {
// Annotations are suppose to be compile time only
exclude group: 'org.jetbrains', module: 'annotations'
exclude group: 'com.google.code.findbugs', module: 'jsr305'
// We don't use audio
exclude module: 'opus-java'
}
}
// Relocations are in buildscript/api.gradle
sourceSets {
ap {
java {
compileClasspath += sourceSets.main.compileClasspath + sourceSets.main.output
}
}
}
jar {
from sourceSets.ap.output
}
license {
// Overwrite the default
header = rootProject.file('buildscript/license/API_LICENSE_HEADER')
}

View File

@ -0,0 +1,113 @@
/*
* 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.processor;
import com.discordsrv.api.event.bus.Subscribe;
import javax.annotation.processing.*;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.*;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.util.Elements;
import javax.lang.model.util.Types;
import java.util.List;
import java.util.Set;
import static javax.tools.Diagnostic.Kind.ERROR;
/**
* Annotation processor for {@link Subscribe}, gives a error during compilation if a given listener method is wrong.
*/
@SupportedAnnotationTypes(SubscribeProcessor.SUBSCRIBE_CLASS_NAME)
@SupportedSourceVersion(SourceVersion.RELEASE_8)
public class SubscribeProcessor extends AbstractProcessor {
protected static final String SUBSCRIBE_CLASS_NAME = "com.discordsrv.api.event.bus.Subscribe";
protected static final String EVENT_CLASS_NAME = "com.discordsrv.api.event.events.Event";
protected static final String JDA_EVENT_CLASS_NAME = "net.dv8tion.jda.api.events.GenericEvent";
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
Elements elements = processingEnv.getElementUtils();
Types types = processingEnv.getTypeUtils();
TypeMirror eventMirror = types.getDeclaredType(elements.getTypeElement(EVENT_CLASS_NAME));
TypeMirror jdaEventMirror = types.getDeclaredType(elements.getTypeElement(JDA_EVENT_CLASS_NAME));
TypeElement subscribeType = elements.getTypeElement(SUBSCRIBE_CLASS_NAME);
boolean hasAnnotation = false;
for (TypeElement annotation : annotations) {
if (annotation.equals(subscribeType)) {
hasAnnotation = true;
break;
}
}
if (!hasAnnotation) {
return false;
}
for (Element element : roundEnv.getElementsAnnotatedWith(Subscribe.class)) {
Messager messager = processingEnv.getMessager();
if (element.getKind() != ElementKind.METHOD) {
messager.printMessage(ERROR, "@Subscribe can only be used on methods", element);
continue;
}
ExecutableElement method = (ExecutableElement) element;
if (method.getEnclosingElement().getKind().isInterface()) {
messager.printMessage(ERROR, "Cannot be used on interfaces", element);
}
if (method.getReturnType().getKind() != TypeKind.VOID) {
messager.printMessage(ERROR, "Must return void", element);
}
Set<Modifier> modifiers = method.getModifiers();
if (!modifiers.contains(Modifier.PUBLIC)) {
messager.printMessage(ERROR, "Must be public", element);
}
if (modifiers.contains(Modifier.STATIC)) {
messager.printMessage(ERROR, "Must not be static", element);
}
if (modifiers.contains(Modifier.ABSTRACT)) {
messager.printMessage(ERROR, "Cannot be abstract", element);
}
List<? extends VariableElement> parameters = method.getParameters();
if (parameters.isEmpty()) {
messager.printMessage(ERROR, "Method doesn't have a DiscordSRV or JDA event as the only parameter", element);
continue;
}
if (parameters.size() > 1) {
messager.printMessage(ERROR, "Method should only have the DiscordSRV or JDA event as a parameter", element);
}
TypeMirror firstParameter = parameters.get(0).asType();
if (!types.isAssignable(firstParameter, eventMirror) && !types.isAssignable(firstParameter, jdaEventMirror)) {
messager.printMessage(ERROR, "First argument is not a DiscordSRV or JDA event", element);
}
}
return false;
}
}

View File

@ -0,0 +1 @@
com.discordsrv.api.processor.SubscribeProcessor

View File

@ -0,0 +1,203 @@
/*
* 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;
import com.discordsrv.api.component.MinecraftComponentFactory;
import com.discordsrv.api.discord.api.DiscordAPI;
import com.discordsrv.api.discord.connection.DiscordConnectionDetails;
import com.discordsrv.api.event.bus.EventBus;
import com.discordsrv.api.player.DiscordSRVPlayer;
import com.discordsrv.api.player.IPlayerProvider;
import net.dv8tion.jda.api.JDA;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* The DiscordSRV API.
*
* Use your platform's service provider or {@link DiscordSRVApiProvider} to get the instance.
*/
@SuppressWarnings("unused") // API
public interface DiscordSRVApi {
/**
* The status of this DiscordSRV instance.
* @return the current status of this DiscordSRV instance
*/
@NotNull
Status status();
/**
* The event bus, can be used for listening to DiscordSRV and JDA events.
* @return the event bus
*/
@NotNull
EventBus eventBus();
/**
* A provider for {@link com.discordsrv.api.component.MinecraftComponent}s.
* @return the {@link com.discordsrv.api.component.MinecraftComponentFactory} instance.
*/
@NotNull
MinecraftComponentFactory componentFactory();
/**
* A provider for {@link DiscordSRVPlayer} instances.
* @return the {@link IPlayerProvider} instance
*/
@NotNull
IPlayerProvider playerProvider();
/**
* Gets DiscordSRV's first party API wrapper for Discord. This contains limited methods but is less likely to break compared to {@link #jda()}.
* @return the {@link DiscordAPI} instance
* @see #isReady()
*/
@NotNull
DiscordAPI discordAPI();
/**
* Access to {@link JDA}, the Discord library used by DiscordSRV.
* @return the JDA instance, if available
*
* <p>
* JDA is an external API, using DiscordSRV's APIs where possible is recommended. Please see <a href="https://github.com/DV8FromTheWorld/JDA#deprecation-policy">JDA's deprecation policy</a>.
* @see #isReady()
* @see #discordConnectionDetails()
*/
@Nullable
JDA jda();
/**
* Discord connection detail manager, specify {@link net.dv8tion.jda.api.requests.GatewayIntent}s and {@link net.dv8tion.jda.api.utils.cache.CacheFlag}s you need here.
* @return the {@link DiscordConnectionDetails} instance
*/
@NotNull
DiscordConnectionDetails discordConnectionDetails();
/**
* {@link #status()} = {@link Status#CONNECTED}.
* @return if DiscordSRV is ready
*/
@ApiStatus.NonExtendable
default boolean isReady() {
return status().isReady();
}
/**
* {@link #status()} = {@link Status#SHUTTING_DOWN} or {@link Status#SHUTDOWN}.
* @return if DiscordSRV is shutting down or has shutdown
*/
@ApiStatus.NonExtendable
default boolean isShutdown() {
return status().isShutdown();
}
enum Status {
/**
* DiscordSRV has not yet started.
*/
INITIALIZED,
/**
* DiscordSRV failed to load its configuration.
* @see #isError()
* @see #isStartupError()
*/
FAILED_TO_LOAD_CONFIG(true),
/**
* DiscordSRV failed to start, unless the configuration failed to load, in that case the status will be {@link #FAILED_TO_LOAD_CONFIG}.
* @see #isError()
* @see #isStartupError()
*/
FAILED_TO_START(true),
/**
* DiscordSRV is attempting to connect to Discord.
*/
ATTEMPTING_TO_CONNECT,
/**
* DiscordSRV failed to connect to Discord.
* @see #isError()
*/
FAILED_TO_CONNECT(true),
/**
* DiscordSRV is connected to Discord & is ready.
* @see #isReady()
*/
CONNECTED,
/**
* DiscordSRV is shutting down.
* @see #isShutdown()
*/
SHUTTING_DOWN(false, true),
/**
* DiscordSRV has shutdown.
* @see #isShutdown()
*/
SHUTDOWN(false, true),
;
private final boolean error;
private final boolean shutdown;
Status() {
this(false);
}
Status(boolean error) {
this(error, false);
}
Status(boolean error, boolean shutdown) {
this.error = error;
this.shutdown = shutdown;
}
public boolean isError() {
return error;
}
public boolean isShutdown() {
return shutdown;
}
public boolean isStartupError() {
return this == FAILED_TO_START || this == FAILED_TO_LOAD_CONFIG;
}
public boolean isReady() {
return this == CONNECTED;
}
}
}

View File

@ -0,0 +1,72 @@
/*
* 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;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.Nullable;
import java.util.Optional;
/**
* The {@link DiscordSRVApi} provider.
*/
@SuppressWarnings("unused") // API, Reflection
public final class DiscordSRVApiProvider {
private static DiscordSRVApi API;
private DiscordSRVApiProvider() {}
@ApiStatus.Internal
private static void provide(DiscordSRVApi api) {
DiscordSRVApiProvider.API = api;
}
/**
* Checks if the API instance is available.
* @return true if {@link #get()} and {@link #optional()} will return the API instance
*/
public static boolean isAvailable() {
return API != null;
}
/**
* Gets the instance of {@link DiscordSRVApi}.
* @return the DiscordSRV api, or {@code null} if not available
* @see #isAvailable()
*/
@Nullable
public static DiscordSRVApi get() {
return API;
}
/**
* Returns a {@link Optional} of {@link DiscordSRVApi}.
* @return the DiscordSRV api in an optional
* @see #isAvailable()
*/
public static Optional<DiscordSRVApi> optional() {
return Optional.ofNullable(API);
}
}

View File

@ -0,0 +1,56 @@
/*
* 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.channel;
import com.discordsrv.api.component.MinecraftComponent;
/**
* An in-game channel for sending Minecraft messages.
*/
public interface GameChannel {
/**
* Gets the name of the plugin/mod/extension that 'owns' this game channel.
* @return the name of the owner of this game channel
*/
String getOwnerName();
/**
* Gets the name of this channel.
* @return the channel name
*/
String getChannelName();
/**
* Determines if this channel is a two-way chat channel.
* @return if this is a two-way chat channel
*/
boolean isChat();
/**
* Send a message to this {@link GameChannel}'s participants.
* @param component the message
*/
void sendMessage(MinecraftComponent component);
}

View File

@ -0,0 +1,116 @@
/*
* 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.component;
import com.discordsrv.api.DiscordSRVApi;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* 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)} & {@link #adventureAdapter(MinecraftComponentAdapter)}
* but is compatible with anything able to handle Minecraft's json format.
* Legacy is <b>not supported</b>.
*/
@SuppressWarnings("unused") // API
@ApiStatus.NonExtendable
public interface MinecraftComponent {
/**
* Gets this component as json.
* @return json of this component
*/
@NotNull
String asJson();
/**
* Sets this component from json.
* @param json valid Minecraft message component json
* @throws IllegalArgumentException if the provided json is not valid
*/
void setJson(@NotNull String json);
/**
* Gets this message as a plain {@link String} losing any coloring, click and hover components it may have had.
* Use for reference only, <b>this is not a substitute for legacy</b>.
* @return the plain message
*/
String asPlainString();
/**
* Creates an Adventure adapter for convenience.
*
* @param gsonSerializerClass the gson serializer class
* @return a adapter that will convert to/from relocated or unrelocated adventure classes to/from json
* @throws IllegalArgumentException if the provided class is not a Adventure GsonComponentSerializer
*/
@NotNull
Adapter adventureAdapter(@NotNull Class<?> gsonSerializerClass);
/**
* Creates an Adventure adapter from a {@link MinecraftComponentAdapter} for convenience.
*
* @param adapter the premade {@link MinecraftComponentAdapter}
* @return a {@link Adapter} for this component using the given {@link MinecraftComponentAdapter}
*/
@NotNull
Adapter adventureAdapter(@NotNull MinecraftComponentAdapter adapter);
/**
* Creates an Adventure adapter for the unrelocated adventure.
*
* @return a {@link Adapter} for this component using the unrelocated adventure, {@code null} if not available
*/
@Nullable
@ApiStatus.NonExtendable
default Adapter unrelocatedAdapter() {
MinecraftComponentAdapter adapter = MinecraftComponentAdapter.UNRELOCATED;
if (adapter == null) {
return null;
}
return adventureAdapter(adapter);
}
/**
* A Adventure adapter, converts from/to given adventure components from/to json.
*/
interface Adapter {
/**
* Returns the Adventure Component returned by the gson serializer of this adapter.
* @return the {@code net.kyori.adventure.text.Component} (or relocated), cast this to your end class
*/
Object getComponent();
/**
* Sets the component to the component that can be serialized by the gson serializer for this class.
* @param adventureComponent the component
* @throws IllegalArgumentException if the provided component cannot be processed by the gson serializer of this apdater
*/
void setComponent(Object adventureComponent);
}
}

View File

@ -0,0 +1,90 @@
/*
* 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.component;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* A persistent Adventure adapter for {@link MinecraftComponent}s, this is more efficient than using {@link MinecraftComponent#adventureAdapter(Class)}.
* @see MinecraftComponent#adventureAdapter(MinecraftComponentAdapter)
*/
public class MinecraftComponentAdapter {
public static final MinecraftComponentAdapter UNRELOCATED;
static {
MinecraftComponentAdapter unrelocated = null;
try {
unrelocated = MinecraftComponentAdapter.create(
Class.forName("net.ky".concat("ori.adventure.text.serializer.gson.GsonComponentSerializer"))
);
} catch (ClassNotFoundException ignored) {}
UNRELOCATED = unrelocated;
}
/**
* Creates a {@link MinecraftComponentAdapter} that can be used with {@link MinecraftComponent}s.
*
* @param gsonSerializerClass a GsonComponentSerializer class
* @return a new {@link MinecraftComponentAdapter} with the provided GsonComponentSerializer
* @throws IllegalArgumentException if the provided argument is not a GsonComponentSerialize class
*/
public static MinecraftComponentAdapter create(Class<?> gsonSerializerClass) {
return new MinecraftComponentAdapter(gsonSerializerClass);
}
private final Class<?> gsonSerializerClass;
private final Object instance;
private final Method deserialize;
private final Method serialize;
private MinecraftComponentAdapter(Class<?> gsonSerializerClass) {
try {
this.gsonSerializerClass = gsonSerializerClass;
this.instance = gsonSerializerClass.getDeclaredMethod("gson").invoke(null);
this.deserialize = gsonSerializerClass.getMethod("deserialize", Object.class);
Class<?> componentClass = deserialize.getReturnType();
this.serialize = gsonSerializerClass.getMethod("serialize", componentClass);
} catch (InvocationTargetException | IllegalAccessException | NoSuchMethodException e) {
throw new IllegalArgumentException("The provided class is not a GsonComponentSerializer", e);
}
}
public Class<?> gsonSerializerClass() {
return gsonSerializerClass;
}
public Object instance() {
return instance;
}
public Method deserialize() {
return deserialize;
}
public Method serialize() {
return serialize;
}
}

View File

@ -0,0 +1,40 @@
/*
* 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.component;
import com.discordsrv.api.DiscordSRVApi;
/**
* A factory for creating {@link MinecraftComponent}s.
* @see DiscordSRVApi#componentFactory()
*/
public interface MinecraftComponentFactory {
/**
* Creates an empty {@link MinecraftComponent}.
*
* @return a new {@link MinecraftComponent}
*/
MinecraftComponent empty();
}

View File

@ -0,0 +1,39 @@
/*
* 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.discord.api;
import com.discordsrv.api.discord.api.channel.DiscordTextChannel;
/**
* A basic Discord API wrapper for a limited amount of functions, with a minimal amount of breaking changes.
*/
public interface DiscordAPI {
/**
* Gets a Discord text channel by id.
* @param id the id for the text channel
* @return the text channel
*/
DiscordTextChannel getTextChannelById(String id);
}

View File

@ -0,0 +1,43 @@
/*
* 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.discord.api.channel;
import com.discordsrv.api.discord.api.message.ReceivedDiscordMessage;
import com.discordsrv.api.discord.api.message.SendableDiscordMessage;
import java.util.concurrent.CompletableFuture;
public interface DiscordTextChannel {
String getId();
long getIdLong();
String getName();
String getTopic();
CompletableFuture<ReceivedDiscordMessage> sendMessage(SendableDiscordMessage message);
CompletableFuture<ReceivedDiscordMessage> editMessageById(String id, SendableDiscordMessage message);
}

View File

@ -0,0 +1,77 @@
/*
* 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.discord.api.message;
import net.dv8tion.jda.api.entities.Message;
public interface AllowedMention {
AllowedMention EVERYONE = Standard.EVERYONE;
AllowedMention ALL_ROLES = Standard.ROLE;
AllowedMention ALL_USERS = Standard.USER;
static AllowedMention user(String id) {
return new Snowflake(id, true);
}
static AllowedMention role(String id) {
return new Snowflake(id, false);
}
enum Standard implements AllowedMention {
EVERYONE(Message.MentionType.EVERYONE),
ROLE(Message.MentionType.ROLE),
USER(Message.MentionType.USER),
;
private final Message.MentionType mentionType;
Standard(Message.MentionType mentionType) {
this.mentionType = mentionType;
}
public Message.MentionType getMentionType() {
return mentionType;
}
}
class Snowflake implements AllowedMention {
private final String id;
private final boolean user;
public Snowflake(String id, boolean user) {
this.id = id;
this.user = user;
}
public String getId() {
return id;
}
public boolean isUser() {
return user;
}
}
}

View File

@ -0,0 +1,372 @@
/*
* 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.discord.api.message;
import net.dv8tion.jda.api.entities.MessageEmbed;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.awt.Color;
import java.time.OffsetDateTime;
import java.util.ArrayList;
import java.util.List;
@SuppressWarnings("unused") // API
public class DiscordMessageEmbed {
public static Builder builder() {
return new Builder();
}
private final int color;
private final String authorName, authorUrl, authorImageUrl;
private final String title, titleUrl;
private final String description;
private final List<Field> fields;
private final String thumbnailUrl;
private final String imageUrl;
private final OffsetDateTime timestamp;
private final String footer, footerImageUrl;
public DiscordMessageEmbed(MessageEmbed embed) {
MessageEmbed.AuthorInfo author = embed.getAuthor();
MessageEmbed.Thumbnail thumbnail = embed.getThumbnail();
MessageEmbed.ImageInfo image = embed.getImage();
MessageEmbed.Footer footer = embed.getFooter();
List<Field> fields = new ArrayList<>();
for (MessageEmbed.Field field : embed.getFields()) {
fields.add(new Field(field.getName(), field.getValue(), field.isInline()));
}
this.color = embed.getColorRaw();
this.authorName = author != null ? author.getName(): null;
this.authorUrl = author != null ? author.getUrl() : null;
this.authorImageUrl = author != null ? author.getIconUrl() : null;
this.title = embed.getTitle();
this.titleUrl = embed.getUrl();
this.description = embed.getDescription();
this.fields = fields;
this.thumbnailUrl = thumbnail != null ? thumbnail.getUrl() : null;
this.imageUrl = image != null ? image.getUrl() : null;
this.timestamp = embed.getTimestamp();
this.footer = footer != null ? footer.getText() : null;
this.footerImageUrl = footer != null ? footer.getIconUrl() : null;
}
public DiscordMessageEmbed(int color, String authorName, String authorUrl, String authorAvatarUrl, String title,
String titleUrl, String description, List<Field> fields, String thumbnailUrl,
String imageUrl, OffsetDateTime timestamp, String footer, String footerImageUrl) {
this.color = color;
this.authorName = authorName;
this.authorUrl = authorUrl;
this.authorImageUrl = authorAvatarUrl;
this.title = title;
this.titleUrl = titleUrl;
this.description = description;
this.fields = fields;
this.thumbnailUrl = thumbnailUrl;
this.imageUrl = imageUrl;
this.timestamp = timestamp;
this.footer = footer;
this.footerImageUrl = footerImageUrl;
}
public int getColor() {
return color;
}
public String getAuthorName() {
return authorName;
}
public String getAuthorUrl() {
return authorUrl;
}
public String getAuthorImageUrl() {
return authorImageUrl;
}
public String getTitle() {
return title;
}
public String getTitleUrl() {
return titleUrl;
}
public String getDescription() {
return description;
}
public List<Field> getFields() {
return fields;
}
public String getThumbnailUrl() {
return thumbnailUrl;
}
public String getImageUrl() {
return imageUrl;
}
public OffsetDateTime getTimestamp() {
return timestamp;
}
public String getFooter() {
return footer;
}
public String getFooterImageUrl() {
return footerImageUrl;
}
public static class Field {
private final String title;
private final String value;
private final boolean inline;
public Field(String title, String value, boolean inline) {
this.title = title;
this.value = value;
this.inline = inline;
}
public String getTitle() {
return title;
}
public String getValue() {
return value;
}
public boolean isInline() {
return inline;
}
}
public static class Builder {
private int color;
private String authorName, authorUrl, authorImageUrl;
private String title, titleUrl;
private String description;
private final List<Field> fields;
private String thumbnailUrl;
private String imageUrl;
private OffsetDateTime timestamp;
private String footer, footerImageUrl;
public Builder() {
this.fields = new ArrayList<>();
}
public Builder(int color, String authorName, String authorUrl, String authorImageUrl, String title,
String titleUrl, String description, List<Field> fields, String thumbnailUrl, String imageUrl,
OffsetDateTime timestamp, String footer, String footerImageUrl) {
this.color = color;
this.authorName = authorName;
this.authorUrl = authorUrl;
this.authorImageUrl = authorImageUrl;
this.title = title;
this.titleUrl = titleUrl;
this.description = description;
this.fields = new ArrayList<>(fields);
this.thumbnailUrl = thumbnailUrl;
this.imageUrl = imageUrl;
this.timestamp = timestamp;
this.footer = footer;
this.footerImageUrl = footerImageUrl;
}
public int getColor() {
return color;
}
public Builder setColor(Color color) {
return setColor(color.getRGB());
}
public Builder setColor(int color) {
this.color = color;
return this;
}
public Builder setAuthor(@Nullable String authorName, @Nullable String authorUrl) {
return setAuthor(authorName, authorUrl, null);
}
public Builder setAuthor(@Nullable String authorName, @Nullable String authorUrl, @Nullable String authorImageUrl) {
this.authorName = authorName;
this.authorUrl = authorUrl;
this.authorImageUrl = authorImageUrl;
return this;
}
public String getAuthorName() {
return authorName;
}
public Builder setAuthorName(@Nullable String authorName) {
this.authorName = authorName;
return this;
}
public String getAuthorUrl() {
return authorUrl;
}
public Builder setAuthorUrl(@Nullable String authorUrl) {
this.authorUrl = authorUrl;
return this;
}
public String getAuthorImageUrl() {
return authorImageUrl;
}
public Builder setAuthorImageUrl(String authorImageUrl) {
this.authorImageUrl = authorImageUrl;
return this;
}
public Builder setTitle(@Nullable String title, @Nullable String titleUrl) {
this.title = title;
this.titleUrl = titleUrl;
return this;
}
public String getTitle() {
return title;
}
public Builder setTitle(@Nullable String title) {
this.title = title;
return this;
}
public String getTitleUrl() {
return titleUrl;
}
public Builder setTitleUrl(@Nullable String titleUrl) {
this.titleUrl = titleUrl;
return this;
}
public String getDescription() {
return description;
}
public Builder setDescription(@Nullable String description) {
this.description = description;
return this;
}
public List<Field> getFields() {
return fields;
}
public Builder addField(@NotNull String title, @NotNull String value, boolean inline) {
return addField(new Field(title, value, inline));
}
public Builder addField(@NotNull Field field) {
this.fields.add(field);
return this;
}
public Builder removeField(@NotNull Field field) {
this.fields.remove(field);
return this;
}
public String getThumbnailUrl() {
return thumbnailUrl;
}
public Builder setThumbnailUrl(@Nullable String thumbnailUrl) {
this.thumbnailUrl = thumbnailUrl;
return this;
}
public String getImageUrl() {
return imageUrl;
}
public Builder setImageUrl(@Nullable String imageUrl) {
this.imageUrl = imageUrl;
return this;
}
public OffsetDateTime getTimestamp() {
return timestamp;
}
public Builder setTimestamp(@Nullable OffsetDateTime timestamp) {
this.timestamp = timestamp;
return this;
}
public Builder setFooter(@Nullable String footer, @Nullable String footerImageUrl) {
this.footer = footer;
this.footerImageUrl = footerImageUrl;
return this;
}
public String getFooter() {
return footer;
}
public Builder setFooter(@Nullable String footer) {
this.footer = footer;
return this;
}
public String getFooterImageUrl() {
return footerImageUrl;
}
public Builder setFooterImageUrl(@Nullable String footerImageUrl) {
this.footerImageUrl = footerImageUrl;
return this;
}
public DiscordMessageEmbed build() {
return new DiscordMessageEmbed(color, authorName, authorUrl, authorImageUrl, title, titleUrl, description,
fields, thumbnailUrl, imageUrl, timestamp, footer, footerImageUrl);
}
@SuppressWarnings({"MethodDoesntCallSuperMethod", "CloneDoesntDeclareCloneNotSupportedException"})
@Override
protected Builder clone() {
return new Builder(color, authorName, authorUrl, authorImageUrl, title, titleUrl, description,
fields, thumbnailUrl, imageUrl, timestamp, footer, footerImageUrl);
}
}
}

View File

@ -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.discord.api.message;
import java.util.concurrent.CompletableFuture;
public interface ReceivedDiscordMessage extends SendableDiscordMessage {
/**
* Gets the ID for this message.
* @return the id from Discord for this message
*/
String getId();
// TODO: Author
@Override
String getContent();
/**
* Gets the content displayed on Discord, without markdown or other formatting.
* @return the displayed content of the message
*/
String getDisplayedContent();
/**
* Gets the raw content with markdown characters stripped from it.
* @return the stripped content of the message
*/
String getStrippedContent();
/**
* Edits this message to the provided message, the webhook username and avatar url will be ignored.
*
* @param message the new message
* @return the future for the message edit
*/
CompletableFuture<ReceivedDiscordMessage> edit(SendableDiscordMessage message);
}

View File

@ -0,0 +1,139 @@
/*
* 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.discord.api.message;
import com.discordsrv.api.discord.api.message.impl.SendableDiscordMessageImpl;
import java.util.List;
@SuppressWarnings("unused") // API
public interface SendableDiscordMessage {
static Builder builder() {
return new SendableDiscordMessageImpl.BuilderImpl();
}
/**
* The raw content of the message.
* @return the unmodified content of the message
*/
String getContent();
/**
* Gets the embeds of the message.
* @return the unmodifiable list of embeds in this message
*/
List<DiscordMessageEmbed> getEmbeds();
/**
* Gets the webhook username.
* @return the webhook username or {@code null} if this isn't a webhook message
*/
String getWebhookUsername();
/**
* Gets the webhook avatar url.
* @return the webhook avatar url or {@code null} if no webhook avatar url is specified
*/
String getWebhookAvatarUrl();
/**
* Returns true if the {@link #getWebhookUsername() webhook username} is specified.
* @return true if this is a webhook message
*/
default boolean isWebhookMessage() {
return getWebhookUsername() != null;
}
interface Builder {
/**
* Gets the current content of this message in this builder.
* @return the content
*/
String getContent();
/**
* Changes the content of this builder.
* @param content the new content
* @return the builder, useful for chaining
*/
Builder setContent(String content);
/**
* Gets the embeds that are currently in this builder.
* @return this builder's current embeds
*/
List<DiscordMessageEmbed> getEmbeds();
/**
* Adds an embed to this builder.
* @param embed the embed to add
* @return the builder, useful for chaining
*/
Builder addEmbed(DiscordMessageEmbed embed);
/**
* Removes an embed from this builder.
* @param embed the embed to remove
* @return the builder, useful for chaining
*/
Builder removeEmbed(DiscordMessageEmbed embed);
/**
* Gets the webhook username for this builder or {@code null} if webhooks are not being used.
* @return the webhook username
*/
String getWebhookUsername();
/**
* Sets the webhook username, setting this enabled webhooks for this message.
* @param webhookUsername the new webhook username
* @return the builder, useful for chaining
*/
Builder setWebhookUsername(String webhookUsername);
/**
* Gets the webhook avatar url for this builder.
* @return the webhook avatar url
*/
String getWebhookAvatarUrl();
/**
* Sets the webhook avatar url for this builder.
* @param webhookAvatarUrl the new webhook avatar url
* @throws IllegalStateException if there is no webhook username set
* @return the builder, useful for chaining
*/
Builder setWebhookAvatarUrl(String webhookAvatarUrl);
/**
* Builds a {@link SendableDiscordMessage} from this builder.
* @return the new {@link SendableDiscordMessage}
*/
SendableDiscordMessage build();
}
}

View File

@ -0,0 +1,129 @@
/*
* 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.discord.api.message.impl;
import com.discordsrv.api.discord.api.message.DiscordMessageEmbed;
import com.discordsrv.api.discord.api.message.SendableDiscordMessage;
import java.util.ArrayList;
import java.util.List;
public class SendableDiscordMessageImpl implements SendableDiscordMessage {
private final String content;
private final List<DiscordMessageEmbed> embeds;
private final String webhookUsername;
private final String webhookAvatarUrl;
public SendableDiscordMessageImpl(String content, List<DiscordMessageEmbed> embeds,
String webhookUsername, String webhookAvatarUrl) {
this.content = content;
this.embeds = embeds;
this.webhookUsername = webhookUsername;
this.webhookAvatarUrl = webhookAvatarUrl;
}
@Override
public String getContent() {
return content;
}
@Override
public List<DiscordMessageEmbed> getEmbeds() {
return embeds;
}
@Override
public String getWebhookUsername() {
return webhookUsername;
}
@Override
public String getWebhookAvatarUrl() {
return webhookAvatarUrl;
}
public static class BuilderImpl implements Builder {
private String content;
private final List<DiscordMessageEmbed> embeds = new ArrayList<>();
private String webhookUsername;
private String webhookAvatarUrl;
@Override
public String getContent() {
return content;
}
@Override
public BuilderImpl setContent(String content) {
this.content = content;
return this;
}
@Override
public List<DiscordMessageEmbed> getEmbeds() {
return embeds;
}
@Override
public Builder addEmbed(DiscordMessageEmbed embed) {
this.embeds.add(embed);
return this;
}
@Override
public Builder removeEmbed(DiscordMessageEmbed embed) {
this.embeds.remove(embed);
return this;
}
@Override
public String getWebhookUsername() {
return webhookUsername;
}
@Override
public BuilderImpl setWebhookUsername(String webhookUsername) {
this.webhookUsername = webhookUsername;
return this;
}
@Override
public String getWebhookAvatarUrl() {
return webhookAvatarUrl;
}
@Override
public BuilderImpl setWebhookAvatarUrl(String webhookAvatarUrl) {
this.webhookAvatarUrl = webhookAvatarUrl;
return this;
}
@Override
public SendableDiscordMessage build() {
return new SendableDiscordMessageImpl(content, embeds, webhookUsername, webhookAvatarUrl);
}
}
}

View File

@ -0,0 +1,78 @@
/*
* 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.discord.connection;
import com.discordsrv.api.DiscordSRVApi;
import net.dv8tion.jda.api.requests.GatewayIntent;
import net.dv8tion.jda.api.utils.cache.CacheFlag;
import java.util.Set;
/**
* A helper class to provide {@link GatewayIntent}s and {@link CacheFlag}s to the {@link net.dv8tion.jda.api.JDA} instance created by DiscordSRV during startup.
* @see DiscordSRVApi#discordConnectionDetails()
*/
@SuppressWarnings("unused") // API
public interface DiscordConnectionDetails {
/**
* If {@link #requestGatewayIntent(GatewayIntent, GatewayIntent...)}} and {@link #requestCacheFlag(CacheFlag, CacheFlag...)} can be used.
* @return true, if {@link GatewayIntent}s and {@link CacheFlag} will be accepted
*/
boolean readyToTakeDetails();
/**
* The current gateway intents.
* @return the current set of gateway intents
*/
Set<GatewayIntent> getGatewayIntents();
/**
* Requests that the provided {@link GatewayIntent}s be passed to {@link net.dv8tion.jda.api.JDA}.
*
* @param gatewayIntent the first gateway intent to add
* @param gatewayIntents more gateway intents
* @throws IllegalStateException if DiscordSRV is already connecting/connected to Discord
* @see #readyToTakeDetails()
*/
void requestGatewayIntent(GatewayIntent gatewayIntent, GatewayIntent... gatewayIntents);
/**
* The current cache flags.
* @return the current set of cache flags
*/
Set<CacheFlag> getCacheFlags();
/**
* Requests that the provided {@link CacheFlag} be passed to {@link net.dv8tion.jda.api.JDA}.
*
* @param cacheFlag the first cache flag
* @param cacheFlags more cache flags
* @throws IllegalStateException if DiscordSRV is already connecting/connected to Discord
* @throws IllegalArgumentException if one of the requested {@link CacheFlag}s requires a {@link GatewayIntent} that hasn't been requested
* @see #readyToTakeDetails()
*/
void requestCacheFlag(CacheFlag cacheFlag, CacheFlag... cacheFlags);
}

View File

@ -0,0 +1,64 @@
/*
* 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.bus;
import com.discordsrv.api.event.events.Event;
import net.dv8tion.jda.api.events.GenericEvent;
import org.jetbrains.annotations.NotNull;
/**
* DiscordSRV's event bus, handling all events extending {@link Event}s and {@link GenericEvent}s.
*/
@SuppressWarnings("unused") // API
public interface EventBus {
/**
* Subscribes the provided event listener to this {@link EventBus}.
* @param eventListener a event listener with atleast one valid {@link Subscribe} method.
*
* @throws IllegalArgumentException if the given listener does not contain any valid listeners
*/
void subscribe(@NotNull Object eventListener);
/**
* Unsubscribes a listener that was registered before.
* @param eventListener a listener that was subscribed with {@link #subscribe(Object)} before
*/
void unsubscribe(@NotNull Object eventListener);
/**
* Publishes a DiscordSRV {@link Event} to this {@link EventBus}.
*
* @param event the event
*/
void publish(@NotNull Event event);
/**
* Publishes a JDA {@link GenericEvent} to this {@link EventBus}.
*
* @param event the event
*/
void publish(@NotNull GenericEvent event);
}

View File

@ -0,0 +1,48 @@
/*
* 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.bus;
import java.lang.reflect.Method;
/**
* A event listener.
*/
@SuppressWarnings("unused") // API
public interface EventListener {
/**
* The full name of the class for this event listener.
* @return the event listener class name
* @see Class#getName()
*/
String className();
/**
* The name of the method for this event listener
* @return the method name for this event listener
* @see Method#getName()
*/
String methodName();
}

View File

@ -0,0 +1,67 @@
/*
* 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.bus;
/**
* A simple enum to dictate the order that event listeners will be executed, going from {@link #POST} to {@link #POST}.
*/
public enum EventPriority {
/**
* This is the first in the priority order, this should be used to observe the event before any processing.
*/
PRE,
/**
* This is the earliest in the processing. This should be used to cancel events.
*/
EARLIEST,
/**
* This should be used to modify events.
*/
EARLY,
/**
* The default priority, right in the middle of the priority order. Use this if you need to override
* one of DiscordSRV's implementations for {@link com.discordsrv.api.event.events.Processable}s.
*/
DEFAULT,
/**
* This is where DiscordSRV's integrations for other plugins will process {@link com.discordsrv.api.event.events.Processable}'s.
*/
LATE,
/**
* This is where DiscordSRV's default implementations for {@link com.discordsrv.api.event.events.Processable}'s will run.
*/
LAST,
/**
* This is the last in the priority order, this should be used to observe the event after all processing is complete.
*/
POST
}

View File

@ -0,0 +1,58 @@
/*
* 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.bus;
import com.discordsrv.api.DiscordSRVApi;
import com.discordsrv.api.event.events.Cancellable;
import com.discordsrv.api.event.events.Event;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Placed on a public non-abstract non-static method that has only 1 parameters,
* being an event extending {@link Event} or {@link net.dv8tion.jda.api.events.GenericEvent}.
*
* You can register a listener through {@link EventBus#subscribe(Object)}, {@link DiscordSRVApi#eventBus()} to get the event bus.
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Subscribe {
/**
* If this listener ignores events that are cancelled via {@link Cancellable}.
* @return if cancelled events are ignored
* @see Cancellable
*/
boolean ignoreCancelled() default false;
/**
* The priority for this event listener, this determines the order that event listeners receive events.
* @return the priority of this event listener
*/
EventPriority priority() default EventPriority.DEFAULT;
}

View File

@ -0,0 +1,49 @@
/*
* 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.bus.internal;
import com.discordsrv.api.event.bus.EventListener;
import org.jetbrains.annotations.ApiStatus;
@ApiStatus.Internal
public final class EventStateHolder {
public static final ThreadLocal<EventListener> CANCELLED = new ThreadLocal<>();
public static final ThreadLocal<EventListener> PROCESSED = new ThreadLocal<>();
public static final EventListener FAKE_LISTENER = new FakeListener();
private static class FakeListener implements EventListener {
@Override
public String className() {
return null;
}
@Override
public String methodName() {
return null;
}
}
}

View File

@ -0,0 +1,70 @@
/*
* 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;
import com.discordsrv.api.event.bus.EventListener;
import com.discordsrv.api.event.bus.internal.EventStateHolder;
import com.discordsrv.api.event.bus.Subscribe;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.Nullable;
/**
* A {@link Event} that can be cancelled.
*/
@SuppressWarnings("unused") // API
public interface Cancellable extends Event {
/**
* If this event is cancelled.
* @return true if this event is cancelled
*/
boolean isCancelled();
/**
* Sets the cancelled state of this event, which may or may not be followed by event listeners.
* @param cancelled the new cancelled state of this event
* @see Subscribe#ignoreCancelled()
*/
void setCancelled(boolean cancelled);
/**
* Returns the {@link EventListener} that cancelled this event.
* This is changed every time the event goes from not being cancelled to being cancelled.
*
* @return the event listener that cancelled this event or {@code null} if it was cancelled before being passed to the {@link com.discordsrv.api.event.bus.EventBus}
* @throws IllegalStateException if the event isn't cancelled
*/
@ApiStatus.NonExtendable
@Nullable
default EventListener whoCancelled() {
EventListener listener = EventStateHolder.CANCELLED.get();
if (listener == null) {
throw new IllegalStateException("Event is not cancelled");
} else if (listener == EventStateHolder.FAKE_LISTENER) {
return null;
}
return listener;
}
}

View File

@ -0,0 +1,29 @@
/*
* 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;
/**
* A DiscordSRV event.
*/
public interface Event {}

View File

@ -0,0 +1,38 @@
/*
* 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;
import com.discordsrv.api.player.DiscordSRVPlayer;
/**
* An event that is related to a {@link DiscordSRVPlayer}.
*/
public interface PlayerEvent extends Event {
/**
* The player that this event is related to.
* @return the player
*/
DiscordSRVPlayer getPlayer();
}

View File

@ -0,0 +1,66 @@
/*
* 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;
import com.discordsrv.api.event.bus.EventListener;
import com.discordsrv.api.event.bus.internal.EventStateHolder;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.Nullable;
/**
* A {@link Event} that can be processed.
*/
@SuppressWarnings("unused") // API
public interface Processable extends Event {
/**
* Has this event has been processed.
* @return true if this event has been processed
*/
boolean isProcessed();
/**
* Marks this event as processed. This cannot be reversed, events cannot be unprocessed.
*/
void markAsProcessed();
/**
* Returns the {@link EventListener} that processed this event.
*
* @return the event listener that processed this event or {@code null} if it was processed before being passed to the {@link com.discordsrv.api.event.bus.EventBus}
* @throws IllegalStateException if the event has not been processed
*/
@ApiStatus.NonExtendable
@Nullable
default EventListener whoProcessed() {
EventListener listener = EventStateHolder.PROCESSED.get();
if (listener == null) {
throw new IllegalStateException("Event has not been processed");
} else if (listener == EventStateHolder.FAKE_LISTENER) {
return null;
}
return listener;
}
}

View File

@ -0,0 +1,105 @@
/*
* 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.channel;
import com.discordsrv.api.channel.GameChannel;
import com.discordsrv.api.event.events.Processable;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Objects;
/**
*
*/
public class GameChannelLookupEvent implements Processable {
private final String pluginName;
private final String channelName;
private boolean processed;
private GameChannel channel;
public GameChannelLookupEvent(@Nullable String pluginName, @NotNull String channelName) {
this.pluginName = pluginName;
this.channelName = channelName;
}
/**
* The channel name being looked up, this should be case insensitive wherever possible.
* @return the channel name
*/
@NotNull
public String getChannelName() {
return channelName;
}
/**
* Returns the channel from a {@link #process(GameChannel)} matching required criteria.
* @return the game channel provided by a listener
* @throws IllegalStateException if {@link #isProcessed()} doesn't return true
*/
@NotNull
public GameChannel getChannelFromProcessing() {
if (!processed) {
throw new IllegalStateException("This event has not been successfully processed yet, no channel is available");
}
return channel;
}
@Override
public boolean isProcessed() {
return processed;
}
/**
* Provides a {@link GameChannel} for the provided channel name ({@link #getChannelName()}).
* @param channel the channel
*/
public void process(GameChannel channel) {
Objects.requireNonNull(channel, "channel");
if (pluginName != null && !pluginName.equalsIgnoreCase(channel.getOwnerName())) {
// Not the plugin we're looking for, ignore
return;
}
String channelName = channel.getChannelName();
if (!channelName.equalsIgnoreCase(this.channelName)) {
throw new IllegalArgumentException("The provided channel is named "
+ channelName + " when it should've been: " + this.channelName);
}
this.channel = channel;
this.processed = true;
}
/**
* @deprecated Use {@link #process(GameChannel)}.
*/
@Override
@Deprecated
public void markAsProcessed() {
throw new RuntimeException("Please use process(GameChannel) instead");
}
}

View File

@ -0,0 +1,33 @@
/*
* 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.lifecycle;
import com.discordsrv.api.event.events.Event;
/**
* Indicates that DiscordSRV's systems (including Discord connection) are ready.
*/
public class DiscordSRVReadyEvent implements Event {
}

View File

@ -0,0 +1,43 @@
/*
* 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.lifecycle;
import com.discordsrv.api.event.events.Event;
import com.discordsrv.api.event.bus.EventPriority;
/**
* Indicates that DiscordSRV is shutting down.
*
* DiscordSRV's own systems will shutdown at the following times:
* {@link EventPriority#EARLY}<br/>
* - DiscordSRV's own modules shutdown<br/>
*
* {@link EventPriority#LATE}<br/>
* - Discord connections are shutdown<br/>
*
* {@link EventPriority#LAST}<br/>
* - DiscordSRV's scheduler is shutdown<br/>
*/
public class DiscordSRVShuttingDownEvent implements Event {
}

View File

@ -0,0 +1,24 @@
/*
* 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;

View File

@ -0,0 +1,78 @@
/*
* 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.event.events.Cancellable;
import com.discordsrv.api.event.events.Processable;
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) {
this.message = message;
this.gameChannel = gameChannel;
this.cancelled = cancelled;
}
@NotNull
public MinecraftComponent message() {
return message;
}
@NotNull
public GameChannel getGameChannel() {
return gameChannel;
}
public void setGameChannel(@NotNull GameChannel gameChannel) {
this.gameChannel = gameChannel;
}
@Override
public boolean isCancelled() {
return cancelled;
}
@Override
public void setCancelled(boolean cancelled) {
this.cancelled = cancelled;
}
@Override
public boolean isProcessed() {
return processed;
}
@Override
public void markAsProcessed() {
this.processed = true;
}
}

View File

@ -0,0 +1,44 @@
/*
* 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.event.events.PlayerEvent;
import com.discordsrv.api.player.DiscordSRVPlayer;
public class ChatMessageReceiveEvent extends AbstractGameMessageReceiveEvent implements PlayerEvent {
private final DiscordSRVPlayer player;
public ChatMessageReceiveEvent(DiscordSRVPlayer player, MinecraftComponent message, GameChannel gameChannel, boolean cancelled) {
super(message, gameChannel, cancelled);
this.player = player;
}
@Override
public DiscordSRVPlayer getPlayer() {
return player;
}
}

View File

@ -0,0 +1,24 @@
/*
* 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;

View File

@ -0,0 +1,92 @@
/*
* 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.send.game;
import com.discordsrv.api.channel.GameChannel;
import com.discordsrv.api.event.events.Cancellable;
import com.discordsrv.api.event.events.Processable;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public abstract class AbstractGameMessageSendEvent implements Cancellable, Processable {
private String discordMessage;
private String discordUsername;
private GameChannel targetChannel;
private boolean cancelled;
private boolean processed;
public AbstractGameMessageSendEvent(@NotNull String discordMessage, @Nullable String discordUsername, @NotNull GameChannel targetChannel) {
this.discordMessage = discordMessage;
this.discordUsername = discordUsername;
this.targetChannel = targetChannel;
}
@NotNull
public String getDiscordMessage() {
return discordMessage;
}
public void setDiscordMessage(@NotNull String discordMessage) {
this.discordMessage = discordMessage;
}
@Nullable
public String getDiscordUsername() {
return discordUsername;
}
public void setDiscordUsername(@Nullable String discordUsername) {
this.discordUsername = discordUsername;
}
@NotNull
public GameChannel getTargetChannel() {
return targetChannel;
}
public void setTargetChannel(@NotNull GameChannel targetChannel) {
this.targetChannel = targetChannel;
}
@Override
public boolean isCancelled() {
return cancelled;
}
@Override
public void setCancelled(boolean cancelled) {
this.cancelled = cancelled;
}
@Override
public boolean isProcessed() {
return processed;
}
@Override
public void markAsProcessed() {
this.processed = true;
}
}

View File

@ -0,0 +1,35 @@
/*
* 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.send.game;
import com.discordsrv.api.channel.GameChannel;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class ChatMessageSendEvent extends AbstractGameMessageSendEvent {
public ChatMessageSendEvent(@NotNull String discordMessage, @Nullable String discordUsername, @NotNull GameChannel targetChannel) {
super(discordMessage, discordUsername, targetChannel);
}
}

View File

@ -0,0 +1,24 @@
/*
* 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.send;

View File

@ -0,0 +1,45 @@
/*
* 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.player;
import java.util.UUID;
/**
* A DiscordSRV player.
*/
public interface DiscordSRVPlayer {
/**
* The username of the player.
* @return the player's username
*/
String getUsername();
/**
* The {@link UUID} of the player.
* @return the player's unique id
*/
UUID uuid();
}

View File

@ -0,0 +1,50 @@
/*
* 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.player;
import org.jetbrains.annotations.NotNull;
import java.util.Optional;
import java.util.UUID;
/**
* A provider for {@link DiscordSRVPlayer} instances.
*/
public interface IPlayerProvider {
/**
* Gets a player from the cache of online players.
* @param player the uuid for the player
* @return the {@link DiscordSRVPlayer} instance for the player, if available
*/
Optional<? extends DiscordSRVPlayer> player(@NotNull UUID player);
/**
* Gets a player from the cache of online players.
* @param username case-insensitive username for the player
* @return the {@link DiscordSRVPlayer} instance for the player, if available
*/
Optional<? extends DiscordSRVPlayer> player(@NotNull String username);
}

131
build.gradle Normal file
View File

@ -0,0 +1,131 @@
import dev.vankka.dependencydownload.task.GenerateDependencyDownloadResourceTask
plugins {
id 'com.github.johnrengelman.shadow' version '7.0.0' 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
id 'dev.vankka.dependencydownload.plugin' version '1.0.3-SNAPSHOT' apply false
}
version '2.0.0-SNAPSHOT'
ext {
// DependencyDownload (change plugin version above)
ddVersion = '1.0.3-SNAPSHOT'
// MinecraftDependencyDownload
mddVersion = '1.0.0-SNAPSHOT'
// JDA
jdaVersion = '4.3.0_278'
// Configurate
configurateVersion = '4.1.1'
// Adventure & Adventure Platform
adventureVersion = '4.8.1'
adventurePlatformVersion = '4.0.0-SNAPSHOT'
}
allprojects {
apply plugin: 'java'
apply plugin: 'java-library'
apply plugin: 'com.github.johnrengelman.shadow'
apply plugin: 'org.cadixdev.licenser'
apply plugin: 'dev.vankka.dependencydownload.plugin'
apply plugin: 'io.freefair.lombok'
group 'com.discordsrv'
version = rootProject.version
generateLombokConfig.enabled = false
java {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
configurations {
runtimeDownloadApi
compileOnlyApi.extendsFrom runtimeDownloadApi
}
ext {
dependenciesDirectory = new File(sourceSets.main.output.resourcesDir, 'dependencies')
}
task generateResourceForRuntimeDownloadApi(type: GenerateDependencyDownloadResourceTask) {
configuration = configurations.runtimeDownloadApi
fileLocation = new File(dependenciesDirectory, 'runtimeDownloadApi-' + project.name + '.txt')
}
generateRuntimeDownloadResourceForRuntimeDownload {
fileLocation = new File(dependenciesDirectory, 'runtimeDownload-' + project.name + '.txt')
}
generateRuntimeDownloadResourceForRuntimeDownloadOnly {
fileLocation = new File(dependenciesDirectory, 'runtimeDownloadOnly-' + project.name + '.txt')
}
repositories {
// Snapshot repositories
maven { url 'https://oss.sonatype.org/content/repositories/snapshots/' }
maven { url 'https://s01.oss.sonatype.org/content/repositories/snapshots/' }
mavenLocal()
mavenCentral()
maven { url 'https://nexus.scarsz.me/content/groups/public/' }
maven { url 'https://m2.dv8tion.net/releases/' }
}
dependencies {
// Test dependencies
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.7.0'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.7.0'
}
test {
useJUnitPlatform()
}
task deleteJarsDir(type: Delete) {
delete rootProject.file('jars')
}
clean.dependsOn deleteJarsDir
jar {
duplicatesStrategy = DuplicatesStrategy.INCLUDE
// If CI then check that licenses are correct, otherwise automatically apply licenses on build
dependsOn (System.getenv('CI') === 'true' ? licenseCheck : licenseFormat)
// Always run shadowJar
finalizedBy shadowJar
}
shadowJar {
// Exclude signatures, maven/ and proguard/ from META-INF
exclude 'META-INF/*.SF'
exclude 'META-INF/*.DSA'
exclude 'META-INF/*.RSA'
exclude 'META-INF/maven/**'
exclude 'META-INF/proguard/**'
}
gradle.projectsEvaluated {
tasks.withType(JavaCompile) {
// Enable compiler warnings for unchecked & deprecation
options.compilerArgs << "-Xlint:unchecked" << "-Xlint:deprecation"
}
}
processResources {
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
}
license {
header = rootProject.file('buildscript/license/LICENSE_HEADER')
properties {
var inception = '2016'
var currentYear = String.valueOf(Calendar.getInstance().get(Calendar.YEAR))
year = inception == currentYear ? currentYear : inception + '-' + currentYear
}
include '**/*.java' // only java files
}
}

18
buildscript/final.gradle Normal file
View File

@ -0,0 +1,18 @@
// Buildscript for loaders & standalone platforms
task copyOutput(type: Copy) {
from(this.shadowJar)
into rootProject.file('jars')
}
shadowJar {
// Don't add -all to the end of the jar name
archiveClassifier = ''
// Include the license in the jar
from(rootProject.file('licenses/GPLv3.txt')) {
rename { fileName -> 'LICENSE.txt' }
}
finalizedBy copyOutput
}

View File

@ -0,0 +1,20 @@
This file is part of the DiscordSRV API, licensed under the MIT License
Copyright (c) ${year} 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.

View File

@ -0,0 +1,15 @@
This file is part of DiscordSRV, licensed under the GPLv3 License
Copyright (c) ${year} 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/>.

11
buildscript/loader.gradle Normal file
View File

@ -0,0 +1,11 @@
// Common buildscript for loaders
apply from: rootProject.file('buildscript/relocations.gradle')
apply from: rootProject.file('buildscript/final.gradle')
shadowJar {
// Include the bootstrap
from parent.tasks.shadowJar.archiveFile
// Relocate the dependency
relocate 'dev.vankka.mcdependencydownload', 'com.discordsrv.dependencies.dev.vankka.mcdependencydownload'
}

View File

@ -0,0 +1,25 @@
// Relocations
shadowJar {
[
// JDA
'net.dv8tion.jda',
'gnu.trove',
'com.neovisionaries.ws',
'com.iwebpp',
'okhttp3',
'okio',
// DependencyDownload
'dev.vankka.dependencydownload',
'dev.vankka.mcdependencydownload',
'me.lucko.jarrelocator',
'org.objectweb.asm',
// Other
'org.apache.commons',
'org.spongepowered.configurate',
'org.yaml.snakeyaml',
'net.kyori'
].each {
relocate it, 'com.discordsrv.dependencies.' + it
}
}

View File

@ -0,0 +1,13 @@
// Common build script for bootstraps & standalone platforms
apply from: rootProject.file('buildscript/relocations.gradle')
jar {
dependsOn generateResourceForRuntimeDownloadApi
}
shadowJar {
from {
// Include translations
findProject(':i18n').sourceSets.main.resources
}
}

View File

@ -0,0 +1,3 @@
// Common buildscript for standalone platforms
apply from: rootProject.file('buildscript/runtime.gradle')
apply from: rootProject.file('buildscript/final.gradle')

37
bukkit/build.gradle Normal file
View File

@ -0,0 +1,37 @@
apply from: rootProject.file('buildscript/runtime.gradle')
allprojects {
repositories {
maven { url 'https://papermc.io/repo/repository/maven-public/' }
}
dependencies {
// API
annotationProcessor project(':api')
// Platform
compileOnly 'com.destroystokyo.paper:paper-api:1.16.5-R0.1-SNAPSHOT'
}
}
dependencies {
// Common
implementation project(':common:common-server')
// DependencyDownload
implementation 'dev.vankka.minecraftdependencydownload:bukkit:' + rootProject.mddVersion
// Adventure
runtimeDownloadApi 'net.kyori:adventure-platform-bukkit:' + rootProject.adventurePlatformVersion
runtimeDownloadApi 'net.kyori:adventure-text-serializer-craftbukkit:' + rootProject.adventurePlatformVersion
}
shadowJar {
archiveFileName = 'bukkit.jarinjar'
// [
// 'net.kyori.adventure'
// ].each {
// relocate it, 'com.discordsrv.dependencies.' + it
// }
}

View File

@ -0,0 +1,21 @@
import org.apache.tools.ant.filters.ReplaceTokens
apply from: rootProject.file('buildscript/loader.gradle')
dependencies {
// API
implementation project(':api')
// DependencyDownload
implementation 'dev.vankka.minecraftdependencydownload:bukkit-loader:' + rootProject.mddVersion
}
processResources {
filter(ReplaceTokens, tokens: ['VERSION': project.version])
}
shadowJar {
archiveBaseName = 'DiscordSRV-Bukkit'
}
// buildscript/loader.gradle includes the jarinjar in the jar

View File

@ -0,0 +1,45 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package com.discordsrv.bukkit.loader;
import dev.vankka.mcdependencydownload.bukkit.loader.BukkitLoader;
import dev.vankka.mcdependencydownload.loader.exception.LoadingException;
import java.net.URL;
import java.util.logging.Level;
import java.util.logging.Logger;
@SuppressWarnings("unused") // Used by Bukkit
public class DiscordSRVBukkitLoader extends BukkitLoader {
@Override
public String getBootstrapClassName() {
return "com.discordsrv.bukkit.DiscordSRVBukkitBootstrap";
}
@Override
public URL getJarInJarResource() {
return getClassLoader().getResource("bukkit.jarinjar");
}
@Override
public void handleLoadingException(LoadingException exception) {
getLogger().logp(Level.SEVERE, null, null, exception.getCause(), exception::getMessage);
}
}

View File

@ -0,0 +1,7 @@
name: DiscordSRV
main: com.discordsrv.bukkit.loader.DiscordSRVBukkitLoader
version: @VERSION@
description: ""
authors: [Scarsz, Vankka]
load: STARTUP
api-version: 1.13

View File

@ -0,0 +1,137 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package com.discordsrv.bukkit;
import com.discordsrv.api.DiscordSRVApi;
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.bukkit.console.BukkitConsole;
import com.discordsrv.bukkit.listener.BukkitChatListener;
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.common.logging.logger.Logger;
import com.discordsrv.common.logging.logger.impl.JavaLoggerImpl;
import com.discordsrv.common.server.ServerDiscordSRV;
import net.kyori.adventure.platform.bukkit.BukkitAudiences;
import org.bukkit.Server;
import org.bukkit.plugin.ServicePriority;
import org.bukkit.plugin.java.JavaPlugin;
import org.jetbrains.annotations.NotNull;
import java.nio.file.Path;
public class BukkitDiscordSRV extends ServerDiscordSRV<BukkitConfig, BukkitConnectionConfig> {
private final DiscordSRVBukkitBootstrap bootstrap;
private BukkitAudiences audiences;
private final Logger logger;
private final Path dataDirectory;
private final BukkitScheduler scheduler;
private final BukkitConsole console;
private final BukkitPlayerProvider playerProvider;
private final BukkitConnectionConfigManager connectionConfigManager;
private final BukkitConfigManager configManager;
public BukkitDiscordSRV(DiscordSRVBukkitBootstrap bootstrap) {
this.bootstrap = bootstrap;
this.logger = new JavaLoggerImpl(bootstrap.getPlugin().getLogger());
this.dataDirectory = bootstrap.getPlugin().getDataFolder().toPath();
this.scheduler = new BukkitScheduler(this);
this.console = new BukkitConsole(this);
this.playerProvider = new BukkitPlayerProvider(this);
// Config
this.connectionConfigManager = new BukkitConnectionConfigManager(this);
this.configManager = new BukkitConfigManager(this);
}
public JavaPlugin plugin() {
return bootstrap.getPlugin();
}
public Server server() {
return plugin().getServer();
}
public BukkitAudiences audiences() {
return audiences;
}
@Override
public Logger logger() {
return logger;
}
@Override
public Path dataDirectory() {
return dataDirectory;
}
@Override
public BukkitScheduler scheduler() {
return scheduler;
}
@Override
public BukkitConsole console() {
return console;
}
@Override
public @NotNull BukkitPlayerProvider playerProvider() {
return playerProvider;
}
@Override
public String version() {
return bootstrap.getPlugin().getDescription().getVersion();
}
@Override
public ConnectionConfigManager<BukkitConnectionConfig> connectionConfigManager() {
return connectionConfigManager;
}
@Override
public MainConfigManager<BukkitConfig> configManager() {
return configManager;
}
@Override
protected void enable() throws Throwable {
// Service provider
server().getServicesManager().register(DiscordSRVApi.class, this, plugin(), ServicePriority.Normal);
// Player related
this.audiences = BukkitAudiences.create(bootstrap.getPlugin());
playerProvider().subscribe();
super.enable();
// Register listeners
server().getPluginManager().registerEvents(BukkitChatListener.get(this), plugin());
}
}

View File

@ -0,0 +1,55 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package com.discordsrv.bukkit;
import com.discordsrv.common.dependency.InitialDependencyLoader;
import dev.vankka.mcdependencydownload.bukkit.bootstrap.BukkitBootstrap;
import dev.vankka.mcdependencydownload.classloader.JarInJarClassLoader;
import org.bukkit.plugin.java.JavaPlugin;
import java.io.IOException;
public class DiscordSRVBukkitBootstrap extends BukkitBootstrap {
private final InitialDependencyLoader dependencies;
private BukkitDiscordSRV discordSRV;
public DiscordSRVBukkitBootstrap(JarInJarClassLoader classLoader, JavaPlugin plugin) throws IOException {
// Don't change these parameters
super(classLoader, plugin);
this.dependencies = new InitialDependencyLoader(
plugin.getDataFolder().toPath(),
new String[] {"dependencies/runtimeDownloadApi-bukkit.txt"},
getClasspathAppender()
);
dependencies.whenComplete(() -> this.discordSRV = new BukkitDiscordSRV(this));
}
@Override
public void onEnable() {
dependencies.whenComplete(() -> discordSRV.invokeEnable());
getPlugin().getServer().getScheduler().runTaskLater(getPlugin(),
() -> dependencies.whenComplete(() -> discordSRV.invokeServerStarted()), 1L);
}
@Override
public void onDisable() {
dependencies.whenComplete(() -> discordSRV.invokeDisable());
}
}

View File

@ -0,0 +1,27 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package com.discordsrv.bukkit.config.connection;
import com.discordsrv.common.config.connection.ConnectionConfig;
import org.spongepowered.configurate.objectmapping.ConfigSerializable;
@ConfigSerializable
public class BukkitConnectionConfig extends ConnectionConfig {
}

View File

@ -0,0 +1,26 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package com.discordsrv.bukkit.config.main;
import com.discordsrv.common.config.main.MainConfig;
import org.spongepowered.configurate.objectmapping.ConfigSerializable;
@ConfigSerializable
public class BukkitConfig extends MainConfig {
}

View File

@ -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 <https://www.gnu.org/licenses/>.
*/
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;
public class BukkitConfigManager extends MainConfigManager<BukkitConfig> {
public BukkitConfigManager(DiscordSRV discordSRV) {
super(discordSRV);
}
@Override
public BukkitConfig createConfiguration() {
return new BukkitConfig();
}
}

View File

@ -0,0 +1,36 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package com.discordsrv.bukkit.config.manager;
import com.discordsrv.bukkit.config.connection.BukkitConnectionConfig;
import com.discordsrv.common.DiscordSRV;
import com.discordsrv.common.config.manager.ConnectionConfigManager;
public class BukkitConnectionConfigManager extends ConnectionConfigManager<BukkitConnectionConfig> {
public BukkitConnectionConfigManager(DiscordSRV discordSRV) {
super(discordSRV);
}
@Override
public BukkitConnectionConfig createConfiguration() {
return new BukkitConnectionConfig();
}
}

View File

@ -0,0 +1,67 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package com.discordsrv.bukkit.console;
import com.discordsrv.bukkit.BukkitDiscordSRV;
import com.discordsrv.common.console.Console;
import com.discordsrv.common.logging.logger.backend.LoggingBackend;
import com.discordsrv.common.logging.logger.impl.JavaLoggerImpl;
import com.discordsrv.common.logging.logger.impl.Log4JLoggerImpl;
import net.kyori.adventure.identity.Identity;
import net.kyori.adventure.text.Component;
public class BukkitConsole implements Console {
private final BukkitDiscordSRV discordSRV;
private final LoggingBackend loggingBackend;
public BukkitConsole(BukkitDiscordSRV discordSRV) {
this.discordSRV = discordSRV;
LoggingBackend logging;
try {
// Check that log4j is there
Class.forName("org.apache.logging.log4j.core.Filter");
logging = Log4JLoggerImpl.getRoot();
} catch (ClassNotFoundException ignored) {
// Log4j with Filter has been in the vanilla server since Minecraft 1.7,
// this is mostly for Bukkit servers that don't use the vanilla server software
discordSRV.logger().debug("Not using Log4j for advanced console features");
logging = JavaLoggerImpl.getRoot();
}
this.loggingBackend = logging;
}
@Override
public void sendMessage(Identity identity, Component message) {
discordSRV.audiences().console().sendMessage(identity, message);
}
@Override
public void runCommand(String command) {
discordSRV.scheduler().runOnMainThread(() ->
discordSRV.server().dispatchCommand(
discordSRV.server().getConsoleSender(), command));
}
@Override
public LoggingBackend loggingBackend() {
return loggingBackend;
}
}

View File

@ -0,0 +1,128 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package com.discordsrv.bukkit.listener;
import com.discordsrv.api.component.MinecraftComponent;
import com.discordsrv.api.event.events.message.receive.game.ChatMessageReceiveEvent;
import com.discordsrv.bukkit.BukkitDiscordSRV;
import com.discordsrv.common.channel.DefaultGlobalChannel;
import com.discordsrv.common.component.util.ComponentUtil;
import io.papermc.paper.event.player.AsyncChatEvent;
import net.kyori.adventure.text.serializer.craftbukkit.BukkitComponentSerializer;
import org.bukkit.entity.Player;
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) {}
}
return new Bukkit(discordSRV);
}
protected final BukkitDiscordSRV discordSRV;
public BukkitChatListener(BukkitDiscordSRV discordSRV) {
this.discordSRV = discordSRV;
}
protected void publishEvent(Player player, MinecraftComponent component, boolean cancelled) {
discordSRV.eventBus().publish(
new ChatMessageReceiveEvent(
discordSRV.playerProvider().player(player),
component,
new DefaultGlobalChannel(discordSRV),
cancelled
)
);
}
static class Bukkit extends BukkitChatListener {
public Bukkit(BukkitDiscordSRV discordSRV) {
super(discordSRV);
}
@SuppressWarnings("deprecation") // Paper
@EventHandler(priority = EventPriority.MONITOR)
public void onAsyncPlayerChat(org.bukkit.event.player.AsyncPlayerChatEvent event) {
MinecraftComponent component = ComponentUtil.toAPI(
BukkitComponentSerializer.legacy().deserialize(event.getMessage()));
publishEvent(event.getPlayer(), component, event.isCancelled());
}
}
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();
if (adapter == null) {
discordSRV.logger().error("Failed to get unrelocated adventure adapter for Paper AsyncChatEvent listener");
return;
}
adapter.setComponent(unrelocated);
publishEvent(
event.getPlayer(),
component,
event.isCancelled()
);
}
}
}

View File

@ -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 <https://www.gnu.org/licenses/>.
*/
package com.discordsrv.bukkit.player;
import com.discordsrv.bukkit.BukkitDiscordSRV;
import com.discordsrv.common.player.IOfflinePlayer;
import net.kyori.adventure.identity.Identity;
import org.bukkit.OfflinePlayer;
import org.jetbrains.annotations.NotNull;
public class BukkitOfflinePlayer implements IOfflinePlayer {
protected final BukkitDiscordSRV discordSRV;
private final OfflinePlayer offlinePlayer;
private final Identity identity;
public BukkitOfflinePlayer(BukkitDiscordSRV discordSRV, OfflinePlayer offlinePlayer) {
this.discordSRV = discordSRV;
this.offlinePlayer = offlinePlayer;
this.identity = Identity.identity(offlinePlayer.getUniqueId());
}
@Override
public String getUsername() {
return offlinePlayer.getName();
}
@Override
public @NotNull Identity identity() {
return identity;
}
}

View File

@ -0,0 +1,84 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package com.discordsrv.bukkit.player;
import com.discordsrv.bukkit.BukkitDiscordSRV;
import com.discordsrv.common.component.util.ComponentUtil;
import com.discordsrv.common.player.IPlayer;
import net.kyori.adventure.audience.Audience;
import net.kyori.adventure.identity.Identity;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.serializer.craftbukkit.BukkitComponentSerializer;
import org.bukkit.entity.Player;
import java.lang.reflect.Method;
public class BukkitPlayer extends BukkitOfflinePlayer implements IPlayer {
private static final Method DISPLAY_NAME_METHOD; // Paper 1.16+
static {
Method displayNameMethod = null;
try {
displayNameMethod = Player.class.getMethod("displayName");
} catch (Throwable ignored) {}
DISPLAY_NAME_METHOD = displayNameMethod;
}
private final Player player;
private final Audience audience;
public BukkitPlayer(BukkitDiscordSRV discordSRV, Player player) {
super(discordSRV, player);
this.player = player;
this.audience = discordSRV.audiences().player(player);
}
@Override
public void sendMessage(Identity identity, Component message) {
if (audience != null) {
audience.sendMessage(identity, message);
} else {
player.sendMessage(BukkitComponentSerializer.legacy().serialize(message));
}
}
@Override
public boolean hasPermission(String permission) {
return player.hasPermission(permission);
}
@Override
public void runCommand(String command) {
discordSRV.scheduler().runOnMainThread(() ->
discordSRV.server().dispatchCommand(player, command));
}
@SuppressWarnings("deprecation") // Paper
@Override
public Component displayName() {
if (DISPLAY_NAME_METHOD != null) {
try {
return ComponentUtil.fromUnrelocated(DISPLAY_NAME_METHOD.invoke(player));
} catch (Throwable ignored) {}
}
// Use the legacy method
return BukkitComponentSerializer.legacy().deserialize(player.getDisplayName());
}
}

View File

@ -0,0 +1,101 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package com.discordsrv.bukkit.player;
import com.discordsrv.bukkit.BukkitDiscordSRV;
import com.discordsrv.common.player.IOfflinePlayer;
import com.discordsrv.common.server.player.ServerPlayerProvider;
import org.bukkit.OfflinePlayer;
import org.bukkit.entity.Player;
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;
import java.util.Optional;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
public class BukkitPlayerProvider extends ServerPlayerProvider<BukkitPlayer> implements Listener {
private final BukkitDiscordSRV discordSRV;
public BukkitPlayerProvider(BukkitDiscordSRV discordSRV) {
this.discordSRV = discordSRV;
}
// IPlayer
@Override
public void subscribe() {
discordSRV.server().getPluginManager().registerEvents(this, discordSRV.plugin());
// Add players that are already connected
for (Player player : discordSRV.server().getOnlinePlayers()) {
addPlayer(player);
}
}
@EventHandler(priority = EventPriority.LOWEST)
public void onPlayerLogin(PlayerJoinEvent event) {
addPlayer(event.getPlayer());
}
private void addPlayer(Player player) {
addPlayer(player.getUniqueId(), new BukkitPlayer(discordSRV, player));
}
@EventHandler(priority = EventPriority.MONITOR)
public void onPlayerQuit(PlayerQuitEvent event) {
removePlayer(event.getPlayer().getUniqueId());
}
public BukkitPlayer player(Player player) {
return player(player.getUniqueId()).orElseThrow(() -> new IllegalStateException("Player not available"));
}
// IOfflinePlayer
private Optional<IOfflinePlayer> convert(OfflinePlayer offlinePlayer) {
if (offlinePlayer == null) {
return Optional.empty();
}
return Optional.of(new BukkitOfflinePlayer(discordSRV, offlinePlayer));
}
@Override
public CompletableFuture<Optional<IOfflinePlayer>> offlinePlayer(UUID uuid) {
CompletableFuture<Optional<IOfflinePlayer>> future = new CompletableFuture<>();
future.complete(convert(discordSRV.server().getOfflinePlayer(uuid)));
return future;
}
@SuppressWarnings("deprecation") // Shut up, I know
@Override
public CompletableFuture<Optional<IOfflinePlayer>> offlinePlayer(String username) {
CompletableFuture<Optional<IOfflinePlayer>> future = new CompletableFuture<>();
future.complete(convert(discordSRV.server().getOfflinePlayer(username)));
return future;
}
public IOfflinePlayer offlinePlayer(OfflinePlayer offlinePlayer) {
return new BukkitOfflinePlayer(discordSRV, offlinePlayer);
}
}

View File

@ -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 <https://www.gnu.org/licenses/>.
*/
package com.discordsrv.bukkit.scheduler;
import com.discordsrv.bukkit.BukkitDiscordSRV;
import com.discordsrv.common.server.scheduler.ServerScheduler;
import com.discordsrv.common.scheduler.StandardScheduler;
public class BukkitScheduler extends StandardScheduler implements ServerScheduler {
private final BukkitDiscordSRV discordSRV;
public BukkitScheduler(BukkitDiscordSRV discordSRV) {
super(discordSRV);
this.discordSRV = discordSRV;
}
@Override
public void runOnMainThread(Runnable task) {
discordSRV.server().getScheduler().runTask(discordSRV.plugin(), task);
}
@Override
public void runOnMainThreadLaterInTicks(Runnable task, int ticks) {
discordSRV.server().getScheduler().runTaskLater(discordSRV.plugin(), task, ticks);
}
@Override
public void runOnMainThreadAtFixedRateInTicks(Runnable task, int initialTicks, int rateTicks) {
discordSRV.server().getScheduler().runTaskTimer(discordSRV.plugin(), task, initialTicks, rateTicks);
}
}

37
bungee/build.gradle Normal file
View File

@ -0,0 +1,37 @@
apply from: rootProject.file('buildscript/runtime.gradle')
allprojects {
repositories {
maven { url 'https://oss.sonatype.org/content/repositories/snapshots' }
}
dependencies {
// API
annotationProcessor project(':api')
// Platform
compileOnly 'net.md-5:bungeecord-api:1.17-R0.1-SNAPSHOT'
}
}
dependencies {
// Common
implementation project(':common:common-proxy')
// DependencyDownload
implementation 'dev.vankka.minecraftdependencydownload:bungee:' + rootProject.mddVersion
// Adventure
runtimeDownloadApi 'net.kyori:adventure-platform-bungeecord:' + rootProject.adventurePlatformVersion
runtimeDownloadApi 'net.kyori:adventure-text-serializer-bungeecord:' + rootProject.adventurePlatformVersion
}
shadowJar {
archiveFileName = 'bungee.jarinjar'
[
'net.kyori.adventure'
].each {
relocate it, 'com.discordsrv.dependencies.' + it
}
}

View File

@ -0,0 +1,21 @@
import org.apache.tools.ant.filters.ReplaceTokens
apply from: rootProject.file('buildscript/loader.gradle')
dependencies {
// API
implementation project(':api')
// DependencyDownload
implementation 'dev.vankka.minecraftdependencydownload:bungee-loader:' + rootProject.mddVersion
}
processResources {
filter(ReplaceTokens, tokens: ['VERSION': project.version])
}
shadowJar {
archiveBaseName = 'DiscordSRV-Bungee'
}
// buildscript/loader.gradle includes the jarinjar in the jar

View File

@ -0,0 +1,44 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package com.discordsrv.bungee.loader;
import dev.vankka.mcdependencydownload.bungee.loader.BungeeLoader;
import dev.vankka.mcdependencydownload.loader.exception.LoadingException;
import java.net.URL;
import java.util.logging.Level;
@SuppressWarnings("unused") // Used by Bungee
public class DiscordSRVBungeeLoader extends BungeeLoader {
@Override
public String getBootstrapClassName() {
return "com.discordsrv.bungee.DiscordSRVBungeeBootstrap";
}
@Override
public URL getJarInJarResource() {
return getClass().getClassLoader().getResource("bungee.jarinjar");
}
@Override
public void handleLoadingException(LoadingException exception) {
getLogger().logp(Level.SEVERE, null, null, exception.getCause(), exception::getMessage);
}
}

View File

@ -0,0 +1,5 @@
name: DiscordSRV
main: com.discordsrv.bungee.loader.DiscordSRVBungeeLoader
version: @VERSION@
description: ""
author: "Scarsz, Vankka"

View File

@ -0,0 +1,119 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package com.discordsrv.bungee;
import com.discordsrv.bungee.console.BungeeConsole;
import com.discordsrv.bungee.player.BungeePlayerProvider;
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.logging.logger.Logger;
import com.discordsrv.common.logging.logger.impl.JavaLoggerImpl;
import com.discordsrv.common.proxy.ProxyDiscordSRV;
import com.discordsrv.common.scheduler.StandardScheduler;
import net.kyori.adventure.platform.bungeecord.BungeeAudiences;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.plugin.Plugin;
import org.jetbrains.annotations.NotNull;
import java.nio.file.Path;
public class BungeeDiscordSRV extends ProxyDiscordSRV<MainConfig, ConnectionConfig> {
private final DiscordSRVBungeeBootstrap bootstrap;
private BungeeAudiences audiences;
private final Logger logger;
private final Path dataDirectory;
private final StandardScheduler scheduler;
private final BungeeConsole console;
private final BungeePlayerProvider playerProvider;
public BungeeDiscordSRV(DiscordSRVBungeeBootstrap bootstrap) {
this.bootstrap = bootstrap;
this.logger = new JavaLoggerImpl(bootstrap.getPlugin().getLogger());
this.dataDirectory = bootstrap.getPlugin().getDataFolder().toPath();
this.scheduler = new StandardScheduler(this);
this.console = new BungeeConsole(this);
this.playerProvider = new BungeePlayerProvider(this);
}
public Plugin plugin() {
return bootstrap.getPlugin();
}
public ProxyServer proxy() {
return plugin().getProxy();
}
public BungeeAudiences audiences() {
return audiences;
}
@Override
public Logger logger() {
return logger;
}
@Override
public Path dataDirectory() {
return dataDirectory;
}
@Override
public StandardScheduler scheduler() {
return scheduler;
}
@Override
public BungeeConsole console() {
return console;
}
@Override
public @NotNull BungeePlayerProvider playerProvider() {
return playerProvider;
}
@Override
public String version() {
return bootstrap.getPlugin().getDescription().getVersion();
}
@Override
public ConnectionConfigManager<ConnectionConfig> connectionConfigManager() {
return null;
}
@Override
public MainConfigManager<MainConfig> configManager() {
return null;
}
@Override
protected void enable() throws Throwable {
// Player related
this.audiences = BungeeAudiences.create(bootstrap.getPlugin());
playerProvider().subscribe();
super.enable();
}
}

View File

@ -0,0 +1,53 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package com.discordsrv.bungee;
import com.discordsrv.common.dependency.InitialDependencyLoader;
import dev.vankka.mcdependencydownload.bungee.bootstrap.BungeeBootstrap;
import dev.vankka.mcdependencydownload.classloader.JarInJarClassLoader;
import net.md_5.bungee.api.plugin.Plugin;
import java.io.IOException;
public class DiscordSRVBungeeBootstrap extends BungeeBootstrap {
private final InitialDependencyLoader dependencies;
private BungeeDiscordSRV discordSRV;
public DiscordSRVBungeeBootstrap(JarInJarClassLoader classLoader, Plugin plugin) throws IOException {
// Don't change these parameters
super(classLoader, plugin);
this.dependencies = new InitialDependencyLoader(
plugin.getDataFolder().toPath(),
new String[] {"dependencies/runtimeDownloadApi-bungee.txt"},
getClasspathAppender()
);
dependencies.whenComplete(() -> this.discordSRV = new BungeeDiscordSRV(this));
}
@Override
public void onEnable() {
dependencies.whenComplete(discordSRV::invokeEnable);
}
@Override
public void onDisable() {
dependencies.whenComplete(discordSRV::invokeDisable);
}
}

View File

@ -0,0 +1,19 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package com.discordsrv.bungee.component;

View File

@ -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 <https://www.gnu.org/licenses/>.
*/
package com.discordsrv.bungee.component.util;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.serializer.bungeecord.BungeeComponentSerializer;
import net.md_5.bungee.api.chat.BaseComponent;
import net.md_5.bungee.api.chat.TextComponent;
public final class BungeeComponentUtil {
private BungeeComponentUtil() {}
public static Component fromLegacy(String legacy) {
BaseComponent[] components = TextComponent.fromLegacyText(legacy);
return BungeeComponentSerializer.get().deserialize(components);
}
}

View File

@ -0,0 +1,53 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package com.discordsrv.bungee.console;
import com.discordsrv.bungee.BungeeDiscordSRV;
import com.discordsrv.common.console.Console;
import com.discordsrv.common.logging.logger.backend.LoggingBackend;
import com.discordsrv.common.logging.logger.impl.JavaLoggerImpl;
import net.kyori.adventure.identity.Identity;
import net.kyori.adventure.text.Component;
public class BungeeConsole implements Console {
private final BungeeDiscordSRV discordSRV;
private final LoggingBackend loggingBackend;
public BungeeConsole(BungeeDiscordSRV discordSRV) {
this.discordSRV = discordSRV;
this.loggingBackend = JavaLoggerImpl.getRoot();
}
@Override
public void sendMessage(Identity identity, Component message) {
discordSRV.audiences().console().sendMessage(identity, message);
}
@Override
public void runCommand(String command) {
discordSRV.proxy().getPluginManager().dispatchCommand(
discordSRV.proxy().getConsole(), command);
}
@Override
public LoggingBackend loggingBackend() {
return loggingBackend;
}
}

View File

@ -0,0 +1,73 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package com.discordsrv.bungee.player;
import com.discordsrv.bungee.BungeeDiscordSRV;
import com.discordsrv.bungee.component.util.BungeeComponentUtil;
import com.discordsrv.common.player.IPlayer;
import net.kyori.adventure.audience.Audience;
import net.kyori.adventure.identity.Identity;
import net.kyori.adventure.text.Component;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import org.jetbrains.annotations.NotNull;
public class BungeePlayer implements IPlayer {
private final BungeeDiscordSRV discordSRV;
private final ProxiedPlayer player;
private final Identity identity;
private final Audience audience;
public BungeePlayer(BungeeDiscordSRV discordSRV, ProxiedPlayer player) {
this.discordSRV = discordSRV;
this.player = player;
this.identity = Identity.identity(player.getUniqueId());
this.audience = discordSRV.audiences().player(player);
}
@Override
public void sendMessage(Identity identity, Component message) {
audience.sendMessage(identity, message);
}
@Override
public boolean hasPermission(String permission) {
return player.hasPermission(permission);
}
@Override
public void runCommand(String command) {
discordSRV.proxy().getPluginManager().dispatchCommand(player, command);
}
@Override
public String getUsername() {
return player.getName();
}
@Override
public @NotNull Identity identity() {
return identity;
}
@Override
public Component displayName() {
return BungeeComponentUtil.fromLegacy(player.getDisplayName());
}
}

View File

@ -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 <https://www.gnu.org/licenses/>.
*/
package com.discordsrv.bungee.player;
import com.discordsrv.bungee.BungeeDiscordSRV;
import com.discordsrv.common.player.provider.AbstractPlayerProvider;
import com.discordsrv.common.player.provider.PlayerProvider;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.event.PlayerDisconnectEvent;
import net.md_5.bungee.api.event.PostLoginEvent;
import net.md_5.bungee.api.plugin.Listener;
import net.md_5.bungee.event.EventHandler;
public class BungeePlayerProvider extends AbstractPlayerProvider<BungeePlayer> implements PlayerProvider<BungeePlayer>, Listener {
private final BungeeDiscordSRV discordSRV;
public BungeePlayerProvider(BungeeDiscordSRV discordSRV) {
this.discordSRV = discordSRV;
}
@Override
public void subscribe() {
discordSRV.proxy().getPluginManager().registerListener(discordSRV.plugin(), this);
// Add players that are already connected
for (ProxiedPlayer player : discordSRV.proxy().getPlayers()) {
addPlayer(player);
}
}
@EventHandler(priority = Byte.MIN_VALUE) // Runs first
public void onPostLogin(PostLoginEvent event) {
addPlayer(event.getPlayer());
}
private void addPlayer(ProxiedPlayer player) {
addPlayer(player.getUniqueId(), new BungeePlayer(discordSRV, player));
}
@EventHandler(priority = Byte.MAX_VALUE) // Runs last
public void onDisconnect(PlayerDisconnectEvent event) {
removePlayer(event.getPlayer().getUniqueId());
}
public BungeePlayer player(ProxiedPlayer player) {
return player(player.getUniqueId()).orElseThrow(() -> new IllegalStateException("Player not available"));
}
}

67
common/build.gradle Normal file
View File

@ -0,0 +1,67 @@
import dev.vankka.dependencydownload.task.GenerateDependencyDownloadResourceTask
configurations {
h2Driver
mysqlDriver
}
task generateResourceForH2Driver(type: GenerateDependencyDownloadResourceTask) {
var conf = configurations.h2Driver
configuration = conf
fileLocation = new File(dependenciesDirectory, conf.name + '.txt')
}
task generateResourceForMySQLDriver(type: GenerateDependencyDownloadResourceTask) {
var conf = configurations.mysqlDriver
configuration = conf
fileLocation = new File(dependenciesDirectory, conf.name + '.txt')
}
dependencies {
// API
annotationProcessor project(':api')
compileOnlyApi project(':api')
// DependencyDownload
api 'dev.vankka.dependencydownload:runtime:' + rootProject.ddVersion
// Discord Webhooks
runtimeDownloadApi 'club.minnced:discord-webhooks:0.5.7'
// Apache Commons
runtimeDownloadApi 'org.apache.commons:commons-lang3:3.12.0'
runtimeDownloadApi 'commons-io:commons-io:2.10.0'
// Caffeine
runtimeDownloadApi 'com.github.ben-manes.caffeine:caffeine:2.9.2'
// Config
runtimeDownloadApi 'org.spongepowered:configurate-yaml:' + rootProject.configurateVersion
runtimeDownloadApi 'org.spongepowered:configurate-hocon:' + rootProject.configurateVersion
// Adventure, MCDiscordReserializer, EnhancedLegacyText
runtimeDownloadApi 'net.kyori:adventure-api:' + rootProject.adventureVersion
runtimeDownloadApi 'net.kyori:adventure-text-serializer-plain:' + rootProject.adventureVersion
runtimeDownloadApi 'net.kyori:adventure-text-serializer-legacy:' + rootProject.adventureVersion
runtimeDownloadApi 'net.kyori:adventure-text-serializer-gson:' + rootProject.adventureVersion
runtimeDownloadApi 'dev.vankka:mcdiscordreserializer:4.2.4-SNAPSHOT'
runtimeDownloadApi 'dev.vankka:enhancedlegacytext:1.0.0-SNAPSHOT'
// Database Drivers & SLF4J
h2Driver 'com.h2database:h2:1.4.200'
mysqlDriver 'mysql:mysql-connector-java:8.0.25'
// Logging (provided by platforms)
compileOnlyApi 'org.apache.logging.log4j:log4j-core:2.0-beta9'
compileOnlyApi 'org.slf4j:slf4j-api:1.7.32'
}
jar {
dependsOn(
generateRuntimeDownloadResourceForRuntimeDownloadOnly,
generateResourceForRuntimeDownloadApi,
generateResourceForH2Driver,
generateResourceForMySQLDriver
)
}
// Relocations in buildscript/relocations.gradle

View File

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

View File

@ -0,0 +1,19 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package com.discordsrv.common;

View File

@ -0,0 +1,27 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package com.discordsrv.common.proxy;
import com.discordsrv.common.AbstractDiscordSRV;
import com.discordsrv.common.config.connection.ConnectionConfig;
import com.discordsrv.common.config.main.MainConfig;
public abstract class ProxyDiscordSRV<C extends MainConfig, CC extends ConnectionConfig> extends AbstractDiscordSRV<C, CC> {
}

View File

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

View File

@ -0,0 +1,53 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
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.server.player.ServerPlayerProvider;
import com.discordsrv.common.server.scheduler.ServerScheduler;
import org.jetbrains.annotations.NotNull;
import javax.annotation.OverridingMethodsMustInvokeSuper;
import java.util.concurrent.CompletableFuture;
public abstract class ServerDiscordSRV<C extends MainConfig, CC extends ConnectionConfig> extends AbstractDiscordSRV<C, CC> {
@Override
public abstract ServerScheduler scheduler();
@Override
public abstract @NotNull ServerPlayerProvider<?> playerProvider();
public final CompletableFuture<Void> invokeServerStarted() {
return CompletableFuture.runAsync(() -> {
try {
serverStarted();
} catch (Throwable t) {
logger().error("Failed to enable", t);
}
}, scheduler().executor());
}
@OverridingMethodsMustInvokeSuper
protected void serverStarted() {
}
}

View File

@ -0,0 +1,33 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package com.discordsrv.common.server.player;
import com.discordsrv.common.player.IOfflinePlayer;
import com.discordsrv.common.player.IPlayer;
import com.discordsrv.common.player.provider.AbstractPlayerProvider;
import java.util.Optional;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
public abstract class ServerPlayerProvider<T extends IPlayer> extends AbstractPlayerProvider<T> {
public abstract CompletableFuture<Optional<IOfflinePlayer>> offlinePlayer(UUID uuid);
public abstract CompletableFuture<Optional<IOfflinePlayer>> offlinePlayer(String username);
}

View File

@ -0,0 +1,83 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package com.discordsrv.common.server.scheduler;
import com.discordsrv.common.scheduler.Scheduler;
import org.jetbrains.annotations.ApiStatus;
import java.util.concurrent.TimeUnit;
@SuppressWarnings("unused") // API
public interface ServerScheduler extends Scheduler {
int TICKS_PER_SECOND = 20;
long MILLISECONDS_PER_TICK = (1000L / TICKS_PER_SECOND);
@ApiStatus.NonExtendable
default long timeToTicks(long time, TimeUnit unit) {
return millisToTicks(unit.toMillis(time));
}
@ApiStatus.NonExtendable
default long millisToTicks(long milliseconds) {
return milliseconds / MILLISECONDS_PER_TICK;
}
@ApiStatus.NonExtendable
default long ticksToMillis(long ticks) {
return ticks * MILLISECONDS_PER_TICK;
}
/**
* Runs the provided task on the server's main thread as soon as possible.
* @param task the task
*/
void runOnMainThread(Runnable task);
/**
* Runs the provided task in on the server's main thread in the provided amount of ticks.
* @param task the task
* @param ticks the time in ticks
* @see #TICKS_PER_SECOND
* @see #timeToTicks(long, TimeUnit)
*/
void runOnMainThreadLaterInTicks(Runnable task, int ticks);
/**
* Runs the task on the server's main thread continuously at provided rate in ticks.
*
* @param task the task
* @param rateTicks the rate in ticks
*/
@ApiStatus.NonExtendable
default void runOnMainThreadAtFixedRateInTicks(Runnable task, int rateTicks) {
runOnMainThreadAtFixedRateInTicks(task, 0, rateTicks);
}
/**
* Runs the task on the server's main thread continuously at provided rate in ticks after the initial delay in ticks.
*
* @param task the task
* @param initialTicks the initial delay in ticks
* @param rateTicks the rate in ticks
*/
void runOnMainThreadAtFixedRateInTicks(Runnable task, int initialTicks, int rateTicks);
}

View File

@ -0,0 +1,238 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package com.discordsrv.common;
import com.discordsrv.api.discord.api.DiscordAPI;
import com.discordsrv.api.discord.connection.DiscordConnectionDetails;
import com.discordsrv.api.event.bus.EventBus;
import com.discordsrv.api.event.events.lifecycle.DiscordSRVShuttingDownEvent;
import com.discordsrv.common.api.util.ApiInstanceUtil;
import com.discordsrv.common.channel.ChannelConfig;
import com.discordsrv.common.channel.DefaultGlobalChannel;
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.discord.api.DiscordAPIImpl;
import com.discordsrv.common.discord.connection.DiscordConnectionManager;
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.listener.DefaultChannelLookupListener;
import com.discordsrv.common.listener.DefaultChatListener;
import com.discordsrv.common.logging.DependencyLoggingFilter;
import com.discordsrv.common.logging.logger.backend.LoggingBackend;
import net.dv8tion.jda.api.JDA;
import org.jetbrains.annotations.NotNull;
import javax.annotation.OverridingMethodsMustInvokeSuper;
import java.util.Locale;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicReference;
public abstract class AbstractDiscordSRV<C extends MainConfig, CC extends ConnectionConfig> implements DiscordSRV {
private final AtomicReference<Status> status = new AtomicReference<>(Status.INITIALIZED);
// DiscordSRVApi
private final EventBus eventBus;
private final ComponentFactory componentFactory;
private final DiscordAPI discordAPI;
private final DiscordConnectionDetails discordConnectionDetails;
// DiscordSRV
private final DefaultGlobalChannel defaultGlobalChannel = new DefaultGlobalChannel(this);
private ChannelConfig channelConfig;
private DiscordConnectionManager discordConnectionManager;
// Internal
private final DependencyLoggingFilter dependencyLoggingFilter = new DependencyLoggingFilter(this);
public AbstractDiscordSRV() {
ApiInstanceUtil.setInstance(this);
this.eventBus = new EventBusImpl(this);
this.componentFactory = new ComponentFactory();
this.discordAPI = new DiscordAPIImpl(this);
this.discordConnectionDetails = new DiscordConnectionDetailsImpl(this);
}
// DiscordSRVApi
@Override
public @NotNull Status status() {
synchronized (status) {
return status.get();
}
}
@Override
public @NotNull EventBus eventBus() {
return eventBus;
}
@Override
public @NotNull ComponentFactory componentFactory() {
return componentFactory;
}
@Override
public @NotNull DiscordAPI discordAPI() {
return discordAPI;
}
@Override
public JDA jda() {
return discordConnectionManager != null ? discordConnectionManager.instance() : null;
}
@Override
public @NotNull DiscordConnectionDetails discordConnectionDetails() {
return discordConnectionDetails;
}
// DiscordSRV
@Override
public DefaultGlobalChannel defaultGlobalChannel() {
return defaultGlobalChannel;
}
@Override
public ChannelConfig channelConfig() {
return channelConfig;
}
@Override
public DiscordConnectionManager discordConnectionManager() {
return discordConnectionManager;
}
// Config
@Override
public abstract ConnectionConfigManager<CC> connectionConfigManager();
@Override
public CC connectionConfig() {
return connectionConfigManager().config();
}
@Override
public abstract MainConfigManager<C> configManager();
@Override
public C config() {
return configManager().config();
}
@Override
public Locale locale() {
// TODO: config
return Locale.getDefault();
}
@Override
public void setStatus(Status status) {
synchronized (this.status) {
this.status.set(status);
}
}
private CompletableFuture<Void> invoke(CheckedRunnable runnable, String message) {
return CompletableFuture.runAsync(() -> {
try {
runnable.run();
} catch (Throwable t) {
setStatus(Status.FAILED_TO_START);
disable();
logger().error(message, t);
}
}, scheduler().executor());
}
@Override
public final CompletableFuture<Void> invokeEnable() {
return invoke(this::enable, "Failed to enable");
}
@Override
public final CompletableFuture<Void> invokeDisable() {
return invoke(this::disable, "Failed to disable");
}
@Override
public final CompletableFuture<Void> invokeReload() {
return invoke(this::reload, "Failed to reload");
}
@OverridingMethodsMustInvokeSuper
protected void enable() throws Throwable {
// Config
try {
connectionConfigManager().load();
configManager().load();
// Utility
channelConfig = new ChannelConfig(this);
} catch (Throwable t) {
setStatus(Status.FAILED_TO_LOAD_CONFIG);
throw t;
}
// Logging
LoggingBackend backend = console().loggingBackend();
backend.addFilter(dependencyLoggingFilter);
discordConnectionManager = new JDAConnectionManager(this);
discordConnectionManager.connect().join();
// Register PlayerProvider listeners
playerProvider().subscribe();
// Register listeners
// Chat
eventBus().subscribe(new DefaultChannelLookupListener(this));
eventBus().subscribe(new DefaultChatListener(this));
}
@OverridingMethodsMustInvokeSuper
protected void disable() {
synchronized (this.status) {
Status status = this.status.get();
if (status.isShutdown()) {
// Already shutting down/shutdown
return;
}
if (status != Status.FAILED_TO_START) {
this.status.set(Status.SHUTTING_DOWN);
}
}
eventBus().publish(new DiscordSRVShuttingDownEvent());
// Logging
LoggingBackend backend = console().loggingBackend();
backend.removeFilter(dependencyLoggingFilter);
}
@OverridingMethodsMustInvokeSuper
protected void reload() {
}
}

View File

@ -0,0 +1,77 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package com.discordsrv.common;
import com.discordsrv.api.DiscordSRVApi;
import com.discordsrv.common.channel.ChannelConfig;
import com.discordsrv.common.channel.DefaultGlobalChannel;
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.connection.DiscordConnectionManager;
import com.discordsrv.common.logging.logger.Logger;
import com.discordsrv.common.player.provider.AbstractPlayerProvider;
import com.discordsrv.common.scheduler.Scheduler;
import org.jetbrains.annotations.NotNull;
import java.nio.file.Path;
import java.util.Locale;
import java.util.concurrent.CompletableFuture;
public interface DiscordSRV extends DiscordSRVApi {
// Platform
Logger logger();
Path dataDirectory();
Scheduler scheduler();
Console console();
String version();
// DiscordSRVApi
@Override
@NotNull
AbstractPlayerProvider<?> playerProvider();
@Override
@NotNull
ComponentFactory componentFactory();
// Config
ConnectionConfigManager<? extends ConnectionConfig> connectionConfigManager();
ConnectionConfig connectionConfig();
MainConfigManager<? extends MainConfig> configManager();
MainConfig config();
// Internal
DefaultGlobalChannel defaultGlobalChannel();
ChannelConfig channelConfig();
DiscordConnectionManager discordConnectionManager();
Locale locale();
void setStatus(Status status);
// Lifecycle
CompletableFuture<Void> invokeEnable();
CompletableFuture<Void> invokeDisable();
CompletableFuture<Void> invokeReload();
}

View File

@ -0,0 +1,46 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package com.discordsrv.common.api.util;
import com.discordsrv.api.DiscordSRVApi;
import com.discordsrv.common.DiscordSRV;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
@ApiStatus.Internal
public final class ApiInstanceUtil {
private ApiInstanceUtil() {}
@ApiStatus.Internal
public static void setInstance(@NotNull DiscordSRV discordSRV) {
// Avoids illegal access
try {
Class<?> apiProviderClass = Class.forName("com.discordsrv.api.DiscordSRVApiProvider");
Method provideMethod = apiProviderClass.getDeclaredMethod("provide", DiscordSRVApi.class);
provideMethod.setAccessible(true);
provideMethod.invoke(null, discordSRV);
} catch (ClassNotFoundException | IllegalAccessException | NoSuchMethodException | InvocationTargetException e) {
discordSRV.logger().error("Failed to set API instance", e);
}
}
}

View File

@ -0,0 +1,89 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package com.discordsrv.common.channel;
import com.discordsrv.api.channel.GameChannel;
import com.discordsrv.api.event.events.channel.GameChannelLookupEvent;
import com.discordsrv.common.DiscordSRV;
import com.discordsrv.common.config.main.channels.BaseChannelConfig;
import com.discordsrv.common.config.main.channels.ChannelConfigHolder;
import com.discordsrv.common.function.OrDefault;
import com.github.benmanes.caffeine.cache.CacheLoader;
import com.github.benmanes.caffeine.cache.Caffeine;
import com.github.benmanes.caffeine.cache.LoadingCache;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import java.util.Map;
import java.util.concurrent.TimeUnit;
public class ChannelConfig {
private final DiscordSRV discordSRV;
private final LoadingCache<String, GameChannel> CHANNELS = Caffeine.newBuilder()
.expireAfterWrite(30, TimeUnit.SECONDS)
.build(new CacheLoader<String, GameChannel>() {
@Override
public @Nullable GameChannel load(@NonNull String channelName) {
GameChannelLookupEvent event = new GameChannelLookupEvent(null, channelName);
discordSRV.eventBus().publish(event);
if (!event.isProcessed()) {
return null;
}
return event.getChannelFromProcessing();
}
});
public ChannelConfig(DiscordSRV discordSRV) {
this.discordSRV = discordSRV;
}
private Map<String, ChannelConfigHolder> channels() {
return discordSRV.config().channels;
}
public OrDefault<BaseChannelConfig> orDefault(GameChannel gameChannel) {
return orDefault(gameChannel.getOwnerName(), gameChannel.getChannelName());
}
public OrDefault<BaseChannelConfig> orDefault(String pluginName, String channelName) {
ChannelConfigHolder defaultConfig = channels().computeIfAbsent(
"default", key -> new ChannelConfigHolder(new BaseChannelConfig()));
return new OrDefault<>(
get(pluginName, channelName),
defaultConfig.get()
);
}
public BaseChannelConfig get(GameChannel gameChannel) {
return get(gameChannel.getOwnerName(), gameChannel.getChannelName());
}
public BaseChannelConfig get(String pluginName, String channelName) {
if (pluginName != null) {
ChannelConfigHolder config = channels().get(pluginName + ":" + channelName);
return config != null ? config.get() : null;
}
GameChannel gameChannel = CHANNELS.get(channelName);
return gameChannel != null ? get(gameChannel) : null;
}
}

View File

@ -0,0 +1,58 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package com.discordsrv.common.channel;
import com.discordsrv.api.channel.GameChannel;
import com.discordsrv.api.component.MinecraftComponent;
import com.discordsrv.common.DiscordSRV;
import com.discordsrv.common.component.util.ComponentUtil;
import com.discordsrv.common.player.IPlayer;
import net.kyori.adventure.text.Component;
public class DefaultGlobalChannel implements GameChannel {
private final DiscordSRV discordSRV;
public DefaultGlobalChannel(DiscordSRV discordSRV) {
this.discordSRV = discordSRV;
}
@Override
public String getOwnerName() {
return "DiscordSRV";
}
@Override
public String getChannelName() {
return "global";
}
@Override
public boolean isChat() {
return true;
}
@Override
public void sendMessage(MinecraftComponent minecraftComponent) {
Component component = ComponentUtil.fromAPI(minecraftComponent);
for (IPlayer player : discordSRV.playerProvider().allPlayers()) {
player.sendMessage(component);
}
}
}

View File

@ -0,0 +1,19 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package com.discordsrv.common.command.game;

View File

@ -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 <https://www.gnu.org/licenses/>.
*/
package com.discordsrv.common.command.game.sender;
import net.kyori.adventure.identity.Identity;
import net.kyori.adventure.text.Component;
public interface ICommandSender {
default void sendMessage(Component message) {
sendMessage(null, message);
}
void sendMessage(Identity identity, Component message);
boolean hasPermission(String permission);
void runCommand(String command);
}

View File

@ -0,0 +1,30 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package com.discordsrv.common.component;
import com.discordsrv.api.component.MinecraftComponent;
import com.discordsrv.api.component.MinecraftComponentFactory;
public class ComponentFactory implements MinecraftComponentFactory {
@Override
public MinecraftComponent empty() {
return MinecraftComponentImpl.empty();
}
}

View File

@ -0,0 +1,129 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package com.discordsrv.common.component;
import com.discordsrv.api.component.MinecraftComponent;
import com.discordsrv.api.component.MinecraftComponentAdapter;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
import org.jetbrains.annotations.NotNull;
import java.lang.reflect.InvocationTargetException;
public class MinecraftComponentImpl implements MinecraftComponent {
private String json;
private Component component;
public static MinecraftComponentImpl empty() {
return new MinecraftComponentImpl("{}");
}
public MinecraftComponentImpl(String json) {
setJson(json);
}
public MinecraftComponentImpl(Component component) {
setComponent(component);
}
@Override
public @NotNull String asJson() {
return json;
}
@Override
public void setJson(@NotNull String json) throws IllegalArgumentException {
Component component;
try {
component = GsonComponentSerializer.gson().deserialize(json);
} catch (Throwable t) {
throw new IllegalArgumentException("Provided json is not valid", t);
}
this.component = component;
this.json = json;
}
@Override
public String asPlainString() {
return PlainTextComponentSerializer.plainText().serialize(component);
}
public Component getComponent() {
return component;
}
public void setComponent(Component component) {
this.component = component;
this.json = GsonComponentSerializer.gson().serialize(component);
}
@Override
public @NotNull MinecraftComponent.Adapter adventureAdapter(@NotNull Class<?> gsonSerializerClass) {
return new Adapter(gsonSerializerClass);
}
@Override
public @NotNull MinecraftComponent.Adapter adventureAdapter(@NotNull MinecraftComponentAdapter adapter) {
return new Adapter(adapter);
}
public class Adapter implements MinecraftComponent.Adapter {
private final MinecraftComponentAdapter adapter;
private Adapter(Class<?> gsonSerializerClass) {
this(MinecraftComponentAdapter.create(gsonSerializerClass));
}
private Adapter(MinecraftComponentAdapter adapter) {
this.adapter = adapter;
}
@Override
public Object getComponent() {
try {
return adapter.deserialize()
.invoke(
adapter.instance(),
json
);
} catch (IllegalAccessException | InvocationTargetException e) {
throw new RuntimeException("Failed to convert to adventure component", e);
}
}
@Override
public void setComponent(Object adventureComponent) {
try {
json = (String) adapter.serialize()
.invoke(
adapter.instance(),
adventureComponent
);
} catch (InvocationTargetException e) {
throw new IllegalArgumentException("The provided class is not a Component for the GsonComponentSerializer " + adapter.gsonSerializerClass().getName(), e);
} catch (IllegalAccessException e) {
throw new RuntimeException("Failed to convert from adventure component", e);
}
}
}
}

View File

@ -0,0 +1,60 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package com.discordsrv.common.component.util;
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.serializer.gson.GsonComponentSerializer;
import java.util.Objects;
/**
* A util class for {@link Component}s and {@link MinecraftComponent}s.
*/
public final class ComponentUtil {
public static final MinecraftComponentAdapter ADAPTER = MinecraftComponentAdapter.create(GsonComponentSerializer.class);
private ComponentUtil() {}
public static MinecraftComponent toAPI(Component component) {
return new MinecraftComponentImpl(component);
}
public static Component fromAPI(MinecraftComponent component) {
if (component instanceof MinecraftComponentImpl) {
return ((MinecraftComponentImpl) component).getComponent();
} else {
return (Component) component.adventureAdapter(ADAPTER).getComponent();
}
}
public static void set(MinecraftComponent minecraftComponent, Component component) {
minecraftComponent.adventureAdapter(ADAPTER).setComponent(component);
}
public static Component fromUnrelocated(Object unrelocatedAdventure) {
MinecraftComponentImpl component = MinecraftComponentImpl.empty();
Objects.requireNonNull(component.unrelocatedAdapter(), "Could not get unrelocated adventure gson serializer")
.setComponent(unrelocatedAdventure);
return fromAPI(component);
}
}

View File

@ -0,0 +1,27 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package com.discordsrv.common.config;
/**
* Helper class to identify which file a given config instance belongs to.
*/
public interface Config {
String getFileName();
}

View File

@ -0,0 +1,43 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
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;
/**
* Prevents the annotated options from being (partially) merged into existing configs (only being added to new configs).
*/
@Retention(value = RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface DefaultOnly {
/**
* The children that are whitelisted/blacklisted based on {@link #whitelist()},
* if this is empty the entire option will be blacklisted from being merged into existing configs.
*/
String[] value() default {};
/**
* Only the provided {@link #value()} otherwise everything except the provided {@link #value()}.
*/
boolean whitelist() default true;
}

View File

@ -0,0 +1,71 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
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;
/**
* Specifies that the given option will be partially or completely undocumented.
*/
@Retention(value = RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Untranslated {
/**
* Specifies which part of this option will be undocumented. The default value is {@link Type#FULL}.
* @return the {@link Type} specifying the parts that will be undocumented
*/
Type value() default Type.FULL;
enum Type {
/**
* The option's value and it's comment will be undocumented.
*/
FULL(true, true),
/**
* Only the comment of the option is undocumented.
*/
COMMENT(true, false),
/**
* Only the option's value will be undocumented.
*/
VALUE(false, true);
private final boolean comment;
private final boolean value;
Type(boolean comment, boolean value) {
this.comment = comment;
this.value = value;
}
public boolean isComment() {
return comment;
}
public boolean isValue() {
return value;
}
}
}

View File

@ -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 <https://www.gnu.org/licenses/>.
*/
package com.discordsrv.common.config.connection;
import com.discordsrv.common.config.Config;
import org.spongepowered.configurate.objectmapping.ConfigSerializable;
import org.spongepowered.configurate.objectmapping.meta.Comment;
@ConfigSerializable
public class ConnectionConfig implements Config {
public static final String FILE_NAME = "connections.yaml";
public final String getFileName() {
return FILE_NAME;
}
public Bot bot = new Bot();
@ConfigSerializable
public static class Bot {
@Comment("Don't know what this is? Neither do I")
public String token = "Token here";
}
}

View File

@ -0,0 +1,44 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
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.ChannelConfigHolder;
import org.spongepowered.configurate.objectmapping.ConfigSerializable;
import java.util.HashMap;
import java.util.Map;
@ConfigSerializable
public class MainConfig implements Config {
public static final String FILE_NAME = "config.yaml";
public final String getFileName() {
return FILE_NAME;
}
@DefaultOnly("default")
public Map<String, ChannelConfigHolder> channels = new HashMap<String, ChannelConfigHolder>() {{
put("default", new ChannelConfigHolder(new BaseChannelConfig()));
put("global", new ChannelConfigHolder(new ChannelConfig()));
}};
}

Some files were not shown because too many files have changed in this diff Show More