mirror of
https://github.com/MinecraftForge/MinecraftForge.git
synced 2026-11-12 08:17:35 +00:00
[1.16] Add missing Multipart Blockstate Builder feature: Nested condition groups (#7677)
This commit is contained in:
1 parent
9d0d249eaf
commit
7bf02e7dcd
1 file changed
+161
-16
+161
-16
@@ -29,6 +29,7 @@ import com.google.common.base.Preconditions;
|
||||
import com.google.common.collect.Multimap;
|
||||
import com.google.common.collect.MultimapBuilder;
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
@@ -75,11 +76,15 @@ public final class MultiPartBlockStateBuilder implements IGeneratedBlockstate {
|
||||
public BlockStateProvider.ConfiguredModelList models;
|
||||
public boolean useOr;
|
||||
public final Multimap<Property<?>, Comparable<?>> conditions = MultimapBuilder.linkedHashKeys().arrayListValues().build();
|
||||
public final List<ConditionGroup> nestedConditionGroups = new ArrayList<>();
|
||||
|
||||
PartBuilder(BlockStateProvider.ConfiguredModelList models) {
|
||||
this.models = models;
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes this part get applied if any of the conditions/condition groups are true, instead of all of them needing to be true.
|
||||
*/
|
||||
public PartBuilder useOr() {
|
||||
this.useOr = true;
|
||||
return this;
|
||||
@@ -99,6 +104,7 @@ public final class MultiPartBlockStateBuilder implements IGeneratedBlockstate {
|
||||
* @throws IllegalArgumentException if {@code prop} has already been configured
|
||||
* @throws IllegalArgumentException if {@code prop} is not applicable to the
|
||||
* current block's state
|
||||
* @throws IllegalStateException if {@code !nestedConditionGroups.isEmpty()}
|
||||
*/
|
||||
@SafeVarargs
|
||||
public final <T extends Comparable<T>> PartBuilder condition(Property<T> prop, T... values) {
|
||||
@@ -107,31 +113,33 @@ public final class MultiPartBlockStateBuilder implements IGeneratedBlockstate {
|
||||
Preconditions.checkArgument(values.length > 0, "Value list must not be empty");
|
||||
Preconditions.checkArgument(!conditions.containsKey(prop), "Cannot set condition for property \"%s\" more than once", prop.getName());
|
||||
Preconditions.checkArgument(canApplyTo(owner), "IProperty %s is not valid for the block %s", prop, owner);
|
||||
Preconditions.checkState(nestedConditionGroups.isEmpty(), "Can't have normal conditions if there are already nested condition groups");
|
||||
this.conditions.putAll(prop, Arrays.asList(values));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows having nested groups of conditions if there are not any normal conditions.
|
||||
* @throws IllegalStateException if {@code !conditions.isEmpty()}
|
||||
*/
|
||||
public final ConditionGroup nestedGroup()
|
||||
{
|
||||
Preconditions.checkState(conditions.isEmpty(), "Can't have nested condition groups if there are already normal conditions");
|
||||
ConditionGroup group = new ConditionGroup();
|
||||
this.nestedConditionGroups.add(group);
|
||||
return group;
|
||||
}
|
||||
|
||||
public MultiPartBlockStateBuilder end() { return MultiPartBlockStateBuilder.this; }
|
||||
|
||||
JsonObject toJson() {
|
||||
JsonObject out = new JsonObject();
|
||||
if (!conditions.isEmpty()) {
|
||||
JsonObject when = new JsonObject();
|
||||
for (Entry<Property<?>, Collection<Comparable<?>>> e : conditions.asMap().entrySet()) {
|
||||
StringBuilder activeString = new StringBuilder();
|
||||
for (Comparable<?> val : e.getValue()) {
|
||||
if (activeString.length() > 0)
|
||||
activeString.append("|");
|
||||
activeString.append(((Property) e.getKey()).getName(val));
|
||||
}
|
||||
when.addProperty(e.getKey().getName(), activeString.toString());
|
||||
}
|
||||
if (useOr) {
|
||||
JsonObject innerWhen = when;
|
||||
when = new JsonObject();
|
||||
when.add("OR", innerWhen);
|
||||
}
|
||||
out.add("when", when);
|
||||
out.add("when", MultiPartBlockStateBuilder.toJson(this.conditions, this.useOr));
|
||||
}
|
||||
else if (!nestedConditionGroups.isEmpty())
|
||||
{
|
||||
out.add("when", MultiPartBlockStateBuilder.toJson(this.nestedConditionGroups, this.useOr));
|
||||
}
|
||||
out.add("apply", models.toJSON());
|
||||
return out;
|
||||
@@ -140,5 +148,142 @@ public final class MultiPartBlockStateBuilder implements IGeneratedBlockstate {
|
||||
public boolean canApplyTo(Block b) {
|
||||
return b.getStateDefinition().getProperties().containsAll(conditions.keySet());
|
||||
}
|
||||
|
||||
public class ConditionGroup
|
||||
{
|
||||
public final Multimap<Property<?>, Comparable<?>> conditions = MultimapBuilder.linkedHashKeys().arrayListValues().build();
|
||||
public final List<ConditionGroup> nestedConditionGroups = new ArrayList<>();
|
||||
private ConditionGroup parent = null;
|
||||
public boolean useOr;
|
||||
|
||||
/**
|
||||
* Set a condition for this part, which consists of a property and a set of
|
||||
* valid values. Can be called multiple times for multiple different properties.
|
||||
*
|
||||
* @param <T> the type of the property value
|
||||
* @param prop the property
|
||||
* @param values a set of valid values
|
||||
* @return this builder
|
||||
* @throws NullPointerException if {@code prop} is {@code null}
|
||||
* @throws NullPointerException if {@code values} is {@code null}
|
||||
* @throws IllegalArgumentException if {@code values} is empty
|
||||
* @throws IllegalArgumentException if {@code prop} has already been configured
|
||||
* @throws IllegalArgumentException if {@code prop} is not applicable to the
|
||||
* current block's state
|
||||
* @throws IllegalStateException if {@code !nestedConditionGroups.isEmpty()}
|
||||
*/
|
||||
@SafeVarargs
|
||||
public final <T extends Comparable<T>> ConditionGroup condition(Property<T> prop, T... values)
|
||||
{
|
||||
Preconditions.checkNotNull(prop, "Property must not be null");
|
||||
Preconditions.checkNotNull(values, "Value list must not be null");
|
||||
Preconditions.checkArgument(values.length > 0, "Value list must not be empty");
|
||||
Preconditions.checkArgument(!conditions.containsKey(prop), "Cannot set condition for property \"%s\" more than once", prop.getName());
|
||||
Preconditions.checkArgument(canApplyTo(owner), "IProperty %s is not valid for the block %s", prop, owner);
|
||||
Preconditions.checkState(nestedConditionGroups.isEmpty(), "Can't have normal conditions if there are already nested condition groups");
|
||||
this.conditions.putAll(prop, Arrays.asList(values));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows having nested groups of conditions if there are not any normal conditions.
|
||||
* @throws IllegalStateException if {@code !conditions.isEmpty()}
|
||||
*/
|
||||
public ConditionGroup nestedGroup()
|
||||
{
|
||||
Preconditions.checkState(conditions.isEmpty(), "Can't have nested condition groups if there are already normal conditions");
|
||||
ConditionGroup group = new ConditionGroup();
|
||||
group.parent = this;
|
||||
this.nestedConditionGroups.add(group);
|
||||
return group;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ends this nested condition group and returns the parent condition group
|
||||
*
|
||||
* @throws IllegalStateException If this is not a nested condition group
|
||||
*/
|
||||
public ConditionGroup endNestedGroup()
|
||||
{
|
||||
if (parent == null)
|
||||
throw new IllegalStateException("This condition group is not nested, use end() instead");
|
||||
return parent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ends this condition group and returns the part builder
|
||||
*
|
||||
* @throws IllegalStateException If this is a nested condition group
|
||||
*/
|
||||
public MultiPartBlockStateBuilder.PartBuilder end()
|
||||
{
|
||||
if (this.parent != null)
|
||||
throw new IllegalStateException("This is a nested condition group, use endNestedGroup() instead");
|
||||
return MultiPartBlockStateBuilder.PartBuilder.this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes this part get applied if any of the conditions/condition groups are true, instead of all of them needing to be true.
|
||||
*/
|
||||
public ConditionGroup useOr()
|
||||
{
|
||||
this.useOr = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
JsonObject toJson()
|
||||
{
|
||||
if (!this.conditions.isEmpty())
|
||||
{
|
||||
return MultiPartBlockStateBuilder.toJson(this.conditions, this.useOr);
|
||||
}
|
||||
else if (!this.nestedConditionGroups.isEmpty())
|
||||
{
|
||||
return MultiPartBlockStateBuilder.toJson(this.nestedConditionGroups, this.useOr);
|
||||
}
|
||||
return new JsonObject();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static JsonObject toJson(List<PartBuilder.ConditionGroup> conditions, boolean useOr)
|
||||
{
|
||||
JsonObject groupJson = new JsonObject();
|
||||
JsonArray innerGroupJson = new JsonArray();
|
||||
groupJson.add(useOr ? "OR" : "AND", innerGroupJson);
|
||||
for (PartBuilder.ConditionGroup group : conditions)
|
||||
{
|
||||
innerGroupJson.add(group.toJson());
|
||||
}
|
||||
return groupJson;
|
||||
}
|
||||
|
||||
private static JsonObject toJson(Multimap<Property<?>, Comparable<?>> conditions, boolean useOr)
|
||||
{
|
||||
JsonObject groupJson = new JsonObject();
|
||||
for (Entry<Property<?>, Collection<Comparable<?>>> e : conditions.asMap().entrySet())
|
||||
{
|
||||
StringBuilder activeString = new StringBuilder();
|
||||
for (Comparable<?> val : e.getValue())
|
||||
{
|
||||
if (activeString.length() > 0)
|
||||
activeString.append("|");
|
||||
activeString.append(((Property) e.getKey()).getName(val));
|
||||
}
|
||||
groupJson.addProperty(e.getKey().getName(), activeString.toString());
|
||||
}
|
||||
if (useOr)
|
||||
{
|
||||
JsonArray innerWhen = new JsonArray();
|
||||
for (Entry<String, JsonElement> entry : groupJson.entrySet())
|
||||
{
|
||||
JsonObject obj = new JsonObject();
|
||||
obj.add(entry.getKey(), entry.getValue());
|
||||
innerWhen.add(obj);
|
||||
}
|
||||
groupJson = new JsonObject();
|
||||
groupJson.add("OR", innerWhen);
|
||||
}
|
||||
return groupJson;
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user