6767public class ParticleDisplay implements Cloneable {
6868 /**
6969 * Checks if spawn methods should use particle data classes such as {@link org.bukkit.Particle.DustOptions}
70- * which is only available from 1.13+
70+ * which is only available from 1.13+ (FOOTSTEP was removed in 1.13)
7171 *
7272 * @since 1.0.0
7373 */
7474 private static final boolean ISFLAT = XParticle .getParticle ("FOOTSTEP" ) == null ;
75+ /**
76+ * Checks if spawn methods should use particle data classes such as {@link org.bukkit.Particle.DustTransition}
77+ * which is only available from 1.17+ (DUST_COLOR_TRANSITION was released in 1.17)
78+ *
79+ * @since 8.6.0.0.1
80+ */
81+ private static final boolean ISFLAT2 = XParticle .getParticle ("DUST_COLOR_TRANSITION" ) != null ;
7582 private static final Axis [] DEFAULT_ROTATION_ORDER = {Axis .X , Axis .Y , Axis .Z };
7683 private static final Particle DEFAULT_PARTICLE = Particle .CLOUD ;
7784
@@ -262,22 +269,29 @@ public static ParticleDisplay edit(@Nonnull ParticleDisplay display, @Nonnull Co
262269 String item = config .getString ("itemstack" ); // material name
263270 String materialdata = config .getString ("materialdata" ); // material name
264271
265- float size = 1.0f ;
266- if (display .data instanceof float []) {
267- float [] datas = (float []) display .data ;
268- if (datas .length >= 4 ) {
269- if (config .isSet ("size" )) datas [3 ] = size = (float ) config .getDouble ("size" );
270- else size = datas [3 ];
272+ float size ;
273+ if (config .isSet ("size" )) {
274+ size = (float ) config .getDouble ("size" );
275+ if (display .data instanceof float []) {
276+ float [] datas = (float []) display .data ;
277+ if (datas .length > 3 ) {
278+ datas [3 ] = size ;
279+ }
271280 }
281+ } else {
282+ size = 1f ;
272283 }
273284
274285 if (color != null ) {
275286 String [] colors = StringUtils .split (StringUtils .deleteWhitespace (color ), ',' );
276- if (colors .length == 1 || colors .length == 3 ) {
277- Color parsedColor = Color .white ;
278- if (colors .length == 1 ) {
287+ if (colors .length <= 3 || colors .length == 6 ) { // 1 or 3 : single color, 2 or 6 : two colors for DUST_TRANSITION
288+ Color parsedColor1 = Color .white ;
289+ Color parsedColor2 = null ;
290+ if (colors .length <= 2 ) {
279291 try {
280- parsedColor = Color .decode (colors [0 ]);
292+ parsedColor1 = Color .decode (colors [0 ]);
293+ if (colors .length == 2 )
294+ parsedColor2 = Color .decode (colors [1 ]);
281295 } catch (NumberFormatException ex ) {
282296 /* I don't think it's worth it.
283297 try {
@@ -286,13 +300,23 @@ public static ParticleDisplay edit(@Nonnull ParticleDisplay display, @Nonnull Co
286300 */
287301 }
288302 } else {
289- parsedColor = new Color (NumberUtils .toInt (colors [0 ]), NumberUtils .toInt (colors [1 ]), NumberUtils .toInt (colors [2 ]));
303+ parsedColor1 = new Color (NumberUtils .toInt (colors [0 ]), NumberUtils .toInt (colors [1 ]), NumberUtils .toInt (colors [2 ]));
304+ if (colors .length == 6 )
305+ parsedColor2 = new Color (NumberUtils .toInt (colors [3 ]), NumberUtils .toInt (colors [4 ]), NumberUtils .toInt (colors [5 ]));
290306 }
291307
292- display .data = new float []{
293- parsedColor .getRed (), parsedColor .getGreen (), parsedColor .getBlue (),
294- size
295- };
308+ if (parsedColor2 != null ) {
309+ display .data = new float []{
310+ parsedColor1 .getRed (), parsedColor1 .getGreen (), parsedColor1 .getBlue (),
311+ size ,
312+ parsedColor2 .getRed (), parsedColor2 .getGreen (), parsedColor2 .getBlue ()
313+ };
314+ } else {
315+ display .data = new float []{
316+ parsedColor1 .getRed (), parsedColor1 .getGreen (), parsedColor1 .getBlue (),
317+ size
318+ };
319+ }
296320 }
297321 } else if (blockdata != null ) {
298322 Material material = Material .getMaterial (blockdata );
@@ -543,6 +567,24 @@ public ParticleDisplay withColor(@Nonnull Color color, float size) {
543567 return withColor (color .getRed (), color .getGreen (), color .getBlue (), size );
544568 }
545569
570+ /**
571+ * Adds color properties to the particle settings.
572+ * The particle must be {@link Particle#DUST_COLOR_TRANSITION}
573+ * to get custom colors.
574+ *
575+ * @param color1 the RGB color of the particle on spawn.
576+ * @param size the size of the particle.
577+ * @param color2 the RGB color of the particle at the end.
578+ *
579+ * @return the same particle display, but modified.
580+ * @see #colored(Location, Color, float)
581+ * @since 8.6.0.0.1
582+ */
583+ @ Nonnull
584+ public ParticleDisplay withTransitionColor (@ Nonnull Color color1 , float size , @ Nonnull Color color2 ) {
585+ return withTransitionColor (color1 .getRed (), color1 .getGreen (), color1 .getBlue (), size , color2 .getRed (), color2 .getGreen (), color2 .getBlue ());
586+ }
587+
546588 /**
547589 * @since 7.1.0
548590 */
@@ -553,9 +595,18 @@ public ParticleDisplay withColor(float red, float green, float blue, float size)
553595 }
554596
555597 /**
556- * Adds data for {@link Particle#BLOCK_CRACK}, {@link Particle#BLOCK_DUST}
557- * and {@link Particle#FALLING_DUST} particles. The displayed particle
558- * will depend on the given block data for its color.
598+ * @since 8.6.0.0.1
599+ */
600+ @ Nonnull
601+ public ParticleDisplay withTransitionColor (float red1 , float green1 , float blue1 , float size , float red2 , float green2 , float blue2 ) {
602+ this .data = new float []{red1 , green1 , blue1 , size , red2 , green2 , blue2 };
603+ return this ;
604+ }
605+
606+ /**
607+ * Adds data for {@link Particle#BLOCK_CRACK}, {@link Particle#BLOCK_DUST},
608+ * {@link Particle#FALLING_DUST} and {@link Particle#BLOCK_MARKER} particles.
609+ * The displayed particle will depend on the given block data for its color.
559610 * <p>
560611 * Only works on minecraft version 1.13 and more, because
561612 * {@link BlockData} didn't exist before.
@@ -941,7 +992,7 @@ public Location spawn(@Nonnull Location loc) {
941992 * @since 5.0.0
942993 */
943994 @ Nonnull
944- public Location spawn (@ Nonnull Location loc , @ Nullable Player ... players ) {
995+ public Location spawn (Location loc , @ Nullable Player ... players ) {
945996 if (loc == null ) throw new IllegalStateException ("Attempting to spawn particle when no location is set" );
946997 if (onSpawn != null ) {
947998 if (!onSpawn .test (loc )) return loc ;
@@ -960,6 +1011,14 @@ public Location spawn(@Nonnull Location loc, @Nullable Player... players) {
9601011 if (players == null ) world .spawnParticle (particle , loc , count , offsetx , offsety , offsetz , extra , dust , force );
9611012 else for (Player player : players ) player .spawnParticle (particle , loc , count , offsetx , offsety , offsetz , extra , dust );
9621013
1014+ } else if (ISFLAT2 && particle .getDataType () == Particle .DustTransition .class ) {
1015+ Particle .DustOptions dust = new Particle .DustTransition (
1016+ org .bukkit .Color .fromRGB ((int ) datas [0 ], (int ) datas [1 ], (int ) datas [2 ]),
1017+ org .bukkit .Color .fromRGB ((int ) datas [4 ], (int ) datas [5 ], (int ) datas [6 ]),
1018+ datas [3 ]);
1019+ if (players == null ) world .spawnParticle (particle , loc , count , offsetx , offsety , offsetz , extra , dust , force );
1020+ else for (Player player : players ) player .spawnParticle (particle , loc , count , offsetx , offsety , offsetz , extra , dust );
1021+
9631022 } else if (isDirectional ()) {
9641023 // With count=0, color on offset e.g. for MOB_SPELL or 1.12 REDSTONE
9651024 float [] rgb = {datas [0 ] / 255f , datas [1 ] / 255f , datas [2 ] / 255f };
0 commit comments