package de.take_weiland.mods.commons.meta; import net.minecraft.item.ItemStack; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; /** * <p>Factory methods for MetadataProperties.</p> * * @author diesieben07 * @see de.take_weiland.mods.commons.meta.MetadataProperty */ public final class MetaProperties { /** * <p>Create a MetadataProperty, whose values are the constants of the given enum class.</p> * * @param startBit the first bit containing the data (0-31) * @param clazz the enum class * @param <T> the type of the values * @return a MetadataProperty */ public static <T extends Enum<T>> MetadataProperty<T> newProperty(int startBit, Class<T> clazz) { return new EnumProperty<>(checkBit(startBit), checkNotNull(clazz, "clazz")); } /** * <p>Create a MetadataProperty, whose values are given those of the given array.</p> * <p>The array must not be modified after being passed to this method.</p> * * @param startBit the first bit containing the data (0-31) * @param values the values for this property * @param <T> the type of the values * @return a MetadataProperty */ @SafeVarargs public static <T> MetadataProperty<T> newProperty(int startBit, T... values) { checkBit(startBit); int len = checkNotNull(values, "values").length; checkArgument(len >= 2, "Need at least 2 elements"); return new RegularArrayProperty<>(startBit, values); } /** * @deprecated use {@link #newProperty(int, Class)} for Enum properties */ @Deprecated @SafeVarargs public static <T extends Enum<T>> MetadataProperty<T> newProperty(int startBit, T... values) { throw new UnsupportedOperationException(); } /** * <p>Create a new MetadataProperty, representing a boolean value.</p> * * @param startBit the bit containing the data (0-31) * @return a BooleanProperty */ public static BooleanProperty newBooleanProperty(int startBit) { return BooleanPropertyImpl.get(checkBit(startBit)); } /** * <p>Create a new MetadataProperty, representing an integer value</p> * <p>This property can hold values from 0 through 2<sup>bits</sup> - 1</p> * * @param startBit the first bit containing the data (0-31) * @param bits the number of bits to reserve (1-32) * @return an IntProperty */ public static IntProperty newIntProperty(int startBit, int bits) { return new IntPropertyImpl(checkBit(startBit), checkBitCount(bits)); } /** * <p>Create a metadata value that represents both the first and then second value.</p> * * @param p1 the first MetadataProperty * @param v1 the value for the first property * @param p2 the second MetadataProperty * @param v2 the value for the second property * @return a metadata value */ public static <A, B> int combine(MetadataProperty<? super A> p1, A v1, MetadataProperty<? super B> p2, B v2) { return apply(0, p1, v1, p2, v2); } /** * <p>Apply both the first and the second value to the ItemStack.</p> * * @param p1 the first MetadataProperty * @param v1 the value for the first property * @param p2 the second MetadataProperty * @param v2 the value for the second property */ public static <A, B> void apply(ItemStack stack, MetadataProperty<? super A> p1, A v1, MetadataProperty<? super B> p2, B v2) { stack.setItemDamage(apply(stack.getItemDamage(), p1, v1, p2, v2)); } /** * <p>Apply both the first and the second value to the given metadata.</p> * * @param meta the original metadata * @param p1 the first MetadataProperty * @param v1 the value for the first property * @param p2 the second MetadataProperty * @param v2 the value for the second property * @return the new metadata */ public static <A, B> int apply(int meta, MetadataProperty<? super A> p1, A v1, MetadataProperty<? super B> p2, B v2) { return p2.toMeta(v2, p1.toMeta(v1, meta)); } /** * <p>Create a metadata value that represents all three values.</p> * * @param p1 the first MetadataProperty * @param v1 the value for the first property * @param p2 the second MetadataProperty * @param v2 the value for the second property * @param p3 the third MetadataProperty * @param v3 the value for the third property * @return a metadata value */ public static <A, B, C> int combine(MetadataProperty<? super A> p1, A v1, MetadataProperty<? super B> p2, B v2, MetadataProperty<? super C> p3, C v3) { return apply(0, p1, v1, p2, v2, p3, v3); } /** * <p>Apply all three values to the ItemStack.</p> * * @param p1 the first MetadataProperty * @param v1 the value for the first property * @param p2 the second MetadataProperty * @param v2 the value for the second property * @param p3 the third MetadataProperty * @param v3 the value for the third property */ public static <A, B, C> void apply(ItemStack stack, MetadataProperty<? super A> p1, A v1, MetadataProperty<? super B> p2, B v2, MetadataProperty<? super C> p3, C v3) { stack.setItemDamage(apply(stack.getItemDamage(), p1, v1, p2, v2, p3, v3)); } /** * <p>Apply all three value to the given metadata.</p> * * @param p1 the first MetadataProperty * @param v1 the value for the first property * @param p2 the second MetadataProperty * @param v2 the value for the second property * @param p3 the third MetadataProperty * @param v3 the value for the third property * @return the new metadata */ public static <A, B, C> int apply(int meta, MetadataProperty<? super A> p1, A v1, MetadataProperty<? super B> p2, B v2, MetadataProperty<? super C> p3, C v3) { return p3.toMeta(v3, p2.toMeta(v2, p1.toMeta(v1, meta))); } // going beyond 3 is madness, for anything more use the MetaBuilder private static int checkBit(int bit) { checkArgument(bit >= 0 && bit <= 31, "Invalid start bit"); return bit; } private static int checkBitCount(int bits) { checkArgument(bits >= 1 && bits <= 32, "Invalid bit count"); return bits; } }