forked from John-Paul-R/Essential-Commands
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathNicknameTargetResolver.java
More file actions
114 lines (98 loc) · 4.33 KB
/
Copy pathNicknameTargetResolver.java
File metadata and controls
114 lines (98 loc) · 4.33 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
package com.fibermc.essentialcommands.commands;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import com.fibermc.essentialcommands.access.EntitySelectorNicknameAccess;
import com.fibermc.essentialcommands.playerdata.PlayerData;
import com.fibermc.essentialcommands.playerdata.PlayerDataManager;
import com.fibermc.essentialcommands.types.NicknameCommandArgMode;
import com.mojang.brigadier.builder.RequiredArgumentBuilder;
import com.mojang.brigadier.context.CommandContext;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import com.mojang.brigadier.suggestion.Suggestions;
import com.mojang.brigadier.suggestion.SuggestionsBuilder;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.commands.Commands;
import net.minecraft.commands.arguments.EntityArgument;
import net.minecraft.commands.arguments.selector.EntitySelector;
import net.minecraft.network.chat.Component;
import net.minecraft.server.level.ServerPlayer;
import static com.fibermc.essentialcommands.EssentialCommands.CONFIG;
/**
* Adds optional nickname fallback on top of Minecraft's normal player
* argument handling. Vanilla resolution is always attempted first.
*/
public final class NicknameTargetResolver {
private NicknameTargetResolver() {}
public static RequiredArgumentBuilder<CommandSourceStack, EntitySelector> targetPlayerArgument() {
return Commands.argument("target_player", EntityArgument.player())
.suggests(NicknameTargetResolver::suggestPlayers);
}
public static RequiredArgumentBuilder<CommandSourceStack, EntitySelector> targetPlayerArgumentNonGreedy() {
return targetPlayerArgument();
}
private static CompletableFuture<Suggestions> suggestPlayers(
CommandContext<CommandSourceStack> context,
SuggestionsBuilder builder
) throws CommandSyntaxException {
if (CONFIG.NICKNAMES_AS_COMMAND_ARG != NicknameCommandArgMode.Never) {
addNicknameSuggestions(builder);
}
return EntityArgument.player().listSuggestions(context, builder);
}
public static void addNicknameSuggestions(SuggestionsBuilder builder) {
if (!PlayerDataManager.exists()) {
return;
}
String remaining = PlayerData.normalizeNickname(builder.getRemaining());
for (PlayerData playerData : PlayerDataManager.getInstance().getAllPlayerData()) {
String normalized = playerData.getNormalizedNickname();
if (normalized == null || !normalized.startsWith(remaining)) {
continue;
}
playerData.getNickname()
.map(Component::getString)
.map(nick -> nick.replaceAll("\\s+", ""))
.filter(nick -> !nick.isBlank())
.ifPresent(builder::suggest);
}
}
public static ServerPlayer getPlayer(
CommandContext<CommandSourceStack> context,
String argumentName
) throws CommandSyntaxException {
try {
return EntityArgument.getPlayer(context, argumentName);
} catch (CommandSyntaxException vanillaFailure) {
if (CONFIG.NICKNAMES_AS_COMMAND_ARG != NicknameCommandArgMode.EssentialCommandsOnly) {
throw vanillaFailure;
}
EntitySelector selector = context.getArgument(argumentName, EntitySelector.class);
String playerName = ((EntitySelectorNicknameAccess) selector).ec$getPlayerName();
ServerPlayer nicknameMatch = resolvePlayerByNickname(playerName);
if (nicknameMatch != null) {
return nicknameMatch;
}
throw vanillaFailure;
}
}
/**
* Finds one online player whose nickname matches the literal command
* player name after normalization (whitespace removal + case folding).
*
* Returns null for no match or an ambiguous match.
*/
public static ServerPlayer resolvePlayerByNickname(String playerName) {
if (
playerName == null
|| playerName.isBlank()
) {
return null;
}
List<PlayerData> matches = PlayerDataManager.getInstance().getByNickname(playerName);
// Ambiguous (>1) or no match -- never choose one arbitrarily.
if (matches.size() != 1) {
return null;
}
return matches.getFirst().getPlayer();
}
}