001//
002// MIT License
003//
004// Copyright (c) 2021 Alexander Söderberg & Contributors
005//
006// Permission is hereby granted, free of charge, to any person obtaining a copy
007// of this software and associated documentation files (the "Software"), to deal
008// in the Software without restriction, including without limitation the rights
009// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
010// copies of the Software, and to permit persons to whom the Software is
011// furnished to do so, subject to the following conditions:
012//
013// The above copyright notice and this permission notice shall be included in all
014// copies or substantial portions of the Software.
015//
016// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
017// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
018// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
019// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
020// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
021// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
022// SOFTWARE.
023//
024package cloud.commandframework.cloudburst;
025
026import cloud.commandframework.CommandManager;
027import cloud.commandframework.CommandTree;
028import cloud.commandframework.execution.CommandExecutionCoordinator;
029import cloud.commandframework.meta.CommandMeta;
030import cloud.commandframework.meta.SimpleCommandMeta;
031import org.checkerframework.checker.nullness.qual.NonNull;
032import org.cloudburstmc.server.command.CommandSender;
033import org.cloudburstmc.server.event.EventPriority;
034import org.cloudburstmc.server.event.Listener;
035import org.cloudburstmc.server.event.server.RegistriesClosedEvent;
036import org.cloudburstmc.server.plugin.Plugin;
037
038import java.util.function.Function;
039
040/**
041 * Command manager for the Cloudburst platform
042 *
043 * @param <C> Command sender type
044 */
045public class CloudburstCommandManager<C> extends CommandManager<C> {
046
047    private final Function<CommandSender, C> commandSenderMapper;
048    private final Function<C, CommandSender> backwardsCommandSenderMapper;
049
050    private final Plugin owningPlugin;
051
052    /**
053     * Construct a new Cloudburst command manager
054     *
055     * @param owningPlugin                 Plugin that is constructing the manager
056     * @param commandExecutionCoordinator  Coordinator provider
057     * @param commandSenderMapper          Function that maps {@link CommandSender} to the command sender type
058     * @param backwardsCommandSenderMapper Function that maps the command sender type to {@link CommandSender}
059     */
060    @SuppressWarnings("unchecked")
061    public CloudburstCommandManager(
062            final @NonNull Plugin owningPlugin,
063            final @NonNull Function<@NonNull CommandTree<C>,
064                    @NonNull CommandExecutionCoordinator<C>> commandExecutionCoordinator,
065            final @NonNull Function<@NonNull CommandSender, @NonNull C> commandSenderMapper,
066            final @NonNull Function<@NonNull C, @NonNull CommandSender> backwardsCommandSenderMapper
067    ) {
068        super(commandExecutionCoordinator, new CloudburstPluginRegistrationHandler<>());
069        ((CloudburstPluginRegistrationHandler<C>) this.getCommandRegistrationHandler()).initialize(this);
070        this.commandSenderMapper = commandSenderMapper;
071        this.backwardsCommandSenderMapper = backwardsCommandSenderMapper;
072        this.owningPlugin = owningPlugin;
073
074        // Prevent commands from being registered when the server would reject them anyways
075        this.owningPlugin.getServer().getPluginManager().registerEvent(
076                RegistriesClosedEvent.class,
077                CloudListener.INSTANCE,
078                EventPriority.NORMAL,
079                (listener, event) -> this.lockRegistration(),
080                this.owningPlugin
081        );
082    }
083
084    @Override
085    public final boolean hasPermission(
086            final @NonNull C sender,
087            final @NonNull String permission
088    ) {
089        return this.backwardsCommandSenderMapper.apply(sender).hasPermission(permission);
090    }
091
092    @Override
093    public final @NonNull CommandMeta createDefaultCommandMeta() {
094        return SimpleCommandMeta.builder().build();
095    }
096
097    @Override
098    public final boolean isCommandRegistrationAllowed() {
099        return this.getRegistrationState() != RegistrationState.AFTER_REGISTRATION;
100    }
101
102    final @NonNull Function<@NonNull CommandSender, @NonNull C> getCommandSenderMapper() {
103        return this.commandSenderMapper;
104    }
105
106    /**
107     * Get the plugin that owns the manager
108     *
109     * @return Owning plugin
110     */
111    public final @NonNull Plugin getOwningPlugin() {
112        return this.owningPlugin;
113    }
114
115    static final class CloudListener implements Listener {
116
117        static final CloudListener INSTANCE = new CloudListener();
118
119        private CloudListener() {
120        }
121
122    }
123
124}