-
Notifications
You must be signed in to change notification settings - Fork 754
/
MaterialNBT.java
164 lines (143 loc) · 5.08 KB
/
MaterialNBT.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
package slimeknights.tconstruct.library.tools.nbt;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableList;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.ToString;
import net.minecraft.nbt.ListTag;
import net.minecraft.nbt.StringTag;
import net.minecraft.nbt.Tag;
import slimeknights.tconstruct.library.materials.definition.IMaterial;
import slimeknights.tconstruct.library.materials.definition.MaterialVariant;
import slimeknights.tconstruct.library.materials.definition.MaterialVariantId;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
/**
* All the materials contained within the tool. Determines a portion of the modifiers, along with the stats.
*/
@EqualsAndHashCode
@ToString
public class MaterialNBT {
/** Instance containing no materials, for errors with parsing NBT */
public final static MaterialNBT EMPTY = new MaterialNBT(ImmutableList.of());
/** List of materials contained in this NBT */
@Getter
private final List<MaterialVariant> list;
/** Creates a new material NBT */
public MaterialNBT(List<MaterialVariant> list) {
this.list = ImmutableList.copyOf(list);
}
/** Creates a new material NBT */
@VisibleForTesting
public static MaterialNBT of(IMaterial... materials) {
return new MaterialNBT(Arrays.stream(materials).map(MaterialVariant::of).toList());
}
/** Creates a builder for this NBT */
public static Builder builder() {
return new Builder();
}
/**
* Gets the material at the given index
* @param index Index
* @return Material, or unknown if index is invalid
*/
public MaterialVariant get(int index) {
if (index >= list.size() || index < 0) {
return MaterialVariant.UNKNOWN;
}
return list.get(index);
}
/** Gets the number of materials in this list */
public int size() {
return list.size();
}
/**
* Creates a copy of this material list with the material at the given index substituted
* @param index Index to replace. Can be greater than the material list size
* @param replacement New material for that index
* @return Copy of NBt with the new material
* @throws IndexOutOfBoundsException If the index is invalid
*/
public MaterialNBT replaceMaterial(int index, MaterialVariantId replacement) {
if (index < 0) {
throw new IndexOutOfBoundsException("Material index is out of bounds");
}
// start by copying all materials over
int size = list.size();
ArrayList<MaterialVariant> list = new ArrayList<>(Math.max(size, index + 1));
for (int i = 0; i < size; i++) {
if (i == index) {
list.add(MaterialVariant.of(replacement));
} else {
list.add(this.list.get(i));
}
}
// if the index is bigger, copy in unknown materials until we reach it
// handles the case where a tool has broken material NBT without crashing
if (index >= size) {
for (int i = size; i < index; i++) {
list.add(MaterialVariant.of(IMaterial.UNKNOWN, ""));
}
list.add(MaterialVariant.of(replacement));
}
return new MaterialNBT(list);
}
/**
* Parses the material list from NBT
* @param nbt NBT instance
* @return MaterialNBT instance
*/
public static MaterialNBT readFromNBT(@Nullable Tag nbt) {
if (nbt == null || nbt.getId() != Tag.TAG_LIST) {
return EMPTY;
}
ListTag listNBT = (ListTag) nbt;
if (listNBT.getElementType() != Tag.TAG_STRING) {
return EMPTY;
}
List<MaterialVariant> materials = listNBT.stream()
.map(tag -> MaterialVariantId.tryParse(tag.getAsString()))
.filter(Objects::nonNull)
.map(MaterialVariant::of)
.collect(Collectors.toList());
return new MaterialNBT(materials);
}
/**
* Writes this material list to NBT
* @return List of materials
*/
public ListTag serializeToNBT() {
return list.stream()
.map(lazy -> StringTag.valueOf(lazy.getVariant().toString()))
.collect(Collectors.toCollection(ListTag::new));
}
/** Builder for material NBT */
public static class Builder {
private final ImmutableList.Builder<MaterialVariant> builder = ImmutableList.builder();
/** Adds a material to the builder */
public Builder add(MaterialVariant variant) {
builder.add(variant);
return this;
}
/** Adds a material to the builder */
public Builder add(MaterialVariantId variantId) {
return add(MaterialVariant.of(variantId));
}
/** Adds a material to the builder */
public Builder add(IMaterial material) {
return add(MaterialVariant.of(material));
}
/** Builds the final list */
public MaterialNBT build() {
List<MaterialVariant> materials = builder.build();
if (materials.isEmpty()) {
return MaterialNBT.EMPTY;
}
return new MaterialNBT(materials);
}
}
}