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.bungee;
025
026import cloud.commandframework.CommandManager;
027import cloud.commandframework.CommandTree;
028import cloud.commandframework.bungee.arguments.PlayerArgument;
029import cloud.commandframework.bungee.arguments.ServerArgument;
030import cloud.commandframework.captions.FactoryDelegatingCaptionRegistry;
031import cloud.commandframework.execution.CommandExecutionCoordinator;
032import cloud.commandframework.meta.SimpleCommandMeta;
033import io.leangen.geantyref.TypeToken;
034import net.md_5.bungee.api.CommandSender;
035import net.md_5.bungee.api.config.ServerInfo;
036import net.md_5.bungee.api.connection.ProxiedPlayer;
037import net.md_5.bungee.api.plugin.Plugin;
038import org.checkerframework.checker.nullness.qual.NonNull;
039
040import java.util.function.Function;
041
042public class BungeeCommandManager<C> extends CommandManager<C> {
043
044    /**
045     * Default caption for {@link BungeeCaptionKeys#ARGUMENT_PARSE_FAILURE_PLAYER}
046     */
047    public static final String ARGUMENT_PARSE_FAILURE_PLAYER = "'{input}' is not a valid player";
048
049    /**
050     * Default caption for {@link BungeeCaptionKeys#ARGUMENT_PARSE_FAILURE_SERVER}
051     */
052    public static final String ARGUMENT_PARSE_FAILURE_SERVER = "'{input}' is not a valid server";
053
054    private final Plugin owningPlugin;
055    private final Function<CommandSender, C> commandSenderMapper;
056    private final Function<C, CommandSender> backwardsCommandSenderMapper;
057
058    /**
059     * Construct a new Bungee command manager
060     *
061     * @param owningPlugin                 Plugin that is constructing the manager
062     * @param commandExecutionCoordinator  Coordinator provider
063     * @param commandSenderMapper          Function that maps {@link CommandSender} to the command sender type
064     * @param backwardsCommandSenderMapper Function that maps the command sender type to {@link CommandSender}
065     */
066    @SuppressWarnings("unchecked")
067    public BungeeCommandManager(
068            final @NonNull Plugin owningPlugin,
069            final @NonNull Function<@NonNull CommandTree<C>,
070                    @NonNull CommandExecutionCoordinator<C>> commandExecutionCoordinator,
071            final @NonNull Function<@NonNull CommandSender, @NonNull C> commandSenderMapper,
072            final @NonNull Function<@NonNull C, @NonNull CommandSender> backwardsCommandSenderMapper
073    ) {
074        super(commandExecutionCoordinator, new BungeePluginRegistrationHandler<>());
075        ((BungeePluginRegistrationHandler<C>) this.getCommandRegistrationHandler()).initialize(this);
076        this.owningPlugin = owningPlugin;
077        this.commandSenderMapper = commandSenderMapper;
078        this.backwardsCommandSenderMapper = backwardsCommandSenderMapper;
079
080        /* Register Bungee Preprocessor */
081        this.registerCommandPreProcessor(new BungeeCommandPreprocessor<>(this));
082
083        /* Register Bungee Parsers */
084        this.getParserRegistry().registerParserSupplier(TypeToken.get(ProxiedPlayer.class), parserParameters ->
085                new PlayerArgument.PlayerParser<>());
086        this.getParserRegistry().registerParserSupplier(TypeToken.get(ServerInfo.class), parserParameters ->
087                new ServerArgument.ServerParser<>());
088
089        /* Register default captions */
090        if (this.getCaptionRegistry() instanceof FactoryDelegatingCaptionRegistry) {
091            final FactoryDelegatingCaptionRegistry<C> factoryDelegatingCaptionRegistry = (FactoryDelegatingCaptionRegistry<C>)
092                    this.getCaptionRegistry();
093            factoryDelegatingCaptionRegistry.registerMessageFactory(
094                    BungeeCaptionKeys.ARGUMENT_PARSE_FAILURE_PLAYER,
095                    (context, key) -> ARGUMENT_PARSE_FAILURE_PLAYER
096            );
097            factoryDelegatingCaptionRegistry.registerMessageFactory(
098                    BungeeCaptionKeys.ARGUMENT_PARSE_FAILURE_SERVER,
099                    (context, key) -> ARGUMENT_PARSE_FAILURE_SERVER
100            );
101        }
102    }
103
104    @Override
105    public final boolean hasPermission(
106            final @NonNull C sender,
107            final @NonNull String permission
108    ) {
109        if (permission.isEmpty()) {
110            return true;
111        }
112        return this.backwardsCommandSenderMapper.apply(sender).hasPermission(permission);
113    }
114
115    @Override
116    public final @NonNull SimpleCommandMeta createDefaultCommandMeta() {
117        return SimpleCommandMeta.empty();
118    }
119
120    final @NonNull Function<@NonNull CommandSender, @NonNull C> getCommandSenderMapper() {
121        return this.commandSenderMapper;
122    }
123
124    /**
125     * Get the owning plugin
126     *
127     * @return Owning plugin
128     */
129    public @NonNull Plugin getOwningPlugin() {
130        return this.owningPlugin;
131    }
132
133}