162 lines
6.4 KiB
Java
162 lines
6.4 KiB
Java
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<O, S extends StateHolder<O, S>> {
|
|
static final Pattern NAME_PATTERN = Pattern.compile("^[a-z0-9_]+$");
|
|
private final O owner;
|
|
private final ImmutableSortedMap<String, Property<?>> propertiesByName;
|
|
private final ImmutableList<S> states;
|
|
|
|
protected StateDefinition(Function<O, S> p_61052_, O p_61053_, StateDefinition.Factory<O, S> p_61054_, Map<String, Property<?>> p_61055_) {
|
|
this.owner = p_61053_;
|
|
this.propertiesByName = ImmutableSortedMap.copyOf(p_61055_);
|
|
Supplier<S> supplier = () -> p_61052_.apply(p_61053_);
|
|
MapCodec<S> mapcodec = MapCodec.of(Encoder.empty(), Decoder.unit(supplier));
|
|
|
|
for (Entry<String, Property<?>> entry : this.propertiesByName.entrySet()) {
|
|
mapcodec = appendPropertyCodec(mapcodec, supplier, entry.getKey(), entry.getValue());
|
|
}
|
|
|
|
MapCodec<S> mapcodec1 = mapcodec;
|
|
Map<Map<Property<?>, Comparable<?>>, S> map = Maps.newLinkedHashMap();
|
|
List<S> list = Lists.newArrayList();
|
|
Stream<List<Pair<Property<?>, Comparable<?>>>> stream = Stream.of(Collections.emptyList());
|
|
|
|
for (Property<?> property : this.propertiesByName.values()) {
|
|
stream = stream.flatMap(p_360551_ -> property.getPossibleValues().stream().map(p_155961_ -> {
|
|
List<Pair<Property<?>, Comparable<?>>> list1 = Lists.newArrayList(p_360551_);
|
|
list1.add(Pair.of(property, p_155961_));
|
|
return list1;
|
|
}));
|
|
}
|
|
|
|
stream.forEach(p_327405_ -> {
|
|
Reference2ObjectArrayMap<Property<?>, Comparable<?>> reference2objectarraymap = new Reference2ObjectArrayMap<>(p_327405_.size());
|
|
|
|
for (Pair<Property<?>, 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 <S extends StateHolder<?, S>, T extends Comparable<T>> MapCodec<S> appendPropertyCodec(
|
|
MapCodec<S> p_61077_, Supplier<S> p_61078_, String p_61079_, Property<T> 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<S> getPossibleStates() {
|
|
return this.states;
|
|
}
|
|
|
|
public S any() {
|
|
return this.states.get(0);
|
|
}
|
|
|
|
public O getOwner() {
|
|
return this.owner;
|
|
}
|
|
|
|
public Collection<Property<?>> 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<O, S extends StateHolder<O, S>> {
|
|
private final O owner;
|
|
private final Map<String, Property<?>> properties = Maps.newHashMap();
|
|
|
|
public Builder(O p_61098_) {
|
|
this.owner = p_61098_;
|
|
}
|
|
|
|
public StateDefinition.Builder<O, S> add(Property<?>... p_61105_) {
|
|
for (Property<?> property : p_61105_) {
|
|
this.validateProperty(property);
|
|
this.properties.put(property.getName(), property);
|
|
}
|
|
|
|
return this;
|
|
}
|
|
|
|
private <T extends Comparable<T>> void validateProperty(Property<T> 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<T> 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<O, S> create(Function<O, S> p_61102_, StateDefinition.Factory<O, S> p_61103_) {
|
|
return new StateDefinition<>(p_61102_, this.owner, p_61103_, this.properties);
|
|
}
|
|
}
|
|
|
|
public interface Factory<O, S> {
|
|
S create(O p_61107_, Reference2ObjectArrayMap<Property<?>, Comparable<?>> p_328366_, MapCodec<S> p_61109_);
|
|
}
|
|
} |