package net.minecraft.world.level.block.state; import com.google.common.base.MoreObjects; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSortedMap; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.mojang.datafixers.util.Pair; import com.mojang.serialization.Codec; import com.mojang.serialization.Decoder; import com.mojang.serialization.Encoder; import com.mojang.serialization.MapCodec; import it.unimi.dsi.fastutil.objects.Reference2ObjectArrayMap; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.function.Function; import java.util.function.Supplier; import java.util.regex.Pattern; import java.util.stream.Collectors; import java.util.stream.Stream; import javax.annotation.Nullable; import net.minecraft.world.level.block.state.properties.Property; public class StateDefinition> { static final Pattern NAME_PATTERN = Pattern.compile("^[a-z0-9_]+$"); private final O owner; private final ImmutableSortedMap> propertiesByName; private final ImmutableList states; protected StateDefinition(Function p_61052_, O p_61053_, StateDefinition.Factory p_61054_, Map> p_61055_) { this.owner = p_61053_; this.propertiesByName = ImmutableSortedMap.copyOf(p_61055_); Supplier supplier = () -> p_61052_.apply(p_61053_); MapCodec mapcodec = MapCodec.of(Encoder.empty(), Decoder.unit(supplier)); for (Entry> entry : this.propertiesByName.entrySet()) { mapcodec = appendPropertyCodec(mapcodec, supplier, entry.getKey(), entry.getValue()); } MapCodec mapcodec1 = mapcodec; Map, Comparable>, S> map = Maps.newLinkedHashMap(); List list = Lists.newArrayList(); Stream, Comparable>>> stream = Stream.of(Collections.emptyList()); for (Property property : this.propertiesByName.values()) { stream = stream.flatMap(p_360551_ -> property.getPossibleValues().stream().map(p_155961_ -> { List, Comparable>> list1 = Lists.newArrayList(p_360551_); list1.add(Pair.of(property, p_155961_)); return list1; })); } stream.forEach(p_327405_ -> { Reference2ObjectArrayMap, Comparable> reference2objectarraymap = new Reference2ObjectArrayMap<>(p_327405_.size()); for (Pair, Comparable> pair : p_327405_) { reference2objectarraymap.put(pair.getFirst(), pair.getSecond()); } S s1 = p_61054_.create(p_61053_, reference2objectarraymap, mapcodec1); map.put(reference2objectarraymap, s1); list.add(s1); }); for (S s : list) { s.populateNeighbours(map); } this.states = ImmutableList.copyOf(list); } private static , T extends Comparable> MapCodec appendPropertyCodec( MapCodec p_61077_, Supplier p_61078_, String p_61079_, Property p_61080_ ) { return Codec.mapPair(p_61077_, p_61080_.valueCodec().fieldOf(p_61079_).orElseGet(p_187541_ -> {}, () -> p_61080_.value(p_61078_.get()))) .xmap( p_187536_ -> p_187536_.getFirst().setValue(p_61080_, p_187536_.getSecond().value()), p_187533_ -> Pair.of((S)p_187533_, p_61080_.value(p_187533_)) ); } public ImmutableList getPossibleStates() { return this.states; } public S any() { return this.states.get(0); } public O getOwner() { return this.owner; } public Collection> getProperties() { return this.propertiesByName.values(); } @Override public String toString() { return MoreObjects.toStringHelper(this) .add("block", this.owner) .add("properties", this.propertiesByName.values().stream().map(Property::getName).collect(Collectors.toList())) .toString(); } @Nullable public Property getProperty(String p_61082_) { return this.propertiesByName.get(p_61082_); } public static class Builder> { private final O owner; private final Map> properties = Maps.newHashMap(); public Builder(O p_61098_) { this.owner = p_61098_; } public StateDefinition.Builder add(Property... p_61105_) { for (Property property : p_61105_) { this.validateProperty(property); this.properties.put(property.getName(), property); } return this; } private > void validateProperty(Property p_61100_) { String s = p_61100_.getName(); if (!StateDefinition.NAME_PATTERN.matcher(s).matches()) { throw new IllegalArgumentException(this.owner + " has invalidly named property: " + s); } else { Collection collection = p_61100_.getPossibleValues(); if (collection.size() <= 1) { throw new IllegalArgumentException(this.owner + " attempted use property " + s + " with <= 1 possible values"); } else { for (T t : collection) { String s1 = p_61100_.getName(t); if (!StateDefinition.NAME_PATTERN.matcher(s1).matches()) { throw new IllegalArgumentException(this.owner + " has property: " + s + " with invalidly named value: " + s1); } } if (this.properties.containsKey(s)) { throw new IllegalArgumentException(this.owner + " has duplicate property: " + s); } } } } public StateDefinition create(Function p_61102_, StateDefinition.Factory p_61103_) { return new StateDefinition<>(p_61102_, this.owner, p_61103_, this.properties); } } public interface Factory { S create(O p_61107_, Reference2ObjectArrayMap, Comparable> p_328366_, MapCodec p_61109_); } }