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
115
116
|
package dev.isxander.yacl3.gui.utils;
import net.minecraft.ResourceLocationException;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.Items;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;
import java.util.Comparator;
import java.util.HashSet;
import java.util.Set;
import java.util.function.Predicate;
import java.util.stream.Stream;
public final class ItemRegistryHelper {
/**
* Checks whether the given string is an identifier referring to a known item
*
* @param identifier Item identifier, either of the format "namespace:path" or "path". If no namespace is included,
* the default vanilla namespace "minecraft" is used.
* @return true if the identifier refers to a registered item, false otherwise
*/
public static boolean isRegisteredItem(String identifier) {
try {
ResourceLocation itemIdentifier = new ResourceLocation(identifier.toLowerCase());
return BuiltInRegistries.ITEM.containsKey(itemIdentifier);
} catch (ResourceLocationException e) {
return false;
}
}
/**
* Looks up the item of the given identifier string.
*
* @param identifier Item identifier, either of the format "namespace:path" or "path". If no namespace is included,
* the default vanilla namespace "minecraft" is used.
* @param defaultItem Fallback item that gets returned if the identifier does not name a registered item.
* @return The item identified by the given string, or the fallback if the identifier is not known.
*/
public static Item getItemFromName(String identifier, Item defaultItem) {
try {
ResourceLocation itemIdentifier = new ResourceLocation(identifier.toLowerCase());
if (BuiltInRegistries.ITEM.containsKey(itemIdentifier)) {
return BuiltInRegistries.ITEM.get(itemIdentifier);
}
} catch (ResourceLocationException ignored) {
}
return defaultItem;
}
/**
* Looks up the item of the given identifier string.
*
* @param identifier Item identifier, either of the format "namespace:path" or "path". If no namespace is included,
* the default vanilla namespace "minecraft" is used.
* @return The item identified by the given string, or `Items.AIR` if the identifier is not known.
*/
public static Item getItemFromName(String identifier) {
return getItemFromName(identifier, Items.AIR);
}
/**
* Returns a list of item identifiers matching the given string. The value matches an identifier if:
* <li>No namespace is provided in the value and the value is a substring of the path segment of any identifier,
* regardless of namespace.</li>
* <li>A namespace is provided, equals the identifier's namespace, and the value is the begin of the identifier's
* path segment.</li>
*
* @param value (partial) identifier, either of the format "namespace:path" or "path".
* @return list of matching item identifiers; empty if the given string does not correspond to any known identifiers
*/
public static Stream<ResourceLocation> getMatchingItemIdentifiers(String value) {
int sep = value.indexOf(ResourceLocation.NAMESPACE_SEPARATOR);
Predicate<ResourceLocation> filterPredicate;
if (sep == -1) {
filterPredicate = identifier ->
identifier.getPath().contains(value)
|| BuiltInRegistries.ITEM.get(identifier).getDescription().getString().toLowerCase().contains(value.toLowerCase());
} else {
String namespace = value.substring(0, sep);
String path = value.substring(sep + 1);
filterPredicate = identifier -> identifier.getNamespace().equals(namespace) && identifier.getPath().startsWith(path);
}
return BuiltInRegistries.ITEM.holders()
.map(holder -> holder.key().location())
.filter(filterPredicate)
/*
Sort items as follows based on the given "value" string's path:
- if both items' paths begin with the entered string, sort the identifiers (including namespace)
- otherwise, if either of the items' path begins with the entered string, sort it to the left
- else neither path matches: sort by identifiers again
This allows the user to enter "diamond_ore" and match "minecraft:diamond_ore" before
"minecraft:deepslate_diamond_ore", even though the second is lexicographically smaller
*/
.sorted((id1, id2) -> {
String path = (sep == -1 ? value : value.substring(sep + 1)).toLowerCase();
boolean id1StartsWith = id1.getPath().toLowerCase().startsWith(path);
boolean id2StartsWith = id2.getPath().toLowerCase().startsWith(path);
if (id1StartsWith) {
if (id2StartsWith) {
return id1.compareTo(id2);
}
return -1;
}
if (id2StartsWith) {
return 1;
}
return id1.compareTo(id2);
});
}
}
|