-
Notifications
You must be signed in to change notification settings - Fork 110
/
ItemOutput.java
211 lines (190 loc) · 6.19 KB
/
ItemOutput.java
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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
package slimeknights.mantle.recipe;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonPrimitive;
import com.google.gson.JsonSyntaxException;
import lombok.RequiredArgsConstructor;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.network.PacketBuffer;
import net.minecraft.tags.ITag;
import net.minecraft.tags.TagCollectionManager;
import net.minecraft.util.IItemProvider;
import net.minecraft.util.JSONUtils;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.common.crafting.CraftingHelper;
import java.util.Objects;
import java.util.function.Supplier;
/**
* Class representing an item stack output. Supports both direct stacks and tag output, behaving like an ingredient used for output
*/
public abstract class ItemOutput implements Supplier<ItemStack> {
/**
* Gets the item output of this recipe
* @return Item output
*/
@Override
public abstract ItemStack get();
/**
* Writes this output to JSON
* @return Json element
*/
public abstract JsonElement serialize();
/**
* Creates a new output for the given stack
* @param stack Stack
* @return Output
*/
public static ItemOutput fromStack(ItemStack stack) {
return new OfStack(stack);
}
/**
* Creates a new output for the given item
* @param item Item
* @param count Stack count
* @return Output
*/
public static ItemOutput fromItem(IItemProvider item, int count) {
return new OfItem(item.asItem(), count);
}
/**
* Creates a new output for the given item
* @param item Item
* @return Output
*/
public static ItemOutput fromItem(IItemProvider item) {
return fromItem(item, 1);
}
/**
* Creates a new output for the given tag
* @param tag Tag
* @return Output
*/
public static ItemOutput fromTag(ITag<Item> tag, int count) {
return new OfTagPreference(tag, count);
}
/**
* Reads an item output from JSON
* @param element Json element
* @return Read output
*/
public static ItemOutput fromJson(JsonElement element) {
if (element.isJsonPrimitive()) {
return fromItem(JSONUtils.getItem(element, "item"));
}
if (!element.isJsonObject()) {
throw new JsonSyntaxException("Invalid item output, must be a string or an object");
}
// if it has a tag, parse as tag
JsonObject json = element.getAsJsonObject();
if (json.has("tag")) {
String name = JSONUtils.getString(json, "tag");
ITag<Item> tag = TagCollectionManager.getManager().getItemTags().get(new ResourceLocation(name));
if (tag == null) {
throw new JsonSyntaxException("Unknown tag " + name + " for item output");
}
int count = JSONUtils.getInt(json, "count", 1);
return fromTag(tag, count);
}
// default: parse as item stack using Forge
return fromStack(CraftingHelper.getItemStack(json, true));
}
/**
* Writes this output to the packet buffer
* @param buffer Packet buffer instance
*/
public void write(PacketBuffer buffer) {
buffer.writeItemStack(get());
}
/**
* Reads an item output from the packet buffer
* @param buffer Buffer instance
* @return Item output
*/
public static ItemOutput read(PacketBuffer buffer) {
return fromStack(buffer.readItemStack());
}
/** Class for an output that is just an item, simplifies NBT for serializing as vanilla forces NBT to be set for tools and forge goes through extra steps when NBT is set */
@RequiredArgsConstructor
private static class OfItem extends ItemOutput {
private final Item item;
private final int count;
private ItemStack cachedStack;
@Override
public ItemStack get() {
if (cachedStack == null) {
cachedStack = new ItemStack(item, count);
}
return cachedStack;
}
@Override
public JsonElement serialize() {
String itemName = Objects.requireNonNull(item.getRegistryName()).toString();
if (count > 1) {
JsonObject json = new JsonObject();
json.addProperty("item", itemName);
json.addProperty("count", count);
return json;
} else {
return new JsonPrimitive(itemName);
}
}
}
/** Class for an output that is just a stack */
@RequiredArgsConstructor
private static class OfStack extends ItemOutput {
private final ItemStack stack;
@Override
public ItemStack get() {
return stack;
}
@Override
public JsonElement serialize() {
String itemName = Objects.requireNonNull(stack.getItem().getRegistryName()).toString();
int count = stack.getCount();
// if the item has NBT or a count, write as object
if (stack.hasTag() || count > 1) {
JsonObject jsonResult = new JsonObject();
jsonResult.addProperty("item", itemName);
if (count > 1) {
jsonResult.addProperty("count", count);
}
CompoundNBT nbt = stack.getTag();
if (nbt != null) {
jsonResult.addProperty("nbt", nbt.toString());
}
return jsonResult;
} else {
return new JsonPrimitive(itemName);
}
}
}
/** Class for an output from a tag preference */
@RequiredArgsConstructor
private static class OfTagPreference extends ItemOutput {
private final ITag<Item> tag;
private final int count;
private ItemStack cachedResult = null;
@Override
public ItemStack get() {
// cache the result from the tag preference to save effort, especially helpful if the tag becomes invalid
// this object should only exist in recipes so no need to invalidate the cache
if (cachedResult == null) {
cachedResult = TagPreference.getItems().getPreference(tag)
.map(item -> new ItemStack(item, count))
.orElse(ItemStack.EMPTY);
}
return cachedResult;
}
@Override
public JsonElement serialize() {
JsonObject json = new JsonObject();
json.addProperty("tag", TagCollectionManager.getManager().getItemTags().getValidatedIdFromTag(tag).toString());
if (count != 1) {
json.addProperty("count", count);
}
return json;
}
}
}