Skip to content

Commit

Permalink
shadow color: support in json serializer, fill in some style gaps
Browse files Browse the repository at this point in the history
  • Loading branch information
zml2008 committed Dec 7, 2024
1 parent 08a5875 commit de37bf6
Show file tree
Hide file tree
Showing 6 changed files with 112 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -562,7 +562,7 @@ default boolean hasDecoration(final @NotNull TextDecoration decoration) {
*/
enum Merge {
/**
* Merges {@link Style#color()}.
* Merges {@link Style#color()} and {@link Style#shadowColor()}.
*
* @since 4.0.0
*/
Expand Down
16 changes: 16 additions & 0 deletions api/src/main/java/net/kyori/adventure/text/format/StyleImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,10 @@ final class StyleImpl implements Style {
builder.color(null);
}

if (Objects.equals(this.shadowColor(), that.shadowColor())) {
builder.shadowColor(null);
}

for (int i = 0, length = DecorationMap.DECORATIONS.length; i < length; i++) {
final TextDecoration decoration = DecorationMap.DECORATIONS[i];
if (this.decoration(decoration) == that.decoration(decoration)) {
Expand Down Expand Up @@ -269,6 +273,7 @@ public boolean isEmpty() {
this.decorations.examinableProperties(),
Stream.of(
ExaminableProperty.of("color", this.color),
ExaminableProperty.of("shadowColor", this.shadowColor),
ExaminableProperty.of("clickEvent", this.clickEvent),
ExaminableProperty.of("hoverEvent", this.hoverEvent),
ExaminableProperty.of("insertion", this.insertion),
Expand All @@ -289,6 +294,7 @@ public boolean equals(final @Nullable Object other) {
final StyleImpl that = (StyleImpl) other;
return Objects.equals(this.color, that.color)
&& this.decorations.equals(that.decorations)
&& Objects.equals(this.shadowColor, that.shadowColor)
&& Objects.equals(this.clickEvent, that.clickEvent)
&& Objects.equals(this.hoverEvent, that.hoverEvent)
&& Objects.equals(this.insertion, that.insertion)
Expand All @@ -298,6 +304,7 @@ public boolean equals(final @Nullable Object other) {
@Override
public int hashCode() {
int result = Objects.hashCode(this.color);
result = (31 * result) + Objects.hashCode(this.shadowColor);
result = (31 * result) + this.decorations.hashCode();
result = (31 * result) + Objects.hashCode(this.clickEvent);
result = (31 * result) + Objects.hashCode(this.hoverEvent);
Expand All @@ -321,6 +328,7 @@ static final class BuilderImpl implements Builder {

BuilderImpl(final @NotNull StyleImpl style) {
this.color = style.color;
this.shadowColor = style.shadowColor;
this.decorations = new EnumMap<>(style.decorations);
this.clickEvent = style.clickEvent;
this.hoverEvent = style.hoverEvent;
Expand Down Expand Up @@ -418,6 +426,13 @@ static final class BuilderImpl implements Builder {
this.color(color);
}
}

final ShadowColor shadowColor = that.shadowColor();
if (shadowColor != null) {
if (strategy == Merge.Strategy.ALWAYS || (strategy == Merge.Strategy.IF_ABSENT_ON_TARGET && this.shadowColor == null)) {
this.shadowColor(shadowColor);
}
}
}

if (merges.contains(Merge.DECORATIONS)) {
Expand Down Expand Up @@ -481,6 +496,7 @@ static final class BuilderImpl implements Builder {

private boolean isEmpty() {
return this.color == null
&& this.shadowColor == null
&& this.decorations.values().stream().allMatch(state -> state == TextDecoration.State.NOT_SET)
&& this.clickEvent == null
&& this.hoverEvent == null
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ public <T> TypeAdapter<T> create(final Gson gson, final TypeToken<T> type) {
} else if (COLOR_TYPE.isAssignableFrom(rawType)) {
return (TypeAdapter<T>) (this.features.value(JSONOptions.EMIT_RGB) ? TextColorSerializer.INSTANCE : TextColorSerializer.DOWNSAMPLE_COLOR);
} else if (SHADOW_COLOR_TYPE.isAssignableFrom(rawType)) {
return (TypeAdapter<T>) ShadowColorSerializer.INSTANCE;
return (TypeAdapter<T>) ShadowColorSerializer.create(this.features);
} else if (TEXT_DECORATION_TYPE.isAssignableFrom(rawType)) {
return (TypeAdapter<T>) TextDecorationSerializer.INSTANCE;
} else if (BLOCK_NBT_POS_TYPE.isAssignableFrom(rawType)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,27 +23,71 @@
*/
package net.kyori.adventure.text.serializer.gson;

import com.google.gson.JsonParseException;
import com.google.gson.TypeAdapter;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonToken;
import com.google.gson.stream.JsonWriter;
import java.io.IOException;
import net.kyori.adventure.text.format.ShadowColor;
import net.kyori.adventure.text.serializer.json.JSONOptions;
import net.kyori.option.OptionState;

final class ShadowColorSerializer extends TypeAdapter<ShadowColor> {
static final TypeAdapter<ShadowColor> INSTANCE = new ShadowColorSerializer().nullSafe();
static TypeAdapter<ShadowColor> create(final OptionState options) {
return new ShadowColorSerializer(options.value(JSONOptions.SHADOW_COLOR_MODE) == JSONOptions.ShadowColorEmitMode.EMIT_ARRAY).nullSafe();
}

private final boolean emitArray;

private ShadowColorSerializer(final boolean emitArray) {
this.emitArray = emitArray;
}

@Override
public void write(final JsonWriter out, final ShadowColor value) throws IOException {
out.value(value.value());
if (this.emitArray) {
out.beginArray()
.value(componentAsFloat(value.red()))
.value(componentAsFloat(value.green()))
.value(componentAsFloat(value.blue()))
.value(componentAsFloat(value.alpha()))
.endArray();

} else {
out.value(value.value());
}
}

@Override
public ShadowColor read(final JsonReader in) throws IOException {
if (in.peek() == JsonToken.BEGIN_ARRAY) {
throw new UnsupportedOperationException(); // TODO
in.beginArray();
final double r = in.nextDouble();
final double g = in.nextDouble();
final double b = in.nextDouble();
final double a = in.nextDouble();
if (in.peek() != JsonToken.END_ARRAY) {
throw new JsonParseException("Failed to parse shadow colour at " + in.getPath() + ": expected end of 4-element array but got " + in.peek() + " instead.");
}
in.endArray();

return ShadowColor.shadowColor(
componentFromFloat(r),
componentFromFloat(g),
componentFromFloat(b),
componentFromFloat(a)
);
}

return ShadowColor.shadowColor(in.nextInt());
}

static float componentAsFloat(final int element) {
return (float) element / 0xff;
}

static int componentFromFloat(final double element) {
return (int) ((float) element) * 0xff;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ static TypeAdapter<Style> create(final net.kyori.adventure.text.serializer.json.
hoverMode == JSONOptions.HoverEventValueMode.LEGACY_ONLY || hoverMode == JSONOptions.HoverEventValueMode.BOTH,
hoverMode == JSONOptions.HoverEventValueMode.MODERN_ONLY || hoverMode == JSONOptions.HoverEventValueMode.BOTH,
features.value(JSONOptions.VALIDATE_STRICT_EVENTS),
features.value(JSONOptions.SHADOW_COLOR_MODE) != JSONOptions.ShadowColorEmitMode.NONE,
gson
).nullSafe();
}
Expand All @@ -99,19 +100,22 @@ static TypeAdapter<Style> create(final net.kyori.adventure.text.serializer.json.
private final boolean emitLegacyHover;
private final boolean emitModernHover;
private final boolean strictEventValues;
private final boolean emitShadowColor;
private final Gson gson;

private StyleSerializer(
final net.kyori.adventure.text.serializer.json.@Nullable LegacyHoverEventSerializer legacyHover,
final boolean emitLegacyHover,
final boolean emitModernHover,
final boolean strictEventValues,
final boolean emitShadowColor,
final Gson gson
) {
this.legacyHover = legacyHover;
this.emitLegacyHover = emitLegacyHover;
this.emitModernHover = emitModernHover;
this.strictEventValues = strictEventValues;
this.emitShadowColor = emitShadowColor;
this.gson = gson;
}

Expand All @@ -131,6 +135,8 @@ public Style read(final JsonReader in) throws IOException {
} else if (color.decoration != null) {
style.decoration(color.decoration, TextDecoration.State.TRUE);
}
} else if (fieldName.equals(SHADOW_COLOR)) {
style.shadowColor(this.gson.fromJson(in, SerializerFactory.SHADOW_COLOR_TYPE));
} else if (TextDecoration.NAMES.keys().contains(fieldName)) {
style.decoration(TextDecoration.NAMES.value(fieldName), GsonHacks.readBoolean(in));
} else if (fieldName.equals(INSERTION)) {
Expand Down Expand Up @@ -269,7 +275,7 @@ public void write(final JsonWriter out, final Style value) throws IOException {
}

final @Nullable ShadowColor shadowColor = value.shadowColor();
if (shadowColor != null) {
if (shadowColor != null && this.emitShadowColor) {
out.name(SHADOW_COLOR);
this.gson.toJson(shadowColor, SerializerFactory.SHADOW_COLOR_TYPE, out);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ private JSONOptions() {
private static final int VERSION_1_16 = 2526; // 20w16a
private static final int VERSION_1_20_3 = 3679; // 23w40a
private static final int VERSION_1_20_5 = 3819; // 24w09a
private static final int VERSION_1_21_4 = 4174; // 24w44a

/**
* Whether to emit RGB text.
Expand Down Expand Up @@ -99,6 +100,13 @@ private JSONOptions() {
*/
public static final Option<ShowItemHoverDataMode> SHOW_ITEM_HOVER_DATA_MODE = Option.enumOption(key("emit/show_item_hover_data"), ShowItemHoverDataMode.class, ShowItemHoverDataMode.EMIT_EITHER);

/**
* How to emit shadow colour data.
*
* @since 4.18.0
*/
public static final Option<ShadowColorEmitMode> SHADOW_COLOR_MODE = Option.enumOption(key("emit/shadow_color"), ShadowColorEmitMode.class, ShadowColorEmitMode.EMIT_INTEGER);

/**
* Versioned by world data version.
*/
Expand All @@ -111,6 +119,7 @@ private JSONOptions() {
.value(VALIDATE_STRICT_EVENTS, false)
.value(EMIT_DEFAULT_ITEM_HOVER_QUANTITY, false)
.value(SHOW_ITEM_HOVER_DATA_MODE, ShowItemHoverDataMode.EMIT_LEGACY_NBT)
.value(SHADOW_COLOR_MODE, ShadowColorEmitMode.NONE)
)
.version(
VERSION_1_16,
Expand All @@ -128,6 +137,10 @@ private JSONOptions() {
b -> b.value(EMIT_DEFAULT_ITEM_HOVER_QUANTITY, true)
.value(SHOW_ITEM_HOVER_DATA_MODE, ShowItemHoverDataMode.EMIT_DATA_COMPONENTS)
)
.version(
VERSION_1_21_4,
b -> b.value(SHADOW_COLOR_MODE, ShadowColorEmitMode.EMIT_INTEGER)
)
.build();

/**
Expand All @@ -141,6 +154,7 @@ private JSONOptions() {
.value(EMIT_COMPACT_TEXT_COMPONENT, false)
.value(VALIDATE_STRICT_EVENTS, false)
.value(SHOW_ITEM_HOVER_DATA_MODE, ShowItemHoverDataMode.EMIT_EITHER)
.value(SHADOW_COLOR_MODE, ShadowColorEmitMode.EMIT_INTEGER)
.build();

private static String key(final String value) {
Expand Down Expand Up @@ -220,4 +234,30 @@ public enum ShowItemHoverDataMode {
*/
EMIT_EITHER,
}

/**
* How text shadow colors should be emitted.
*
* @since 4.18.0
* @sinceMinecraft 1.21.4
*/
public enum ShadowColorEmitMode {
/**
* Do not emit shadow colours.
*/
NONE,
/**
* Emit as a single packed integer value containing, in order, ARGB bytes.
*
* @since 4.18.0
*/
EMIT_INTEGER,
/**
* Emit a colour as 4-element float array of the RGBA components of the colour.
*
* @since 4.18.0
*/
EMIT_ARRAY

}
}

0 comments on commit de37bf6

Please sign in to comment.