/* * Decompiled with CFR 0.152. * * Could not load the following classes: * com.google.common.collect.Lists * com.mojang.brigadier.context.CommandContext * com.mojang.brigadier.suggestion.Suggestions * com.mojang.brigadier.suggestion.SuggestionsBuilder * org.jspecify.annotations.Nullable */ package net.minecraft.client.multiplayer; import com.google.common.collect.Lists; import com.mojang.brigadier.context.CommandContext; import com.mojang.brigadier.suggestion.Suggestions; import com.mojang.brigadier.suggestion.SuggestionsBuilder; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Locale; import java.util.Set; import java.util.concurrent.CompletableFuture; import java.util.stream.Stream; import net.minecraft.client.Minecraft; import net.minecraft.client.multiplayer.ClientPacketListener; import net.minecraft.client.multiplayer.PlayerInfo; import net.minecraft.commands.SharedSuggestionProvider; import net.minecraft.core.BlockPos; import net.minecraft.core.HolderLookup; import net.minecraft.core.Registry; import net.minecraft.core.RegistryAccess; import net.minecraft.network.protocol.game.ClientboundCustomChatCompletionsPacket; import net.minecraft.network.protocol.game.ServerboundCommandSuggestionPacket; import net.minecraft.resources.Identifier; import net.minecraft.resources.ResourceKey; import net.minecraft.server.permissions.PermissionSet; import net.minecraft.world.flag.FeatureFlagSet; import net.minecraft.world.level.Level; import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.EntityHitResult; import net.minecraft.world.phys.HitResult; import net.minecraft.world.phys.Vec3; import org.jspecify.annotations.Nullable; public class ClientSuggestionProvider implements SharedSuggestionProvider { private final ClientPacketListener connection; private final Minecraft minecraft; private int pendingSuggestionsId = -1; private @Nullable CompletableFuture pendingSuggestionsFuture; private final Set customCompletionSuggestions = new HashSet(); private final PermissionSet permissions; public ClientSuggestionProvider(ClientPacketListener connection, Minecraft minecraft, PermissionSet permissions) { this.connection = connection; this.minecraft = minecraft; this.permissions = permissions; } @Override public Collection getOnlinePlayerNames() { ArrayList result = Lists.newArrayList(); for (PlayerInfo info : this.connection.getOnlinePlayers()) { result.add(info.getProfile().name()); } return result; } @Override public Collection getCustomTabSugggestions() { if (this.customCompletionSuggestions.isEmpty()) { return this.getOnlinePlayerNames(); } HashSet result = new HashSet(this.getOnlinePlayerNames()); result.addAll(this.customCompletionSuggestions); return result; } @Override public Collection getSelectedEntities() { if (this.minecraft.hitResult != null && this.minecraft.hitResult.getType() == HitResult.Type.ENTITY) { return Collections.singleton(((EntityHitResult)this.minecraft.hitResult).getEntity().getStringUUID()); } return Collections.emptyList(); } @Override public Collection getAllTeams() { return this.connection.scoreboard().getTeamNames(); } @Override public Stream getAvailableSounds() { return this.minecraft.getSoundManager().getAvailableSounds().stream(); } @Override public PermissionSet permissions() { return this.permissions; } @Override public CompletableFuture suggestRegistryElements(ResourceKey> key, SharedSuggestionProvider.ElementSuggestionType elements, SuggestionsBuilder builder, CommandContext context) { return this.registryAccess().lookup(key).map(registry -> { this.suggestRegistryElements((HolderLookup)registry, elements, builder); return builder.buildFuture(); }).orElseGet(() -> this.customSuggestion(context)); } @Override public CompletableFuture customSuggestion(CommandContext context) { if (this.pendingSuggestionsFuture != null) { this.pendingSuggestionsFuture.cancel(false); } this.pendingSuggestionsFuture = new CompletableFuture(); int id = ++this.pendingSuggestionsId; this.connection.send(new ServerboundCommandSuggestionPacket(id, context.getInput())); return this.pendingSuggestionsFuture; } private static String prettyPrint(double value) { return String.format(Locale.ROOT, "%.2f", value); } private static String prettyPrint(int value) { return Integer.toString(value); } @Override public Collection getRelevantCoordinates() { HitResult hitResult = this.minecraft.hitResult; if (hitResult == null || hitResult.getType() != HitResult.Type.BLOCK) { return SharedSuggestionProvider.super.getRelevantCoordinates(); } BlockPos pos = ((BlockHitResult)hitResult).getBlockPos(); return Collections.singleton(new SharedSuggestionProvider.TextCoordinates(ClientSuggestionProvider.prettyPrint(pos.getX()), ClientSuggestionProvider.prettyPrint(pos.getY()), ClientSuggestionProvider.prettyPrint(pos.getZ()))); } @Override public Collection getAbsoluteCoordinates() { HitResult hitResult = this.minecraft.hitResult; if (hitResult == null || hitResult.getType() != HitResult.Type.BLOCK) { return SharedSuggestionProvider.super.getAbsoluteCoordinates(); } Vec3 pos = hitResult.getLocation(); return Collections.singleton(new SharedSuggestionProvider.TextCoordinates(ClientSuggestionProvider.prettyPrint(pos.x), ClientSuggestionProvider.prettyPrint(pos.y), ClientSuggestionProvider.prettyPrint(pos.z))); } @Override public Set> levels() { return this.connection.levels(); } @Override public RegistryAccess registryAccess() { return this.connection.registryAccess(); } @Override public FeatureFlagSet enabledFeatures() { return this.connection.enabledFeatures(); } public void completeCustomSuggestions(int id, Suggestions result) { if (id == this.pendingSuggestionsId) { this.pendingSuggestionsFuture.complete(result); this.pendingSuggestionsFuture = null; this.pendingSuggestionsId = -1; } } public void modifyCustomCompletions(ClientboundCustomChatCompletionsPacket.Action action, List entries) { switch (action) { case ADD: { this.customCompletionSuggestions.addAll(entries); break; } case REMOVE: { entries.forEach(this.customCompletionSuggestions::remove); break; } case SET: { this.customCompletionSuggestions.clear(); this.customCompletionSuggestions.addAll(entries); } } } }