diff --git a/fabric/src/main/java/net/draycia/carbon/fabric/CarbonChatFabric.java b/fabric/src/main/java/net/draycia/carbon/fabric/CarbonChatFabric.java index 7800db208..9e218eb4a 100644 --- a/fabric/src/main/java/net/draycia/carbon/fabric/CarbonChatFabric.java +++ b/fabric/src/main/java/net/draycia/carbon/fabric/CarbonChatFabric.java @@ -67,13 +67,14 @@ private CarbonChatFabric( final @PeriodicTasks ScheduledExecutorService periodicTasks, final ProfileCache profileCache, final ProfileResolver profileResolver, - final CarbonMessages carbonMessages, final PlatformUserManager userManager, final ExecutionCoordinatorHolder commandExecutor, final CarbonServer carbonServer, + final CarbonMessages carbonMessages, final CarbonEventHandler eventHandler, final CarbonChannelRegistry channelRegistry, final Provider messagingManagerProvider, + @SuppressWarnings("unused") // Make sure it initializes now final MinecraftServerHolder minecraftServerHolder ) { diff --git a/paper/src/main/java/net/draycia/carbon/paper/CarbonChatPaper.java b/paper/src/main/java/net/draycia/carbon/paper/CarbonChatPaper.java index 1985db6e9..45b2cc769 100644 --- a/paper/src/main/java/net/draycia/carbon/paper/CarbonChatPaper.java +++ b/paper/src/main/java/net/draycia/carbon/paper/CarbonChatPaper.java @@ -67,18 +67,18 @@ public final class CarbonChatPaper extends CarbonChatInternal { @Inject private CarbonChatPaper( - final Injector injector, final JavaPlugin plugin, - final CarbonMessages carbonMessages, - final CarbonEventHandler eventHandler, - final CarbonChannelRegistry channelRegistry, - final Provider messagingManager, - final CarbonServer carbonServer, - final PlatformUserManager userManager, + final Injector injector, @PeriodicTasks final ScheduledExecutorService periodicTasks, final ProfileCache profileCache, final ProfileResolver profileResolver, - final ExecutionCoordinatorHolder commandExecutor + final PlatformUserManager userManager, + final ExecutionCoordinatorHolder commandExecutor, + final CarbonServer carbonServer, + final CarbonMessages carbonMessages, + final CarbonEventHandler eventHandler, + final CarbonChannelRegistry channelRegistry, + final Provider messagingManager ) { super( injector, diff --git a/settings.gradle.kts b/settings.gradle.kts index 65d0e3836..1e78b0895 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -71,7 +71,7 @@ sequenceOf( "api", "common", "paper", - // "sponge", // TODO API 10 + "sponge", "fabric", "velocity" ).forEach { diff --git a/sponge/build.gradle.kts b/sponge/build.gradle.kts index fff403b60..c440a953c 100644 --- a/sponge/build.gradle.kts +++ b/sponge/build.gradle.kts @@ -27,7 +27,7 @@ tasks { sponge { injectRepositories(false) // We specify repositories in settings.gradle.kts - apiVersion("10.0.0-SNAPSHOT") + apiVersion("11.0.0-SNAPSHOT") plugin(rootProject.name.toLowerCase(Locale.ROOT)) { loader { name(PluginLoaders.JAVA_PLAIN) @@ -58,3 +58,13 @@ sponge { } } } + +configurations.spongeRuntime { + resolutionStrategy { + eachDependency { + if (target.name == "spongevanilla") { + useVersion("1.20.1-11.0.0-RC1356") + } + } + } +} diff --git a/sponge/src/main/java/net/draycia/carbon/sponge/CarbonChatSponge.java b/sponge/src/main/java/net/draycia/carbon/sponge/CarbonChatSponge.java index b88462b7a..118a8d91d 100644 --- a/sponge/src/main/java/net/draycia/carbon/sponge/CarbonChatSponge.java +++ b/sponge/src/main/java/net/draycia/carbon/sponge/CarbonChatSponge.java @@ -21,45 +21,32 @@ import com.google.inject.Inject; import com.google.inject.Injector; -import com.google.inject.TypeLiteral; -import java.nio.file.Path; +import com.google.inject.Provider; import java.util.Set; -import java.util.UUID; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.TimeUnit; -import net.draycia.carbon.api.CarbonChat; -import net.draycia.carbon.api.CarbonChatProvider; -import net.draycia.carbon.api.channels.ChannelRegistry; -import net.draycia.carbon.api.events.CarbonEventHandler; -import net.draycia.carbon.api.users.UserManager; -import net.draycia.carbon.api.util.Component; +import java.util.concurrent.ScheduledExecutorService; +import net.draycia.carbon.api.CarbonServer; +import net.draycia.carbon.api.event.CarbonEventHandler; +import net.draycia.carbon.common.CarbonChatInternal; +import net.draycia.carbon.common.PeriodicTasks; import net.draycia.carbon.common.channels.CarbonChannelRegistry; +import net.draycia.carbon.common.command.ExecutionCoordinatorHolder; import net.draycia.carbon.common.messages.CarbonMessages; import net.draycia.carbon.common.messaging.MessagingManager; -import net.draycia.carbon.common.users.CarbonPlayerCommon; -import net.draycia.carbon.common.util.CloudUtils; -import net.draycia.carbon.common.util.ListenerUtils; -import net.draycia.carbon.common.util.PlayerUtils; +import net.draycia.carbon.common.users.PlatformUserManager; +import net.draycia.carbon.common.users.ProfileCache; +import net.draycia.carbon.common.users.ProfileResolver; import net.draycia.carbon.sponge.listeners.SpongeChatListener; import net.draycia.carbon.sponge.listeners.SpongePlayerJoinListener; import net.draycia.carbon.sponge.listeners.SpongeReloadListener; -import net.kyori.adventure.audience.Audience; import net.kyori.adventure.text.Component; -import net.kyori.moonshine.message.IMessageRenderer; -import ninja.egg82.messenger.services.PacketService; import org.apache.logging.log4j.Logger; -import org.checkerframework.checker.nullness.qual.MonotonicNonNull; import org.checkerframework.checker.nullness.qual.NonNull; -import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.framework.qual.DefaultQualifier; -import org.spongepowered.api.Game; import org.spongepowered.api.Server; import org.spongepowered.api.Sponge; -import org.spongepowered.api.config.ConfigDir; import org.spongepowered.api.event.Listener; import org.spongepowered.api.event.lifecycle.StartingEngineEvent; import org.spongepowered.api.event.lifecycle.StoppingEngineEvent; -import org.spongepowered.api.scheduler.Task; import org.spongepowered.api.service.permission.PermissionDescription; import org.spongepowered.api.service.permission.PermissionService; import org.spongepowered.plugin.PluginContainer; @@ -67,58 +54,61 @@ @Plugin("carbonchat") @DefaultQualifier(NonNull.class) -public final class CarbonChatSponge implements CarbonChat { +public final class CarbonChatSponge extends CarbonChatInternal { private static final Set> LISTENER_CLASSES = Set.of(SpongeChatListener.class, SpongePlayerJoinListener.class, SpongeReloadListener.class); private static final int BSTATS_PLUGIN_ID = 11279; - private final CarbonMessages carbonMessages; - private final CarbonServerSponge carbonServerSponge; - private final ChannelRegistry channelRegistry; - private final Injector injector; - private final Logger logger; - private final Path dataDirectory; private final PluginContainer pluginContainer; - private final UserManager userManager; - private final CarbonEventHandler eventHandler = new CarbonEventHandler(); - private final UUID serverId = UUID.randomUUID(); - - private @MonotonicNonNull MessagingManager messagingManager = null; @Inject public CarbonChatSponge( //final Metrics.Factory metricsFactory, - final Game game, final PluginContainer pluginContainer, final Injector injector, final Logger logger, - @ConfigDir(sharedRoot = false) final Path dataDirectory + @PeriodicTasks final ScheduledExecutorService periodicTasks, + final ProfileCache profileCache, + final ProfileResolver profileResolver, + final PlatformUserManager userManager, + final ExecutionCoordinatorHolder commandExecutor, + final CarbonServer carbonServer, + final CarbonMessages carbonMessages, + final CarbonEventHandler eventHandler, + final CarbonChannelRegistry channelRegistry, + final Provider messagingManager ) { - CarbonChatProvider.register(this); - + super( + injector, + logger, + periodicTasks, + profileCache, + profileResolver, + userManager, + commandExecutor, + carbonServer, + carbonMessages, + eventHandler, + channelRegistry, + messagingManager + ); this.pluginContainer = pluginContainer; + } - this.injector = injector.createChildInjector(new CarbonChatSpongeModule(this, dataDirectory, pluginContainer)); - this.logger = logger; - this.carbonMessages = this.injector.getInstance(CarbonMessages.class); - this.channelRegistry = this.injector.getInstance(ChannelRegistry.class); - this.carbonServerSponge = this.injector.getInstance(CarbonServerSponge.class); - this.userManager = this.injector.getInstance(com.google.inject.Key.get(new TypeLiteral>() {})); - this.dataDirectory = dataDirectory; + @Listener + public void onInitialize(final StartingEngineEvent event) { + this.init(); for (final Class clazz : LISTENER_CLASSES) { - game.eventManager().registerListeners(this.pluginContainer, this.injector.getInstance(clazz)); + event.game().eventManager().registerListeners(this.pluginContainer, this.injector().getInstance(clazz)); } + // TODO: metrics //metricsFactory.make(BSTATS_PLUGIN_ID); - // Listeners - ListenerUtils.registerCommonListeners(this.injector); - - // Load channels - ((CarbonChannelRegistry) this.channelRegistry()).loadConfigChannels(this.carbonMessages); + this.checkVersion(); // TODO: Register these in a central location, pull from that in this and plugin.yml Sponge.serviceProvider().provide(PermissionService.class).ifPresent(permissionService -> { @@ -220,74 +210,11 @@ public CarbonChatSponge( .description(Component.text("Allows the player to send messages to vanished players.")) .register(); }); - - // Commands - CloudUtils.loadCommands(this.injector); - final var commandSettings = CloudUtils.loadCommandSettings(this.injector); - CloudUtils.registerCommands(commandSettings); - } - - @Override - public UUID serverId() { - return this.serverId; - } - - @Override - public @Nullable PacketService packetService() { - if (this.messagingManager == null) { - this.messagingManager = this.injector.getInstance(MessagingManager.class); - } - - return this.messagingManager.packetService(); - } - - @Listener - public void onInitialize(final StartingEngineEvent event) { - // Player data saving - Sponge.asyncScheduler().submit(Task.builder() - .interval(5, TimeUnit.MINUTES) - .plugin(this.pluginContainer) - .execute(() -> PlayerUtils.saveLoggedInPlayers(this.carbonServerSponge, this.userManager)) - .build()); } @Listener public void onDisable(final StoppingEngineEvent event) { - PlayerUtils.saveLoggedInPlayers(this.carbonServerSponge, this.userManager).forEach(CompletableFuture::join); - } - - @Override - public Logger logger() { - return this.logger; - } - - @Override - public Path dataDirectory() { - return this.dataDirectory; - } - - @Override - public CarbonServerSponge server() { - return this.carbonServerSponge; - } - - @Override - public ChannelRegistry channelRegistry() { - return this.channelRegistry; - } - - @Override - public IMessageRenderer messageRenderer() { - return this.injector.getInstance(SpongeMessageRenderer.class); - } - - public CarbonMessages carbonMessages() { - return this.carbonMessages; - } - - @Override - public @NonNull CarbonEventHandler eventHandler() { - return this.eventHandler; + this.shutdown(); } } diff --git a/sponge/src/main/java/net/draycia/carbon/sponge/CarbonChatSpongeModule.java b/sponge/src/main/java/net/draycia/carbon/sponge/CarbonChatSpongeModule.java index 5af4cf2db..ed2658ef6 100644 --- a/sponge/src/main/java/net/draycia/carbon/sponge/CarbonChatSpongeModule.java +++ b/sponge/src/main/java/net/draycia/carbon/sponge/CarbonChatSpongeModule.java @@ -20,28 +20,28 @@ package net.draycia.carbon.sponge; import cloud.commandframework.CommandManager; -import cloud.commandframework.execution.AsynchronousCommandExecutionCoordinator; import cloud.commandframework.sponge.SpongeCommandManager; -import cloud.commandframework.sponge.argument.SinglePlayerSelectorArgument; import com.google.inject.AbstractModule; -import com.google.inject.Injector; +import com.google.inject.Provider; import com.google.inject.Provides; import com.google.inject.Singleton; import java.nio.file.Path; import net.draycia.carbon.api.CarbonChat; import net.draycia.carbon.api.CarbonServer; -import net.draycia.carbon.api.util.Component; -import net.draycia.carbon.api.util.SourcedAudience; import net.draycia.carbon.common.CarbonCommonModule; -import net.draycia.carbon.common.ForCarbon; +import net.draycia.carbon.common.DataDirectory; +import net.draycia.carbon.common.PlatformScheduler; import net.draycia.carbon.common.command.Commander; -import net.draycia.carbon.common.command.argument.PlayerSuggestions; +import net.draycia.carbon.common.command.ExecutionCoordinatorHolder; +import net.draycia.carbon.common.messages.CarbonMessageRenderer; +import net.draycia.carbon.common.messages.CarbonMessages; +import net.draycia.carbon.common.users.PlatformUserManager; +import net.draycia.carbon.common.users.ProfileResolver; import net.draycia.carbon.common.util.CloudUtils; import net.draycia.carbon.sponge.command.SpongeCommander; import net.draycia.carbon.sponge.command.SpongePlayerCommander; -import net.kyori.adventure.audience.Audience; -import net.kyori.adventure.text.Component; -import net.kyori.moonshine.message.IMessageRenderer; +import net.draycia.carbon.sponge.users.CarbonPlayerSponge; +import net.draycia.carbon.sponge.users.SpongeProfileResolver; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.framework.qual.DefaultQualifier; import org.spongepowered.api.entity.living.player.server.ServerPlayer; @@ -50,63 +50,56 @@ @DefaultQualifier(NonNull.class) public final class CarbonChatSpongeModule extends AbstractModule { - private final CarbonChatSponge carbonChat; private final Path configDir; private final PluginContainer pluginContainer; public CarbonChatSpongeModule( - final CarbonChatSponge carbonChat, final Path configDir, final PluginContainer pluginContainer ) { - this.carbonChat = carbonChat; this.configDir = configDir; this.pluginContainer = pluginContainer; } @Provides @Singleton - public CommandManager commandManager() { + public CommandManager commandManager( + final ExecutionCoordinatorHolder executionCoordinatorHolder, + final Provider carbonChat, + final CarbonMessages carbonMessages + ) { final SpongeCommandManager commandManager = new SpongeCommandManager<>( this.pluginContainer, - AsynchronousCommandExecutionCoordinator.builder().build(), + executionCoordinatorHolder.executionCoordinator(), commander -> ((SpongeCommander) commander).commandCause(), commandCause -> { if (commandCause.subject() instanceof ServerPlayer player) { - return new SpongePlayerCommander(this.carbonChat, player, commandCause); + return new SpongePlayerCommander(carbonChat.get(), player, commandCause); } return SpongeCommander.from(commandCause); } ); - CloudUtils.decorateCommandManager(commandManager, this.carbonChat.carbonMessages()); + CloudUtils.decorateCommandManager(commandManager, carbonMessages); commandManager.parserMapper().cloudNumberSuggestions(true); return commandManager; } - @Provides - @Singleton - public IMessageRenderer messageRenderer(final Injector injector) { - return injector.getInstance(SpongeMessageRenderer.class); - } - - @Provides - @Singleton - public IMessageRenderer sourcedRenderer(final Injector injector) { - return injector.getInstance(SpongeMessageRenderer.class); - } - @Override public void configure() { this.install(new CarbonCommonModule()); - this.bind(Path.class).annotatedWith(ForCarbon.class).toInstance(this.configDir); - this.bind(CarbonChat.class).toInstance(this.carbonChat); + this.bind(CarbonChat.class).to(CarbonChatSponge.class); + this.bind(Path.class).annotatedWith(DataDirectory.class).toInstance(this.configDir); this.bind(CarbonServer.class).to(CarbonServerSponge.class); - this.bind(PlayerSuggestions.class).toInstance(new SinglePlayerSelectorArgument.Parser()::suggestions); + this.bind(CarbonMessageRenderer.class).to(SpongeMessageRenderer.class); + this.bind(ProfileResolver.class).to(SpongeProfileResolver.class); + this.bind(PlatformScheduler.class).to(SpongeScheduler.class); + this.install(PlatformUserManager.PlayerFactory.moduleFor(CarbonPlayerSponge.class)); + this.bind(CarbonMessageRenderer.class).to(SpongeMessageRenderer.class); } } diff --git a/sponge/src/main/java/net/draycia/carbon/sponge/CarbonServerSponge.java b/sponge/src/main/java/net/draycia/carbon/sponge/CarbonServerSponge.java index cc46c4180..68725a0aa 100644 --- a/sponge/src/main/java/net/draycia/carbon/sponge/CarbonServerSponge.java +++ b/sponge/src/main/java/net/draycia/carbon/sponge/CarbonServerSponge.java @@ -21,36 +21,30 @@ import com.google.inject.Inject; import com.google.inject.Singleton; -import java.util.ArrayList; import java.util.List; -import java.util.UUID; -import java.util.concurrent.CompletableFuture; +import java.util.Objects; import net.draycia.carbon.api.CarbonServer; -import net.draycia.carbon.api.users.ComponentPlayerResult; +import net.draycia.carbon.api.users.CarbonPlayer; import net.draycia.carbon.api.users.UserManager; -import net.draycia.carbon.common.users.CarbonPlayerCommon; -import net.draycia.carbon.sponge.users.CarbonPlayerSponge; +import net.draycia.carbon.common.users.UserManagerInternal; import net.kyori.adventure.audience.Audience; import net.kyori.adventure.audience.ForwardingAudience; import org.checkerframework.checker.nullness.qual.NonNull; -import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.framework.qual.DefaultQualifier; import org.jetbrains.annotations.NotNull; import org.spongepowered.api.Game; -import org.spongepowered.api.Sponge; -import org.spongepowered.api.profile.ProfileNotFoundException; @Singleton @DefaultQualifier(NonNull.class) public final class CarbonServerSponge implements CarbonServer, ForwardingAudience.Single { private final Game game; - private final UserManager userManager; + private final UserManager userManager; @Inject - private CarbonServerSponge(final UserManager userManager, final Game game) { + private CarbonServerSponge(final Game game, final UserManagerInternal userManager) { this.game = game; - this.userManager = new SpongeUserManager(userManager); + this.userManager = userManager; } @Override @@ -64,45 +58,11 @@ public Audience console() { } @Override - public List players() { - final var players = new ArrayList(); - - for (final var player : Sponge.server().onlinePlayers()) { - final ComponentPlayerResult result = this.userManager.carbonPlayer(player.uniqueId()).join(); - - if (result.player() != null) { - players.add(result.player()); - } - } - - return players; - } - - @Override - public UserManager userManager() { - return this.userManager; - } - - @Override - public CompletableFuture<@Nullable UUID> resolveUUID(final String username) { - return CompletableFuture.supplyAsync(() -> { - try { - return Sponge.server().gameProfileManager().basicProfile(username).join().uuid(); - } catch (final ProfileNotFoundException exception) { - return null; - } - }); - } - - @Override - public CompletableFuture<@Nullable String> resolveName(final UUID uuid) { - return CompletableFuture.supplyAsync(() -> { - try { - return Sponge.server().gameProfileManager().basicProfile(uuid).join().name().orElse(null); - } catch (final ProfileNotFoundException exception) { - return null; - } - }); + public List players() { + return this.game.server().onlinePlayers().stream() + .map(sponge -> this.userManager.user(sponge.uniqueId()).getNow(null)) + .filter(Objects::nonNull) + .toList(); } } diff --git a/sponge/src/main/java/net/draycia/carbon/sponge/CarbonSpongeBootstrap.java b/sponge/src/main/java/net/draycia/carbon/sponge/CarbonSpongeBootstrap.java new file mode 100644 index 000000000..3bfbfda8f --- /dev/null +++ b/sponge/src/main/java/net/draycia/carbon/sponge/CarbonSpongeBootstrap.java @@ -0,0 +1,50 @@ +package net.draycia.carbon.sponge; + +import com.google.inject.Guice; +import com.google.inject.Inject; +import com.google.inject.Injector; +import java.nio.file.Path; +import net.draycia.carbon.api.CarbonChatProvider; +import org.checkerframework.checker.nullness.qual.MonotonicNonNull; +import org.spongepowered.api.Server; +import org.spongepowered.api.config.ConfigDir; +import org.spongepowered.api.event.Listener; +import org.spongepowered.api.event.lifecycle.StartingEngineEvent; +import org.spongepowered.api.event.lifecycle.StoppingEngineEvent; +import org.spongepowered.plugin.PluginContainer; + +public class CarbonSpongeBootstrap { + + private @MonotonicNonNull CarbonChatSponge carbonChat; + private final PluginContainer pluginContainer; + private final Path dataDirectory; + private final Injector parentInjector; + private @MonotonicNonNull Injector injector; + + @Inject + public CarbonSpongeBootstrap( + final Injector injector, + final PluginContainer pluginContainer, + @ConfigDir(sharedRoot = false) final Path dataDirectory + ) { + this.parentInjector = injector; + this.pluginContainer = pluginContainer; + this.dataDirectory = dataDirectory; + } + + @Listener + public void onInitialize(final StartingEngineEvent event) { + // TODO: move somewhere earlier like ctor? other modules have these two lines under onLoad + this.injector = this.parentInjector.createChildInjector(new CarbonChatSpongeModule(this.dataDirectory, this.pluginContainer)); + this.carbonChat = this.injector.getInstance(CarbonChatSponge.class); + + this.carbonChat.onInitialize(event); + CarbonChatProvider.register(this.carbonChat); + } + + @Listener + public void onDisable(final StoppingEngineEvent event) { + this.carbonChat.onDisable(event); + } + +} diff --git a/sponge/src/main/java/net/draycia/carbon/sponge/SpongeMessageRenderer.java b/sponge/src/main/java/net/draycia/carbon/sponge/SpongeMessageRenderer.java index 6ef1c0b89..f34556b5b 100644 --- a/sponge/src/main/java/net/draycia/carbon/sponge/SpongeMessageRenderer.java +++ b/sponge/src/main/java/net/draycia/carbon/sponge/SpongeMessageRenderer.java @@ -20,52 +20,53 @@ package net.draycia.carbon.sponge; import com.google.inject.Inject; +import com.google.inject.Singleton; import java.lang.reflect.Method; import java.lang.reflect.Type; import java.util.Map; -import net.draycia.carbon.common.config.ConfigFactory; -import net.draycia.carbon.common.util.ChatType; +import net.draycia.carbon.common.config.ConfigManager; +import net.draycia.carbon.common.messages.CarbonMessageRenderer; import net.kyori.adventure.audience.Audience; -import net.kyori.adventure.audience.MessageType; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.minimessage.MiniMessage; import net.kyori.adventure.text.minimessage.tag.Tag; import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder; import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver; -import net.kyori.moonshine.message.IMessageRenderer; import org.checkerframework.checker.nullness.qual.NonNull; -import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.framework.qual.DefaultQualifier; @DefaultQualifier(NonNull.class) -public class SpongeMessageRenderer implements IMessageRenderer { +@Singleton +public class SpongeMessageRenderer implements CarbonMessageRenderer { - private final ConfigFactory configFactory; + private final ConfigManager configManager; @Inject - public SpongeMessageRenderer(final ConfigFactory configFactory) { - this.configFactory = configFactory; + public SpongeMessageRenderer(final ConfigManager configManager) { + this.configManager = configManager; } @Override public Component render( - final T receiver, + final Audience receiver, final String intermediateMessage, - final Map resolvedPlaceholders, + final Map resolvedPlaceholders, final Method method, final Type owner ) { final TagResolver.Builder tagResolver = TagResolver.builder(); for (final var entry : resolvedPlaceholders.entrySet()) { - tagResolver.tag(entry.getKey(), Tag.inserting(entry.getValue())); + tagResolver.tag(entry.getKey(), entry.getValue()); } - this.configFactory.primaryConfig().customPlaceholders().forEach( + this.configManager.primaryConfig().customPlaceholders().forEach( (key, value) -> tagResolver.resolver(Placeholder.unparsed(key, value)) ); - return MiniMessage.miniMessage().deserialize(intermediateMessage, tagResolver.build());; + // TODO: MiniPlaceholders support + + return MiniMessage.miniMessage().deserialize(intermediateMessage, tagResolver.build()); } } diff --git a/sponge/src/main/java/net/draycia/carbon/sponge/SpongeScheduler.java b/sponge/src/main/java/net/draycia/carbon/sponge/SpongeScheduler.java new file mode 100644 index 000000000..fe8fcbb11 --- /dev/null +++ b/sponge/src/main/java/net/draycia/carbon/sponge/SpongeScheduler.java @@ -0,0 +1,19 @@ +package net.draycia.carbon.sponge; + +import com.google.inject.Singleton; +import net.draycia.carbon.api.users.CarbonPlayer; +import net.draycia.carbon.common.PlatformScheduler; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.framework.qual.DefaultQualifier; +import org.spongepowered.api.scheduler.Task; + +@Singleton +@DefaultQualifier(NonNull.class) +public final class SpongeScheduler implements PlatformScheduler { + + @Override + public void scheduleForPlayer(final CarbonPlayer carbonPlayer, final Runnable runnable) { + Task.builder().execute(runnable); + } + +} diff --git a/sponge/src/main/java/net/draycia/carbon/sponge/SpongeUserManager.java b/sponge/src/main/java/net/draycia/carbon/sponge/SpongeUserManager.java deleted file mode 100644 index 53954aada..000000000 --- a/sponge/src/main/java/net/draycia/carbon/sponge/SpongeUserManager.java +++ /dev/null @@ -1,158 +0,0 @@ -/* - * CarbonChat - * - * Copyright (c) 2021 Josua Parks (Vicarious) - * 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 . - */ -package net.draycia.carbon.sponge; - -import java.util.UUID; -import java.util.concurrent.CompletableFuture; -import net.draycia.carbon.api.users.ComponentPlayerResult; -import net.draycia.carbon.api.users.UserManager; -import net.draycia.carbon.common.users.CarbonPlayerCommon; -import net.draycia.carbon.common.users.SaveOnChange; -import net.draycia.carbon.sponge.users.CarbonPlayerSponge; -import net.kyori.adventure.key.Key; -import net.kyori.adventure.text.Component; -import org.checkerframework.checker.nullness.qual.NonNull; -import org.checkerframework.checker.nullness.qual.Nullable; -import org.checkerframework.framework.qual.DefaultQualifier; - -@DefaultQualifier(NonNull.class) -public class SpongeUserManager implements UserManager, SaveOnChange { - - protected final UserManager proxiedUserManager; - - public SpongeUserManager(final UserManager proxiedUserManager) { - this.proxiedUserManager = proxiedUserManager; - } - - @Override - public CompletableFuture> carbonPlayer(final UUID uuid) { - return this.proxiedUserManager.carbonPlayer(uuid).thenApply(result -> { - if (result.player() == null) { - return new ComponentPlayerResult<>(null, result.reason()); - } - - return new ComponentPlayerResult<>(new CarbonPlayerSponge(result.player()), result.reason()); - }); - } - - @Override - public CompletableFuture> savePlayer(final CarbonPlayerSponge player) { - return this.proxiedUserManager.savePlayer(player.carbonPlayerCommon()).thenApply(result -> { - if (result.player() == null) { - return new ComponentPlayerResult<>(null, result.reason()); - } - - return new ComponentPlayerResult<>(new CarbonPlayerSponge(result.player()), result.reason()); - }); - } - - @Override - public CompletableFuture> saveAndInvalidatePlayer(final CarbonPlayerSponge player) { - return this.proxiedUserManager.saveAndInvalidatePlayer(player.carbonPlayerCommon()).thenApply(result -> { - if (result.player() == null) { - return new ComponentPlayerResult<>(null, result.reason()); - } - - return new ComponentPlayerResult<>(new CarbonPlayerSponge(result.player()), result.reason()); - }); - } - - @Override - public int saveDisplayName(final UUID id, final @Nullable Component component) { - if (this.proxiedUserManager instanceof SaveOnChange saveOnChange) { - return saveOnChange.saveDisplayName(id, component); - } - - return -1; - } - - @Override - public int saveMuted(final UUID id, final boolean muted) { - if (this.proxiedUserManager instanceof SaveOnChange saveOnChange) { - return saveOnChange.saveMuted(id, muted); - } - - return -1; - } - - @Override - public int saveDeafened(final UUID id, final boolean deafened) { - if (this.proxiedUserManager instanceof SaveOnChange saveOnChange) { - return saveOnChange.saveDeafened(id, deafened); - } - - return -1; - } - - @Override - public int saveSpying(final UUID id, final boolean spying) { - if (this.proxiedUserManager instanceof SaveOnChange saveOnChange) { - return saveOnChange.saveSpying(id, spying); - } - - return -1; - } - - @Override - public int saveSelectedChannel(final UUID id, final @Nullable Key selectedChannel) { - if (this.proxiedUserManager instanceof SaveOnChange saveOnChange) { - return saveOnChange.saveSelectedChannel(id, selectedChannel); - } - - return -1; - } - - @Override - public int saveLastWhisperTarget(final UUID id, final @Nullable UUID lastWhisperTarget) { - if (this.proxiedUserManager instanceof SaveOnChange saveOnChange) { - return saveOnChange.saveLastWhisperTarget(id, lastWhisperTarget); - } - - return -1; - } - - @Override - public int saveWhisperReplyTarget(final UUID id, final @Nullable UUID whisperReplyTarget) { - if (this.proxiedUserManager instanceof SaveOnChange saveOnChange) { - return saveOnChange.saveWhisperReplyTarget(id, whisperReplyTarget); - } - - return -1; - } - - @Override - public int addIgnore(final UUID id, final UUID ignoredPlayer) { - if (this.proxiedUserManager instanceof SaveOnChange saveOnChange) { - return saveOnChange.addIgnore(id, ignoredPlayer); - } - - return -1; - } - - @Override - public int removeIgnore(final UUID id, final UUID ignoredPlayer) { - if (this.proxiedUserManager instanceof SaveOnChange saveOnChange) { - return saveOnChange.removeIgnore(id, ignoredPlayer); - } - - return -1; - } - -} diff --git a/sponge/src/main/java/net/draycia/carbon/sponge/listeners/SpongePlayerJoinListener.java b/sponge/src/main/java/net/draycia/carbon/sponge/listeners/SpongePlayerJoinListener.java index 34181500b..1b139470d 100644 --- a/sponge/src/main/java/net/draycia/carbon/sponge/listeners/SpongePlayerJoinListener.java +++ b/sponge/src/main/java/net/draycia/carbon/sponge/listeners/SpongePlayerJoinListener.java @@ -20,40 +20,86 @@ package net.draycia.carbon.sponge.listeners; import com.google.inject.Inject; +import com.google.inject.Provider; +import java.util.List; import net.draycia.carbon.api.CarbonChat; import net.draycia.carbon.api.users.UserManager; +import net.draycia.carbon.common.config.ConfigManager; +import net.draycia.carbon.common.messaging.MessagingManager; +import net.draycia.carbon.common.messaging.packets.PacketFactory; import net.draycia.carbon.common.users.CarbonPlayerCommon; +import net.draycia.carbon.common.users.ProfileCache; +import net.draycia.carbon.common.users.UserManagerInternal; import net.draycia.carbon.common.util.PlayerUtils; import net.draycia.carbon.sponge.users.CarbonPlayerSponge; +import org.apache.logging.log4j.Logger; import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.framework.qual.DefaultQualifier; +import org.spongepowered.api.data.Keys; import org.spongepowered.api.event.Listener; +import org.spongepowered.api.event.Order; import org.spongepowered.api.event.network.ServerSideConnectionEvent; +import static net.draycia.carbon.common.users.PlayerUtils.joinExceptionHandler; +import static net.draycia.carbon.common.users.PlayerUtils.saveExceptionHandler; @DefaultQualifier(NonNull.class) public class SpongePlayerJoinListener { - private final CarbonChat carbonChat; - private final UserManager userManager; + + private final ConfigManager configManager; + private final Logger logger; + private final ProfileCache profileCache; + private final UserManagerInternal userManager; + private final Provider messaging; + private final PacketFactory packetFactory; @Inject public SpongePlayerJoinListener( - final CarbonChat carbonChat, - final UserManager userManager + final ConfigManager configManager, + final Logger logger, + final ProfileCache profileCache, + final UserManagerInternal userManager, + final Provider messaging, + final PacketFactory packetFactory ) { - this.carbonChat = carbonChat; + this.configManager = configManager; + this.logger = logger; + this.profileCache = profileCache; this.userManager = userManager; + this.messaging = messaging; + this.packetFactory = packetFactory; } @Listener - public void onPlayerQuit(final ServerSideConnectionEvent.Disconnect event) { - this.carbonChat.server().userManager().carbonPlayer(event.player().uniqueId()).thenAccept(result -> { - if (result.player() == null) { - return; - } + public void onLogin(final ServerSideConnectionEvent.Login event) { // or Handshake/Auth + this.profileCache.cache(event.user().uniqueId(), event.user().name()); + } - PlayerUtils.saveAndInvalidatePlayer(this.carbonChat.server(), this.userManager, (CarbonPlayerSponge) result.player()); + @Listener(order = Order.EARLY) + public void onJoinEarly(final ServerSideConnectionEvent.Join event) { + this.messaging.get().withPacketService(packetService -> { + packetService.queuePacket(this.packetFactory.addLocalPlayerPacket(event.player().uniqueId(), event.player().name())); }); } + @Listener(order = Order.LATE) + public void onJoin(final ServerSideConnectionEvent.Join event) { + this.userManager.user(event.player().uniqueId()).exceptionally(joinExceptionHandler(this.logger, event.player().name(), event.player().uniqueId())); + +// final @Nullable List suggestions = this.configManager.primaryConfig().customChatSuggestions(); +// +// if (suggestions == null || suggestions.isEmpty()) { +// return; +// } +// +// event.player().addAdditionalChatCompletions(suggestions); + } + + @Listener(order = Order.LATE) + public void onQuit(final ServerSideConnectionEvent.Disconnect event) { + this.userManager.loggedOut(event.player().uniqueId()) + .exceptionally(saveExceptionHandler(this.logger, event.player().name(), event.player().uniqueId())); + } + } diff --git a/sponge/src/main/java/net/draycia/carbon/sponge/users/SpongeProfileResolver.java b/sponge/src/main/java/net/draycia/carbon/sponge/users/SpongeProfileResolver.java new file mode 100644 index 000000000..9935c319a --- /dev/null +++ b/sponge/src/main/java/net/draycia/carbon/sponge/users/SpongeProfileResolver.java @@ -0,0 +1,45 @@ +package net.draycia.carbon.sponge.users; + +import com.google.inject.Inject; +import com.google.inject.Singleton; +import java.util.UUID; +import java.util.concurrent.CompletableFuture; +import net.draycia.carbon.common.users.MojangProfileResolver; +import net.draycia.carbon.common.users.ProfileResolver; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.checkerframework.framework.qual.DefaultQualifier; +import org.spongepowered.api.Sponge; +import org.spongepowered.api.profile.GameProfile; + +@Singleton +@DefaultQualifier(NonNull.class) +public class SpongeProfileResolver implements ProfileResolver { + + private final ProfileResolver mojang; + + @Inject + private SpongeProfileResolver(final MojangProfileResolver mojang) { + this.mojang = mojang; + } + + @Override + public CompletableFuture<@Nullable UUID> resolveUUID(final String username, final boolean cacheOnly) { + // TODO: handle profile lookup failure + // TODO: do we need the mojang profile resolver here? Sponge's profile manager automatically caches and uses its own version + return Sponge.server().gameProfileManager().basicProfile(username).thenApply(GameProfile::uuid); + } + + @Override + public CompletableFuture<@Nullable String> resolveName(final UUID uuid, final boolean cacheOnly) { + // TODO: handle profile lookup failure + // TODO: do we need the mojang profile resolver here? Sponge's profile manager automatically caches and uses its own version + return Sponge.server().gameProfileManager().basicProfile(uuid).thenApply(profile -> profile.name().orElse(null)); + } + + @Override + public void shutdown() { + this.mojang.shutdown(); + } + +} diff --git a/velocity/src/main/java/net/draycia/carbon/velocity/CarbonChatVelocity.java b/velocity/src/main/java/net/draycia/carbon/velocity/CarbonChatVelocity.java index 4b65fe9f4..ff1de0196 100644 --- a/velocity/src/main/java/net/draycia/carbon/velocity/CarbonChatVelocity.java +++ b/velocity/src/main/java/net/draycia/carbon/velocity/CarbonChatVelocity.java @@ -59,17 +59,18 @@ public class CarbonChatVelocity extends CarbonChatInternal { private final ProxyServer proxyServer; @Inject + // TODO: this is public and paper/fabric's are private, does this have to be public and do the others have to be private? public CarbonChatVelocity( final ProxyServer proxyServer, - final Injector injector, final PluginContainer pluginContainer, + final Injector injector, @PeriodicTasks final ScheduledExecutorService periodicTasks, final ProfileCache profileCache, final ProfileResolver profileResolver, - final ExecutionCoordinatorHolder commandExecutor, - final CarbonMessages carbonMessages, final PlatformUserManager userManager, + final ExecutionCoordinatorHolder commandExecutor, final CarbonServerVelocity carbonServer, + final CarbonMessages carbonMessages, final CarbonEventHandler eventHandler, final CarbonChannelRegistry channelRegistry, final Provider messagingManager @@ -90,7 +91,7 @@ public CarbonChatVelocity( ); this.proxyServer = proxyServer; - CarbonChatProvider.register(this); + CarbonChatProvider.register(this); // TODO: move to bootstrap? } public void onInitialization(final CarbonVelocityBootstrap carbonVelocityBootstrap) { diff --git a/velocity/src/main/java/net/draycia/carbon/velocity/CarbonVelocityBootstrap.java b/velocity/src/main/java/net/draycia/carbon/velocity/CarbonVelocityBootstrap.java index 3ee97251f..cbd638fa4 100644 --- a/velocity/src/main/java/net/draycia/carbon/velocity/CarbonVelocityBootstrap.java +++ b/velocity/src/main/java/net/draycia/carbon/velocity/CarbonVelocityBootstrap.java @@ -73,6 +73,8 @@ public void onProxyInitialize(final ProxyInitializeEvent event) { final Metrics metrics = this.metricsFactory.make(this, BSTATS_PLUGIN_ID); metrics.addCustomChart(new SimplePie("user_manager_type", () -> this.injector.getInstance(ConfigManager.class).primaryConfig().storageType().name())); + + } @Subscribe