Skip to content

Instantly share code, notes, and snippets.

@Sollace
Last active April 8, 2020 19:49
Show Gist options
  • Save Sollace/4bc682784670e85ad5b944fb5ea3e819 to your computer and use it in GitHub Desktop.
Save Sollace/4bc682784670e85ad5b944fb5ea3e819 to your computer and use it in GitHub Desktop.
import net.minecraft.client.model.ModelPart;
import net.minecraft.client.render.VertexConsumer;
import net.minecraft.client.util.math.MatrixStack;
import javax.annotation.Nullable;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.function.Consumer;
import java.util.function.Supplier;
@SuppressWarnings("unchecked")
public abstract class RenderList<T> implements Iterable<T> {
private static final RenderConsumer<ModelPart> MODEL_PART_CONSUMER = ModelPart::render;
public static RenderList<ModelPart> of(Iterable<ModelPart> list) {
return of(list, MODEL_PART_CONSUMER);
}
public static <T> RenderList<T> of(Iterable<T> list, RenderConsumer<T> consumer) {
return new Impl<>(toArray(list), consumer);
}
public static RenderList<ModelPart> create(Supplier<Iterable<ModelPart>> factory) {
return create(factory, MODEL_PART_CONSUMER);
}
public static <T> RenderList<T> create(Supplier<Iterable<T>> factory, RenderConsumer<T> consumer) {
return new Lazy<>(() -> toArray(factory.get()), consumer);
}
private static <T> Object[] toArray(Iterable<T> list) {
if (list instanceof RenderList) {
return ((RenderList<T>)list).values();
}
@SuppressWarnings("serial")
List<T> items = new LinkedList<T>() {
@Override
public boolean add(T t) {
return super.add(Objects.requireNonNull(t));
}
};
list.forEach(items::add);
return items.toArray();
}
private final RenderConsumer<T> consumer;
private RenderList(RenderConsumer<T> consumer) {
this.consumer = consumer;
}
abstract Object[] values();
public void render(MatrixStack matrices, VertexConsumer vertices, int light, int overlay, float red, float green, float blue, float alpha) {
Object[] values = values();
for (int i = 0; i < values.length; i++) {
consumer.render((T)values[i], matrices, vertices, light, overlay, red, green, blue, alpha);
}
}
public RenderList<T> concat(Iterable<T> other) {
return new Lazy<>(() -> {
Object[] myArr = values();
Object[] otherArr = toArray(other);
Object[] combined = new Object[myArr.length + otherArr.length];
System.arraycopy(myArr, 0, combined, 0, myArr.length);
System.arraycopy(otherArr, 0, combined, myArr.length, otherArr.length);
return combined;
}, consumer);
}
@Override
public void forEach(Consumer<? super T> action) {
Objects.requireNonNull(action);
Object[] values = values();
for (int i = 0; i < values.length; i++) {
action.accept((T)values[i]);
}
}
@Override
public Iterator<T> iterator() {
return new Iterator<T>() {
private int index;
private final Object[] values = values();
@Override
public boolean hasNext() {
return index < values.length;
}
@Override
public T next() {
if (++index < values.length) {
return (T)values[index];
}
throw new NoSuchElementException();
}
};
}
private static final class Lazy<T> extends RenderList<T> {
private final Supplier<Object[]> factory;
@Nullable
Object[] values;
Lazy(Supplier<Object[]> factory, RenderConsumer<T> consumer) {
super(consumer);
this.factory = factory;
}
@Override
Object[] values() {
if (values == null) {
values = factory.get();
}
return values;
}
}
private static final class Impl<T> extends RenderList<T> {
private final Object[] values;
Impl(Object[] values, RenderConsumer<T> consumer) {
super(consumer);
this.values = values;
}
@Override
Object[] values() {
return values;
}
}
public interface RenderConsumer<T> {
void render(T obj, MatrixStack matrices, VertexConsumer vertices, int light, int overlay, float red, float green, float blue, float alpha);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment