package net.minecraft.client.resources.metadata.gui; import com.mojang.serialization.Codec; import com.mojang.serialization.DataResult; import com.mojang.serialization.MapCodec; import com.mojang.serialization.codecs.RecordCodecBuilder; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; import net.minecraft.client.resources.metadata.gui.GuiSpriteScaling.NineSlice.Border; import net.minecraft.util.ExtraCodecs; import net.minecraft.util.StringRepresentable; @Environment(EnvType.CLIENT) public interface GuiSpriteScaling { Codec CODEC = GuiSpriteScaling.Type.CODEC.dispatch(GuiSpriteScaling::type, GuiSpriteScaling.Type::codec); GuiSpriteScaling DEFAULT = new GuiSpriteScaling.Stretch(); GuiSpriteScaling.Type type(); @Environment(EnvType.CLIENT) public record NineSlice(int width, int height, Border border, boolean stretchInner) implements GuiSpriteScaling { public static final MapCodec CODEC = RecordCodecBuilder.mapCodec( instance -> instance.group( ExtraCodecs.POSITIVE_INT.fieldOf("width").forGetter(GuiSpriteScaling.NineSlice::width), ExtraCodecs.POSITIVE_INT.fieldOf("height").forGetter(GuiSpriteScaling.NineSlice::height), Border.CODEC.fieldOf("border").forGetter(GuiSpriteScaling.NineSlice::border), Codec.BOOL.optionalFieldOf("stretch_inner", false).forGetter(GuiSpriteScaling.NineSlice::stretchInner) ) .apply(instance, GuiSpriteScaling.NineSlice::new) ) .validate(GuiSpriteScaling.NineSlice::validate); private static DataResult validate(GuiSpriteScaling.NineSlice nineSlice) { Border border = nineSlice.border(); if (border.left() + border.right() >= nineSlice.width()) { return DataResult.error(() -> "Nine-sliced texture has no horizontal center slice: " + border.left() + " + " + border.right() + " >= " + nineSlice.width()); } else { return border.top() + border.bottom() >= nineSlice.height() ? DataResult.error(() -> "Nine-sliced texture has no vertical center slice: " + border.top() + " + " + border.bottom() + " >= " + nineSlice.height()) : DataResult.success(nineSlice); } } @Override public GuiSpriteScaling.Type type() { return GuiSpriteScaling.Type.NINE_SLICE; } } @Environment(EnvType.CLIENT) public record Stretch() implements GuiSpriteScaling { public static final MapCodec CODEC = MapCodec.unit(GuiSpriteScaling.Stretch::new); @Override public GuiSpriteScaling.Type type() { return GuiSpriteScaling.Type.STRETCH; } } @Environment(EnvType.CLIENT) public record Tile(int width, int height) implements GuiSpriteScaling { public static final MapCodec CODEC = RecordCodecBuilder.mapCodec( instance -> instance.group( ExtraCodecs.POSITIVE_INT.fieldOf("width").forGetter(GuiSpriteScaling.Tile::width), ExtraCodecs.POSITIVE_INT.fieldOf("height").forGetter(GuiSpriteScaling.Tile::height) ) .apply(instance, GuiSpriteScaling.Tile::new) ); @Override public GuiSpriteScaling.Type type() { return GuiSpriteScaling.Type.TILE; } } @Environment(EnvType.CLIENT) public static enum Type implements StringRepresentable { STRETCH("stretch", GuiSpriteScaling.Stretch.CODEC), TILE("tile", GuiSpriteScaling.Tile.CODEC), NINE_SLICE("nine_slice", GuiSpriteScaling.NineSlice.CODEC); public static final Codec CODEC = StringRepresentable.fromEnum(GuiSpriteScaling.Type::values); private final String key; private final MapCodec codec; private Type(final String key, final MapCodec codec) { this.key = key; this.codec = codec; } @Override public String getSerializedName() { return this.key; } public MapCodec codec() { return this.codec; } } }