Add model predicate flattening
This commit is contained in:
parent
6b28cb5ebc
commit
f2de12329e
|
|
@ -35,6 +35,7 @@ public class ModernFixEarlyConfig {
|
|||
this.addMixinRule("perf.parallel_blockstate_cache_rebuild", true);
|
||||
this.addMixinRule("perf.compress_biome_container", true);
|
||||
this.addMixinRule("perf.nuke_empty_chunk_sections", true);
|
||||
this.addMixinRule("perf.flatten_model_predicates", true);
|
||||
this.addMixinRule("perf.deduplicate_location", true);
|
||||
this.addMixinRule("safety", true);
|
||||
this.addMixinRule("launch.transformer_cache", false);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,32 @@
|
|||
package org.embeddedt.modernfix.mixin.perf.flatten_model_predicates;
|
||||
|
||||
import com.google.common.collect.Streams;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.client.renderer.model.multipart.AndCondition;
|
||||
import net.minecraft.client.renderer.model.multipart.ICondition;
|
||||
import net.minecraft.state.StateContainer;
|
||||
import org.embeddedt.modernfix.predicate.StatePropertyPredicateHelper;
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Overwrite;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Mixin(AndCondition.class)
|
||||
public class AndConditionMixin {
|
||||
@Shadow @Final private Iterable<? extends ICondition> conditions;
|
||||
|
||||
/**
|
||||
* @author JellySquid
|
||||
* @reason Flatten predicates
|
||||
*/
|
||||
@Overwrite
|
||||
public Predicate<BlockState> getPredicate(StateContainer<Block, BlockState> stateManager) {
|
||||
return StatePropertyPredicateHelper.allMatch(Streams.stream(this.conditions).map((multipartModelSelector) -> {
|
||||
return multipartModelSelector.getPredicate(stateManager);
|
||||
}).collect(Collectors.toList()));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
package org.embeddedt.modernfix.mixin.perf.flatten_model_predicates;
|
||||
|
||||
import com.google.common.collect.Streams;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.client.renderer.model.multipart.ICondition;
|
||||
import net.minecraft.client.renderer.model.multipart.OrCondition;
|
||||
import net.minecraft.state.StateContainer;
|
||||
import org.embeddedt.modernfix.predicate.StatePropertyPredicateHelper;
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Overwrite;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Mixin(OrCondition.class)
|
||||
public class OrConditionMixin {
|
||||
@Shadow @Final private Iterable<? extends ICondition> conditions;
|
||||
|
||||
/**
|
||||
* @author JellySquid
|
||||
* @reason Flatten predicates
|
||||
*/
|
||||
@Overwrite
|
||||
public Predicate<BlockState> getPredicate(StateContainer<Block, BlockState> stateManager) {
|
||||
return StatePropertyPredicateHelper.anyMatch(Streams.stream(this.conditions).map((multipartModelSelector) -> {
|
||||
return multipartModelSelector.getPredicate(stateManager);
|
||||
}).collect(Collectors.toList()));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
package org.embeddedt.modernfix.mixin.perf.flatten_model_predicates;
|
||||
|
||||
import com.google.common.base.Splitter;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.client.renderer.model.multipart.PropertyValueCondition;
|
||||
import net.minecraft.state.Property;
|
||||
import net.minecraft.state.StateContainer;
|
||||
import org.embeddedt.modernfix.predicate.single.SingleMatchAny;
|
||||
import org.embeddedt.modernfix.predicate.single.SingleMatchOne;
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Overwrite;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Mixin(PropertyValueCondition.class)
|
||||
public class PropertyValueConditionMixin {
|
||||
@Shadow @Final private String key;
|
||||
|
||||
@Shadow @Final private String value;
|
||||
|
||||
@Shadow @Final private static Splitter PIPE_SPLITTER;
|
||||
|
||||
/**
|
||||
* @author JellySquid
|
||||
* @reason De-duplication
|
||||
*/
|
||||
@Overwrite
|
||||
public Predicate<BlockState> getPredicate(StateContainer<Block, BlockState> stateManager) {
|
||||
Property<?> property = stateManager.getProperty(this.key);
|
||||
|
||||
if (property == null) {
|
||||
throw new RuntimeException(String.format("Unknown property '%s' on '%s'", this.key, stateManager.getOwner().toString()));
|
||||
}
|
||||
|
||||
String valueString = this.value;
|
||||
boolean negate = !valueString.isEmpty() && valueString.charAt(0) == '!';
|
||||
|
||||
if (negate) {
|
||||
valueString = valueString.substring(1);
|
||||
}
|
||||
|
||||
List<String> split = PIPE_SPLITTER.splitToList(valueString);
|
||||
|
||||
if (split.isEmpty()) {
|
||||
throw new RuntimeException(String.format("Empty value '%s' for property '%s' on '%s'", this.value, this.key, stateManager.getOwner().toString()));
|
||||
}
|
||||
|
||||
Predicate<BlockState> predicate;
|
||||
|
||||
if (split.size() == 1) {
|
||||
predicate = new SingleMatchOne(property, this.getPropertyValue(stateManager, property, valueString));
|
||||
} else {
|
||||
predicate = SingleMatchAny.create(property, split.stream()
|
||||
.map(str -> this.getPropertyValue(stateManager, property, str))
|
||||
.collect(Collectors.toList()));
|
||||
}
|
||||
|
||||
return negate ? predicate.negate() : predicate;
|
||||
}
|
||||
|
||||
private Object getPropertyValue(StateContainer<Block, BlockState> stateFactory, Property<?> property, String valueString) {
|
||||
Object value = property.getValue(valueString)
|
||||
.orElse(null);
|
||||
|
||||
if (value == null) {
|
||||
throw new RuntimeException(String.format("Unknown value '%s' for property '%s' on '%s' in '%s'",
|
||||
valueString, this.key, stateFactory.getOwner().toString(), this.value));
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
package org.embeddedt.modernfix.predicate;
|
||||
|
||||
import java.util.function.Predicate;
|
||||
|
||||
public class AllPredicate<T> implements Predicate<T> {
|
||||
private final Predicate<T>[] predicates;
|
||||
|
||||
public AllPredicate(Predicate<T>[] predicates) {
|
||||
this.predicates = predicates;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean test(T t) {
|
||||
for (Predicate<T> predicate : this.predicates) {
|
||||
if (!predicate.test(t)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
package org.embeddedt.modernfix.predicate;
|
||||
|
||||
import java.util.function.Predicate;
|
||||
|
||||
public class AnyPredicate<T> implements Predicate<T> {
|
||||
private final Predicate<T>[] predicates;
|
||||
|
||||
public AnyPredicate(Predicate<T>[] predicates) {
|
||||
this.predicates = predicates;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean test(T t) {
|
||||
for (Predicate<T> predicate : this.predicates) {
|
||||
if (predicate.test(t)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
package org.embeddedt.modernfix.predicate;
|
||||
|
||||
import me.jellysquid.mods.hydrogen.common.state.all.AllMatchOneBoolean;
|
||||
import net.minecraft.block.BlockState;
|
||||
import org.embeddedt.modernfix.predicate.all.AllMatchOneObject;
|
||||
import org.embeddedt.modernfix.predicate.any.AllMatchAnyObject;
|
||||
import org.embeddedt.modernfix.predicate.single.SingleMatchAny;
|
||||
import org.embeddedt.modernfix.predicate.single.SingleMatchOne;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
public class StatePropertyPredicateHelper {
|
||||
@SuppressWarnings("unchecked")
|
||||
public static Predicate<BlockState> allMatch(List<Predicate<BlockState>> predicates) {
|
||||
if (SingleMatchOne.areOfType(predicates)) {
|
||||
if (SingleMatchOne.valuesMatchType(predicates, Boolean.class)) {
|
||||
return new AllMatchOneBoolean(predicates);
|
||||
}
|
||||
|
||||
return new AllMatchOneObject(predicates);
|
||||
} else if (SingleMatchAny.areOfType(predicates)) {
|
||||
return new AllMatchAnyObject(predicates);
|
||||
}
|
||||
|
||||
return new AllPredicate<>(predicates.toArray(new Predicate[0]));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static Predicate<BlockState> anyMatch(List<Predicate<BlockState>> predicates) {
|
||||
return new AnyPredicate<>(predicates.toArray(new Predicate[0]));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
package me.jellysquid.mods.hydrogen.common.state.all;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.state.Property;
|
||||
import org.embeddedt.modernfix.predicate.single.SingleMatchOne;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
public class AllMatchOneBoolean implements Predicate<BlockState> {
|
||||
private final Property<?>[] properties;
|
||||
private final boolean[] values;
|
||||
|
||||
public AllMatchOneBoolean(List<Predicate<BlockState>> list) {
|
||||
int size = list.size();
|
||||
|
||||
this.properties = new Property[size];
|
||||
this.values = new boolean[size];
|
||||
|
||||
for (int i = 0; i < size; i++) {
|
||||
SingleMatchOne predicate = (SingleMatchOne) list.get(i);
|
||||
|
||||
this.properties[i] = predicate.property;
|
||||
this.values[i] = (boolean) predicate.value;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean canReplace(List<Predicate<BlockState>> list) {
|
||||
return list.stream()
|
||||
.allMatch(p -> {
|
||||
return p instanceof SingleMatchOne && ((SingleMatchOne) p).value instanceof Boolean;
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean test(BlockState blockState) {
|
||||
for (int i = 0; i < this.properties.length; i++) {
|
||||
Boolean value = (Boolean) blockState.getValue(this.properties[i]);
|
||||
|
||||
if (value != this.values[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
package org.embeddedt.modernfix.predicate.all;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.state.Property;
|
||||
import org.embeddedt.modernfix.predicate.single.SingleMatchOne;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
public class AllMatchOneObject implements Predicate<BlockState> {
|
||||
private final Property<?>[] properties;
|
||||
private final Object[] values;
|
||||
|
||||
public AllMatchOneObject(List<Predicate<BlockState>> list) {
|
||||
int size = list.size();
|
||||
|
||||
this.properties = new Property[size];
|
||||
this.values = new Object[size];
|
||||
|
||||
for (int i = 0; i < size; i++) {
|
||||
SingleMatchOne predicate = (SingleMatchOne) list.get(i);
|
||||
|
||||
this.properties[i] = predicate.property;
|
||||
this.values[i] = predicate.value;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean test(BlockState blockState) {
|
||||
for (int i = 0; i < this.properties.length; i++) {
|
||||
if (blockState.getValue(this.properties[i]) != this.values[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
package org.embeddedt.modernfix.predicate.any;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.state.Property;
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
import org.embeddedt.modernfix.predicate.single.SingleMatchAny;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
public class AllMatchAnyObject implements Predicate<BlockState> {
|
||||
private final Property<?>[] properties;
|
||||
private final Object[][] values;
|
||||
|
||||
public AllMatchAnyObject(List<Predicate<BlockState>> list) {
|
||||
int size = list.size();
|
||||
|
||||
this.properties = new Property[size];
|
||||
this.values = new Object[size][];
|
||||
|
||||
for (int i = 0; i < size; i++) {
|
||||
SingleMatchAny predicate = (SingleMatchAny) list.get(i);
|
||||
|
||||
this.properties[i] = predicate.property;
|
||||
this.values[i] = predicate.values;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean test(BlockState blockState) {
|
||||
for (int i = 0; i < this.properties.length; i++) {
|
||||
if (!ArrayUtils.contains(this.values[i], blockState.getValue(this.properties[i]))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
package org.embeddedt.modernfix.predicate.single;
|
||||
|
||||
import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.state.Property;
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
public class SingleMatchAny implements Predicate<BlockState> {
|
||||
public static final ObjectOpenHashSet<SingleMatchAny> PREDICATES = new ObjectOpenHashSet<>();
|
||||
|
||||
public final Property<?> property;
|
||||
public final Object[] values;
|
||||
|
||||
private SingleMatchAny(Property<?> property, List<Object> values) {
|
||||
this.property = property;
|
||||
this.values = values.toArray();
|
||||
}
|
||||
|
||||
public static SingleMatchAny create(Property<?> property, List<Object> values) {
|
||||
return PREDICATES.addOrGet(new SingleMatchAny(property, values));
|
||||
}
|
||||
|
||||
public static boolean areOfType(List<Predicate<BlockState>> predicates) {
|
||||
return predicates.stream()
|
||||
.allMatch(p -> {
|
||||
return p instanceof SingleMatchAny;
|
||||
});
|
||||
}
|
||||
|
||||
public static boolean valuesMatchType(List<Predicate<BlockState>> predicates, Class<?> type) {
|
||||
return predicates.stream()
|
||||
.allMatch(p -> {
|
||||
return p instanceof SingleMatchAny &&
|
||||
Arrays.stream(((SingleMatchAny) p).values).allMatch(t -> type.isInstance(p));
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean test(BlockState blockState) {
|
||||
return ArrayUtils.contains(this.values, blockState.getValue(this.property));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
SingleMatchAny that = (SingleMatchAny) o;
|
||||
return Objects.equals(property, that.property) &&
|
||||
Arrays.equals(values, that.values);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = Objects.hash(property);
|
||||
result = 31 * result + Arrays.hashCode(values);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
package org.embeddedt.modernfix.predicate.single;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.state.Property;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
public class SingleMatchOne implements Predicate<BlockState> {
|
||||
public final Property<?> property;
|
||||
public final Object value;
|
||||
|
||||
public SingleMatchOne(Property<?> property, Object value) {
|
||||
this.property = property;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public static boolean areOfType(List<Predicate<BlockState>> predicates) {
|
||||
return predicates.stream()
|
||||
.allMatch(p -> {
|
||||
return p instanceof SingleMatchOne;
|
||||
});
|
||||
}
|
||||
|
||||
public static boolean valuesMatchType(List<Predicate<BlockState>> predicates, Class<?> type) {
|
||||
return predicates.stream()
|
||||
.allMatch(p -> {
|
||||
return p instanceof SingleMatchOne && type.isInstance(((SingleMatchOne) p).value);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean test(BlockState blockState) {
|
||||
return blockState.getValue(this.property) == this.value;
|
||||
}
|
||||
}
|
||||
|
|
@ -7,7 +7,6 @@
|
|||
"refmap": "modernfix.refmap.json",
|
||||
"mixins": [
|
||||
"bugfix.edge_chunk_not_saved.ChunkManagerMixin",
|
||||
"feature.measure_time.MinecraftMixin",
|
||||
"perf.remove_biome_temperature_cache.BiomeMixin",
|
||||
"perf.resourcepacks.ModFileResourcePackMixin",
|
||||
"perf.resourcepacks.VanillaPackMixin",
|
||||
|
|
@ -28,6 +27,7 @@
|
|||
"perf.nuke_empty_chunk_sections.MixinChunk"
|
||||
],
|
||||
"client": [
|
||||
"feature.measure_time.MinecraftMixin",
|
||||
"perf.skip_first_datapack_reload.MinecraftMixin",
|
||||
"bugfix.concurrency.RenderTypeMixin",
|
||||
"bugfix.concurrency.MinecraftMixin",
|
||||
|
|
@ -40,7 +40,10 @@
|
|||
"perf.async_jei.PluginCallerMixin",
|
||||
"perf.async_jei.RecipeManagerInternalMixin",
|
||||
"perf.thread_priorities.IntegratedServerMixin",
|
||||
"safety.BlockColorsMixin"
|
||||
"safety.BlockColorsMixin",
|
||||
"perf.flatten_model_predicates.AndConditionMixin",
|
||||
"perf.flatten_model_predicates.OrConditionMixin",
|
||||
"perf.flatten_model_predicates.PropertyValueConditionMixin"
|
||||
],
|
||||
"injectors": {
|
||||
"defaultRequire": 1
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user