-
-
Notifications
You must be signed in to change notification settings - Fork 3.4k
Expand file tree
/
Copy pathPotionEffect.java
More file actions
409 lines (376 loc) · 14.6 KB
/
PotionEffect.java
File metadata and controls
409 lines (376 loc) · 14.6 KB
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
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
package org.bukkit.potion;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableMap;
import io.papermc.paper.registry.RegistryKey;
import java.util.Map;
import java.util.NoSuchElementException;
import org.bukkit.Bukkit;
import org.bukkit.Color;
import org.bukkit.NamespacedKey;
import org.bukkit.Registry;
import org.bukkit.configuration.serialization.ConfigurationSerializable;
import org.bukkit.configuration.serialization.SerializableAs;
import org.bukkit.entity.LivingEntity;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* Represents a potion effect, that can be added to a {@link LivingEntity}. A
* potion effect has a duration that it will last for, an amplifier that will
* enhance its effects, and a {@link PotionEffectType}, that represents its
* effect on an entity.
*/
@SerializableAs("PotionEffect")
public class PotionEffect implements ConfigurationSerializable {
/**
* A constant denoting infinite potion duration.
*/
public static final int INFINITE_DURATION = -1;
private static final String HIDDEN_EFFECT = "hidden_effect"; // Paper
private static final String AMPLIFIER = "amplifier";
private static final String DURATION = "duration";
private static final String TYPE = "effect";
private static final String AMBIENT = "ambient";
private static final String PARTICLES = "has-particles";
private static final String ICON = "has-icon";
private final int amplifier;
private final int duration;
private final PotionEffectType type;
private final boolean ambient;
private final boolean particles;
private final boolean icon;
private final PotionEffect hiddenEffect; // Paper
/**
* Creates a potion effect.
* @param type effect type
* @param duration measured in ticks, see {@link
* PotionEffect#getDuration()}
* @param amplifier the amplifier, see {@link PotionEffect#getAmplifier()}
* @param ambient the ambient status, see {@link PotionEffect#isAmbient()}
* @param particles the particle status, see {@link PotionEffect#hasParticles()}
* @param icon the icon status, see {@link PotionEffect#hasIcon()}
* @param hiddenEffect the hidden PotionEffect
* @hidden Internal-- hidden effects are only shown internally
*/
@org.jetbrains.annotations.ApiStatus.Internal // Paper
public PotionEffect(@NotNull PotionEffectType type, int duration, int amplifier, boolean ambient, boolean particles, boolean icon, @Nullable PotionEffect hiddenEffect) { // Paper
Preconditions.checkArgument(type != null, "effect type cannot be null");
this.type = type;
this.duration = duration;
this.amplifier = amplifier;
this.ambient = ambient;
this.particles = particles;
this.icon = icon;
// Paper start
this.hiddenEffect = hiddenEffect;
}
/**
* Creates a potion effect.
* @param type effect type
* @param duration measured in ticks, see {@link
* PotionEffect#getDuration()}
* @param amplifier the amplifier, see {@link PotionEffect#getAmplifier()}
* @param ambient the ambient status, see {@link PotionEffect#isAmbient()}
* @param particles the particle status, see {@link PotionEffect#hasParticles()}
* @param icon the icon status, see {@link PotionEffect#hasIcon()}
*/
public PotionEffect(@NotNull PotionEffectType type, int duration, int amplifier, boolean ambient, boolean particles, boolean icon) {
this(type, duration, amplifier, ambient, particles, icon, null);
// Paper end
}
/**
* Creates a potion effect with no defined color.
*
* @param type effect type
* @param duration measured in ticks, see {@link
* PotionEffect#getDuration()}
* @param amplifier the amplifier, see {@link PotionEffect#getAmplifier()}
* @param ambient the ambient status, see {@link PotionEffect#isAmbient()}
* @param particles the particle status, see {@link PotionEffect#hasParticles()}
*/
public PotionEffect(@NotNull PotionEffectType type, int duration, int amplifier, boolean ambient, boolean particles) {
this(type, duration, amplifier, ambient, particles, particles);
}
/**
* Creates a potion effect. Assumes that particles are visible
*
* @param type effect type
* @param duration measured in ticks, see {@link
* PotionEffect#getDuration()}
* @param amplifier the amplifier, see {@link PotionEffect#getAmplifier()}
* @param ambient the ambient status, see {@link PotionEffect#isAmbient()}
*/
public PotionEffect(@NotNull PotionEffectType type, int duration, int amplifier, boolean ambient) {
this(type, duration, amplifier, ambient, true);
}
/**
* Creates a potion effect. Assumes ambient is true.
*
* @param type Effect type
* @param duration measured in ticks
* @param amplifier the amplifier for the effect
* @see PotionEffect#PotionEffect(PotionEffectType, int, int, boolean)
*/
public PotionEffect(@NotNull PotionEffectType type, int duration, int amplifier) {
this(type, duration, amplifier, true);
}
/**
* Constructor for deserialization.
*
* @param map the map to deserialize from
*/
public PotionEffect(@NotNull Map<String, Object> map) {
this(getEffectType(map), getInt(map, DURATION), getInt(map, AMPLIFIER), getBool(map, AMBIENT, false), getBool(map, PARTICLES, true), getBool(map, ICON, getBool(map, PARTICLES, true)), (PotionEffect) map.get(HIDDEN_EFFECT)); // Paper
}
// Paper start
/**
* Returns a new potion effect with the provided type and this effect's
* duration, amplifier, ambient, particles, and icon.
*
* @param type effect type
* @return a new potion effect with the provided type
*/
@NotNull
public PotionEffect withType(@NotNull PotionEffectType type) {
return new PotionEffect(type, duration, amplifier, ambient, particles, icon);
}
/**
* Returns a new potion effect with the provided duration and this effect's
* type, amplifier, ambient, particles, and icon.
*
* @param duration measured in ticks, see {@link
* PotionEffect#getDuration()}
* @return a new potion effect with the provided duration
*/
@NotNull
public PotionEffect withDuration(int duration) {
return new PotionEffect(this.type, duration, amplifier, ambient, particles, icon);
}
/**
* Returns a new potion effect with the provided amplifier and this effect's
* type, duration, ambient, particles, and icon.
*
* @param amplifier the amplifier, see {@link PotionEffect#getAmplifier()}
* @return a new potion effect with the provided amplifier
*/
@NotNull
public PotionEffect withAmplifier(int amplifier) {
return new PotionEffect(this.type, duration, amplifier, ambient, particles, icon);
}
/**
* Returns a new potion effect with the provided ambient and this effect's
* type, duration, amplifier, particles, and icon.
*
* @param ambient the ambient status, see {@link PotionEffect#isAmbient()}
* @return a new potion effect with the provided ambient
*/
@NotNull
public PotionEffect withAmbient(boolean ambient) {
return new PotionEffect(this.type, duration, amplifier, ambient, particles, icon);
}
/**
* Returns a new potion effect with the provided particles and this effect's
* type, duration, amplifier, ambient, and icon.
*
* @param particles the particle status, see {@link PotionEffect#hasParticles()}
* @return a new potion effect with the provided particles
*/
@NotNull
public PotionEffect withParticles(boolean particles) {
return new PotionEffect(this.type, duration, amplifier, ambient, particles, icon);
}
/**
* Returns a new potion effect with the provided icon and this effect's
* type, duration, amplifier, ambient, and particles.
*
* @param icon the icon status, see {@link PotionEffect#hasIcon()}
* @return a new potion effect with the provided icon
*/
@NotNull
public PotionEffect withIcon(boolean icon) {
return new PotionEffect(this.type, duration, amplifier, ambient, particles, icon);
}
/**
* Returns the PotionEffect that will become active
* after the current PotionEffect has run out.
* <p>
* Note: This value is only applicable to type applied to living entities.
*
* @return The hidden PotionEffect.
*/
@Nullable
public PotionEffect getHiddenPotionEffect() {
return hiddenEffect;
}
// Paper end
@NotNull
private static PotionEffectType getEffectType(@NotNull Map<?, ?> map) {
PotionEffectType effect;
if (map.get(TYPE) instanceof String value) {
effect = Bukkit.getUnsafe().get(RegistryKey.MOB_EFFECT, NamespacedKey.fromString(value));
} else {
int type = getInt(map, TYPE);
effect = PotionEffectType.getById(type);
}
if (effect != null) {
return effect;
}
throw new NoSuchElementException(map + " does not contain " + TYPE);
}
private static int getInt(@NotNull Map<?, ?> map, @NotNull Object key) {
Object num = map.get(key);
if (num instanceof Integer) {
return (Integer) num;
}
throw new NoSuchElementException(map + " does not contain " + key);
}
private static boolean getBool(@NotNull Map<?, ?> map, @NotNull Object key, boolean def) {
Object bool = map.get(key);
if (bool instanceof Boolean) {
return (Boolean) bool;
}
return def;
}
@Override
@NotNull
public Map<String, Object> serialize() {
ImmutableMap.Builder<String, Object> builder = ImmutableMap.<String, Object>builder() // Paper
.put(TYPE, type.getKey().toString())
.put(DURATION, duration)
.put(AMPLIFIER, amplifier)
.put(AMBIENT, ambient)
.put(PARTICLES, particles)
.put(ICON, icon);
// Paper start
if (this.hiddenEffect != null) {
builder.put(HIDDEN_EFFECT, this.hiddenEffect);
}
return builder.build();
// Paper end
}
/**
* Attempts to add the effect represented by this object to the given
* {@link LivingEntity}.
* <p>
* Note: {@link PotionEffect#getHiddenPotionEffect()} is ignored when
* adding the effect to the entity.
*
* @param entity The entity to add this effect to
* @return Whether the effect could be added
* @see LivingEntity#addPotionEffect(PotionEffect)
*/
public boolean apply(@NotNull LivingEntity entity) {
return entity.addPotionEffect(this);
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof PotionEffect)) {
return false;
}
PotionEffect that = (PotionEffect) obj;
return this.type.equals(that.type) && this.ambient == that.ambient && this.amplifier == that.amplifier && this.duration == that.duration && this.particles == that.particles && this.icon == that.icon && java.util.Objects.equals(this.hiddenEffect, that.hiddenEffect); // Paper
}
/**
* Returns the amplifier of this effect. A higher amplifier means the
* potion effect happens more often over its duration and in some cases
* has more effect on its target.
*
* @return The effect amplifier
*/
public int getAmplifier() {
return amplifier;
}
/**
* Returns the duration (in ticks) that this effect will run for when
* applied to a {@link LivingEntity}.
*
* @return The duration of the effect, or {@value #INFINITE_DURATION} if
* this effect is infinite
* @see #isInfinite()
*/
public int getDuration() {
return duration;
}
/**
* Returns whether or not this potion effect has an infinite duration. Potion
* effects with infinite durations will display an infinite symbol and never
* expire unless manually removed.
*
* @return whether this duration is infinite or not
*/
public boolean isInfinite() {
return duration == INFINITE_DURATION;
}
/**
* Returns whether or not this potion effect has a shorter duration than the
* provided potion effect.
* <p>
* An infinite duration is considered longer than non-infinite durations. If
* both potion effects have infinite durations, then neither is shorter than
* the other and this method will return false.
*
* @param other the other effect
* @return true if this effect is shorter than the other, false if longer or equal
*/
public boolean isShorterThan(@NotNull PotionEffect other) {
return !isInfinite() && (duration < other.duration || other.isInfinite());
}
/**
* Returns the {@link PotionEffectType} of this effect.
*
* @return The potion type of this effect
*/
@NotNull
public PotionEffectType getType() {
return type;
}
/**
* Makes potion effect produce more, translucent, particles.
*
* @return if this effect is ambient
*/
public boolean isAmbient() {
return ambient;
}
/**
* @return whether this effect has particles or not
*/
public boolean hasParticles() {
return particles;
}
/**
* @return color of this potion's particles. May be null if the potion has no particles or defined color.
* @deprecated color is not part of potion effects
*/
@Deprecated(since = "1.13")
@Nullable
@Contract("-> null")
public Color getColor() {
return null;
}
/**
* @return whether this effect has an icon or not
*/
public boolean hasIcon() {
return icon;
}
@Override
public int hashCode() {
int hash = 1;
hash = hash * 31 + type.hashCode();
hash = hash * 31 + amplifier;
hash = hash * 31 + duration;
hash ^= 0x22222222 >> (ambient ? 1 : -1);
hash ^= 0x22222222 >> (particles ? 1 : -1);
hash ^= 0x22222222 >> (icon ? 1 : -1);
if (hiddenEffect != null) hash = hash * 31 + hiddenEffect.hashCode(); // Paper
return hash;
}
@Override
public String toString() {
return "PotionEffect{" + "amplifier=" + amplifier + ", duration=" + duration + ", type=" + type + ", ambient=" + ambient + ", particles=" + particles + ", icon=" + icon + ", hiddenEffect=" + hiddenEffect + '}'; // Paper
}
}