package net.minecraft.stats; import java.util.Objects; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.core.registries.Registries; import net.minecraft.network.RegistryFriendlyByteBuf; import net.minecraft.network.codec.ByteBufCodecs; import net.minecraft.network.codec.StreamCodec; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.scores.criteria.ObjectiveCriteria; import org.jetbrains.annotations.Nullable; /** * An immutable statistic to be counted for a particular entry in the {@linkplain #type}'s registry. This is used as a key in a {@link net.minecraft.stats.StatsCounter} for a corresponding count. *

* By default, the statistic's {@linkplain #getName() name} is formatted {@code .:.}, as created by {@link #buildName(StatType, Object)}. * * @param the type of the registry entry for this statistic * @see net.minecraft.stats.StatType * @see net.minecraft.stats.Stats */ public class Stat extends ObjectiveCriteria { public static final StreamCodec> STREAM_CODEC = ByteBufCodecs.registry(Registries.STAT_TYPE) .dispatch(Stat::getType, StatType::streamCodec); private final StatFormatter formatter; /** * The registry entry for this statistic. */ private final T value; /** * The parent statistic type. */ private final StatType type; protected Stat(StatType type, T value, StatFormatter formatter) { super(buildName(type, value)); this.type = type; this.formatter = formatter; this.value = value; } /** * @return the name for the specified {@code type} and {@code value} in the form {@code .:.} */ public static String buildName(StatType type, T value) { return locationToKey(BuiltInRegistries.STAT_TYPE.getKey(type)) + ":" + locationToKey(type.getRegistry().getKey(value)); } /** * @return the specified {@code location} as a string with {@code .} as the separator character */ private static String locationToKey(@Nullable ResourceLocation location) { return location.toString().replace(':', '.'); } public StatType getType() { return this.type; } public T getValue() { return this.value; } public String format(int value) { return this.formatter.format(value); } public boolean equals(Object object) { return this == object || object instanceof Stat && Objects.equals(this.getName(), ((Stat)object).getName()); } public int hashCode() { return this.getName().hashCode(); } public String toString() { return "Stat{name=" + this.getName() + ", formatter=" + this.formatter + "}"; } }