package net.minecraft.client.data.models.blockstates; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Maps; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.function.BiFunction; import java.util.function.Function; import java.util.stream.Collectors; import java.util.stream.Stream; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; import net.minecraft.world.level.block.state.properties.Property; @Environment(EnvType.CLIENT) public abstract class PropertyDispatch { private final Map> values = Maps.>newHashMap(); protected void putValue(Selector selector, List variants) { List list = (List)this.values.put(selector, variants); if (list != null) { throw new IllegalStateException("Value " + selector + " is already defined"); } } Map> getEntries() { this.verifyComplete(); return ImmutableMap.copyOf(this.values); } private void verifyComplete() { List> list = this.getDefinedProperties(); Stream stream = Stream.of(Selector.empty()); for (Property property : list) { stream = stream.flatMap(selector -> property.getAllValues().map(selector::extend)); } List list2 = (List)stream.filter(selector -> !this.values.containsKey(selector)).collect(Collectors.toList()); if (!list2.isEmpty()) { throw new IllegalStateException("Missing definition for properties: " + list2); } } abstract List> getDefinedProperties(); public static > PropertyDispatch.C1 property(Property property1) { return new PropertyDispatch.C1<>(property1); } public static , T2 extends Comparable> PropertyDispatch.C2 properties(Property property1, Property property2) { return new PropertyDispatch.C2<>(property1, property2); } public static , T2 extends Comparable, T3 extends Comparable> PropertyDispatch.C3 properties( Property property1, Property property2, Property property3 ) { return new PropertyDispatch.C3<>(property1, property2, property3); } public static , T2 extends Comparable, T3 extends Comparable, T4 extends Comparable> PropertyDispatch.C4 properties( Property property1, Property property2, Property property3, Property property4 ) { return new PropertyDispatch.C4<>(property1, property2, property3, property4); } public static , T2 extends Comparable, T3 extends Comparable, T4 extends Comparable, T5 extends Comparable> PropertyDispatch.C5 properties( Property property1, Property property2, Property property3, Property property4, Property property5 ) { return new PropertyDispatch.C5<>(property1, property2, property3, property4, property5); } @Environment(EnvType.CLIENT) public static class C1> extends PropertyDispatch { private final Property property1; C1(Property property1) { this.property1 = property1; } @Override public List> getDefinedProperties() { return ImmutableList.of(this.property1); } public PropertyDispatch.C1 select(T1 value1, List variants) { Selector selector = Selector.of(this.property1.value(value1)); this.putValue(selector, variants); return this; } public PropertyDispatch.C1 select(T1 value1, Variant variant) { return this.select(value1, Collections.singletonList(variant)); } public PropertyDispatch generate(Function generator) { this.property1.getPossibleValues().forEach(comparable -> this.select((T1)comparable, (Variant)generator.apply(comparable))); return this; } public PropertyDispatch generateList(Function> generator) { this.property1.getPossibleValues().forEach(comparable -> this.select((T1)comparable, (List)generator.apply(comparable))); return this; } } @Environment(EnvType.CLIENT) public static class C2, T2 extends Comparable> extends PropertyDispatch { private final Property property1; private final Property property2; C2(Property property1, Property property2) { this.property1 = property1; this.property2 = property2; } @Override public List> getDefinedProperties() { return ImmutableList.of(this.property1, this.property2); } public PropertyDispatch.C2 select(T1 value1, T2 value2, List variants) { Selector selector = Selector.of(this.property1.value(value1), this.property2.value(value2)); this.putValue(selector, variants); return this; } public PropertyDispatch.C2 select(T1 value1, T2 value2, Variant variant) { return this.select(value1, value2, Collections.singletonList(variant)); } public PropertyDispatch generate(BiFunction generator) { this.property1 .getPossibleValues() .forEach( comparable -> this.property2 .getPossibleValues() .forEach(comparable2 -> this.select((T1)comparable, (T2)comparable2, (Variant)generator.apply(comparable, comparable2))) ); return this; } public PropertyDispatch generateList(BiFunction> generator) { this.property1 .getPossibleValues() .forEach( comparable -> this.property2 .getPossibleValues() .forEach(comparable2 -> this.select((T1)comparable, (T2)comparable2, (List)generator.apply(comparable, comparable2))) ); return this; } } @Environment(EnvType.CLIENT) public static class C3, T2 extends Comparable, T3 extends Comparable> extends PropertyDispatch { private final Property property1; private final Property property2; private final Property property3; C3(Property property1, Property property2, Property property3) { this.property1 = property1; this.property2 = property2; this.property3 = property3; } @Override public List> getDefinedProperties() { return ImmutableList.of(this.property1, this.property2, this.property3); } public PropertyDispatch.C3 select(T1 value1, T2 value2, T3 value3, List variants) { Selector selector = Selector.of(this.property1.value(value1), this.property2.value(value2), this.property3.value(value3)); this.putValue(selector, variants); return this; } public PropertyDispatch.C3 select(T1 value1, T2 value2, T3 value3, Variant variant) { return this.select(value1, value2, value3, Collections.singletonList(variant)); } public PropertyDispatch generate(PropertyDispatch.TriFunction generator) { this.property1 .getPossibleValues() .forEach( comparable -> this.property2 .getPossibleValues() .forEach( comparable2 -> this.property3 .getPossibleValues() .forEach( comparable3 -> this.select((T1)comparable, (T2)comparable2, (T3)comparable3, generator.apply((T1)comparable, (T2)comparable2, (T3)comparable3)) ) ) ); return this; } public PropertyDispatch generateList(PropertyDispatch.TriFunction> generator) { this.property1 .getPossibleValues() .forEach( comparable -> this.property2 .getPossibleValues() .forEach( comparable2 -> this.property3 .getPossibleValues() .forEach( comparable3 -> this.select((T1)comparable, (T2)comparable2, (T3)comparable3, generator.apply((T1)comparable, (T2)comparable2, (T3)comparable3)) ) ) ); return this; } } @Environment(EnvType.CLIENT) public static class C4, T2 extends Comparable, T3 extends Comparable, T4 extends Comparable> extends PropertyDispatch { private final Property property1; private final Property property2; private final Property property3; private final Property property4; C4(Property property1, Property property2, Property property3, Property property4) { this.property1 = property1; this.property2 = property2; this.property3 = property3; this.property4 = property4; } @Override public List> getDefinedProperties() { return ImmutableList.of(this.property1, this.property2, this.property3, this.property4); } public PropertyDispatch.C4 select(T1 value1, T2 value2, T3 value3, T4 value4, List variants) { Selector selector = Selector.of(this.property1.value(value1), this.property2.value(value2), this.property3.value(value3), this.property4.value(value4)); this.putValue(selector, variants); return this; } public PropertyDispatch.C4 select(T1 value1, T2 value2, T3 value3, T4 value4, Variant variant) { return this.select(value1, value2, value3, value4, Collections.singletonList(variant)); } public PropertyDispatch generate(PropertyDispatch.QuadFunction generator) { this.property1 .getPossibleValues() .forEach( comparable -> this.property2 .getPossibleValues() .forEach( comparable2 -> this.property3 .getPossibleValues() .forEach( comparable3 -> this.property4 .getPossibleValues() .forEach( comparable4 -> this.select( (T1)comparable, (T2)comparable2, (T3)comparable3, (T4)comparable4, generator.apply((T1)comparable, (T2)comparable2, (T3)comparable3, (T4)comparable4) ) ) ) ) ); return this; } public PropertyDispatch generateList(PropertyDispatch.QuadFunction> generator) { this.property1 .getPossibleValues() .forEach( comparable -> this.property2 .getPossibleValues() .forEach( comparable2 -> this.property3 .getPossibleValues() .forEach( comparable3 -> this.property4 .getPossibleValues() .forEach( comparable4 -> this.select( (T1)comparable, (T2)comparable2, (T3)comparable3, (T4)comparable4, generator.apply((T1)comparable, (T2)comparable2, (T3)comparable3, (T4)comparable4) ) ) ) ) ); return this; } } @Environment(EnvType.CLIENT) public static class C5, T2 extends Comparable, T3 extends Comparable, T4 extends Comparable, T5 extends Comparable> extends PropertyDispatch { private final Property property1; private final Property property2; private final Property property3; private final Property property4; private final Property property5; C5(Property property1, Property property2, Property property3, Property property4, Property property5) { this.property1 = property1; this.property2 = property2; this.property3 = property3; this.property4 = property4; this.property5 = property5; } @Override public List> getDefinedProperties() { return ImmutableList.of(this.property1, this.property2, this.property3, this.property4, this.property5); } public PropertyDispatch.C5 select(T1 value1, T2 value2, T3 value3, T4 value4, T5 value5, List variants) { Selector selector = Selector.of( this.property1.value(value1), this.property2.value(value2), this.property3.value(value3), this.property4.value(value4), this.property5.value(value5) ); this.putValue(selector, variants); return this; } public PropertyDispatch.C5 select(T1 value1, T2 value2, T3 value3, T4 value4, T5 value5, Variant variant) { return this.select(value1, value2, value3, value4, value5, Collections.singletonList(variant)); } public PropertyDispatch generate(PropertyDispatch.PentaFunction generator) { this.property1 .getPossibleValues() .forEach( comparable -> this.property2 .getPossibleValues() .forEach( comparable2 -> this.property3 .getPossibleValues() .forEach( comparable3 -> this.property4 .getPossibleValues() .forEach( comparable4 -> this.property5 .getPossibleValues() .forEach( comparable5 -> this.select( (T1)comparable, (T2)comparable2, (T3)comparable3, (T4)comparable4, (T5)comparable5, generator.apply((T1)comparable, (T2)comparable2, (T3)comparable3, (T4)comparable4, (T5)comparable5) ) ) ) ) ) ); return this; } public PropertyDispatch generateList(PropertyDispatch.PentaFunction> generator) { this.property1 .getPossibleValues() .forEach( comparable -> this.property2 .getPossibleValues() .forEach( comparable2 -> this.property3 .getPossibleValues() .forEach( comparable3 -> this.property4 .getPossibleValues() .forEach( comparable4 -> this.property5 .getPossibleValues() .forEach( comparable5 -> this.select( (T1)comparable, (T2)comparable2, (T3)comparable3, (T4)comparable4, (T5)comparable5, generator.apply((T1)comparable, (T2)comparable2, (T3)comparable3, (T4)comparable4, (T5)comparable5) ) ) ) ) ) ); return this; } } @FunctionalInterface @Environment(EnvType.CLIENT) public interface PentaFunction { R apply(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5); } @FunctionalInterface @Environment(EnvType.CLIENT) public interface QuadFunction { R apply(P1 p1, P2 p2, P3 p3, P4 p4); } @FunctionalInterface @Environment(EnvType.CLIENT) public interface TriFunction { R apply(P1 object, P2 object2, P3 object3); } }