diff --git a/text-minimessage/src/main/java/net/kyori/adventure/text/minimessage/tag/standard/RainbowTag.java b/text-minimessage/src/main/java/net/kyori/adventure/text/minimessage/tag/standard/RainbowTag.java index df990a87a1..18bd84cf0a 100644 --- a/text-minimessage/src/main/java/net/kyori/adventure/text/minimessage/tag/standard/RainbowTag.java +++ b/text-minimessage/src/main/java/net/kyori/adventure/text/minimessage/tag/standard/RainbowTag.java @@ -51,12 +51,14 @@ final class RainbowTag extends AbstractColorChangingTag { private final boolean reversed; private final double dividedPhase; + private final float saturation; private int colorIndex = 0; static Tag create(final ArgumentQueue args, final Context ctx) { boolean reversed = false; int phase = 0; + float saturation = 1f; if (args.hasNext()) { String value = args.pop().value(); @@ -71,15 +73,28 @@ static Tag create(final ArgumentQueue args, final Context ctx) { throw ctx.newException("Expected phase, got " + value); } } + if (args.hasNext()) { + final String saturationValue = args.pop().value(); + if (!saturationValue.isEmpty()) { + try { + saturation = Float.parseFloat(saturationValue); + } catch (final NumberFormatException ex) { + throw ctx.newException("Expected saturation, got " + saturationValue); + } + if (saturation < 0f || saturation > 1f) { + throw ctx.newException(String.format("Rainbow saturation is out of range (%s). Must be in the range [0.0, 1.0] (inclusive).", saturation)); + } + } + } } - - return new RainbowTag(reversed, phase, ctx); + return new RainbowTag(reversed, phase, saturation, ctx); } - private RainbowTag(final boolean reversed, final int phase, final Context ctx) { + private RainbowTag(final boolean reversed, final int phase, final float saturation, final Context ctx) { super(ctx); this.reversed = reversed; this.dividedPhase = ((double) phase) / 10d; + this.saturation = saturation; } @Override @@ -106,7 +121,7 @@ protected void advanceColor() { protected TextColor color() { final float index = this.colorIndex; final float hue = (float) ((index / this.size() + this.dividedPhase) % 1f); - return TextColor.color(HSVLike.hsvLike(hue, 1f, 1f)); + return TextColor.color(HSVLike.hsvLike(hue, this.saturation, 1f)); } @Override diff --git a/text-minimessage/src/test/java/net/kyori/adventure/text/minimessage/tag/standard/RainbowTagTest.java b/text-minimessage/src/test/java/net/kyori/adventure/text/minimessage/tag/standard/RainbowTagTest.java index 980d39d366..51698cc06c 100644 --- a/text-minimessage/src/test/java/net/kyori/adventure/text/minimessage/tag/standard/RainbowTagTest.java +++ b/text-minimessage/src/test/java/net/kyori/adventure/text/minimessage/tag/standard/RainbowTagTest.java @@ -401,4 +401,39 @@ void testDisabledVirtualComponentEmission() { input ); } + + @Test + void testSaturation() { + final String input = "Woo: ||||||||||||||||||||||||!"; + final Component expected = empty().color(YELLOW) + .append(text("Woo: ")) + .append(virtualOfChildren(textOfChildren( + text("|", color(0xFF5959)), + text("|", color(0xff8259)), + text("|", color(0xffac59)), + text("|", color(0xffd559)), + text("|", color(0xffff59)), + text("|", color(0xd5ff59)), + text("|", color(0xacff59)), + text("|", color(0x82ff59)), + text("|", color(0x59FF59)), + text("|", color(0x59ff82)), + text("|", color(0x59ffac)), + text("|", color(0x59ffd5)), + text("|", color(0x59ffff)), + text("|", color(0x59d5ff)), + text("|", color(0x59acff)), + text("|", color(0x5982ff)), + text("|", color(0x5959FF)), + text("|", color(0x8259ff)), + text("|", color(0xac59ff)), + text("|", color(0xd559ff)), + text("|", color(0xff59ff)), + text("|", color(0xff59d5)), + text("|", color(0xff59ac)), + text("|", color(0xFF5982)) + ) + )).append(text("!")); + this.assertParsedEquals(expected, input); + } }