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