1
1
package org .bukkit .inventory ;
2
2
3
3
import com .google .common .base .Preconditions ;
4
+ import io .papermc .paper .registry .RegistryKey ;
5
+ import io .papermc .paper .registry .TypedKey ;
6
+ import io .papermc .paper .registry .set .RegistryKeySet ;
7
+ import io .papermc .paper .registry .tag .TagKey ;
4
8
import java .util .ArrayList ;
5
9
import java .util .Arrays ;
6
10
import java .util .Collections ;
11
15
import org .bukkit .Material ;
12
16
import org .bukkit .Tag ;
13
17
import org .bukkit .material .MaterialData ;
14
- import org .jetbrains .annotations .NotNull ;
18
+ import org .jetbrains .annotations .ApiStatus ;
19
+ import org .jetbrains .annotations .Contract ;
20
+ import org .jspecify .annotations .NullMarked ;
15
21
16
22
/**
17
23
* Represents a potential item match within a recipe. All choices within a
20
26
*
21
27
* <b>This class is not legal for implementation by plugins!</b>
22
28
*/
29
+ @ NullMarked
30
+ @ ApiStatus .NonExtendable
23
31
public interface RecipeChoice extends Predicate <ItemStack >, Cloneable {
24
32
25
- // Paper start - add "empty" choice
26
33
/**
27
34
* An "empty" recipe choice. Only valid as a recipe choice in
28
35
* specific places. Check the javadocs of a method before using it
29
36
* to be sure it's valid for that recipe and ingredient type.
30
37
*
31
38
* @return the empty recipe choice
32
39
*/
33
- static @ NotNull RecipeChoice empty () {
40
+ static RecipeChoice empty () {
34
41
return EmptyRecipeChoice .INSTANCE ;
35
42
}
36
- // Paper end
43
+
44
+ /**
45
+ * Creates a new recipe choice based on a {@link RegistryKeySet} of item types.
46
+ * Can either be created via {@link RegistryKeySet#keySet(RegistryKey, TypedKey[])}
47
+ * or obtained from {@link org.bukkit.Registry#getTag(TagKey)}.
48
+ *
49
+ * @param itemTypes the item types to match
50
+ * @return a new recipe choice
51
+ */
52
+ @ Contract (pure = true , value = "_ -> new" )
53
+ @ ApiStatus .Experimental
54
+ static ItemTypeChoice itemType (final RegistryKeySet <ItemType > itemTypes ) {
55
+ return new ItemTypeRecipeChoiceImpl (itemTypes );
56
+ }
37
57
38
58
/**
39
59
* Gets a single item stack representative of this stack choice.
@@ -42,34 +62,32 @@ public interface RecipeChoice extends Predicate<ItemStack>, Cloneable {
42
62
* @deprecated for compatibility only
43
63
*/
44
64
@ Deprecated (since = "1.13.1" )
45
- @ NotNull
46
65
ItemStack getItemStack ();
47
66
48
- @ NotNull
49
67
RecipeChoice clone ();
50
68
51
69
@ Override
52
- boolean test (@ NotNull ItemStack itemStack );
70
+ boolean test (ItemStack itemStack );
53
71
54
72
// Paper start - check valid ingredients
55
73
@ org .jetbrains .annotations .ApiStatus .Internal
56
- default @ NotNull RecipeChoice validate (final boolean allowEmptyRecipes ) {
74
+ default RecipeChoice validate (final boolean allowEmptyRecipes ) {
57
75
return this ;
58
76
}
59
77
// Paper end - check valid ingredients
60
78
61
79
/**
62
80
* Represents a choice of multiple matching Materials.
63
81
*/
64
- public static class MaterialChoice implements RecipeChoice {
82
+ final class MaterialChoice implements RecipeChoice {
65
83
66
84
private List <Material > choices ;
67
85
68
- public MaterialChoice (@ NotNull Material choice ) {
86
+ public MaterialChoice (Material choice ) {
69
87
this (Arrays .asList (choice ));
70
88
}
71
89
72
- public MaterialChoice (@ NotNull Material ... choices ) {
90
+ public MaterialChoice (Material ... choices ) {
73
91
this (Arrays .asList (choices ));
74
92
}
75
93
@@ -79,11 +97,11 @@ public MaterialChoice(@NotNull Material... choices) {
79
97
*
80
98
* @param choices the tag
81
99
*/
82
- public MaterialChoice (@ NotNull Tag <Material > choices ) {
100
+ public MaterialChoice (Tag <Material > choices ) {
83
101
this (new ArrayList <>(java .util .Objects .requireNonNull (choices , "Cannot create a material choice with null tag" ).getValues ())); // Paper - delegate to list ctor to make sure all checks are called
84
102
}
85
103
86
- public MaterialChoice (@ NotNull List <Material > choices ) {
104
+ public MaterialChoice (List <Material > choices ) {
87
105
Preconditions .checkArgument (choices != null , "choices" );
88
106
Preconditions .checkArgument (!choices .isEmpty (), "Must have at least one choice" );
89
107
@@ -103,7 +121,7 @@ public MaterialChoice(@NotNull List<Material> choices) {
103
121
}
104
122
105
123
@ Override
106
- public boolean test (@ NotNull ItemStack t ) {
124
+ public boolean test (ItemStack t ) {
107
125
for (Material match : choices ) {
108
126
if (t .getType () == match ) {
109
127
return true ;
@@ -113,7 +131,6 @@ public boolean test(@NotNull ItemStack t) {
113
131
return false ;
114
132
}
115
133
116
- @ NotNull
117
134
@ Override
118
135
public ItemStack getItemStack () {
119
136
ItemStack stack = new ItemStack (choices .get (0 ));
@@ -126,12 +143,10 @@ public ItemStack getItemStack() {
126
143
return stack ;
127
144
}
128
145
129
- @ NotNull
130
146
public List <Material > getChoices () {
131
147
return Collections .unmodifiableList (choices );
132
148
}
133
149
134
- @ NotNull
135
150
@ Override
136
151
public MaterialChoice clone () {
137
152
try {
@@ -175,7 +190,7 @@ public String toString() {
175
190
176
191
// Paper start - check valid ingredients
177
192
@ Override
178
- public @ NotNull RecipeChoice validate (final boolean allowEmptyRecipes ) {
193
+ public RecipeChoice validate (final boolean allowEmptyRecipes ) {
179
194
if (this .choices .stream ().anyMatch (Material ::isAir )) {
180
195
throw new IllegalArgumentException ("RecipeChoice.MaterialChoice cannot contain air" );
181
196
}
@@ -188,19 +203,19 @@ public String toString() {
188
203
* Represents a choice that will be valid only if one of the stacks is
189
204
* exactly matched (aside from stack size).
190
205
*/
191
- public static class ExactChoice implements RecipeChoice {
206
+ final class ExactChoice implements RecipeChoice {
192
207
193
208
private List <ItemStack > choices ;
194
209
195
- public ExactChoice (@ NotNull ItemStack stack ) {
210
+ public ExactChoice (ItemStack stack ) {
196
211
this (Arrays .asList (stack ));
197
212
}
198
213
199
- public ExactChoice (@ NotNull ItemStack ... stacks ) {
214
+ public ExactChoice (ItemStack ... stacks ) {
200
215
this (Arrays .asList (stacks ));
201
216
}
202
217
203
- public ExactChoice (@ NotNull List <ItemStack > choices ) {
218
+ public ExactChoice (List <ItemStack > choices ) {
204
219
Preconditions .checkArgument (choices != null , "choices" );
205
220
Preconditions .checkArgument (!choices .isEmpty (), "Must have at least one choice" );
206
221
for (ItemStack choice : choices ) {
@@ -211,18 +226,15 @@ public ExactChoice(@NotNull List<ItemStack> choices) {
211
226
this .choices = new ArrayList <>(choices );
212
227
}
213
228
214
- @ NotNull
215
229
@ Override
216
230
public ItemStack getItemStack () {
217
231
return choices .get (0 ).clone ();
218
232
}
219
233
220
- @ NotNull
221
234
public List <ItemStack > getChoices () {
222
235
return Collections .unmodifiableList (choices );
223
236
}
224
237
225
- @ NotNull
226
238
@ Override
227
239
public ExactChoice clone () {
228
240
try {
@@ -240,7 +252,7 @@ public ExactChoice clone() {
240
252
}
241
253
242
254
@ Override
243
- public boolean test (@ NotNull ItemStack t ) {
255
+ public boolean test (ItemStack t ) {
244
256
for (ItemStack match : choices ) {
245
257
if (t .isSimilar (match )) {
246
258
return true ;
@@ -282,12 +294,29 @@ public String toString() {
282
294
283
295
// Paper start - check valid ingredients
284
296
@ Override
285
- public @ NotNull RecipeChoice validate (final boolean allowEmptyRecipes ) {
297
+ public RecipeChoice validate (final boolean allowEmptyRecipes ) {
286
298
if (this .choices .stream ().anyMatch (s -> s .getType ().isAir ())) {
287
299
throw new IllegalArgumentException ("RecipeChoice.ExactChoice cannot contain air" );
288
300
}
289
301
return this ;
290
302
}
291
303
// Paper end - check valid ingredients
292
304
}
305
+
306
+ /**
307
+ * Represents a choice that will be valid if the {@link ItemStack#getType()}
308
+ * matches any of the item types in the set.
309
+ * @see #itemType(RegistryKeySet)
310
+ */
311
+ @ ApiStatus .Experimental
312
+ @ ApiStatus .NonExtendable
313
+ interface ItemTypeChoice extends RecipeChoice {
314
+
315
+ /**
316
+ * Gets the set of item types that this choice will match.
317
+ *
318
+ * @return the set of item types
319
+ */
320
+ RegistryKeySet <ItemType > itemTypes ();
321
+ }
293
322
}
0 commit comments