-
-
Notifications
You must be signed in to change notification settings - Fork 9
/
ExpansionImpl.java
225 lines (187 loc) · 8.68 KB
/
ExpansionImpl.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
212
213
214
215
216
217
218
219
220
221
222
223
224
225
package io.github.miniplaceholders.api;
import io.github.miniplaceholders.api.placeholder.AudiencePlaceholder;
import io.github.miniplaceholders.api.placeholder.RelationalPlaceholder;
import net.kyori.adventure.audience.Audience;
import net.kyori.adventure.audience.ForwardingAudience;
import net.kyori.adventure.text.minimessage.Context;
import net.kyori.adventure.text.minimessage.tag.Tag;
import net.kyori.adventure.text.minimessage.tag.resolver.ArgumentQueue;
import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.*;
import java.util.function.BiFunction;
import java.util.function.Predicate;
import static io.github.miniplaceholders.api.utils.Conditions.nonNullOrEmptyString;
import static java.util.Objects.requireNonNull;
final class ExpansionImpl implements Expansion {
private static final Tags.Single[] EMPTY_SINGLE_AUDIENCE = new Tags.Single[0];
private static final Tags.Relational[] EMPTY_RELATIONAL_AUDIENCE = new Tags.Relational[0];
private final String name;
private final Tags.Single[] audiencePlaceholders;
private final Tags.Relational[] relationalPlaceholders;
private final TagResolver globalPlaceholders;
private final Class<? extends Audience> filterClass;
private final Predicate<Audience> predicateFilter;
ExpansionImpl(
@NotNull final String expansionName,
@Nullable final Collection<Tags.Single> audiencePlaceholders,
@Nullable final Collection<Tags.Relational> relationalPlaceholders,
@Nullable final TagResolver globalPlaceholders,
@Nullable final Class<? extends Audience> filterClass,
@Nullable final Predicate<Audience> predicateFilter){
this.name = expansionName+"-";
this.audiencePlaceholders = audiencePlaceholders != null
? audiencePlaceholders.toArray(EMPTY_SINGLE_AUDIENCE)
: EMPTY_SINGLE_AUDIENCE;
this.relationalPlaceholders = relationalPlaceholders != null
? relationalPlaceholders.toArray(EMPTY_RELATIONAL_AUDIENCE)
: EMPTY_RELATIONAL_AUDIENCE;
this.globalPlaceholders = globalPlaceholders;
this.filterClass = filterClass;
this.predicateFilter = predicateFilter;
}
@Override
public @NotNull String name(){
return this.name;
}
@Override
public @NotNull TagResolver audiencePlaceholders(@NotNull Audience audience) {
if (audiencePlaceholders.length == 0) return TagResolver.empty();
requireNonNull(audience, "the audience cannot be null");
if ((audience = expansionFilter(audience)) == null) return TagResolver.empty();
final TagResolver.Builder placeholders = TagResolver.builder();
for (final Tags.Single pl : this.audiencePlaceholders) {
placeholders.resolver(pl.of(audience));
}
return placeholders.build();
}
@SuppressWarnings("OverrideOnly")
private Audience expansionFilter(final Audience audience) {
if (audience == null || filterClass == null && predicateFilter == null) {
return audience;
}
final boolean eligible = filterClass != null && filterClass.isInstance(audience)
|| predicateFilter != null && predicateFilter.test(audience);
if (eligible) {
return audience;
}
if (audience instanceof final ForwardingAudience.Single forward) {
return expansionFilter(forward.audience());
}
return null;
}
@Override
public @NotNull TagResolver relationalPlaceholders(@NotNull Audience audience, @NotNull Audience otherAudience){
if (relationalPlaceholders.length == 0) return TagResolver.empty();
requireNonNull(audience, "the audience cannot be null");
requireNonNull(otherAudience, "the other audience cannot be null");
audience = expansionFilter(audience);
otherAudience = expansionFilter(otherAudience);
if (audience == null || otherAudience == null) {
return TagResolver.empty();
}
final TagResolver.Builder placeholders = TagResolver.builder();
for (final Tags.Relational pl : this.relationalPlaceholders) {
placeholders.resolver(pl.of(audience, otherAudience));
}
return placeholders.build();
}
@Override
public @NotNull TagResolver globalPlaceholders(){
return this.globalPlaceholders;
}
@Override
public void register() {
if (this.registered()) {
throw new IllegalStateException("Expansion" + this.name + "is already registered");
}
MiniPlaceholders.expansions.add(this);
}
@Override
public void unregister() {
if (!this.registered()) {
throw new IllegalStateException("Expansion " + this.name + " is not registered");
}
MiniPlaceholders.expansions.remove(this);
}
@Override
public boolean registered() {
return MiniPlaceholders.expansions.contains(this);
}
static final class Builder implements Expansion.Builder {
private final String expansionName;
private Set<Tags.Single> audiencePlaceholders;
private Set<Tags.Relational> relationalPlaceholders;
private TagResolver.Builder globalPlaceholders;
private Class<? extends Audience> filterClass;
private Predicate<Audience> predicateFilter;
Builder(@NotNull final String name){
this.expansionName = nonNullOrEmptyString(name, "Expansion name")
.toLowerCase(Locale.ROOT).concat("_");
}
@Override
public @NotNull Builder audiencePlaceholder(@NotNull final String key, @NotNull final AudiencePlaceholder audiencePlaceholder){
nonNullOrEmptyString(key, "Placeholder key");
requireNonNull(audiencePlaceholder, "the audience placeholder cannot be null");
if (this.audiencePlaceholders == null) this.audiencePlaceholders = new HashSet<>(5);
this.audiencePlaceholders.add(Tags.single(expansionName+key, audiencePlaceholder));
return this;
}
@Override
public @NotNull Builder relationalPlaceholder(@NotNull final String key, @NotNull final RelationalPlaceholder relationalPlaceholder){
nonNullOrEmptyString(key, "Placeholder key");
requireNonNull(relationalPlaceholder, "the relational placeholder cannot be null");
if (this.relationalPlaceholders == null) this.relationalPlaceholders = new HashSet<>(4);
this.relationalPlaceholders.add(Tags.relational(expansionName+"rel_"+key, relationalPlaceholder));
return this;
}
@Override
public @NotNull Builder globalPlaceholder(@NotNull final String key, @NotNull final BiFunction<ArgumentQueue, Context, Tag> function){
nonNullOrEmptyString(key, "Placeholder key");
requireNonNull(function, "the global placeholder cannot be null");
if(this.globalPlaceholders == null) this.globalPlaceholders = TagResolver.builder();
this.globalPlaceholders.tag(expansionName+key, function);
return this;
}
@Override
public @NotNull Builder globalPlaceholder(@NotNull final String key, @NotNull final Tag tag){
nonNullOrEmptyString(key, "Placeholder key");
requireNonNull(tag, "the tag cannot be null");
if(this.globalPlaceholders == null) this.globalPlaceholders = TagResolver.builder();
this.globalPlaceholders.tag(expansionName+key, tag);
return this;
}
@Override
public @NotNull Builder filter(@Nullable final Class<? extends Audience> clazz) {
this.filterClass = clazz;
return this;
}
@Override
public @NotNull Builder filter(@Nullable final Predicate<Audience> predicate){
this.predicateFilter = predicate;
return this;
}
@Override
public @NotNull Expansion build(){
return new ExpansionImpl(
this.expansionName,
this.audiencePlaceholders,
this.relationalPlaceholders,
this.globalPlaceholders != null ? this.globalPlaceholders.build() : TagResolver.empty(),
this.filterClass,
this.predicateFilter
);
}
}
@Override
public boolean equals(Object o){
if (this==o) return true;
if (o == null || o.getClass() != ExpansionImpl.class) return false;
return ((ExpansionImpl)o).name.equals(this.name);
}
@Override
public int hashCode(){
return Objects.hash(name.hashCode());
}
}