[CHORE] Code cleanup and small issue fixes for new verification system
This commit is contained in:
@@ -117,7 +117,7 @@ shadowJar {
|
|||||||
relocate 'org.reflections', shade_group + 'org.reflections'
|
relocate 'org.reflections', shade_group + 'org.reflections'
|
||||||
}
|
}
|
||||||
exclude 'META-INF/**'
|
exclude 'META-INF/**'
|
||||||
setArchiveClassifier('verification')
|
setArchiveClassifier('')
|
||||||
}
|
}
|
||||||
|
|
||||||
publishing {
|
publishing {
|
||||||
|
@@ -6,6 +6,7 @@ package com.hypherionmc.sdlink.core.accounts;
|
|||||||
|
|
||||||
import com.hypherionmc.sdlink.core.config.SDLinkConfig;
|
import com.hypherionmc.sdlink.core.config.SDLinkConfig;
|
||||||
import com.hypherionmc.sdlink.core.services.SDLinkPlatform;
|
import com.hypherionmc.sdlink.core.services.SDLinkPlatform;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author HypherionSA
|
* @author HypherionSA
|
||||||
@@ -16,10 +17,19 @@ public class DiscordAuthor {
|
|||||||
// User used for Server Messages
|
// User used for Server Messages
|
||||||
public static final DiscordAuthor SERVER = new DiscordAuthor(SDLinkConfig.INSTANCE.channelsAndWebhooks.serverName, SDLinkConfig.INSTANCE.channelsAndWebhooks.serverAvatar, "server", true, "");
|
public static final DiscordAuthor SERVER = new DiscordAuthor(SDLinkConfig.INSTANCE.channelsAndWebhooks.serverName, SDLinkConfig.INSTANCE.channelsAndWebhooks.serverAvatar, "server", true, "");
|
||||||
|
|
||||||
|
@Getter
|
||||||
private final String displayName;
|
private final String displayName;
|
||||||
|
|
||||||
|
@Getter
|
||||||
private final String avatar;
|
private final String avatar;
|
||||||
|
|
||||||
|
@Getter
|
||||||
private final boolean isServer;
|
private final boolean isServer;
|
||||||
|
|
||||||
|
@Getter
|
||||||
private final String username;
|
private final String username;
|
||||||
|
|
||||||
|
@Getter
|
||||||
private final String uuid;
|
private final String uuid;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -52,23 +62,13 @@ public class DiscordAuthor {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getDisplayName() {
|
public static DiscordAuthor of(String displayName, String avatar, String username, boolean server) {
|
||||||
return displayName;
|
return new DiscordAuthor(
|
||||||
}
|
displayName,
|
||||||
|
avatar,
|
||||||
public String getRawUsername() {
|
username,
|
||||||
return username;
|
server,
|
||||||
}
|
username
|
||||||
|
);
|
||||||
public boolean isServer() {
|
|
||||||
return isServer;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getAvatar() {
|
|
||||||
return avatar;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getUuid() {
|
|
||||||
return uuid;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,26 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of sdlink-core, licensed under the MIT License (MIT).
|
||||||
|
* Copyright HypherionSA and Contributors
|
||||||
|
*/
|
||||||
|
package com.hypherionmc.sdlink.core.accounts;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
@AllArgsConstructor(staticName = "of")
|
||||||
|
public class DiscordUser {
|
||||||
|
|
||||||
|
@Getter @Setter
|
||||||
|
private String effectiveName;
|
||||||
|
|
||||||
|
@Getter @Setter
|
||||||
|
private String avatarUrl;
|
||||||
|
|
||||||
|
@Getter @Setter
|
||||||
|
private long userId;
|
||||||
|
|
||||||
|
@Getter @Setter
|
||||||
|
private String asMention;
|
||||||
|
|
||||||
|
}
|
@@ -7,6 +7,7 @@ package com.hypherionmc.sdlink.core.accounts;
|
|||||||
import com.hypherionmc.sdlink.core.config.SDLinkConfig;
|
import com.hypherionmc.sdlink.core.config.SDLinkConfig;
|
||||||
import com.hypherionmc.sdlink.core.database.SDLinkAccount;
|
import com.hypherionmc.sdlink.core.database.SDLinkAccount;
|
||||||
import com.hypherionmc.sdlink.core.discord.BotController;
|
import com.hypherionmc.sdlink.core.discord.BotController;
|
||||||
|
import com.hypherionmc.sdlink.core.managers.CacheManager;
|
||||||
import com.hypherionmc.sdlink.core.managers.RoleManager;
|
import com.hypherionmc.sdlink.core.managers.RoleManager;
|
||||||
import com.hypherionmc.sdlink.core.messaging.Result;
|
import com.hypherionmc.sdlink.core.messaging.Result;
|
||||||
import com.hypherionmc.sdlink.core.util.SDLinkUtils;
|
import com.hypherionmc.sdlink.core.util.SDLinkUtils;
|
||||||
@@ -29,6 +30,7 @@ import java.net.URL;
|
|||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
@@ -142,17 +144,24 @@ public class MinecraftAccount {
|
|||||||
if (account == null || SDLinkUtils.isNullOrEmpty(account.getDiscordID()))
|
if (account == null || SDLinkUtils.isNullOrEmpty(account.getDiscordID()))
|
||||||
return "Unlinked";
|
return "Unlinked";
|
||||||
|
|
||||||
User discordUser = BotController.INSTANCE.getJDA().getUserById(account.getDiscordID());
|
DiscordUser user = getDiscordUser();
|
||||||
return discordUser == null ? "Unlinked" : discordUser.getEffectiveName();
|
|
||||||
|
return user == null ? "Unlinked" : user.getEffectiveName();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public User getDiscordUser() {
|
public DiscordUser getDiscordUser() {
|
||||||
SDLinkAccount storedAccount = getStoredAccount();
|
SDLinkAccount storedAccount = getStoredAccount();
|
||||||
if (storedAccount == null || SDLinkUtils.isNullOrEmpty(storedAccount.getDiscordID()))
|
if (storedAccount == null || SDLinkUtils.isNullOrEmpty(storedAccount.getDiscordID()))
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
return BotController.INSTANCE.getJDA().getUserById(storedAccount.getDiscordID());
|
if (CacheManager.getDiscordMembers().isEmpty()) {
|
||||||
|
User user = BotController.INSTANCE.getJDA().getUserById(storedAccount.getDiscordID());
|
||||||
|
return user == null ? null : DiscordUser.of(user.getEffectiveName(), user.getEffectiveAvatarUrl(), user.getIdLong(), user.getAsMention());
|
||||||
|
}
|
||||||
|
|
||||||
|
Optional<Member> member = CacheManager.getDiscordMembers().stream().filter(m -> m.getId().equalsIgnoreCase(storedAccount.getDiscordID())).findFirst();
|
||||||
|
return member.map(value -> DiscordUser.of(value.getEffectiveName(), value.getEffectiveAvatarUrl(), value.getIdLong(), value.getAsMention())).orElse(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Result verifyAccount(Member member, Guild guild) {
|
public Result verifyAccount(Member member, Guild guild) {
|
||||||
@@ -230,40 +239,29 @@ public class MinecraftAccount {
|
|||||||
return Result.error("notVerified");
|
return Result.error("notVerified");
|
||||||
|
|
||||||
if (SDLinkConfig.INSTANCE.accessControl.requireDiscordMembership) {
|
if (SDLinkConfig.INSTANCE.accessControl.requireDiscordMembership) {
|
||||||
Guild guild = BotController.INSTANCE.getJDA().getGuilds().get(0);
|
DiscordUser user = getDiscordUser();
|
||||||
|
if (user == null)
|
||||||
if (guild == null)
|
|
||||||
return Result.error("noGuildFound");
|
|
||||||
|
|
||||||
Member member = guild.getMemberById(account.getDiscordID());
|
|
||||||
|
|
||||||
if (member == null)
|
|
||||||
return Result.error("memberNotFound");
|
return Result.error("memberNotFound");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!SDLinkConfig.INSTANCE.accessControl.requiredRoles.isEmpty() && !RoleManager.getVerificationRoles().isEmpty()) {
|
if (!SDLinkConfig.INSTANCE.accessControl.requiredRoles.isEmpty() && !RoleManager.getVerificationRoles().isEmpty()) {
|
||||||
AtomicBoolean anyFound = new AtomicBoolean(false);
|
AtomicBoolean anyFound = new AtomicBoolean(false);
|
||||||
|
|
||||||
Guild guild = BotController.INSTANCE.getJDA().getGuilds().get(0);
|
Optional<Member> member = CacheManager.getDiscordMembers().stream().filter(m -> m.getId().equals(account.getDiscordID())).findFirst();
|
||||||
|
member.ifPresent(m -> m.getRoles().forEach(r -> {
|
||||||
if (guild == null)
|
if (RoleManager.getVerificationRoles().stream().anyMatch(role -> role.getIdLong() == r.getIdLong())) {
|
||||||
return Result.error("noGuildFound");
|
if (!anyFound.get()) {
|
||||||
|
anyFound.set(true);
|
||||||
Member member = guild.getMemberById(account.getDiscordID());
|
|
||||||
if (member != null) {
|
|
||||||
member.getRoles().forEach(r -> {
|
|
||||||
if (RoleManager.getVerificationRoles().stream().anyMatch(role -> role.getIdLong() == r.getIdLong())) {
|
|
||||||
if (!anyFound.get()) {
|
|
||||||
anyFound.set(true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
if (!anyFound.get())
|
|
||||||
return Result.error("rolesNotFound");
|
if (!anyFound.get())
|
||||||
} else {
|
return Result.error("rolesNotFound");
|
||||||
|
|
||||||
|
if (member.isEmpty())
|
||||||
return Result.error("memberNotFound");
|
return Result.error("memberNotFound");
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return Result.success("pass");
|
return Result.success("pass");
|
||||||
|
@@ -1,3 +1,7 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of sdlink-core, licensed under the MIT License (MIT).
|
||||||
|
* Copyright HypherionSA and Contributors
|
||||||
|
*/
|
||||||
package com.hypherionmc.sdlink.core.config.impl;
|
package com.hypherionmc.sdlink.core.config.impl;
|
||||||
|
|
||||||
import me.hypherionmc.moonconfig.core.conversion.Path;
|
import me.hypherionmc.moonconfig.core.conversion.Path;
|
||||||
|
@@ -1,3 +1,7 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of sdlink-core, licensed under the MIT License (MIT).
|
||||||
|
* Copyright HypherionSA and Contributors
|
||||||
|
*/
|
||||||
package com.hypherionmc.sdlink.core.database;
|
package com.hypherionmc.sdlink.core.database;
|
||||||
|
|
||||||
import io.jsondb.annotation.Document;
|
import io.jsondb.annotation.Document;
|
||||||
|
@@ -5,6 +5,7 @@
|
|||||||
package com.hypherionmc.sdlink.core.discord.commands.slash;
|
package com.hypherionmc.sdlink.core.discord.commands.slash;
|
||||||
|
|
||||||
import com.jagrosh.jdautilities.command.SlashCommand;
|
import com.jagrosh.jdautilities.command.SlashCommand;
|
||||||
|
import net.dv8tion.jda.api.Permission;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author HypherionSA
|
* @author HypherionSA
|
||||||
@@ -14,6 +15,10 @@ public abstract class SDLinkSlashCommand extends SlashCommand {
|
|||||||
|
|
||||||
public SDLinkSlashCommand(boolean requiresPerms) {
|
public SDLinkSlashCommand(boolean requiresPerms) {
|
||||||
this.guildOnly = true;
|
this.guildOnly = true;
|
||||||
|
|
||||||
|
if (requiresPerms) {
|
||||||
|
this.userPermissions = new Permission[] { Permission.MANAGE_SERVER };
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -1,3 +1,7 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of sdlink-core, licensed under the MIT License (MIT).
|
||||||
|
* Copyright HypherionSA and Contributors
|
||||||
|
*/
|
||||||
package com.hypherionmc.sdlink.core.discord.commands.slash.verification;
|
package com.hypherionmc.sdlink.core.discord.commands.slash.verification;
|
||||||
|
|
||||||
import com.hypherionmc.sdlink.core.accounts.MinecraftAccount;
|
import com.hypherionmc.sdlink.core.accounts.MinecraftAccount;
|
||||||
@@ -18,7 +22,7 @@ import static com.hypherionmc.sdlink.core.managers.DatabaseManager.sdlinkDatabas
|
|||||||
public class StaffUnverifyCommand extends SDLinkSlashCommand {
|
public class StaffUnverifyCommand extends SDLinkSlashCommand {
|
||||||
|
|
||||||
public StaffUnverifyCommand() {
|
public StaffUnverifyCommand() {
|
||||||
super(false);
|
super(true);
|
||||||
this.name = "staffunverify";
|
this.name = "staffunverify";
|
||||||
this.help = "Unverify another player's Minecraft account";
|
this.help = "Unverify another player's Minecraft account";
|
||||||
|
|
||||||
|
@@ -1,3 +1,7 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of sdlink-core, licensed under the MIT License (MIT).
|
||||||
|
* Copyright HypherionSA and Contributors
|
||||||
|
*/
|
||||||
package com.hypherionmc.sdlink.core.discord.commands.slash.verification;
|
package com.hypherionmc.sdlink.core.discord.commands.slash.verification;
|
||||||
|
|
||||||
import com.hypherionmc.sdlink.core.accounts.MinecraftAccount;
|
import com.hypherionmc.sdlink.core.accounts.MinecraftAccount;
|
||||||
|
@@ -1,3 +1,7 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of sdlink-core, licensed under the MIT License (MIT).
|
||||||
|
* Copyright HypherionSA and Contributors
|
||||||
|
*/
|
||||||
package com.hypherionmc.sdlink.core.discord.commands.slash.verification;
|
package com.hypherionmc.sdlink.core.discord.commands.slash.verification;
|
||||||
|
|
||||||
import com.hypherionmc.sdlink.core.accounts.MinecraftAccount;
|
import com.hypherionmc.sdlink.core.accounts.MinecraftAccount;
|
||||||
|
@@ -1,3 +1,7 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of sdlink-core, licensed under the MIT License (MIT).
|
||||||
|
* Copyright HypherionSA and Contributors
|
||||||
|
*/
|
||||||
package com.hypherionmc.sdlink.core.discord.commands.slash.verification;
|
package com.hypherionmc.sdlink.core.discord.commands.slash.verification;
|
||||||
|
|
||||||
import com.hypherionmc.sdlink.core.accounts.MinecraftAccount;
|
import com.hypherionmc.sdlink.core.accounts.MinecraftAccount;
|
||||||
|
@@ -1,3 +1,7 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of sdlink-core, licensed under the MIT License (MIT).
|
||||||
|
* Copyright HypherionSA and Contributors
|
||||||
|
*/
|
||||||
package com.hypherionmc.sdlink.core.discord.commands.slash.verification;
|
package com.hypherionmc.sdlink.core.discord.commands.slash.verification;
|
||||||
|
|
||||||
import com.hypherionmc.sdlink.core.database.SDLinkAccount;
|
import com.hypherionmc.sdlink.core.database.SDLinkAccount;
|
||||||
|
@@ -138,6 +138,8 @@ public class DiscordEventHandler extends ListenerAdapter {
|
|||||||
if (event.getUser().isBot())
|
if (event.getUser().isBot())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
CacheManager.loadUserCache();
|
||||||
|
|
||||||
if (!SDLinkConfig.INSTANCE.accessControl.enabled)
|
if (!SDLinkConfig.INSTANCE.accessControl.enabled)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@@ -6,15 +6,19 @@ package com.hypherionmc.sdlink.core.managers;
|
|||||||
|
|
||||||
import com.hypherionmc.sdlink.core.discord.BotController;
|
import com.hypherionmc.sdlink.core.discord.BotController;
|
||||||
import net.dv8tion.jda.api.JDA;
|
import net.dv8tion.jda.api.JDA;
|
||||||
|
import net.dv8tion.jda.api.entities.Member;
|
||||||
import net.dv8tion.jda.api.entities.channel.ChannelType;
|
import net.dv8tion.jda.api.entities.channel.ChannelType;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
public class CacheManager {
|
public class CacheManager {
|
||||||
|
|
||||||
private static final HashMap<String, String> serverChannels = new HashMap<>();
|
private static final HashMap<String, String> serverChannels = new HashMap<>();
|
||||||
private static final HashMap<String, String> serverRoles = new HashMap<>();
|
private static final HashMap<String, String> serverRoles = new HashMap<>();
|
||||||
private static final HashMap<String, String> userCache = new HashMap<>();
|
private static final HashMap<String, String> userCache = new HashMap<>();
|
||||||
|
private static Set<Member> discordMembers = new HashSet<>();
|
||||||
|
|
||||||
public static void loadCache() {
|
public static void loadCache() {
|
||||||
loadChannelCache();
|
loadChannelCache();
|
||||||
@@ -54,6 +58,7 @@ public class CacheManager {
|
|||||||
|
|
||||||
public static void loadUserCache() {
|
public static void loadUserCache() {
|
||||||
userCache.clear();
|
userCache.clear();
|
||||||
|
discordMembers.clear();
|
||||||
|
|
||||||
JDA jda = BotController.INSTANCE.getJDA();
|
JDA jda = BotController.INSTANCE.getJDA();
|
||||||
|
|
||||||
@@ -62,6 +67,7 @@ public class CacheManager {
|
|||||||
|
|
||||||
jda.getGuilds().get(0).getMembers().forEach(r -> {
|
jda.getGuilds().get(0).getMembers().forEach(r -> {
|
||||||
userCache.put("@" + r.getEffectiveName(), r.getAsMention());
|
userCache.put("@" + r.getEffectiveName(), r.getAsMention());
|
||||||
|
discordMembers.add(r);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -76,4 +82,8 @@ public class CacheManager {
|
|||||||
public static HashMap<String, String> getUserCache() {
|
public static HashMap<String, String> getUserCache() {
|
||||||
return userCache;
|
return userCache;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Set<Member> getDiscordMembers() {
|
||||||
|
return discordMembers;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -172,7 +172,7 @@ public final class DiscordMessage {
|
|||||||
.replace("%author%", this.author.getDisplayName())
|
.replace("%author%", this.author.getDisplayName())
|
||||||
.replace("%avatar%", this.author.getAvatar())
|
.replace("%avatar%", this.author.getAvatar())
|
||||||
.replace("%message_contents%", this.message)
|
.replace("%message_contents%", this.message)
|
||||||
.replace("%username%", this.author.getRawUsername());
|
.replace("%username%", this.author.getUsername());
|
||||||
|
|
||||||
DataObject object = DataObject.fromJson(embedJson);
|
DataObject object = DataObject.fromJson(embedJson);
|
||||||
return fromData(object);
|
return fromData(object);
|
||||||
|
@@ -5,11 +5,11 @@
|
|||||||
package com.hypherionmc.sdlink.core.messaging.discord;
|
package com.hypherionmc.sdlink.core.messaging.discord;
|
||||||
|
|
||||||
import com.hypherionmc.sdlink.core.accounts.DiscordAuthor;
|
import com.hypherionmc.sdlink.core.accounts.DiscordAuthor;
|
||||||
|
import com.hypherionmc.sdlink.core.accounts.DiscordUser;
|
||||||
import com.hypherionmc.sdlink.core.accounts.MinecraftAccount;
|
import com.hypherionmc.sdlink.core.accounts.MinecraftAccount;
|
||||||
import com.hypherionmc.sdlink.core.config.SDLinkConfig;
|
import com.hypherionmc.sdlink.core.config.SDLinkConfig;
|
||||||
import com.hypherionmc.sdlink.core.config.impl.MessageIgnoreConfig;
|
import com.hypherionmc.sdlink.core.config.impl.MessageIgnoreConfig;
|
||||||
import com.hypherionmc.sdlink.core.messaging.MessageType;
|
import com.hypherionmc.sdlink.core.messaging.MessageType;
|
||||||
import net.dv8tion.jda.api.entities.User;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author HypherionSA
|
* @author HypherionSA
|
||||||
@@ -36,16 +36,16 @@ public final class DiscordMessageBuilder {
|
|||||||
public DiscordMessageBuilder author(DiscordAuthor author) {
|
public DiscordMessageBuilder author(DiscordAuthor author) {
|
||||||
this.author = author;
|
this.author = author;
|
||||||
|
|
||||||
if (author.getRawUsername().equalsIgnoreCase("server")) {
|
if (author.getUsername().equalsIgnoreCase("server")) {
|
||||||
this.author = DiscordAuthor.SERVER;
|
this.author = DiscordAuthor.SERVER;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SDLinkConfig.INSTANCE.chatConfig.useLinkedNames && this.author != DiscordAuthor.SERVER) {
|
if (SDLinkConfig.INSTANCE.chatConfig.useLinkedNames && this.author != DiscordAuthor.SERVER) {
|
||||||
MinecraftAccount account = MinecraftAccount.standard(author.getRawUsername());
|
MinecraftAccount account = MinecraftAccount.standard(author.getUsername());
|
||||||
User discordUser = account.getDiscordUser();
|
DiscordUser discordUser = account.getDiscordUser();
|
||||||
|
|
||||||
if (account != null && discordUser != null) {
|
if (account != null && discordUser != null) {
|
||||||
this.author = DiscordAuthor.of(discordUser.getEffectiveName(), author.getUuid(), author.getRawUsername());
|
this.author = DiscordAuthor.of(discordUser.getEffectiveName(), discordUser.getAvatarUrl(), author.getUsername(), false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,3 +1,7 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of sdlink-core, licensed under the MIT License (MIT).
|
||||||
|
* Copyright HypherionSA and Contributors
|
||||||
|
*/
|
||||||
package com.hypherionmc.sdlink.core.util;
|
package com.hypherionmc.sdlink.core.util;
|
||||||
|
|
||||||
public class SDLinkUtils {
|
public class SDLinkUtils {
|
||||||
|
Reference in New Issue
Block a user