mirror of
https://github.com/DiscordSRV/Ascension.git
synced 2024-11-22 11:55:54 +01:00
More profile stuff
This commit is contained in:
parent
ee1db84ae0
commit
ed674cce8a
@ -63,6 +63,7 @@ public interface DiscordSRVApi {
|
||||
* The profile manager, access the profiles of players and/or users.
|
||||
* @return the instance of {@link IProfileManager}
|
||||
*/
|
||||
@NotNull
|
||||
IProfileManager profileManager();
|
||||
|
||||
/**
|
||||
@ -177,30 +178,24 @@ public interface DiscordSRVApi {
|
||||
* DiscordSRV is shutting down.
|
||||
* @see #isShutdown()
|
||||
*/
|
||||
SHUTTING_DOWN(false, true),
|
||||
SHUTTING_DOWN,
|
||||
|
||||
/**
|
||||
* DiscordSRV has shutdown.
|
||||
* @see #isShutdown()
|
||||
*/
|
||||
SHUTDOWN(false, true),
|
||||
SHUTDOWN,
|
||||
|
||||
;
|
||||
|
||||
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() {
|
||||
@ -208,7 +203,7 @@ public interface DiscordSRVApi {
|
||||
}
|
||||
|
||||
public boolean isShutdown() {
|
||||
return shutdown;
|
||||
return this == SHUTDOWN || this == SHUTTING_DOWN;
|
||||
}
|
||||
|
||||
public boolean isStartupError() {
|
||||
|
@ -23,20 +23,21 @@
|
||||
|
||||
package com.discordsrv.api.profile;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
public interface IProfile {
|
||||
|
||||
@Nullable
|
||||
UUID uniqueId();
|
||||
@NotNull
|
||||
Optional<UUID> playerUUID();
|
||||
|
||||
@Nullable
|
||||
Long userId();
|
||||
@NotNull
|
||||
Optional<Long> userId();
|
||||
|
||||
default boolean isLinked() {
|
||||
return uniqueId() != null && userId() != null;
|
||||
return playerUUID().isPresent() && userId().isPresent();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -29,11 +29,11 @@ import java.util.concurrent.CompletableFuture;
|
||||
|
||||
public interface IProfileManager {
|
||||
|
||||
CompletableFuture<Optional<IProfile>> lookupProfile(UUID playerUUID);
|
||||
CompletableFuture<? extends IProfile> lookupProfile(UUID playerUUID);
|
||||
|
||||
Optional<IProfile> getProfile(UUID playerUUID);
|
||||
Optional<? extends IProfile> getProfile(UUID playerUUID);
|
||||
|
||||
CompletableFuture<Optional<IProfile>> lookupProfile(long userId);
|
||||
CompletableFuture<? extends IProfile> lookupProfile(long userId);
|
||||
|
||||
Optional<IProfile> getProfile(long userId);
|
||||
Optional<? extends IProfile> getProfile(long userId);
|
||||
}
|
||||
|
@ -26,6 +26,7 @@ import com.discordsrv.bukkit.config.manager.BukkitConnectionConfigManager;
|
||||
import com.discordsrv.bukkit.console.BukkitConsole;
|
||||
import com.discordsrv.bukkit.integration.VaultIntegration;
|
||||
import com.discordsrv.bukkit.listener.BukkitChatListener;
|
||||
import com.discordsrv.bukkit.listener.BukkitConnectionListener;
|
||||
import com.discordsrv.bukkit.listener.BukkitDeathListener;
|
||||
import com.discordsrv.bukkit.listener.BukkitStatusMessageListener;
|
||||
import com.discordsrv.bukkit.player.BukkitPlayerProvider;
|
||||
@ -178,6 +179,7 @@ public class BukkitDiscordSRV extends ServerDiscordSRV<BukkitConfig, BukkitConne
|
||||
|
||||
// Register listeners
|
||||
server().getPluginManager().registerEvents(BukkitChatListener.get(this), plugin());
|
||||
server().getPluginManager().registerEvents(new BukkitConnectionListener(this), plugin());
|
||||
server().getPluginManager().registerEvents(new BukkitDeathListener(this), plugin());
|
||||
server().getPluginManager().registerEvents(new BukkitStatusMessageListener(this), plugin());
|
||||
|
||||
|
@ -85,11 +85,7 @@ public abstract class BukkitChatListener implements Listener {
|
||||
@EventHandler(priority = EventPriority.MONITOR)
|
||||
public void onAsyncChat(AsyncChatEvent event) {
|
||||
MinecraftComponent component = PaperComponentUtil.getComponent(discordSRV, event, "message");
|
||||
publishEvent(
|
||||
event.getPlayer(),
|
||||
component,
|
||||
event.isCancelled()
|
||||
);
|
||||
publishEvent(event.getPlayer(), component, event.isCancelled());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,62 @@
|
||||
/*
|
||||
* This file is part of DiscordSRV, licensed under the GPLv3 License
|
||||
* Copyright (c) 2016-2022 Austin "Scarsz" Shapiro, Henri "Vankka" Schubin and DiscordSRV contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.discordsrv.bukkit.listener;
|
||||
|
||||
import com.discordsrv.bukkit.BukkitDiscordSRV;
|
||||
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.PlayerLoginEvent;
|
||||
import org.bukkit.event.player.PlayerQuitEvent;
|
||||
|
||||
public class BukkitConnectionListener implements Listener {
|
||||
|
||||
private final BukkitDiscordSRV discordSRV;
|
||||
|
||||
public BukkitConnectionListener(BukkitDiscordSRV discordSRV) {
|
||||
this.discordSRV = discordSRV;
|
||||
|
||||
for (Player onlinePlayer : discordSRV.server().getOnlinePlayers()) {
|
||||
discordSRV.profileManager().loadProfile(onlinePlayer.getUniqueId());
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.NORMAL)
|
||||
public void onPlayerLoginNormal(PlayerLoginEvent event) {
|
||||
if (event.getResult() != PlayerLoginEvent.Result.ALLOWED) {
|
||||
return;
|
||||
}
|
||||
|
||||
discordSRV.profileManager().loadProfile(event.getPlayer().getUniqueId());
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.MONITOR)
|
||||
public void onPlayerLoginMonitor(PlayerLoginEvent event) {
|
||||
if (event.getResult() != PlayerLoginEvent.Result.ALLOWED) {
|
||||
// Unload in case got blocked after NORMAL
|
||||
discordSRV.profileManager().unloadProfile(event.getPlayer().getUniqueId());
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.MONITOR)
|
||||
public void onPlayerQuit(PlayerQuitEvent event) {
|
||||
discordSRV.profileManager().unloadProfile(event.getPlayer().getUniqueId());
|
||||
}
|
||||
}
|
@ -20,6 +20,7 @@ package com.discordsrv.bukkit.player;
|
||||
|
||||
import com.discordsrv.bukkit.BukkitDiscordSRV;
|
||||
import com.discordsrv.common.player.IOfflinePlayer;
|
||||
import com.discordsrv.common.profile.Profile;
|
||||
import net.kyori.adventure.identity.Identity;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@ -42,6 +43,11 @@ public class BukkitOfflinePlayer implements IOfflinePlayer {
|
||||
return offlinePlayer.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Profile profile() {
|
||||
return discordSRV.profileManager().getProfile(uniqueId()).orElseThrow(IllegalStateException::new);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Identity identity() {
|
||||
return identity;
|
||||
|
@ -53,7 +53,7 @@ public class BukkitPlayerProvider extends ServerPlayerProvider<BukkitPlayer, Buk
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.LOWEST)
|
||||
public void onPlayerLogin(PlayerJoinEvent event) {
|
||||
public void onPlayerJoin(PlayerJoinEvent event) {
|
||||
addPlayer(event.getPlayer(), false);
|
||||
}
|
||||
|
||||
|
@ -22,6 +22,7 @@ import com.discordsrv.bungee.BungeeDiscordSRV;
|
||||
import com.discordsrv.bungee.component.util.BungeeComponentUtil;
|
||||
import com.discordsrv.common.DiscordSRV;
|
||||
import com.discordsrv.common.player.IPlayer;
|
||||
import com.discordsrv.common.profile.Profile;
|
||||
import net.kyori.adventure.audience.Audience;
|
||||
import net.kyori.adventure.identity.Identity;
|
||||
import net.kyori.adventure.text.Component;
|
||||
@ -62,6 +63,11 @@ public class BungeePlayer implements IPlayer {
|
||||
return player.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Profile profile() {
|
||||
return discordSRV.profileManager().getProfile(uniqueId()).orElseThrow(IllegalStateException::new);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Identity identity() {
|
||||
return identity;
|
||||
|
@ -23,13 +23,13 @@ import com.discordsrv.api.event.bus.EventBus;
|
||||
import com.discordsrv.api.event.events.lifecycle.DiscordSRVReloadEvent;
|
||||
import com.discordsrv.api.event.events.lifecycle.DiscordSRVShuttingDownEvent;
|
||||
import com.discordsrv.api.module.type.Module;
|
||||
import com.discordsrv.api.profile.IProfileManager;
|
||||
import com.discordsrv.common.api.util.ApiInstanceUtil;
|
||||
import com.discordsrv.common.channel.ChannelConfigHelper;
|
||||
import com.discordsrv.common.channel.ChannelUpdaterModule;
|
||||
import com.discordsrv.common.channel.GlobalChannelLookupModule;
|
||||
import com.discordsrv.common.component.ComponentFactory;
|
||||
import com.discordsrv.common.config.connection.ConnectionConfig;
|
||||
import com.discordsrv.common.config.main.LinkedAccountConfig;
|
||||
import com.discordsrv.common.config.main.MainConfig;
|
||||
import com.discordsrv.common.config.manager.ConnectionConfigManager;
|
||||
import com.discordsrv.common.config.manager.MainConfigManager;
|
||||
@ -46,8 +46,8 @@ import com.discordsrv.common.function.CheckedRunnable;
|
||||
import com.discordsrv.common.groupsync.GroupSyncModule;
|
||||
import com.discordsrv.common.integration.LuckPermsIntegration;
|
||||
import com.discordsrv.common.linking.LinkProvider;
|
||||
import com.discordsrv.common.linking.LinkStore;
|
||||
import com.discordsrv.common.linking.impl.MemoryLinker;
|
||||
import com.discordsrv.common.linking.impl.StorageLinker;
|
||||
import com.discordsrv.common.logging.adapter.DependencyLoggerAdapter;
|
||||
import com.discordsrv.common.logging.impl.DependencyLoggingHandler;
|
||||
import com.discordsrv.common.logging.impl.DiscordSRVLogger;
|
||||
@ -69,7 +69,6 @@ import org.jetbrains.annotations.NotNull;
|
||||
import javax.annotation.OverridingMethodsMustInvokeSuper;
|
||||
import java.util.Locale;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
@ -97,10 +96,10 @@ public abstract class AbstractDiscordSRV<C extends MainConfig, CC extends Connec
|
||||
// DiscordSRV
|
||||
private DiscordSRVLogger logger;
|
||||
private ModuleManager moduleManager;
|
||||
private ChannelConfigHelper channelConfig;
|
||||
|
||||
private Storage storage;
|
||||
private LinkProvider linkProvider;
|
||||
private ChannelConfigHelper channelConfig;
|
||||
private DiscordConnectionManager discordConnectionManager;
|
||||
|
||||
// Internal
|
||||
@ -122,6 +121,7 @@ public abstract class AbstractDiscordSRV<C extends MainConfig, CC extends Connec
|
||||
this.componentFactory = new ComponentFactory(this);
|
||||
this.discordAPI = new DiscordAPIImpl(this);
|
||||
this.discordConnectionDetails = new DiscordConnectionDetailsImpl(this);
|
||||
this.channelConfig = new ChannelConfigHelper(this);
|
||||
}
|
||||
|
||||
// DiscordSRVApi
|
||||
@ -137,7 +137,7 @@ public abstract class AbstractDiscordSRV<C extends MainConfig, CC extends Connec
|
||||
}
|
||||
|
||||
@Override
|
||||
public IProfileManager profileManager() {
|
||||
public @NotNull ProfileManager profileManager() {
|
||||
return profileManager;
|
||||
}
|
||||
|
||||
@ -327,25 +327,47 @@ public abstract class AbstractDiscordSRV<C extends MainConfig, CC extends Connec
|
||||
try {
|
||||
connectionConfigManager().load();
|
||||
configManager().load();
|
||||
|
||||
// Utility
|
||||
channelConfig = new ChannelConfigHelper(this);
|
||||
|
||||
eventBus().publish(new DiscordSRVReloadEvent(true));
|
||||
} catch (Throwable t) {
|
||||
setStatus(Status.FAILED_TO_LOAD_CONFIG);
|
||||
throw t;
|
||||
}
|
||||
|
||||
// Link provider
|
||||
LinkedAccountConfig linkedAccountConfig = config().linkedAccounts;
|
||||
if (linkedAccountConfig != null && linkedAccountConfig.enabled) {
|
||||
String provider = linkedAccountConfig.provider;
|
||||
switch (provider) {
|
||||
case "auto":
|
||||
case "storage":
|
||||
linkProvider = new StorageLinker(this);
|
||||
break;
|
||||
case "memory": {
|
||||
linkProvider = new MemoryLinker();
|
||||
logger().warning("Using memory for linked accounts");
|
||||
logger().warning("Linked accounts will be lost upon restart");
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
logger().error("Unknown linked account provider: \"" + provider + "\", linked accounts will not be used");
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
logger().info("Linked accounts are disabled");
|
||||
}
|
||||
|
||||
// Storage
|
||||
try {
|
||||
try {
|
||||
StorageType storageType = getStorageType();
|
||||
logger().info("Using " + storageType.prettyName() + " as storage");
|
||||
if (storageType.hikari()) {
|
||||
DependencyLoader.hikari(this).process(classpathAppender()).get();
|
||||
}
|
||||
storage = storageType.storageFunction().apply(this);
|
||||
storage.initialize();
|
||||
logger().info("Storage connection successfully established");
|
||||
} catch (ExecutionException e) {
|
||||
throw new StorageException(e.getCause());
|
||||
} catch (StorageException e) {
|
||||
@ -355,7 +377,7 @@ public abstract class AbstractDiscordSRV<C extends MainConfig, CC extends Connec
|
||||
}
|
||||
} catch (StorageException e) {
|
||||
e.log(this);
|
||||
logger().error("Startup cancelled because of storage connection failure");
|
||||
logger().error("Failed to connect to storage");
|
||||
setStatus(Status.FAILED_TO_START);
|
||||
return;
|
||||
}
|
||||
@ -363,9 +385,6 @@ public abstract class AbstractDiscordSRV<C extends MainConfig, CC extends Connec
|
||||
discordConnectionManager = new JDAConnectionManager(this);
|
||||
discordConnectionManager.connect().join();
|
||||
|
||||
linkProvider = new MemoryLinker();
|
||||
((LinkStore) linkProvider).link(UUID.fromString("6c983d46-0631-48b8-9baf-5e33eb5ffec4"), 185828288466255874L);
|
||||
|
||||
// Placeholder result stringifiers & global contexts
|
||||
placeholderService().addResultMapper(new ComponentResultStringifier(this));
|
||||
placeholderService().addGlobalContext(new GlobalTextHandlingContext(this));
|
||||
|
@ -37,6 +37,7 @@ import com.discordsrv.common.module.type.AbstractModule;
|
||||
import com.discordsrv.common.placeholder.PlaceholderServiceImpl;
|
||||
import com.discordsrv.common.player.provider.AbstractPlayerProvider;
|
||||
import com.discordsrv.common.plugin.PluginManager;
|
||||
import com.discordsrv.common.profile.ProfileManager;
|
||||
import com.discordsrv.common.scheduler.Scheduler;
|
||||
import com.discordsrv.common.storage.Storage;
|
||||
import com.github.benmanes.caffeine.cache.Caffeine;
|
||||
@ -61,6 +62,7 @@ public interface DiscordSRV extends DiscordSRVApi {
|
||||
PluginManager pluginManager();
|
||||
OnlineMode onlineMode();
|
||||
ClasspathAppender classpathAppender();
|
||||
@NotNull AbstractPlayerProvider<?, ?> playerProvider();
|
||||
|
||||
// DiscordSRVApi
|
||||
@Override
|
||||
@ -69,11 +71,11 @@ public interface DiscordSRV extends DiscordSRVApi {
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
PlaceholderServiceImpl placeholderService();
|
||||
ProfileManager profileManager();
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
AbstractPlayerProvider<?, ?> playerProvider();
|
||||
PlaceholderServiceImpl placeholderService();
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
|
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* This file is part of DiscordSRV, licensed under the GPLv3 License
|
||||
* Copyright (c) 2016-2022 Austin "Scarsz" Shapiro, Henri "Vankka" Schubin and DiscordSRV contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.discordsrv.common.config.main;
|
||||
|
||||
import org.spongepowered.configurate.objectmapping.ConfigSerializable;
|
||||
import org.spongepowered.configurate.objectmapping.meta.Comment;
|
||||
|
||||
@ConfigSerializable
|
||||
public class LinkedAccountConfig {
|
||||
|
||||
@Comment("Should linked accounts be enabled?")
|
||||
public boolean enabled = true;
|
||||
|
||||
@Comment("The linked account provider\n"
|
||||
+ "\n"
|
||||
+ " - auto: Automatically chooses the most suitable linked accounts storage\n"
|
||||
+ " - storage: Store linked accounts from the configured databased")
|
||||
public String provider = "auto";
|
||||
}
|
@ -43,6 +43,8 @@ public class MainConfig implements Config {
|
||||
put(ChannelConfig.DEFAULT_KEY, new BaseChannelConfig());
|
||||
}};
|
||||
|
||||
public LinkedAccountConfig linkedAccounts = new LinkedAccountConfig();
|
||||
|
||||
public List<ChannelUpdaterConfig> channelUpdaters = new ArrayList<>(Collections.singletonList(new ChannelUpdaterConfig()));
|
||||
|
||||
@Comment("Configuration options for group-role synchronization")
|
||||
|
@ -23,7 +23,6 @@ import com.discordsrv.api.discord.api.entity.guild.DiscordRole;
|
||||
import com.discordsrv.api.discord.events.member.role.DiscordMemberRoleAddEvent;
|
||||
import com.discordsrv.api.discord.events.member.role.DiscordMemberRoleRemoveEvent;
|
||||
import com.discordsrv.api.event.bus.Subscribe;
|
||||
import com.discordsrv.api.profile.IProfile;
|
||||
import com.discordsrv.common.DiscordSRV;
|
||||
import com.discordsrv.common.config.main.GroupSyncConfig;
|
||||
import com.discordsrv.common.debug.DebugGenerateEvent;
|
||||
@ -166,12 +165,12 @@ public class GroupSyncModule extends AbstractModule<DiscordSRV> {
|
||||
|
||||
private CompletableFuture<Long> lookupLinkedAccount(UUID player) {
|
||||
return discordSRV.profileManager().lookupProfile(player)
|
||||
.thenApply(profile -> profile.map(IProfile::userId).orElse(null));
|
||||
.thenApply(profile -> profile.userId().orElse(null));
|
||||
}
|
||||
|
||||
private CompletableFuture<UUID> lookupLinkedAccount(long userId) {
|
||||
return discordSRV.profileManager().lookupProfile(userId)
|
||||
.thenApply(profile -> profile.map(IProfile::uniqueId).orElse(null));
|
||||
.thenApply(profile -> profile.playerUUID().orElse(null));
|
||||
}
|
||||
|
||||
// Permission data helper methods
|
||||
|
@ -25,7 +25,7 @@ import java.util.concurrent.CompletableFuture;
|
||||
|
||||
public interface LinkStore {
|
||||
|
||||
CompletableFuture<Void> link(@NotNull UUID playerUUID, long userId);
|
||||
CompletableFuture<Void> createLink(@NotNull UUID playerUUID, long userId);
|
||||
|
||||
CompletableFuture<Integer> getLinkedAccountCount();
|
||||
}
|
||||
|
@ -43,7 +43,7 @@ public class MemoryLinker implements LinkProvider, LinkStore {
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> link(@NotNull UUID playerUUID, long userId) {
|
||||
public CompletableFuture<Void> createLink(@NotNull UUID playerUUID, long userId) {
|
||||
map.put(playerUUID, userId);
|
||||
return CompletableFuture.completedFuture(null);
|
||||
}
|
||||
|
@ -31,6 +31,7 @@ public class StorageLinker extends CachedLinkProvider implements LinkProvider, L
|
||||
|
||||
public StorageLinker(DiscordSRV discordSRV) {
|
||||
super(discordSRV);
|
||||
discordSRV.logger().info("Using storage for linked accounts");
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -50,9 +51,9 @@ public class StorageLinker extends CachedLinkProvider implements LinkProvider, L
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> link(@NotNull UUID playerUUID, long userId) {
|
||||
public CompletableFuture<Void> createLink(@NotNull UUID playerUUID, long userId) {
|
||||
return CompletableFuture.runAsync(
|
||||
() -> discordSRV.storage().link(playerUUID, userId),
|
||||
() -> discordSRV.storage().createLink(playerUUID, userId),
|
||||
discordSRV.scheduler().executor()
|
||||
);
|
||||
}
|
||||
|
@ -19,6 +19,7 @@
|
||||
package com.discordsrv.common.player;
|
||||
|
||||
import com.discordsrv.api.placeholder.annotation.Placeholder;
|
||||
import com.discordsrv.common.profile.Profile;
|
||||
import net.kyori.adventure.identity.Identified;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@ -38,4 +39,6 @@ public interface IOfflinePlayer extends Identified {
|
||||
default UUID uniqueId() {
|
||||
return identity().uuid();
|
||||
}
|
||||
|
||||
Profile profile();
|
||||
}
|
||||
|
@ -36,7 +36,6 @@ public interface IPlayer extends DiscordSRVPlayer, IOfflinePlayer, ICommandSende
|
||||
|
||||
DiscordSRV discordSRV();
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
String username();
|
||||
|
||||
|
@ -19,27 +19,28 @@
|
||||
package com.discordsrv.common.profile;
|
||||
|
||||
import com.discordsrv.api.profile.IProfile;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
public class Profile implements IProfile {
|
||||
|
||||
private final UUID uuid;
|
||||
private final UUID playerUUID;
|
||||
private final Long userId;
|
||||
|
||||
public Profile(UUID uuid, Long userId) {
|
||||
this.uuid = uuid;
|
||||
public Profile(UUID playerUUID, Long userId) {
|
||||
this.playerUUID = playerUUID;
|
||||
this.userId = userId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable UUID uniqueId() {
|
||||
return uuid;
|
||||
public @NotNull Optional<UUID> playerUUID() {
|
||||
return Optional.ofNullable(playerUUID);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable Long userId() {
|
||||
return userId;
|
||||
public @NotNull Optional<Long> userId() {
|
||||
return Optional.ofNullable(userId);
|
||||
}
|
||||
}
|
||||
|
@ -19,40 +19,64 @@
|
||||
package com.discordsrv.common.profile;
|
||||
|
||||
import com.discordsrv.api.profile.IProfileManager;
|
||||
import com.discordsrv.api.profile.IProfile;
|
||||
import com.discordsrv.common.DiscordSRV;
|
||||
import org.jetbrains.annotations.Blocking;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public class ProfileManager implements IProfileManager {
|
||||
|
||||
private final DiscordSRV discordSRV;
|
||||
private final Map<UUID, Profile> profiles = new ConcurrentHashMap<>();
|
||||
private final Map<Long, Profile> discordUserMap = new ConcurrentHashMap<>();
|
||||
|
||||
public ProfileManager(DiscordSRV discordSRV) {
|
||||
this.discordSRV = discordSRV;
|
||||
}
|
||||
|
||||
@Blocking
|
||||
public void loadProfile(UUID playerUUID) {
|
||||
Profile profile = lookupProfile(playerUUID).join();
|
||||
profiles.put(playerUUID, profile);
|
||||
if (profile.isLinked()) {
|
||||
discordUserMap.put(profile.userId().orElseThrow(AssertionError::new), profile);
|
||||
}
|
||||
}
|
||||
|
||||
public void unloadProfile(UUID playerUUID) {
|
||||
Profile profile = profiles.remove(playerUUID);
|
||||
if (profile == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (profile.isLinked()) {
|
||||
discordUserMap.remove(profile.userId().orElseThrow(AssertionError::new));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Optional<IProfile>> lookupProfile(UUID playerUUID) {
|
||||
public CompletableFuture<Profile> lookupProfile(UUID playerUUID) {
|
||||
return discordSRV.linkProvider().getUserId(playerUUID)
|
||||
.thenApply(opt -> Optional.of(new Profile(playerUUID, opt.orElse(null))));
|
||||
.thenApply(opt -> new Profile(playerUUID, opt.orElse(null)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<IProfile> getProfile(UUID playerUUID) {
|
||||
return Optional.empty();
|
||||
public Optional<Profile> getProfile(UUID playerUUID) {
|
||||
return Optional.ofNullable(profiles.get(playerUUID));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Optional<IProfile>> lookupProfile(long userId) {
|
||||
public CompletableFuture<Profile> lookupProfile(long userId) {
|
||||
return discordSRV.linkProvider().getPlayerUUID(userId)
|
||||
.thenApply(opt -> Optional.of(new Profile(opt.orElse(null), userId)));
|
||||
.thenApply(opt -> new Profile(opt.orElse(null), userId));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<IProfile> getProfile(long userId) {
|
||||
return Optional.empty();
|
||||
public Optional<Profile> getProfile(long userId) {
|
||||
return Optional.ofNullable(discordUserMap.get(userId));
|
||||
}
|
||||
}
|
||||
|
@ -36,7 +36,7 @@ public interface Storage {
|
||||
@Nullable
|
||||
UUID getPlayerUUID(long userId);
|
||||
|
||||
void link(@NotNull UUID player, long userId);
|
||||
void createLink(@NotNull UUID player, long userId);
|
||||
|
||||
int getLinkedAccountCount();
|
||||
|
||||
|
@ -26,14 +26,16 @@ import java.util.function.Function;
|
||||
|
||||
public enum StorageType {
|
||||
|
||||
H2(H2Storage::new, false),
|
||||
MYSQL(MySQLStorage::new, true);
|
||||
H2(H2Storage::new, "H2", false),
|
||||
MYSQL(MySQLStorage::new, "MySQL", true);
|
||||
|
||||
private final Function<DiscordSRV, Storage> storageFunction;
|
||||
private final String prettyName;
|
||||
private final boolean hikari;
|
||||
|
||||
StorageType(Function<DiscordSRV, Storage> storageFunction, boolean hikari) {
|
||||
StorageType(Function<DiscordSRV, Storage> storageFunction, String prettyName, boolean hikari) {
|
||||
this.storageFunction = storageFunction;
|
||||
this.prettyName = prettyName;
|
||||
this.hikari = hikari;
|
||||
}
|
||||
|
||||
@ -41,6 +43,10 @@ public enum StorageType {
|
||||
return storageFunction;
|
||||
}
|
||||
|
||||
public String prettyName() {
|
||||
return prettyName;
|
||||
}
|
||||
|
||||
public boolean hikari() {
|
||||
return hikari;
|
||||
}
|
||||
|
@ -18,9 +18,11 @@
|
||||
|
||||
package com.discordsrv.common.storage.impl.sql;
|
||||
|
||||
import com.discordsrv.common.DiscordSRV;
|
||||
import com.discordsrv.common.exception.StorageException;
|
||||
import com.discordsrv.common.function.CheckedConsumer;
|
||||
import com.discordsrv.common.function.CheckedFunction;
|
||||
import com.discordsrv.common.linking.impl.StorageLinker;
|
||||
import com.discordsrv.common.storage.Storage;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@ -30,9 +32,15 @@ import java.util.UUID;
|
||||
|
||||
public abstract class SQLStorage implements Storage {
|
||||
|
||||
protected final DiscordSRV discordSRV;
|
||||
|
||||
public SQLStorage(DiscordSRV discordSRV) {
|
||||
this.discordSRV = discordSRV;
|
||||
}
|
||||
|
||||
public abstract Connection getConnection();
|
||||
public abstract boolean isAutoCloseConnections();
|
||||
public abstract void createTables(Connection connection) throws SQLException;
|
||||
public abstract void createTables(Connection connection, boolean linkedAccounts) throws SQLException;
|
||||
|
||||
private void useConnection(CheckedConsumer<Connection> connectionConsumer) throws StorageException {
|
||||
useConnection(connection -> {
|
||||
@ -63,7 +71,7 @@ public abstract class SQLStorage implements Storage {
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
useConnection(this::createTables);
|
||||
useConnection((CheckedConsumer<Connection>) connection -> createTables(connection, discordSRV.linkProvider() instanceof StorageLinker));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -97,7 +105,7 @@ public abstract class SQLStorage implements Storage {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void link(@NotNull UUID player, long userId) {
|
||||
public void createLink(@NotNull UUID player, long userId) {
|
||||
useConnection(connection -> {
|
||||
try (PreparedStatement statement = connection.prepareStatement("insert into LINKED_ACCOUNTS (PLAYER_UUID, USER_ID) values (?, ?);")) {
|
||||
statement.setObject(1, player);
|
||||
|
@ -34,12 +34,11 @@ import java.util.Properties;
|
||||
|
||||
public class H2Storage extends SQLStorage {
|
||||
|
||||
private final DiscordSRV discordSRV;
|
||||
private IsolatedClassLoader classLoader;
|
||||
private Connection connection;
|
||||
|
||||
public H2Storage(DiscordSRV discordSRV) {
|
||||
this.discordSRV = discordSRV;
|
||||
super(discordSRV);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -101,15 +100,17 @@ public class H2Storage extends SQLStorage {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createTables(Connection connection) throws SQLException {
|
||||
try (Statement statement = connection.createStatement()) {
|
||||
statement.execute(
|
||||
"create table if not exists LINKED_ACCOUNTS "
|
||||
+ "(ID int not null auto_increment, "
|
||||
+ "PLAYER_UUID varchar(36), "
|
||||
+ "USER_ID bigint, "
|
||||
+ "constraint LINKED_ACCOUNTS_PK primary key (ID)"
|
||||
+ ")");
|
||||
public void createTables(Connection connection, boolean linkedAccounts) throws SQLException {
|
||||
if (linkedAccounts) {
|
||||
try (Statement statement = connection.createStatement()) {
|
||||
statement.execute(
|
||||
"create table if not exists LINKED_ACCOUNTS "
|
||||
+ "(ID int not null auto_increment, "
|
||||
+ "PLAYER_UUID varchar(36), "
|
||||
+ "USER_ID bigint, "
|
||||
+ "constraint LINKED_ACCOUNTS_PK primary key (ID)"
|
||||
+ ")");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -31,11 +31,10 @@ import java.sql.SQLException;
|
||||
|
||||
public abstract class HikariStorage extends SQLStorage {
|
||||
|
||||
protected final DiscordSRV discordSRV;
|
||||
private HikariDataSource hikariDataSource;
|
||||
|
||||
public HikariStorage(DiscordSRV discordSRV) {
|
||||
this.discordSRV = discordSRV;
|
||||
super(discordSRV);
|
||||
}
|
||||
|
||||
protected abstract void applyConfiguration(HikariConfig config, StorageConfig storageConfig);
|
||||
|
@ -52,15 +52,17 @@ public class MySQLStorage extends HikariStorage {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createTables(Connection connection) throws SQLException {
|
||||
try (Statement statement = connection.createStatement()) {
|
||||
statement.execute(
|
||||
"create table if not exists LINKED_ACCOUNTS "
|
||||
+ "(ID int not null auto_increment, "
|
||||
+ "PLAYER_UUID varchar(36), "
|
||||
+ "USER_ID bigint, "
|
||||
+ "constraint LINKED_ACCOUNTS_PK primary key (ID)"
|
||||
+ ")");
|
||||
public void createTables(Connection connection, boolean linkedAccounts) throws SQLException {
|
||||
if (linkedAccounts) {
|
||||
try (Statement statement = connection.createStatement()) {
|
||||
statement.execute(
|
||||
"create table if not exists LINKED_ACCOUNTS "
|
||||
+ "(ID int not null auto_increment, "
|
||||
+ "PLAYER_UUID varchar(36), "
|
||||
+ "USER_ID bigint, "
|
||||
+ "constraint LINKED_ACCOUNTS_PK primary key (ID)"
|
||||
+ ")");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -19,15 +19,19 @@
|
||||
package com.discordsrv.sponge.player;
|
||||
|
||||
import com.discordsrv.common.player.IOfflinePlayer;
|
||||
import com.discordsrv.common.profile.Profile;
|
||||
import com.discordsrv.sponge.SpongeDiscordSRV;
|
||||
import net.kyori.adventure.identity.Identity;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.spongepowered.api.entity.living.player.User;
|
||||
|
||||
public class SpongeOfflinePlayer implements IOfflinePlayer {
|
||||
|
||||
protected final SpongeDiscordSRV discordSRV;
|
||||
private final User user;
|
||||
|
||||
public SpongeOfflinePlayer(User user) {
|
||||
public SpongeOfflinePlayer(SpongeDiscordSRV discordSRV, User user) {
|
||||
this.discordSRV = discordSRV;
|
||||
this.user = user;
|
||||
}
|
||||
|
||||
@ -36,6 +40,11 @@ public class SpongeOfflinePlayer implements IOfflinePlayer {
|
||||
return user.name();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Profile profile() {
|
||||
return discordSRV.profileManager().getProfile(uniqueId()).orElseThrow(IllegalStateException::new);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Identity identity() {
|
||||
return user.profile();
|
||||
|
@ -29,12 +29,10 @@ import org.spongepowered.api.entity.living.player.server.ServerPlayer;
|
||||
|
||||
public class SpongePlayer extends SpongeOfflinePlayer implements IPlayer {
|
||||
|
||||
private final SpongeDiscordSRV discordSRV;
|
||||
private final ServerPlayer player;
|
||||
|
||||
public SpongePlayer(SpongeDiscordSRV discordSRV, ServerPlayer player) {
|
||||
super(player.user());
|
||||
this.discordSRV = discordSRV;
|
||||
super(discordSRV, player.user());
|
||||
this.player = player;
|
||||
}
|
||||
|
||||
|
@ -71,7 +71,7 @@ public class SpongePlayerProvider extends ServerPlayerProvider<SpongePlayer, Spo
|
||||
// IOfflinePlayer
|
||||
|
||||
private IOfflinePlayer convert(User user) {
|
||||
return new SpongeOfflinePlayer(user);
|
||||
return new SpongeOfflinePlayer(discordSRV, user);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -89,6 +89,6 @@ public class SpongePlayerProvider extends ServerPlayerProvider<SpongePlayer, Spo
|
||||
}
|
||||
|
||||
public IOfflinePlayer offlinePlayer(User user) {
|
||||
return new SpongeOfflinePlayer(user);
|
||||
return convert(user);
|
||||
}
|
||||
}
|
||||
|
@ -20,6 +20,7 @@ package com.discordsrv.velocity.player;
|
||||
|
||||
import com.discordsrv.common.DiscordSRV;
|
||||
import com.discordsrv.common.player.IPlayer;
|
||||
import com.discordsrv.common.profile.Profile;
|
||||
import com.discordsrv.velocity.VelocityDiscordSRV;
|
||||
import com.velocitypowered.api.proxy.Player;
|
||||
import net.kyori.adventure.audience.Audience;
|
||||
@ -57,6 +58,11 @@ public class VelocityPlayer implements IPlayer {
|
||||
return player.getUsername();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Profile profile() {
|
||||
return discordSRV.profileManager().getProfile(uniqueId()).orElseThrow(IllegalStateException::new);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Identity identity() {
|
||||
return player.identity();
|
||||
|
Loading…
Reference in New Issue
Block a user