package net.minecraft.commands; import com.google.common.base.CharMatcher; import com.google.common.base.Strings; import com.google.common.collect.Lists; import com.mojang.brigadier.Message; import com.mojang.brigadier.context.CommandContext; import com.mojang.brigadier.suggestion.Suggestions; import com.mojang.brigadier.suggestion.SuggestionsBuilder; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Locale; import java.util.Set; import java.util.concurrent.CompletableFuture; import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Predicate; import java.util.stream.Stream; import net.minecraft.core.Registry; import net.minecraft.core.RegistryAccess; import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.flag.FeatureFlagSet; import net.minecraft.world.level.Level; public interface SharedSuggestionProvider { CharMatcher MATCH_SPLITTER = CharMatcher.anyOf("._/"); Collection getOnlinePlayerNames(); default Collection getCustomTabSugggestions() { return this.getOnlinePlayerNames(); } default Collection getSelectedEntities() { return Collections.emptyList(); } Collection getAllTeams(); Stream getAvailableSounds(); CompletableFuture customSuggestion(CommandContext context); default Collection getRelevantCoordinates() { return Collections.singleton(SharedSuggestionProvider.TextCoordinates.DEFAULT_GLOBAL); } default Collection getAbsoluteCoordinates() { return Collections.singleton(SharedSuggestionProvider.TextCoordinates.DEFAULT_GLOBAL); } Set> levels(); RegistryAccess registryAccess(); FeatureFlagSet enabledFeatures(); default void suggestRegistryElements(Registry registry, SharedSuggestionProvider.ElementSuggestionType type, SuggestionsBuilder builder) { if (type.shouldSuggestTags()) { suggestResource(registry.getTags().map(named -> named.key().location()), builder, "#"); } if (type.shouldSuggestElements()) { suggestResource(registry.keySet(), builder); } } CompletableFuture suggestRegistryElements( ResourceKey> resourceKey, SharedSuggestionProvider.ElementSuggestionType registryKey, SuggestionsBuilder builder, CommandContext context ); boolean hasPermission(int permissionLevel); static void filterResources(Iterable resources, String input, Function locationFunction, Consumer resourceConsumer) { boolean bl = input.indexOf(58) > -1; for (T object : resources) { ResourceLocation resourceLocation = (ResourceLocation)locationFunction.apply(object); if (bl) { String string = resourceLocation.toString(); if (matchesSubStr(input, string)) { resourceConsumer.accept(object); } } else if (matchesSubStr(input, resourceLocation.getNamespace()) || resourceLocation.getNamespace().equals("minecraft") && matchesSubStr(input, resourceLocation.getPath())) { resourceConsumer.accept(object); } } } static void filterResources( Iterable resources, String remaining, String prefix, Function locationFunction, Consumer resourceConsumer ) { if (remaining.isEmpty()) { resources.forEach(resourceConsumer); } else { String string = Strings.commonPrefix(remaining, prefix); if (!string.isEmpty()) { String string2 = remaining.substring(string.length()); filterResources(resources, string2, locationFunction, resourceConsumer); } } } static CompletableFuture suggestResource(Iterable resources, SuggestionsBuilder builder, String prefix) { String string = builder.getRemaining().toLowerCase(Locale.ROOT); filterResources(resources, string, prefix, resourceLocation -> resourceLocation, resourceLocation -> builder.suggest(prefix + resourceLocation)); return builder.buildFuture(); } static CompletableFuture suggestResource(Stream resources, SuggestionsBuilder builder, String prefix) { return suggestResource(resources::iterator, builder, prefix); } static CompletableFuture suggestResource(Iterable resources, SuggestionsBuilder builder) { String string = builder.getRemaining().toLowerCase(Locale.ROOT); filterResources(resources, string, resourceLocation -> resourceLocation, resourceLocation -> builder.suggest(resourceLocation.toString())); return builder.buildFuture(); } static CompletableFuture suggestResource( Iterable resources, SuggestionsBuilder builder, Function locationFunction, Function suggestionFunction ) { String string = builder.getRemaining().toLowerCase(Locale.ROOT); filterResources( resources, string, locationFunction, object -> builder.suggest(((ResourceLocation)locationFunction.apply(object)).toString(), (Message)suggestionFunction.apply(object)) ); return builder.buildFuture(); } static CompletableFuture suggestResource(Stream resourceLocations, SuggestionsBuilder builder) { return suggestResource(resourceLocations::iterator, builder); } static CompletableFuture suggestResource( Stream resources, SuggestionsBuilder builder, Function locationFunction, Function suggestionFunction ) { return suggestResource(resources::iterator, builder, locationFunction, suggestionFunction); } static CompletableFuture suggestCoordinates( String remaining, Collection coordinates, SuggestionsBuilder builder, Predicate validator ) { List list = Lists.newArrayList(); if (Strings.isNullOrEmpty(remaining)) { for (SharedSuggestionProvider.TextCoordinates textCoordinates : coordinates) { String string = textCoordinates.x + " " + textCoordinates.y + " " + textCoordinates.z; if (validator.test(string)) { list.add(textCoordinates.x); list.add(textCoordinates.x + " " + textCoordinates.y); list.add(string); } } } else { String[] strings = remaining.split(" "); if (strings.length == 1) { for (SharedSuggestionProvider.TextCoordinates textCoordinates2 : coordinates) { String string2 = strings[0] + " " + textCoordinates2.y + " " + textCoordinates2.z; if (validator.test(string2)) { list.add(strings[0] + " " + textCoordinates2.y); list.add(string2); } } } else if (strings.length == 2) { for (SharedSuggestionProvider.TextCoordinates textCoordinates2x : coordinates) { String string2 = strings[0] + " " + strings[1] + " " + textCoordinates2x.z; if (validator.test(string2)) { list.add(string2); } } } } return suggest(list, builder); } static CompletableFuture suggest2DCoordinates( String remaining, Collection coordinates, SuggestionsBuilder builder, Predicate validator ) { List list = Lists.newArrayList(); if (Strings.isNullOrEmpty(remaining)) { for (SharedSuggestionProvider.TextCoordinates textCoordinates : coordinates) { String string = textCoordinates.x + " " + textCoordinates.z; if (validator.test(string)) { list.add(textCoordinates.x); list.add(string); } } } else { String[] strings = remaining.split(" "); if (strings.length == 1) { for (SharedSuggestionProvider.TextCoordinates textCoordinates2 : coordinates) { String string2 = strings[0] + " " + textCoordinates2.z; if (validator.test(string2)) { list.add(string2); } } } } return suggest(list, builder); } static CompletableFuture suggest(Iterable strings, SuggestionsBuilder builder) { String string = builder.getRemaining().toLowerCase(Locale.ROOT); for (String string2 : strings) { if (matchesSubStr(string, string2.toLowerCase(Locale.ROOT))) { builder.suggest(string2); } } return builder.buildFuture(); } static CompletableFuture suggest(Stream strings, SuggestionsBuilder builder) { String string = builder.getRemaining().toLowerCase(Locale.ROOT); strings.filter(string2 -> matchesSubStr(string, string2.toLowerCase(Locale.ROOT))).forEach(builder::suggest); return builder.buildFuture(); } static CompletableFuture suggest(String[] strings, SuggestionsBuilder builder) { String string = builder.getRemaining().toLowerCase(Locale.ROOT); for (String string2 : strings) { if (matchesSubStr(string, string2.toLowerCase(Locale.ROOT))) { builder.suggest(string2); } } return builder.buildFuture(); } static CompletableFuture suggest( Iterable resources, SuggestionsBuilder builder, Function stringFunction, Function suggestionFunction ) { String string = builder.getRemaining().toLowerCase(Locale.ROOT); for (T object : resources) { String string2 = (String)stringFunction.apply(object); if (matchesSubStr(string, string2.toLowerCase(Locale.ROOT))) { builder.suggest(string2, (Message)suggestionFunction.apply(object)); } } return builder.buildFuture(); } static boolean matchesSubStr(String input, String substring) { int i = 0; while (!substring.startsWith(input, i)) { int j = MATCH_SPLITTER.indexIn(substring, i); if (j < 0) { return false; } i = j + 1; } return true; } public static enum ElementSuggestionType { TAGS, ELEMENTS, ALL; public boolean shouldSuggestTags() { return this == TAGS || this == ALL; } public boolean shouldSuggestElements() { return this == ELEMENTS || this == ALL; } } public static class TextCoordinates { public static final SharedSuggestionProvider.TextCoordinates DEFAULT_LOCAL = new SharedSuggestionProvider.TextCoordinates("^", "^", "^"); public static final SharedSuggestionProvider.TextCoordinates DEFAULT_GLOBAL = new SharedSuggestionProvider.TextCoordinates("~", "~", "~"); public final String x; public final String y; public final String z; public TextCoordinates(String x, String y, String z) { this.x = x; this.y = y; this.z = z; } } }