Skip to content
This repository has been archived by the owner on Jan 24, 2022. It is now read-only.

Commit

Permalink
new: Flatten multipart model selector predicates
Browse files Browse the repository at this point in the history
  • Loading branch information
jellysquid3 committed Sep 3, 2020
1 parent 4d891e6 commit ef7c4f9
Show file tree
Hide file tree
Showing 12 changed files with 392 additions and 45 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package me.jellysquid.mods.hydrogen.common.state;

import me.jellysquid.mods.hydrogen.common.state.all.AllMatchOneBoolean;
import me.jellysquid.mods.hydrogen.common.state.all.AllMatchOneObject;
import me.jellysquid.mods.hydrogen.common.state.any.AllMatchAnyObject;
import me.jellysquid.mods.hydrogen.common.state.single.SingleMatchAny;
import me.jellysquid.mods.hydrogen.common.state.single.SingleMatchOne;
import me.jellysquid.mods.hydrogen.common.util.AllPredicate;
import me.jellysquid.mods.hydrogen.common.util.AnyPredicate;
import net.minecraft.block.BlockState;

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]));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package me.jellysquid.mods.hydrogen.common.state.all;

import me.jellysquid.mods.hydrogen.common.state.single.SingleMatchOne;
import net.minecraft.block.BlockState;
import net.minecraft.state.property.Property;

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.get(this.properties[i]);

if (value != this.values[i]) {
return false;
}
}

return true;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package me.jellysquid.mods.hydrogen.common.state.all;

import me.jellysquid.mods.hydrogen.common.state.single.SingleMatchOne;
import net.minecraft.block.BlockState;
import net.minecraft.state.property.Property;

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.get(this.properties[i]) != this.values[i]) {
return false;
}
}

return true;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package me.jellysquid.mods.hydrogen.common.state.any;

import me.jellysquid.mods.hydrogen.common.state.single.SingleMatchAny;
import net.minecraft.block.BlockState;
import net.minecraft.state.property.Property;
import org.apache.commons.lang3.ArrayUtils;

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.get(this.properties[i]))) {
return false;
}
}

return true;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package me.jellysquid.mods.hydrogen.common.state.single;

import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet;
import net.minecraft.block.BlockState;
import net.minecraft.state.property.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.get(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;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package me.jellysquid.mods.hydrogen.common.state.single;

import net.minecraft.block.BlockState;
import net.minecraft.state.property.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.get(this.property) == this.value;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package me.jellysquid.mods.hydrogen.common.util;

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;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package me.jellysquid.mods.hydrogen.common.util;

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;
}
}
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
package me.jellysquid.mods.hydrogen.mixin.client.model.json;

import me.jellysquid.mods.hydrogen.common.collections.CollectionHelper;
import com.google.common.collect.Streams;
import me.jellysquid.mods.hydrogen.common.state.StatePropertyPredicateHelper;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.client.render.model.json.AndMultipartModelSelector;
import net.minecraft.client.render.model.json.MultipartModelSelector;
import net.minecraft.state.StateManager;
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 org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;

import java.util.Collection;
import java.util.List;
import java.util.stream.Collector;
import java.util.function.Predicate;
import java.util.stream.Collectors;

@Mixin(AndMultipartModelSelector.class)
Expand All @@ -20,12 +21,14 @@ public class MixinAndMultipartModelSelector {
@Final
private Iterable<? extends MultipartModelSelector> selectors;

@Redirect(method = "getPredicate", at = @At(value = "INVOKE", target = "Ljava/util/stream/Collectors;toList()Ljava/util/stream/Collector;"))
private <T> Collector<T, ?, List<T>> redirectGetPredicateCollector() {
if (this.selectors instanceof Collection) {
return CollectionHelper.toSizedList(((Collection<?>) this.selectors).size());
}

return Collectors.toList();
/**
* @author JellySquid
* @reason Flatten predicates
*/
@Overwrite
public Predicate<BlockState> getPredicate(StateManager<Block, BlockState> stateManager) {
return StatePropertyPredicateHelper.allMatch(Streams.stream(this.selectors).map((multipartModelSelector) -> {
return multipartModelSelector.getPredicate(stateManager);
}).collect(Collectors.toList()));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package me.jellysquid.mods.hydrogen.mixin.client.model.json;

import com.google.common.collect.Streams;
import me.jellysquid.mods.hydrogen.common.state.StatePropertyPredicateHelper;
import me.jellysquid.mods.hydrogen.common.util.AnyPredicate;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.client.render.model.json.MultipartModelSelector;
import net.minecraft.client.render.model.json.OrMultipartModelSelector;
import net.minecraft.state.StateManager;
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(OrMultipartModelSelector.class)
public class MixinOrMultipartModelSelector {
@Shadow @Final private Iterable<? extends MultipartModelSelector> selectors;

/**
* @author JellySquid
* @reason Flatten predicates
*/
@Overwrite
public Predicate<BlockState> getPredicate(StateManager<Block, BlockState> stateManager) {
return StatePropertyPredicateHelper.anyMatch(Streams.stream(this.selectors).map((multipartModelSelector) -> {
return multipartModelSelector.getPredicate(stateManager);
}).collect(Collectors.toList()));
}
}
Loading

0 comments on commit ef7c4f9

Please sign in to comment.