diff --git a/.idea/compiler.xml b/.idea/compiler.xml index a44334815..c5e4f014e 100644 --- a/.idea/compiler.xml +++ b/.idea/compiler.xml @@ -10,19 +10,22 @@ - - - + + + + + + @@ -37,6 +40,7 @@ + diff --git a/.idea/encodings.xml b/.idea/encodings.xml index 6557e517a..c0c073901 100644 --- a/.idea/encodings.xml +++ b/.idea/encodings.xml @@ -22,8 +22,9 @@ - + + diff --git a/pom.xml b/pom.xml index d1a11023a..02ff79dab 100644 --- a/pom.xml +++ b/pom.xml @@ -204,6 +204,7 @@ paper bungee sponge + sponge10 jda velocity diff --git a/sponge10/pom.xml b/sponge10/pom.xml new file mode 100644 index 000000000..3bf2e4fed --- /dev/null +++ b/sponge10/pom.xml @@ -0,0 +1,80 @@ + + + + + 4.0.0 + + + co.aikar + acf-parent + 0.5.1-SNAPSHOT + ../pom.xml + + + acf-sponge10 + 0.5.1-SNAPSHOT + + ACF (Sponge 10) + + + + spongepowered + https://repo.spongepowered.org/maven/ + + + + + + co.aikar + acf-core + 0.5.1-SNAPSHOT + compile + + + org.spongepowered + spongeapi + 10.1.0-SNAPSHOT + provided + + + + + + ${project.basedir}/../languages/minecraft/ + + + + + org.apache.maven.plugins + maven-compiler-plugin + + 8 + 8 + + + + + diff --git a/sponge10/src/main/java/co/aikar/commands/ACFSpongeUtil.java b/sponge10/src/main/java/co/aikar/commands/ACFSpongeUtil.java new file mode 100644 index 000000000..43fbf5098 --- /dev/null +++ b/sponge10/src/main/java/co/aikar/commands/ACFSpongeUtil.java @@ -0,0 +1,96 @@ +package co.aikar.commands; + +import org.jetbrains.annotations.Nullable; +import org.spongepowered.api.Sponge; +import org.spongepowered.api.entity.living.player.Player; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.stream.Collectors; + +@SuppressWarnings("WeakerAccess") +public class ACFSpongeUtil { + public static Player findPlayerSmart(CommandIssuer issuer, String search) { + SpongeCommandSource requester = issuer.getIssuer(); + if (search == null) { + return null; + } + String name = ACFUtil.replace(search, ":confirm", ""); + + List matches = matchPlayer(name); + List confirmList = new ArrayList<>(); + findMatches(search, requester, matches, confirmList); + + + if (matches.size() > 1 || confirmList.size() > 1) { + String allMatches = matches.stream().map(Player::name).collect(Collectors.joining(", ")); + issuer.sendError(MinecraftMessageKeys.MULTIPLE_PLAYERS_MATCH, + "{search}", name, "{all}", allMatches); + return null; + } + + if (matches.isEmpty()) { + if (!issuer.getManager().isValidName(name)) { + issuer.sendError(MinecraftMessageKeys.IS_NOT_A_VALID_NAME, "{name}", name); + return null; + } + Player player = ACFUtil.getFirstElement(confirmList); + if (player == null) { + issuer.sendError(MinecraftMessageKeys.NO_PLAYER_FOUND_SERVER, "{search}", name); + return null; + } else { + + issuer.sendInfo(MinecraftMessageKeys.PLAYER_IS_VANISHED_CONFIRM, "{vanished}", player.name()); + return null; + } + } + + return matches.get(0); + } + + private static void findMatches(String search, SpongeCommandSource requester, List matches, List confirmList) { + // Remove vanished players from smart matching. + Iterator iter = matches.iterator(); + //noinspection Duplicates + while (iter.hasNext()) { + Player player = iter.next(); + if (requester instanceof Player && !((Player) requester).canSee(player)) { + if (requester.hasPermission("acf.seevanish")) { + if (!search.endsWith(":confirm")) { + confirmList.add(player); + iter.remove(); + } + } else { + iter.remove(); + } + } + } + } + + public static List matchPlayer(String partialName) { + List matchedPlayers = new ArrayList<>(); + + for (Player iterPlayer : Sponge.server().onlinePlayers()) { + String iterPlayerName = iterPlayer.name(); + + if (partialName.equalsIgnoreCase(iterPlayerName)) { + // Exact match + matchedPlayers.clear(); + matchedPlayers.add(iterPlayer); + break; + } + if (iterPlayerName.toLowerCase(java.util.Locale.ENGLISH).contains(partialName.toLowerCase(java.util.Locale.ENGLISH))) { + // Partial match + matchedPlayers.add(iterPlayer); + } + } + + return matchedPlayers; + } + + public static boolean isValidName(@Nullable String name) { + return name != null && !name.isEmpty() && ACFPatterns.VALID_NAME_PATTERN.matcher(name).matches(); + } + +} diff --git a/sponge10/src/main/java/co/aikar/commands/MinecraftMessageKeys.java b/sponge10/src/main/java/co/aikar/commands/MinecraftMessageKeys.java new file mode 100644 index 000000000..a28add753 --- /dev/null +++ b/sponge10/src/main/java/co/aikar/commands/MinecraftMessageKeys.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package co.aikar.commands; + +import co.aikar.locales.MessageKey; +import co.aikar.locales.MessageKeyProvider; + +import java.util.Locale; + +public enum MinecraftMessageKeys implements MessageKeyProvider { + INVALID_WORLD, + YOU_MUST_BE_HOLDING_ITEM, + PLAYER_IS_VANISHED_CONFIRM, + USERNAME_TOO_SHORT, + IS_NOT_A_VALID_NAME, + MULTIPLE_PLAYERS_MATCH, + NO_PLAYER_FOUND_SERVER, + NO_PLAYER_FOUND + ; + + private final MessageKey key = MessageKey.of("acf-minecraft." + this.name().toLowerCase(Locale.ENGLISH)); + public MessageKey getMessageKey() { + return key; + } +} diff --git a/sponge10/src/main/java/co/aikar/commands/SpongeCommandCompletionContext.java b/sponge10/src/main/java/co/aikar/commands/SpongeCommandCompletionContext.java new file mode 100644 index 000000000..d728b053c --- /dev/null +++ b/sponge10/src/main/java/co/aikar/commands/SpongeCommandCompletionContext.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package co.aikar.commands; + +import org.spongepowered.api.entity.living.player.Player; + +@SuppressWarnings("WeakerAccess") +public class SpongeCommandCompletionContext extends CommandCompletionContext { + + SpongeCommandCompletionContext(final RegisteredCommand command, final SpongeCommandIssuer issuer, final String input, final String config, final String[] args) { + super(command, issuer, input, config, args); + } + + public SpongeCommandSource getSource() { + return this.issuer.getIssuer(); + } + + public Player getPlayer() { + return this.issuer.getPlayer(); + } +} diff --git a/sponge10/src/main/java/co/aikar/commands/SpongeCommandCompletions.java b/sponge10/src/main/java/co/aikar/commands/SpongeCommandCompletions.java new file mode 100644 index 000000000..ac757bb3e --- /dev/null +++ b/sponge10/src/main/java/co/aikar/commands/SpongeCommandCompletions.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package co.aikar.commands; + +@SuppressWarnings("WeakerAccess") +public class SpongeCommandCompletions extends CommandCompletions { + + public SpongeCommandCompletions(final SpongeCommandManager manager) { + super(manager); + } +} diff --git a/sponge10/src/main/java/co/aikar/commands/SpongeCommandContexts.java b/sponge10/src/main/java/co/aikar/commands/SpongeCommandContexts.java new file mode 100644 index 000000000..062c33a4e --- /dev/null +++ b/sponge10/src/main/java/co/aikar/commands/SpongeCommandContexts.java @@ -0,0 +1,225 @@ +/* + * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package co.aikar.commands; + +import co.aikar.commands.contexts.CommandResultSupplier; +import co.aikar.commands.sponge.contexts.OnlinePlayer; +import net.kyori.adventure.text.format.NamedTextColor; +import net.kyori.adventure.text.format.TextColor; +import net.kyori.adventure.text.format.TextDecoration; +import org.jetbrains.annotations.Contract; +import org.spongepowered.api.ResourceKey; +import org.spongepowered.api.Sponge; +import org.spongepowered.api.command.CommandCause; +import org.spongepowered.api.entity.living.player.Player; +import org.spongepowered.api.entity.living.player.User; +import org.spongepowered.api.entity.living.player.server.ServerPlayer; +import org.spongepowered.api.user.UserManager; +import org.spongepowered.api.world.World; +import org.spongepowered.api.world.server.ServerWorld; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Locale; +import java.util.Optional; +import java.util.Set; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; +import java.util.regex.Pattern; +import java.util.stream.Collectors; + +@SuppressWarnings("WeakerAccess") +public class SpongeCommandContexts extends CommandContexts { + + public SpongeCommandContexts(final SpongeCommandManager manager) { + super(manager); + + registerIssuerOnlyContext(CommandResultSupplier.class, c -> new CommandResultSupplier()); + registerContext(OnlinePlayer.class, c -> getOnlinePlayer(c.getIssuer(), c.popFirstArg(), false)); + registerContext(co.aikar.commands.contexts.OnlinePlayer.class, c -> { + OnlinePlayer onlinePlayer = getOnlinePlayer(c.getIssuer(), c.popFirstArg(), false); + return new co.aikar.commands.contexts.OnlinePlayer(onlinePlayer.getPlayer()); + }); + registerContext(User.class, c -> { + String name = c.popFirstArg(); + UserManager userNamanger = Sponge.server().userManager(); + CompletableFuture> optionalUser = userNamanger.load(name); + // Fetch the player's profile + CompletableFuture completableFuture = optionalUser.thenCompose(user -> { + if (user.isPresent()) { + return CompletableFuture.completedFuture(user.get()); + } else { + throw new InvalidCommandArgument(MinecraftMessageKeys.NO_PLAYER_FOUND, false, "{search}", name); + } + }); + + try { + return completableFuture.get(); + } catch (InterruptedException | ExecutionException e) { + throw new RuntimeException(e); + } + }); + + registerContext(TextColor.class, c -> { + String arg = c.getFirstArg().toLowerCase(); + TextColor color = NamedTextColor.NAMES.value(arg); + if (color == null) { + color = arg.startsWith("#") ? TextColor.fromHexString(arg) : TextColor.fromHexString("#" + arg); + if (color == null) { + throw new InvalidCommandArgument("Unknown TextColor syntax"); + } + + NamedTextColor closest = NamedTextColor.nearestTo(color); + if (color.compareTo(closest) == 0) { + color = closest; + } + } + + String filter = c.getFlagValue("filter", (String) null); + if (filter != null) { + Set colors = Arrays.stream( + ACFPatterns.COLON.split(filter)) + .map(NamedTextColor.NAMES::value) + .collect(Collectors.toSet()); + if (!(color instanceof NamedTextColor) || !colors.contains(color)) { + throw new InvalidCommandArgument("Not a valid color"); + } + } + + return color; + }); + + registerContext(TextDecoration.class, c -> { + String first = c.popFirstArg().toLowerCase(Locale.ROOT); + TextDecoration decoration = TextDecoration.NAMES.value(first); + + if (decoration == null) { + throw new InvalidCommandArgument("Unknown TextDecoration syntax"); + } + + String filter = c.getFlagValue("filter", (String) null); + if (filter != null) { + Set textDecorations = Arrays.stream( + ACFPatterns.COLON.split(filter)) + .map(TextDecoration.NAMES::value) + .collect(Collectors.toSet()); + if (!textDecorations.contains(decoration)) { + throw new InvalidCommandArgument("Not a valid TextDecoration"); + } + } + + return decoration; + }); + + registerIssuerAwareContext(CommandCause.class, SpongeCommandExecutionContext::getSource); + registerIssuerAwareContext(SpongeCommandSource.class, SpongeCommandExecutionContext::getSource); + registerIssuerAwareContext(ServerPlayer.class, (c) -> { + ServerPlayer serverPlayer = c.getIssuer().getServerPlayer(); + if (serverPlayer == null && !c.isOptional()) { + throw new InvalidCommandArgument(MessageKeys.NOT_ALLOWED_ON_CONSOLE, false); + } + + return serverPlayer; + }); + registerIssuerAwareContext(Player.class, (c) -> { + Player player = c.getIssuer().getPlayer(); + if (player == null && !c.isOptional()) { + throw new InvalidCommandArgument(MessageKeys.NOT_ALLOWED_ON_CONSOLE, false); + } + /*PlayerInventory inventory = player != null ? player.getInventory() : null; + if (inventory != null && c.hasFlag("itemheld") && !ACFBukkitUtil.isValidItem(inventory.getItem(inventory.getHeldItemSlot()))) { + throw new InvalidCommandArgument(MinecraftMessageKeys.YOU_MUST_BE_HOLDING_ITEM, false); + }*/ + return player; + }); + registerContext(OnlinePlayer[].class, (c) -> { + SpongeCommandIssuer issuer = c.getIssuer(); + final String search = c.popFirstArg(); + boolean allowMissing = c.hasFlag("allowmissing"); + Set players = new HashSet<>(); + Pattern split = ACFPatterns.COMMA; + String splitter = c.getFlagValue("splitter", (String) null); + if (splitter != null) { + split = Pattern.compile(Pattern.quote(splitter)); + } + for (String lookup : split.split(search)) { + OnlinePlayer player = getOnlinePlayer(issuer, lookup, allowMissing); + if (player != null) { + players.add(player); + } + } + if (players.isEmpty() && !c.hasFlag("allowempty")) { + issuer.sendError(MinecraftMessageKeys.NO_PLAYER_FOUND_SERVER, + "{search}", search); + + throw new InvalidCommandArgument(false); + } + return players.toArray(new OnlinePlayer[players.size()]); + }); + registerIssuerAwareContext(World.class, (c) -> { + String firstArg = c.getFirstArg(); + + if (firstArg == null) { + if (c.isOptional()) { + return null; + } else { + throw new InvalidCommandArgument(MinecraftMessageKeys.INVALID_WORLD); + } + } + + ResourceKey worldKey = ResourceKey.of("minecraft", firstArg); + Optional serverWorld = Sponge.server().worldManager().world(worldKey); + + Optional world = Optional.empty(); + if (serverWorld.isPresent()) { + world = Optional.of( serverWorld.get() ); + } + + if (world.isPresent()) { + c.popFirstArg(); + } else { + if (c.getSource() instanceof Player) { + world = java.util.Optional.of(((Player) c.getSource()).world()); + } + + if (!world.isPresent()) { + throw new InvalidCommandArgument(MinecraftMessageKeys.INVALID_WORLD); + } + } + return world.get(); + }); + } + + @Contract("_,_,false -> !null") + OnlinePlayer getOnlinePlayer(SpongeCommandIssuer issuer, String lookup, boolean allowMissing) throws InvalidCommandArgument { + Player player = ACFSpongeUtil.findPlayerSmart(issuer, lookup); + if (player == null) { + if (allowMissing) { + return null; + } + throw new InvalidCommandArgument(false); + } + return new OnlinePlayer(player); + } +} diff --git a/sponge10/src/main/java/co/aikar/commands/SpongeCommandExecutionContext.java b/sponge10/src/main/java/co/aikar/commands/SpongeCommandExecutionContext.java new file mode 100644 index 000000000..b3e97f1ca --- /dev/null +++ b/sponge10/src/main/java/co/aikar/commands/SpongeCommandExecutionContext.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package co.aikar.commands; + +import org.spongepowered.api.entity.living.player.Player; + +import java.util.List; +import java.util.Map; + +public class SpongeCommandExecutionContext extends CommandExecutionContext { + + SpongeCommandExecutionContext(RegisteredCommand cmd, CommandParameter param, SpongeCommandIssuer sender, List args, + int index, Map passedArgs) { + super(cmd, param, sender, args, index, passedArgs); + } + + public SpongeCommandSource getSource() { + return this.issuer.getIssuer(); + } + + public Player getPlayer() { + return this.issuer.getPlayer(); + } +} diff --git a/sponge10/src/main/java/co/aikar/commands/SpongeCommandIssuer.java b/sponge10/src/main/java/co/aikar/commands/SpongeCommandIssuer.java new file mode 100644 index 000000000..b57f16491 --- /dev/null +++ b/sponge10/src/main/java/co/aikar/commands/SpongeCommandIssuer.java @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package co.aikar.commands; + +import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; +import org.jetbrains.annotations.NotNull; +import org.spongepowered.api.entity.living.player.Player; +import org.spongepowered.api.entity.living.player.server.ServerPlayer; +import org.spongepowered.api.util.Identifiable; + +import java.nio.charset.StandardCharsets; +import java.util.Objects; +import java.util.UUID; + +public class SpongeCommandIssuer implements CommandIssuer { + + private final SpongeCommandManager manager; + private final SpongeCommandSource source; + + SpongeCommandIssuer(SpongeCommandManager manager, final SpongeCommandSource source) { + this.manager = manager; + this.source = source; + } + + @Override + public boolean isPlayer() { + return this.source instanceof Player; + } + + public boolean isServerPlayer() { + return this.source instanceof ServerPlayer; + } + + @Override + public SpongeCommandSource getIssuer() { + return this.source; + } + + @Override + public @NotNull UUID getUniqueId() { + if (this.source instanceof Identifiable) { + return ((Identifiable) source).uniqueId(); + } + + //generate a unique id based of the name (like for the console command sender) + return UUID.nameUUIDFromBytes(source.identifier().getBytes(StandardCharsets.UTF_8)); + } + + public Player getPlayer() { + return isPlayer() ? (Player) source : null; + } + + public ServerPlayer getServerPlayer() { + return isServerPlayer() ? (ServerPlayer) source : null; + } + + @Override + public CommandManager getManager() { + return manager; + } + + @Override + public void sendMessageInternal(String message) { + try { + source.audience().sendMessage(LegacyComponentSerializer.legacyAmpersand().deserialize(message)); + } catch (Exception ignored) {} + } + + @Override + public boolean hasPermission(final String permission) { + return this.source.hasPermission(permission); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + SpongeCommandIssuer that = (SpongeCommandIssuer) o; + return Objects.equals(source, that.source); + } + + @Override + public int hashCode() { + return Objects.hash(source); + } +} diff --git a/sponge10/src/main/java/co/aikar/commands/SpongeCommandManager.java b/sponge10/src/main/java/co/aikar/commands/SpongeCommandManager.java new file mode 100644 index 000000000..333ed9181 --- /dev/null +++ b/sponge10/src/main/java/co/aikar/commands/SpongeCommandManager.java @@ -0,0 +1,227 @@ +/* + * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package co.aikar.commands; + +import co.aikar.commands.apachecommonslang.ApacheCommonsExceptionUtil; +import net.kyori.adventure.text.format.NamedTextColor; +import net.kyori.adventure.text.format.TextColor; +import org.apache.logging.log4j.Logger; +import org.spongepowered.api.Sponge; +import org.spongepowered.api.command.Command; +import org.spongepowered.api.command.CommandCause; +import org.spongepowered.plugin.PluginContainer; + +import java.lang.reflect.Method; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; + +@SuppressWarnings("WeakerAccess") +public class SpongeCommandManager extends CommandManager< + SpongeCommandSource, + SpongeCommandIssuer, + TextColor, + SpongeMessageFormatter, + SpongeCommandExecutionContext, + SpongeConditionContext + > { + + protected final PluginContainer plugin; + protected Map registeredCommands = new HashMap<>(); + protected SpongeCommandContexts contexts; + protected SpongeCommandCompletions completions; + protected SpongeLocales locales; + + public SpongeCommandManager(PluginContainer plugin) { + this.plugin = plugin; + String pluginName = "acf-" + plugin.metadata().name(); + getLocales().addMessageBundles("acf-minecraft", pluginName, pluginName.toLowerCase(Locale.ENGLISH)); + + this.formatters.put(MessageType.ERROR, defaultFormatter = new SpongeMessageFormatter(NamedTextColor.RED, NamedTextColor.YELLOW, NamedTextColor.RED)); + this.formatters.put(MessageType.SYNTAX, new SpongeMessageFormatter(NamedTextColor.YELLOW, NamedTextColor.GREEN, NamedTextColor.WHITE)); + this.formatters.put(MessageType.INFO, new SpongeMessageFormatter(NamedTextColor.BLUE, NamedTextColor.DARK_GREEN, NamedTextColor.GREEN)); + this.formatters.put(MessageType.HELP, new SpongeMessageFormatter(NamedTextColor.AQUA, NamedTextColor.GREEN, NamedTextColor.YELLOW)); + getLocales(); // auto load locales + + this.validNamePredicate = ACFSpongeUtil::isValidName; + + //TODO more default dependencies for sponge + registerDependency(plugin.getClass(), plugin); + } + + public PluginContainer getPlugin() { + return plugin; + } + + @Override + public boolean isCommandIssuer(Class type) { + return CommandCause.class.isAssignableFrom(type); + } + + @Override + public synchronized CommandContexts getCommandContexts() { + if (this.contexts == null) { + this.contexts = new SpongeCommandContexts(this); + } + return contexts; + } + + @Override + public synchronized CommandCompletions getCommandCompletions() { + if (this.completions == null) { + this.completions = new SpongeCommandCompletions(this); + } + return completions; + } + + @Override + public SpongeLocales getLocales() { + if (this.locales == null) { + this.locales = new SpongeLocales(this); + this.locales.loadLanguages(); + } + return locales; + } + + @Override + public boolean hasRegisteredCommands() { + return !registeredCommands.isEmpty(); + } + + @Override + public void registerCommand(BaseCommand command) { + command.onRegister(this); + + for (Map.Entry entry : command.registeredCommands.entrySet()) { + String commandName = entry.getKey().toLowerCase(Locale.ENGLISH); + SpongeRootCommand spongeCommand = (SpongeRootCommand) entry.getValue(); + if (!spongeCommand.isRegistered) { + Sponge.server().commandManager().registrar(Command.Raw.class).get() + .register(plugin, spongeCommand, commandName); + } + spongeCommand.isRegistered = true; + registeredCommands.put(commandName, spongeCommand); + } + } + + @Override + public RootCommand createRootCommand(String cmd) { + return new SpongeRootCommand(this, cmd); + } + + @Override + public Collection getRegisteredRootCommands() { + return Collections.unmodifiableCollection(registeredCommands.values()); + } + + @Override + public SpongeCommandIssuer getCommandIssuer(Object issuer) { + if (issuer instanceof SpongeCommandSource) { + return new SpongeCommandIssuer(this, (SpongeCommandSource) issuer); + } + + if (issuer instanceof CommandCause) { + return new SpongeCommandIssuer(this, new SpongeCommandSource((CommandCause) issuer)); + } + + throw new IllegalArgumentException(issuer.getClass().getName() + " is not a Command Issuer."); + } + + @Override + public SpongeCommandExecutionContext createCommandContext(RegisteredCommand command, CommandParameter parameter, CommandIssuer sender, List args, int i, Map passedArgs) { + return new SpongeCommandExecutionContext(command, parameter, (SpongeCommandIssuer) sender, args, i, passedArgs); + } + + @Override + public CommandCompletionContext createCompletionContext(RegisteredCommand command, CommandIssuer sender, String input, String config, String[] args) { + return new SpongeCommandCompletionContext(command, (SpongeCommandIssuer) sender, input, config, args); + } + + @Override + public RegisteredCommand createRegisteredCommand(BaseCommand command, String cmdName, Method method, String prefSubCommand) { + return new SpongeRegisteredCommand(command, cmdName, method, prefSubCommand); + } + + @Override + public void log(final LogLevel level, final String message, final Throwable throwable) { + Logger logger = this.plugin.logger(); + switch(level) { + case INFO: + logger.info(LogLevel.LOG_PREFIX + message); + if (throwable != null) { + for (String line : ACFPatterns.NEWLINE.split(ApacheCommonsExceptionUtil.getFullStackTrace(throwable))) { + logger.info(LogLevel.LOG_PREFIX + line); + } + } + return; + case ERROR: + logger.error(LogLevel.LOG_PREFIX + message); + if (throwable != null) { + for (String line : ACFPatterns.NEWLINE.split(ApacheCommonsExceptionUtil.getFullStackTrace(throwable))) { + logger.error(LogLevel.LOG_PREFIX + line); + } + } + } + } + + @Override + CommandOperationContext createCommandOperationContext(BaseCommand command, CommandIssuer issuer, String commandLabel, String[] args, boolean isAsync) { + return new SpongeCommandOperationContext( + this, + issuer, + command, + commandLabel, + args, + isAsync + ); + } + + @Override + public SpongeConditionContext createConditionContext(CommandIssuer issuer, String config) { + return new SpongeConditionContext((SpongeCommandIssuer) issuer, config); + } + + @Override + public Locale getIssuerLocale(CommandIssuer issuer) { + if (usingPerIssuerLocale() && issuer != null) { + SpongeCommandIssuer spongeIssuer = (SpongeCommandIssuer) issuer; + return spongeIssuer.getIssuer().locale(); + } + + return getLocales().getDefaultLocale(); + } + + @Override + public Locale setIssuerLocale(SpongeCommandSource issuer, Locale locale) { + throw new UnsupportedOperationException("You can't set a locale as they are resolved at command execution."); + } + + @Override + public String getCommandPrefix(CommandIssuer issuer) { + return issuer.isPlayer() ? "/" : ""; + } +} diff --git a/sponge10/src/main/java/co/aikar/commands/SpongeCommandOperationContext.java b/sponge10/src/main/java/co/aikar/commands/SpongeCommandOperationContext.java new file mode 100644 index 000000000..aefe6848a --- /dev/null +++ b/sponge10/src/main/java/co/aikar/commands/SpongeCommandOperationContext.java @@ -0,0 +1,18 @@ +package co.aikar.commands; + +import org.spongepowered.api.command.CommandResult; + +public class SpongeCommandOperationContext extends CommandOperationContext { + private CommandResult result = CommandResult.success(); + SpongeCommandOperationContext(CommandManager manager, CommandIssuer issuer, BaseCommand command, String commandLabel, String[] args, boolean isAsync) { + super(manager, issuer, command, commandLabel, args, isAsync); + } + + public CommandResult getResult() { + return result; + } + + public void setResult(CommandResult result) { + this.result = result; + } +} diff --git a/sponge10/src/main/java/co/aikar/commands/SpongeCommandSource.java b/sponge10/src/main/java/co/aikar/commands/SpongeCommandSource.java new file mode 100644 index 000000000..de62c90d1 --- /dev/null +++ b/sponge10/src/main/java/co/aikar/commands/SpongeCommandSource.java @@ -0,0 +1,96 @@ +package co.aikar.commands; + +import net.kyori.adventure.audience.Audience; +import net.kyori.adventure.identity.Identified; +import net.kyori.adventure.identity.Identity; +import net.kyori.adventure.text.Component; +import org.spongepowered.api.block.BlockSnapshot; +import org.spongepowered.api.command.CommandCause; +import org.spongepowered.api.command.parameter.CommandContext; +import org.spongepowered.api.event.Cause; +import org.spongepowered.api.service.permission.Subject; +import org.spongepowered.api.util.locale.LocaleSource; +import org.spongepowered.api.util.locale.Locales; +import org.spongepowered.api.world.server.ServerLocation; +import org.spongepowered.math.vector.Vector3d; + +import java.util.Locale; +import java.util.Optional; + +public class SpongeCommandSource implements LocaleSource, CommandCause { + private CommandCause commandCause; + private LocaleSource localeSource; + + public SpongeCommandSource(CommandContext commandContext) { + commandCause = commandContext.cause(); + Subject subject = commandContext.subject(); + if (subject instanceof LocaleSource) { + localeSource = (LocaleSource) subject; + } else { + localeSource = null; + } + } + + public SpongeCommandSource(T obj) { + if (obj instanceof CommandCause) { + commandCause = (CommandCause) obj; + } + + if (obj instanceof LocaleSource) { + localeSource = (LocaleSource) obj; + } + } + + @Override + public Locale locale() { + if (localeSource == null) { + return Locales.DEFAULT; + } + return localeSource.locale(); + } + + @Override + public Cause cause() { + return commandCause.cause(); + } + + @Override + public Subject subject() { + return commandCause.subject(); + } + + @Override + public Audience audience() { + return commandCause.audience(); + } + + @Override + public Optional location() { + return commandCause.location(); + } + + @Override + public Optional rotation() { + return commandCause.rotation(); + } + + @Override + public Optional targetBlock() { + return commandCause.targetBlock(); + } + + @Override + public void sendMessage(Component message) { + commandCause.sendMessage(message); + } + + @Override + public void sendMessage(Identified source, Component message) { + commandCause.sendMessage(source, message); + } + + @Override + public void sendMessage(Identity source, Component message) { + commandCause.sendMessage(source, message); + } +} diff --git a/sponge10/src/main/java/co/aikar/commands/SpongeConditionContext.java b/sponge10/src/main/java/co/aikar/commands/SpongeConditionContext.java new file mode 100644 index 000000000..7548625a6 --- /dev/null +++ b/sponge10/src/main/java/co/aikar/commands/SpongeConditionContext.java @@ -0,0 +1,18 @@ +package co.aikar.commands; + +import org.spongepowered.api.entity.living.player.Player; + +public class SpongeConditionContext extends ConditionContext { + SpongeConditionContext(SpongeCommandIssuer issuer, String config) { + super(issuer, config); + } + + + public SpongeCommandSource getSource() { + return getIssuer().getIssuer(); + } + + public Player getPlayer() { + return getIssuer().getPlayer(); + } +} diff --git a/sponge10/src/main/java/co/aikar/commands/SpongeLocales.java b/sponge10/src/main/java/co/aikar/commands/SpongeLocales.java new file mode 100644 index 000000000..030cddddd --- /dev/null +++ b/sponge10/src/main/java/co/aikar/commands/SpongeLocales.java @@ -0,0 +1,20 @@ +package co.aikar.commands; + +import java.util.Locale; + +public class SpongeLocales extends Locales{ + private final SpongeCommandManager manager; + + public SpongeLocales(SpongeCommandManager manager) { + super(manager); + this.manager = manager; + this.addBundleClassLoader(this.manager.getPlugin().getClass().getClassLoader()); + } + + @Override + public void loadLanguages() { + super.loadLanguages(); + String pluginName = "acf-" + manager.plugin.metadata().name(); + addMessageBundles("acf-minecraft", pluginName, pluginName.toLowerCase(Locale.ENGLISH)); + } +} diff --git a/sponge10/src/main/java/co/aikar/commands/SpongeMessageFormatter.java b/sponge10/src/main/java/co/aikar/commands/SpongeMessageFormatter.java new file mode 100644 index 000000000..0bf4baa90 --- /dev/null +++ b/sponge10/src/main/java/co/aikar/commands/SpongeMessageFormatter.java @@ -0,0 +1,16 @@ +package co.aikar.commands; + +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.TextColor; +import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; + +public class SpongeMessageFormatter extends MessageFormatter { + + public SpongeMessageFormatter(TextColor... colors) { + super(colors); + } + + public String format(TextColor color, String message) { + return LegacyComponentSerializer.legacyAmpersand().serialize(Component.text(message).color(color)); + } +} diff --git a/sponge10/src/main/java/co/aikar/commands/SpongeRegisteredCommand.java b/sponge10/src/main/java/co/aikar/commands/SpongeRegisteredCommand.java new file mode 100644 index 000000000..b054af314 --- /dev/null +++ b/sponge10/src/main/java/co/aikar/commands/SpongeRegisteredCommand.java @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package co.aikar.commands; + +import java.lang.reflect.Method; + +public class SpongeRegisteredCommand extends RegisteredCommand { + SpongeRegisteredCommand(BaseCommand scope, String command, Method method, String prefSubCommand) { + super(scope, command, method, prefSubCommand); + } + +} diff --git a/sponge10/src/main/java/co/aikar/commands/SpongeRootCommand.java b/sponge10/src/main/java/co/aikar/commands/SpongeRootCommand.java new file mode 100644 index 000000000..7a6302b24 --- /dev/null +++ b/sponge10/src/main/java/co/aikar/commands/SpongeRootCommand.java @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package co.aikar.commands; + +import com.google.common.collect.HashMultimap; +import com.google.common.collect.SetMultimap; +import net.kyori.adventure.text.Component; +import org.spongepowered.api.command.Command; +import org.spongepowered.api.command.CommandCause; +import org.spongepowered.api.command.CommandCompletion; +import org.spongepowered.api.command.CommandResult; +import org.spongepowered.api.command.exception.CommandException; +import org.spongepowered.api.command.parameter.ArgumentReader; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Optional; +import java.util.Set; +import java.util.stream.Collectors; + +import static net.kyori.adventure.text.Component.text; + +public class SpongeRootCommand implements Command.Raw, RootCommand { + + private final SpongeCommandManager manager; + private final String name; + private BaseCommand defCommand; + private SetMultimap subCommands = HashMultimap.create(); + private List children = new ArrayList<>(); + boolean isRegistered = false; + + SpongeRootCommand(SpongeCommandManager manager, String name) { + this.manager = manager; + this.name = name; + } + + @Override + public String getCommandName() { + return name; + } + + private CommandResult executeSponge(CommandIssuer sender, String commandLabel, String[] args) { + BaseCommand cmd = execute(sender, commandLabel, args); + SpongeCommandOperationContext lastContext = (SpongeCommandOperationContext) cmd.getLastCommandOperationContext(); + return lastContext != null ? lastContext.getResult() : CommandResult.success(); + } + + public void addChild(BaseCommand command) { + if (this.defCommand == null || !command.subCommands.get(BaseCommand.DEFAULT).isEmpty()) { + this.defCommand = command; + } + addChildShared(this.children, this.subCommands, command); + } + + @Override + public BaseCommand getDefCommand() { + return defCommand; + } + + @Override + public CommandManager getManager() { + return manager; + } + + @Override + public SetMultimap getSubCommands() { + return subCommands; + } + + @Override + public List getChildren() { + return children; + } + + @Override + public CommandResult process(CommandCause cause, ArgumentReader.Mutable arguments) throws CommandException { + String[] args = argToStrlist(arguments); + return this.executeSponge(manager.getCommandIssuer(cause), this.name, args); + } + + @Override + public List complete(CommandCause cause, ArgumentReader.Mutable arguments) throws CommandException { + String[] args = argToStrlist(arguments); + return getTabCompletions(manager.getCommandIssuer(cause), this.name, args).stream().map(it -> new CommandCompletion() { + @Override + public String completion() { + return it; + } + + @Override + public Optional tooltip() { + return Optional.empty(); + } + }).collect(Collectors.toList()); + } + + @Override + public List getTabCompletions(CommandIssuer sender, String alias, String[] args, boolean commandsOnly, boolean isAsync) { + Set completions = new HashSet<>(); + getChildren().forEach(child -> { + if (!commandsOnly) { + completions.addAll(child.tabComplete(sender, this, args, isAsync)); + } + completions.addAll(child.getCommandsForCompletion(sender, args)); + }); + + return completions.stream() + .filter(it -> Arrays + .stream(args) + .noneMatch(it::equals)) + .collect(Collectors.toList()); + } + + @Override + public boolean canExecute(CommandCause cause) { + return this.hasAnyPermission(manager.getCommandIssuer(cause)); + } + + @Override + public Optional shortDescription(CommandCause cause) { + String description = getDescription(); + return description != null ? Optional.of(text(description)) : Optional.empty(); + } + + @Override + public Optional extendedDescription(CommandCause cause) { + return Optional.empty(); + } + + @Override + public Component usage(CommandCause cause) { + String usage = getUsage(); + return usage != null ? text(usage) : text(""); + } + + private String[] argToStrlist(ArgumentReader.Mutable arguments) { + return Arrays.stream(arguments.input().split(" ")) + .filter(string -> (!string.isEmpty())) + .toArray(String[]::new); + } +} diff --git a/sponge10/src/main/java/co/aikar/commands/contexts/CommandResultSupplier.java b/sponge10/src/main/java/co/aikar/commands/contexts/CommandResultSupplier.java new file mode 100644 index 000000000..30b155e76 --- /dev/null +++ b/sponge10/src/main/java/co/aikar/commands/contexts/CommandResultSupplier.java @@ -0,0 +1,19 @@ +package co.aikar.commands.contexts; + +import co.aikar.commands.CommandManager; +import co.aikar.commands.SpongeCommandOperationContext; +import org.spongepowered.api.command.CommandResult; + +import java.util.function.Consumer; + +public class CommandResultSupplier implements Consumer { + + public CommandResultSupplier() { + } + + @Override + public void accept(CommandResult commandResult) { + SpongeCommandOperationContext context = (SpongeCommandOperationContext) CommandManager.getCurrentCommandOperationContext(); + context.setResult(commandResult); + } +} diff --git a/sponge10/src/main/java/co/aikar/commands/contexts/OnlinePlayer.java b/sponge10/src/main/java/co/aikar/commands/contexts/OnlinePlayer.java new file mode 100644 index 000000000..f36053984 --- /dev/null +++ b/sponge10/src/main/java/co/aikar/commands/contexts/OnlinePlayer.java @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2016-2019 Daniel Ennis (Aikar) - MIT License + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package co.aikar.commands.contexts; + +import org.spongepowered.api.entity.living.player.Player; + +/** + * @deprecated Use {@link co.aikar.commands.sponge.contexts.OnlinePlayer instead} + */ +@Deprecated +public class OnlinePlayer extends co.aikar.commands.sponge.contexts.OnlinePlayer { + public OnlinePlayer(Player player) { + super(player); + } +} diff --git a/sponge10/src/main/java/co/aikar/commands/sponge/contexts/OnlinePlayer.java b/sponge10/src/main/java/co/aikar/commands/sponge/contexts/OnlinePlayer.java new file mode 100644 index 000000000..7cb5ee497 --- /dev/null +++ b/sponge10/src/main/java/co/aikar/commands/sponge/contexts/OnlinePlayer.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package co.aikar.commands.sponge.contexts; + +import org.spongepowered.api.entity.living.player.Player; + +import java.util.Objects; + +public class OnlinePlayer { + public final Player player; + + public OnlinePlayer(Player player) { + this.player = player; + } + + public Player getPlayer() { + return this.player; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + OnlinePlayer that = (OnlinePlayer) o; + return Objects.equals(player, that.player); + } + + @Override + public int hashCode() { + return Objects.hash(player); + } + + @Override + public String toString() { + return "OnlinePlayer{player=" + player + '}'; + } +}