mirror of
https://github.com/Jozufozu/Flywheel.git
synced 2025-02-03 16:54:57 +01:00
Treefactors
- Add MeshTree and InstanceTree - Deprecate ModelPartConverter for removal - Refactor ChestVisual to use InstanceTree - Combine double chest light in ChestVisual
This commit is contained in:
parent
ddb0450105
commit
295ebc7573
13 changed files with 668 additions and 83 deletions
|
@ -1,11 +1,15 @@
|
||||||
package dev.engine_room.flywheel.lib.internal;
|
package dev.engine_room.flywheel.lib.internal;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
|
||||||
import com.mojang.blaze3d.vertex.PoseStack;
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
|
import com.mojang.blaze3d.vertex.VertexConsumer;
|
||||||
|
|
||||||
import dev.engine_room.flywheel.api.internal.DependencyInjection;
|
import dev.engine_room.flywheel.api.internal.DependencyInjection;
|
||||||
import dev.engine_room.flywheel.lib.transform.PoseTransformStack;
|
import dev.engine_room.flywheel.lib.transform.PoseTransformStack;
|
||||||
|
import net.minecraft.client.model.geom.ModelPart;
|
||||||
|
|
||||||
public interface FlwLibLink {
|
public interface FlwLibLink {
|
||||||
FlwLibLink INSTANCE = DependencyInjection.load(FlwLibLink.class, "dev.engine_room.flywheel.impl.FlwLibLinkImpl");
|
FlwLibLink INSTANCE = DependencyInjection.load(FlwLibLink.class, "dev.engine_room.flywheel.impl.FlwLibLinkImpl");
|
||||||
|
@ -13,4 +17,8 @@ public interface FlwLibLink {
|
||||||
Logger getLogger();
|
Logger getLogger();
|
||||||
|
|
||||||
PoseTransformStack getPoseTransformStackOf(PoseStack stack);
|
PoseTransformStack getPoseTransformStackOf(PoseStack stack);
|
||||||
|
|
||||||
|
Map<String, ModelPart> getModelPartChildren(ModelPart part);
|
||||||
|
|
||||||
|
void compileModelPart(ModelPart part, PoseStack.Pose pose, VertexConsumer consumer, int light, int overlay, float red, float green, float blue, float alpha);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
package dev.engine_room.flywheel.lib.model;
|
||||||
|
|
||||||
|
import org.joml.Vector4fc;
|
||||||
|
|
||||||
|
import dev.engine_room.flywheel.api.model.IndexSequence;
|
||||||
|
import dev.engine_room.flywheel.api.model.Mesh;
|
||||||
|
import dev.engine_room.flywheel.api.vertex.MutableVertexList;
|
||||||
|
import dev.engine_room.flywheel.lib.vertex.VertexTransformations;
|
||||||
|
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||||
|
|
||||||
|
public record RetexturedMesh(Mesh mesh, TextureAtlasSprite sprite) implements Mesh {
|
||||||
|
@Override
|
||||||
|
public int vertexCount() {
|
||||||
|
return mesh.vertexCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(MutableVertexList vertexList) {
|
||||||
|
mesh.write(vertexList);
|
||||||
|
VertexTransformations.retexture(vertexList, sprite);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IndexSequence indexSequence() {
|
||||||
|
return mesh.indexSequence();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int indexCount() {
|
||||||
|
return mesh.indexCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Vector4fc boundingSphere() {
|
||||||
|
return mesh.boundingSphere();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,295 @@
|
||||||
|
package dev.engine_room.flywheel.lib.model.part;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.NoSuchElementException;
|
||||||
|
import java.util.function.BiFunction;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
import java.util.function.ObjIntConsumer;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.ApiStatus;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import org.jetbrains.annotations.Unmodifiable;
|
||||||
|
import org.joml.Quaternionf;
|
||||||
|
import org.joml.Vector3fc;
|
||||||
|
|
||||||
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
|
|
||||||
|
import dev.engine_room.flywheel.api.instance.InstancerProvider;
|
||||||
|
import dev.engine_room.flywheel.api.material.Material;
|
||||||
|
import dev.engine_room.flywheel.api.model.Mesh;
|
||||||
|
import dev.engine_room.flywheel.api.model.Model;
|
||||||
|
import dev.engine_room.flywheel.lib.instance.InstanceTypes;
|
||||||
|
import dev.engine_room.flywheel.lib.instance.TransformedInstance;
|
||||||
|
import dev.engine_room.flywheel.lib.model.ModelCache;
|
||||||
|
import dev.engine_room.flywheel.lib.model.SingleMeshModel;
|
||||||
|
import net.minecraft.client.model.geom.ModelLayerLocation;
|
||||||
|
import net.minecraft.client.model.geom.ModelPart;
|
||||||
|
import net.minecraft.client.model.geom.PartPose;
|
||||||
|
|
||||||
|
public final class InstanceTree {
|
||||||
|
private static final ModelCache<Model.ConfiguredMesh> MODEL_CACHE = new ModelCache<>(entry -> new SingleMeshModel(entry.mesh(), entry.material()));
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private final TransformedInstance instance;
|
||||||
|
private final PartPose initialPose;
|
||||||
|
@Unmodifiable
|
||||||
|
private final Map<String, InstanceTree> children;
|
||||||
|
|
||||||
|
private final Quaternionf rotation = new Quaternionf();
|
||||||
|
|
||||||
|
public float x;
|
||||||
|
public float y;
|
||||||
|
public float z;
|
||||||
|
public float xRot;
|
||||||
|
public float yRot;
|
||||||
|
public float zRot;
|
||||||
|
public float xScale;
|
||||||
|
public float yScale;
|
||||||
|
public float zScale;
|
||||||
|
public boolean visible = true;
|
||||||
|
public boolean skipDraw;
|
||||||
|
|
||||||
|
private InstanceTree(@Nullable TransformedInstance instance, PartPose initialPose, @Unmodifiable Map<String, InstanceTree> children) {
|
||||||
|
this.instance = instance;
|
||||||
|
this.initialPose = initialPose;
|
||||||
|
this.children = children;
|
||||||
|
resetPose();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static InstanceTree create(InstancerProvider provider, MeshTree meshTree, BiFunction<String, Mesh, Model.ConfiguredMesh> meshFinalizerFunc, String path) {
|
||||||
|
Map<String, InstanceTree> children = new HashMap<>();
|
||||||
|
String pathSlash = path + "/";
|
||||||
|
|
||||||
|
meshTree.children().forEach((name, meshTreeChild) -> {
|
||||||
|
children.put(name, InstanceTree.create(provider, meshTreeChild, meshFinalizerFunc, pathSlash + name));
|
||||||
|
});
|
||||||
|
|
||||||
|
Mesh mesh = meshTree.mesh();
|
||||||
|
TransformedInstance instance;
|
||||||
|
if (mesh != null) {
|
||||||
|
Model.ConfiguredMesh configuredMesh = meshFinalizerFunc.apply(path, mesh);
|
||||||
|
instance = provider.instancer(InstanceTypes.TRANSFORMED, MODEL_CACHE.get(configuredMesh))
|
||||||
|
.createInstance();
|
||||||
|
} else {
|
||||||
|
instance = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new InstanceTree(instance, meshTree.initialPose(), Collections.unmodifiableMap(children));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static InstanceTree create(InstancerProvider provider, MeshTree meshTree, BiFunction<String, Mesh, Model.ConfiguredMesh> meshFinalizerFunc) {
|
||||||
|
return create(provider, meshTree, meshFinalizerFunc, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static InstanceTree create(InstancerProvider provider, ModelLayerLocation layer, BiFunction<String, Mesh, Model.ConfiguredMesh> meshFinalizerFunc) {
|
||||||
|
return create(provider, MeshTree.of(layer), meshFinalizerFunc);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static InstanceTree create(InstancerProvider provider, MeshTree meshTree, Material material) {
|
||||||
|
return create(provider, meshTree, (path, mesh) -> new Model.ConfiguredMesh(material, mesh));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static InstanceTree create(InstancerProvider provider, ModelLayerLocation layer, Material material) {
|
||||||
|
return create(provider, MeshTree.of(layer), material);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public TransformedInstance instance() {
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PartPose initialPose() {
|
||||||
|
return initialPose;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Unmodifiable
|
||||||
|
public Map<String, InstanceTree> children() {
|
||||||
|
return children;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasChild(String name) {
|
||||||
|
return children.containsKey(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public InstanceTree child(String name) {
|
||||||
|
return children.get(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public InstanceTree childOrThrow(String name) {
|
||||||
|
InstanceTree child = child(name);
|
||||||
|
|
||||||
|
if (child == null) {
|
||||||
|
throw new NoSuchElementException("Can't find part " + name);
|
||||||
|
}
|
||||||
|
|
||||||
|
return child;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void traverse(Consumer<? super TransformedInstance> consumer) {
|
||||||
|
if (instance != null) {
|
||||||
|
consumer.accept(instance);
|
||||||
|
}
|
||||||
|
for (InstanceTree child : children.values()) {
|
||||||
|
child.traverse(consumer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ApiStatus.Experimental
|
||||||
|
public void traverse(int i, ObjIntConsumer<? super TransformedInstance> consumer) {
|
||||||
|
if (instance != null) {
|
||||||
|
consumer.accept(instance, i);
|
||||||
|
}
|
||||||
|
for (InstanceTree child : children.values()) {
|
||||||
|
child.traverse(i, consumer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ApiStatus.Experimental
|
||||||
|
public void traverse(int i, int j, ObjIntIntConsumer<? super TransformedInstance> consumer) {
|
||||||
|
if (instance != null) {
|
||||||
|
consumer.accept(instance, i, j);
|
||||||
|
}
|
||||||
|
for (InstanceTree child : children.values()) {
|
||||||
|
child.traverse(i, j, consumer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void translateAndRotate(PoseStack poseStack) {
|
||||||
|
poseStack.translate(x / 16.0F, y / 16.0F, z / 16.0F);
|
||||||
|
|
||||||
|
if (xRot != 0.0F || yRot != 0.0F || zRot != 0.0F) {
|
||||||
|
poseStack.mulPose(rotation.rotationZYX(zRot, yRot, xRot));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (xScale != 1.0F || yScale != 1.0F || zScale != 1.0F) {
|
||||||
|
poseStack.scale(xScale, yScale, zScale);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateInstances(PoseStack poseStack) {
|
||||||
|
if (visible) {
|
||||||
|
poseStack.pushPose();
|
||||||
|
translateAndRotate(poseStack);
|
||||||
|
|
||||||
|
if (instance != null && !skipDraw) {
|
||||||
|
instance.setTransform(poseStack.last())
|
||||||
|
.setChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (InstanceTree child : children.values()) {
|
||||||
|
child.updateInstances(poseStack);
|
||||||
|
}
|
||||||
|
|
||||||
|
poseStack.popPose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void pos(float x, float y, float z) {
|
||||||
|
this.x = x;
|
||||||
|
this.y = y;
|
||||||
|
this.z = z;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void rotation(float xRot, float yRot, float zRot) {
|
||||||
|
this.xRot = xRot;
|
||||||
|
this.yRot = yRot;
|
||||||
|
this.zRot = zRot;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void scale(float xScale, float yScale, float zScale) {
|
||||||
|
this.xScale = xScale;
|
||||||
|
this.yScale = yScale;
|
||||||
|
this.zScale = zScale;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void offsetPos(float xOffset, float yOffset, float zOffset) {
|
||||||
|
x += xOffset;
|
||||||
|
y += yOffset;
|
||||||
|
z += zOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void offsetRotation(float xOffset, float yOffset, float zOffset) {
|
||||||
|
xRot += xOffset;
|
||||||
|
yRot += yOffset;
|
||||||
|
zRot += zOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void offsetScale(float xOffset, float yOffset, float zOffset) {
|
||||||
|
xScale += xOffset;
|
||||||
|
yScale += yOffset;
|
||||||
|
zScale += zOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void offsetPos(Vector3fc offset) {
|
||||||
|
offsetPos(offset.x(), offset.y(), offset.z());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void offsetRotation(Vector3fc offset) {
|
||||||
|
offsetRotation(offset.x(), offset.y(), offset.z());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void offsetScale(Vector3fc offset) {
|
||||||
|
offsetScale(offset.x(), offset.y(), offset.z());
|
||||||
|
}
|
||||||
|
|
||||||
|
public PartPose storePose() {
|
||||||
|
return PartPose.offsetAndRotation(x, y, z, xRot, yRot, zRot);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void loadPose(PartPose pose) {
|
||||||
|
x = pose.x;
|
||||||
|
y = pose.y;
|
||||||
|
z = pose.z;
|
||||||
|
xRot = pose.xRot;
|
||||||
|
yRot = pose.yRot;
|
||||||
|
zRot = pose.zRot;
|
||||||
|
xScale = ModelPart.DEFAULT_SCALE;
|
||||||
|
yScale = ModelPart.DEFAULT_SCALE;
|
||||||
|
zScale = ModelPart.DEFAULT_SCALE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void resetPose() {
|
||||||
|
loadPose(initialPose);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void copyTransform(InstanceTree tree) {
|
||||||
|
x = tree.x;
|
||||||
|
y = tree.y;
|
||||||
|
z = tree.z;
|
||||||
|
xRot = tree.xRot;
|
||||||
|
yRot = tree.yRot;
|
||||||
|
zRot = tree.zRot;
|
||||||
|
xScale = tree.xScale;
|
||||||
|
yScale = tree.yScale;
|
||||||
|
zScale = tree.zScale;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void copyTransform(ModelPart modelPart) {
|
||||||
|
x = modelPart.x;
|
||||||
|
y = modelPart.y;
|
||||||
|
z = modelPart.z;
|
||||||
|
xRot = modelPart.xRot;
|
||||||
|
yRot = modelPart.yRot;
|
||||||
|
zRot = modelPart.zRot;
|
||||||
|
xScale = modelPart.xScale;
|
||||||
|
yScale = modelPart.yScale;
|
||||||
|
zScale = modelPart.zScale;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void delete() {
|
||||||
|
if (instance != null) {
|
||||||
|
instance.delete();
|
||||||
|
}
|
||||||
|
children.values()
|
||||||
|
.forEach(InstanceTree::delete);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ApiStatus.Experimental
|
||||||
|
@FunctionalInterface
|
||||||
|
public interface ObjIntIntConsumer<T> {
|
||||||
|
void accept(T t, int i, int j);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,136 @@
|
||||||
|
package dev.engine_room.flywheel.lib.model.part;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.NoSuchElementException;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.ApiStatus;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import org.jetbrains.annotations.Unmodifiable;
|
||||||
|
|
||||||
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
|
|
||||||
|
import dev.engine_room.flywheel.api.model.Mesh;
|
||||||
|
import dev.engine_room.flywheel.lib.internal.FlwLibLink;
|
||||||
|
import dev.engine_room.flywheel.lib.memory.MemoryBlock;
|
||||||
|
import dev.engine_room.flywheel.lib.model.SimpleQuadMesh;
|
||||||
|
import dev.engine_room.flywheel.lib.vertex.PosTexNormalVertexView;
|
||||||
|
import dev.engine_room.flywheel.lib.vertex.VertexView;
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
import net.minecraft.client.model.geom.EntityModelSet;
|
||||||
|
import net.minecraft.client.model.geom.ModelLayerLocation;
|
||||||
|
import net.minecraft.client.model.geom.ModelPart;
|
||||||
|
import net.minecraft.client.model.geom.PartPose;
|
||||||
|
import net.minecraft.client.renderer.LightTexture;
|
||||||
|
import net.minecraft.client.renderer.texture.OverlayTexture;
|
||||||
|
|
||||||
|
public final class MeshTree {
|
||||||
|
private static final ThreadLocal<ThreadLocalObjects> THREAD_LOCAL_OBJECTS = ThreadLocal.withInitial(ThreadLocalObjects::new);
|
||||||
|
private static final PoseStack.Pose IDENTITY_POSE = new PoseStack().last();
|
||||||
|
private static final Map<ModelLayerLocation, MeshTree> CACHE = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private final Mesh mesh;
|
||||||
|
private final PartPose initialPose;
|
||||||
|
@Unmodifiable
|
||||||
|
private final Map<String, MeshTree> children;
|
||||||
|
|
||||||
|
private MeshTree(@Nullable Mesh mesh, PartPose initialPose, @Unmodifiable Map<String, MeshTree> children) {
|
||||||
|
this.mesh = mesh;
|
||||||
|
this.initialPose = initialPose;
|
||||||
|
this.children = children;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static MeshTree of(ModelLayerLocation layer) {
|
||||||
|
return CACHE.computeIfAbsent(layer, MeshTree::convert);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static MeshTree convert(ModelLayerLocation layer) {
|
||||||
|
EntityModelSet entityModels = Minecraft.getInstance()
|
||||||
|
.getEntityModels();
|
||||||
|
ModelPart modelPart = entityModels.bakeLayer(layer);
|
||||||
|
|
||||||
|
return convert(modelPart, THREAD_LOCAL_OBJECTS.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static MeshTree convert(ModelPart modelPart, ThreadLocalObjects objects) {
|
||||||
|
var modelPartChildren = FlwLibLink.INSTANCE.getModelPartChildren(modelPart);
|
||||||
|
Map<String, MeshTree> children = new HashMap<>();
|
||||||
|
|
||||||
|
modelPartChildren.forEach((name, modelPartChild) -> {
|
||||||
|
children.put(name, convert(modelPartChild, objects));
|
||||||
|
});
|
||||||
|
|
||||||
|
return new MeshTree(compile(modelPart, objects), modelPart.getInitialPose(), Collections.unmodifiableMap(children));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private static Mesh compile(ModelPart modelPart, ThreadLocalObjects objects) {
|
||||||
|
if (modelPart.isEmpty()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
VertexWriter vertexWriter = objects.vertexWriter;
|
||||||
|
FlwLibLink.INSTANCE.compileModelPart(modelPart, IDENTITY_POSE, vertexWriter, LightTexture.FULL_BRIGHT, OverlayTexture.NO_OVERLAY, 1.0F, 1.0F, 1.0F, 1.0F);
|
||||||
|
MemoryBlock data = vertexWriter.copyDataAndReset();
|
||||||
|
|
||||||
|
VertexView vertexView = new PosTexNormalVertexView();
|
||||||
|
vertexView.load(data);
|
||||||
|
return new SimpleQuadMesh(vertexView, "source=MeshTree");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public Mesh mesh() {
|
||||||
|
return mesh;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PartPose initialPose() {
|
||||||
|
return initialPose;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Unmodifiable
|
||||||
|
public Map<String, MeshTree> children() {
|
||||||
|
return children;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasChild(String name) {
|
||||||
|
return children.containsKey(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public MeshTree child(String name) {
|
||||||
|
return children.get(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public MeshTree childOrThrow(String name) {
|
||||||
|
MeshTree child = child(name);
|
||||||
|
|
||||||
|
if (child == null) {
|
||||||
|
throw new NoSuchElementException("Can't find part " + name);
|
||||||
|
}
|
||||||
|
|
||||||
|
return child;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void traverse(Consumer<Mesh> consumer) {
|
||||||
|
if (mesh != null) {
|
||||||
|
consumer.accept(mesh);
|
||||||
|
}
|
||||||
|
for (MeshTree child : children.values()) {
|
||||||
|
child.traverse(consumer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ApiStatus.Internal
|
||||||
|
public static void onEndClientResourceReload() {
|
||||||
|
CACHE.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class ThreadLocalObjects {
|
||||||
|
public final VertexWriter vertexWriter = new VertexWriter();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -18,6 +18,7 @@ import net.minecraft.client.renderer.LightTexture;
|
||||||
import net.minecraft.client.renderer.texture.OverlayTexture;
|
import net.minecraft.client.renderer.texture.OverlayTexture;
|
||||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||||
|
|
||||||
|
@Deprecated(forRemoval = true)
|
||||||
public final class ModelPartConverter {
|
public final class ModelPartConverter {
|
||||||
private static final ThreadLocal<ThreadLocalObjects> THREAD_LOCAL_OBJECTS = ThreadLocal.withInitial(ThreadLocalObjects::new);
|
private static final ThreadLocal<ThreadLocalObjects> THREAD_LOCAL_OBJECTS = ThreadLocal.withInitial(ThreadLocalObjects::new);
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
package dev.engine_room.flywheel.lib.vertex;
|
||||||
|
|
||||||
|
import dev.engine_room.flywheel.api.vertex.MutableVertexList;
|
||||||
|
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||||
|
|
||||||
|
public final class VertexTransformations {
|
||||||
|
private VertexTransformations() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void retexture(MutableVertexList vertexList, int index, TextureAtlasSprite sprite) {
|
||||||
|
vertexList.u(index, sprite.getU(vertexList.u(index) * 16));
|
||||||
|
vertexList.v(index, sprite.getV(vertexList.v(index) * 16));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void retexture(MutableVertexList vertexList, TextureAtlasSprite sprite) {
|
||||||
|
for (int i = 0; i < vertexList.vertexCount(); i++) {
|
||||||
|
retexture(vertexList, i, sprite);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,12 +1,17 @@
|
||||||
package dev.engine_room.flywheel.impl;
|
package dev.engine_room.flywheel.impl;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
|
||||||
import com.mojang.blaze3d.vertex.PoseStack;
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
|
import com.mojang.blaze3d.vertex.VertexConsumer;
|
||||||
|
|
||||||
import dev.engine_room.flywheel.impl.extension.PoseStackExtension;
|
import dev.engine_room.flywheel.impl.extension.PoseStackExtension;
|
||||||
|
import dev.engine_room.flywheel.impl.mixin.ModelPartAccessor;
|
||||||
import dev.engine_room.flywheel.lib.internal.FlwLibLink;
|
import dev.engine_room.flywheel.lib.internal.FlwLibLink;
|
||||||
import dev.engine_room.flywheel.lib.transform.PoseTransformStack;
|
import dev.engine_room.flywheel.lib.transform.PoseTransformStack;
|
||||||
|
import net.minecraft.client.model.geom.ModelPart;
|
||||||
|
|
||||||
public class FlwLibLinkImpl implements FlwLibLink {
|
public class FlwLibLinkImpl implements FlwLibLink {
|
||||||
@Override
|
@Override
|
||||||
|
@ -18,4 +23,14 @@ public class FlwLibLinkImpl implements FlwLibLink {
|
||||||
public PoseTransformStack getPoseTransformStackOf(PoseStack stack) {
|
public PoseTransformStack getPoseTransformStackOf(PoseStack stack) {
|
||||||
return ((PoseStackExtension) stack).flywheel$transformStack();
|
return ((PoseStackExtension) stack).flywheel$transformStack();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, ModelPart> getModelPartChildren(ModelPart part) {
|
||||||
|
return ((ModelPartAccessor) (Object) part).flywheel$children();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void compileModelPart(ModelPart part, PoseStack.Pose pose, VertexConsumer consumer, int light, int overlay, float red, float green, float blue, float alpha) {
|
||||||
|
((ModelPartAccessor) (Object) part).flywheel$compile(pose, consumer, light, overlay, red, green, blue, alpha);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
package dev.engine_room.flywheel.impl.mixin;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||||
|
import org.spongepowered.asm.mixin.gen.Invoker;
|
||||||
|
|
||||||
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
|
import com.mojang.blaze3d.vertex.VertexConsumer;
|
||||||
|
|
||||||
|
import net.minecraft.client.model.geom.ModelPart;
|
||||||
|
|
||||||
|
@Mixin(ModelPart.class)
|
||||||
|
public interface ModelPartAccessor {
|
||||||
|
@Accessor("children")
|
||||||
|
Map<String, ModelPart> flywheel$children();
|
||||||
|
|
||||||
|
@Invoker("compile")
|
||||||
|
void flywheel$compile(PoseStack.Pose pose, VertexConsumer vertexConsumer, int packedLight, int packedOverlay, float red, float green, float blue, float alpha);
|
||||||
|
}
|
|
@ -5,26 +5,30 @@ import java.util.EnumMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
import org.joml.Quaternionf;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
|
import com.mojang.math.Axis;
|
||||||
|
|
||||||
import dev.engine_room.flywheel.api.instance.Instance;
|
import dev.engine_room.flywheel.api.instance.Instance;
|
||||||
|
import dev.engine_room.flywheel.api.model.Model;
|
||||||
import dev.engine_room.flywheel.api.visualization.VisualizationContext;
|
import dev.engine_room.flywheel.api.visualization.VisualizationContext;
|
||||||
import dev.engine_room.flywheel.lib.instance.InstanceTypes;
|
|
||||||
import dev.engine_room.flywheel.lib.instance.OrientedInstance;
|
|
||||||
import dev.engine_room.flywheel.lib.instance.TransformedInstance;
|
|
||||||
import dev.engine_room.flywheel.lib.material.CutoutShaders;
|
import dev.engine_room.flywheel.lib.material.CutoutShaders;
|
||||||
import dev.engine_room.flywheel.lib.material.SimpleMaterial;
|
import dev.engine_room.flywheel.lib.material.SimpleMaterial;
|
||||||
import dev.engine_room.flywheel.lib.model.ModelCache;
|
import dev.engine_room.flywheel.lib.model.RetexturedMesh;
|
||||||
import dev.engine_room.flywheel.lib.model.SingleMeshModel;
|
import dev.engine_room.flywheel.lib.model.part.InstanceTree;
|
||||||
import dev.engine_room.flywheel.lib.model.part.ModelPartConverter;
|
import dev.engine_room.flywheel.lib.transform.TransformStack;
|
||||||
import dev.engine_room.flywheel.lib.util.Pair;
|
|
||||||
import dev.engine_room.flywheel.lib.visual.AbstractBlockEntityVisual;
|
import dev.engine_room.flywheel.lib.visual.AbstractBlockEntityVisual;
|
||||||
import dev.engine_room.flywheel.lib.visual.SimpleDynamicVisual;
|
import dev.engine_room.flywheel.lib.visual.SimpleDynamicVisual;
|
||||||
import it.unimi.dsi.fastutil.floats.Float2FloatFunction;
|
import it.unimi.dsi.fastutil.floats.Float2FloatFunction;
|
||||||
|
import it.unimi.dsi.fastutil.longs.LongSet;
|
||||||
import net.minecraft.client.model.geom.ModelLayerLocation;
|
import net.minecraft.client.model.geom.ModelLayerLocation;
|
||||||
import net.minecraft.client.model.geom.ModelLayers;
|
import net.minecraft.client.model.geom.ModelLayers;
|
||||||
|
import net.minecraft.client.renderer.LevelRenderer;
|
||||||
|
import net.minecraft.client.renderer.LightTexture;
|
||||||
import net.minecraft.client.renderer.Sheets;
|
import net.minecraft.client.renderer.Sheets;
|
||||||
import net.minecraft.client.resources.model.Material;
|
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||||
|
import net.minecraft.core.SectionPos;
|
||||||
import net.minecraft.world.level.block.AbstractChestBlock;
|
import net.minecraft.world.level.block.AbstractChestBlock;
|
||||||
import net.minecraft.world.level.block.Block;
|
import net.minecraft.world.level.block.Block;
|
||||||
import net.minecraft.world.level.block.ChestBlock;
|
import net.minecraft.world.level.block.ChestBlock;
|
||||||
|
@ -35,7 +39,7 @@ import net.minecraft.world.level.block.entity.LidBlockEntity;
|
||||||
import net.minecraft.world.level.block.state.properties.ChestType;
|
import net.minecraft.world.level.block.state.properties.ChestType;
|
||||||
|
|
||||||
public class ChestVisual<T extends BlockEntity & LidBlockEntity> extends AbstractBlockEntityVisual<T> implements SimpleDynamicVisual {
|
public class ChestVisual<T extends BlockEntity & LidBlockEntity> extends AbstractBlockEntityVisual<T> implements SimpleDynamicVisual {
|
||||||
public static final dev.engine_room.flywheel.api.material.Material MATERIAL = SimpleMaterial.builder()
|
private static final dev.engine_room.flywheel.api.material.Material MATERIAL = SimpleMaterial.builder()
|
||||||
.cutout(CutoutShaders.ONE_TENTH)
|
.cutout(CutoutShaders.ONE_TENTH)
|
||||||
.texture(Sheets.CHEST_SHEET)
|
.texture(Sheets.CHEST_SHEET)
|
||||||
.mipmap(false)
|
.mipmap(false)
|
||||||
|
@ -48,68 +52,55 @@ public class ChestVisual<T extends BlockEntity & LidBlockEntity> extends Abstrac
|
||||||
LAYER_LOCATIONS.put(ChestType.RIGHT, ModelLayers.DOUBLE_CHEST_RIGHT);
|
LAYER_LOCATIONS.put(ChestType.RIGHT, ModelLayers.DOUBLE_CHEST_RIGHT);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final ModelCache<Pair<ChestType, Material>> BOTTOM_MODELS = new ModelCache<>(key -> {
|
@Nullable
|
||||||
return new SingleMeshModel(ModelPartConverter.convert(LAYER_LOCATIONS.get(key.first()), key.second().sprite(), "bottom"), MATERIAL);
|
private final InstanceTree instances;
|
||||||
});
|
@Nullable
|
||||||
private static final ModelCache<Pair<ChestType, Material>> LID_MODELS = new ModelCache<>(key -> {
|
private final InstanceTree lid;
|
||||||
return new SingleMeshModel(ModelPartConverter.convert(LAYER_LOCATIONS.get(key.first()), key.second().sprite(), "lid"), MATERIAL);
|
@Nullable
|
||||||
});
|
private final InstanceTree lock;
|
||||||
private static final ModelCache<Pair<ChestType, Material>> LOCK_MODELS = new ModelCache<>(key -> {
|
|
||||||
return new SingleMeshModel(ModelPartConverter.convert(LAYER_LOCATIONS.get(key.first()), key.second().sprite(), "lock"), MATERIAL);
|
|
||||||
});
|
|
||||||
|
|
||||||
private final OrientedInstance bottom;
|
private final PoseStack poseStack = new PoseStack();
|
||||||
private final TransformedInstance lid;
|
private final BrightnessCombiner brightnessCombiner = new BrightnessCombiner();
|
||||||
private final TransformedInstance lock;
|
@Nullable
|
||||||
|
private final DoubleBlockCombiner.NeighborCombineResult<? extends ChestBlockEntity> neighborCombineResult;
|
||||||
private final ChestType chestType;
|
@Nullable
|
||||||
private final Float2FloatFunction lidProgress;
|
private final Float2FloatFunction lidProgress;
|
||||||
|
|
||||||
private final Quaternionf baseRotation = new Quaternionf();
|
|
||||||
|
|
||||||
private float lastProgress = Float.NaN;
|
private float lastProgress = Float.NaN;
|
||||||
|
|
||||||
public ChestVisual(VisualizationContext ctx, T blockEntity, float partialTick) {
|
public ChestVisual(VisualizationContext ctx, T blockEntity, float partialTick) {
|
||||||
super(ctx, blockEntity, partialTick);
|
super(ctx, blockEntity, partialTick);
|
||||||
|
|
||||||
chestType = blockState.hasProperty(ChestBlock.TYPE) ? blockState.getValue(ChestBlock.TYPE) : ChestType.SINGLE;
|
|
||||||
Material texture = Sheets.chooseMaterial(blockEntity, chestType, isChristmas());
|
|
||||||
|
|
||||||
bottom = createBottomInstance(texture).position(getVisualPosition());
|
|
||||||
lid = createLidInstance(texture);
|
|
||||||
lock = createLockInstance(texture);
|
|
||||||
|
|
||||||
Block block = blockState.getBlock();
|
Block block = blockState.getBlock();
|
||||||
if (block instanceof AbstractChestBlock<?> chestBlock) {
|
if (block instanceof AbstractChestBlock<?> chestBlock) {
|
||||||
|
ChestType chestType = blockState.hasProperty(ChestBlock.TYPE) ? blockState.getValue(ChestBlock.TYPE) : ChestType.SINGLE;
|
||||||
|
TextureAtlasSprite sprite = Sheets.chooseMaterial(blockEntity, chestType, isChristmas()).sprite();
|
||||||
|
|
||||||
|
instances = InstanceTree.create(instancerProvider, LAYER_LOCATIONS.get(chestType), (path, mesh) -> {
|
||||||
|
return new Model.ConfiguredMesh(MATERIAL, new RetexturedMesh(mesh, sprite));
|
||||||
|
});
|
||||||
|
lid = instances.childOrThrow("lid");
|
||||||
|
lock = instances.childOrThrow("lock");
|
||||||
|
|
||||||
|
poseStack.pushPose();
|
||||||
|
TransformStack.of(poseStack).translate(getVisualPosition());
|
||||||
float horizontalAngle = blockState.getValue(ChestBlock.FACING).toYRot();
|
float horizontalAngle = blockState.getValue(ChestBlock.FACING).toYRot();
|
||||||
baseRotation.setAngleAxis(Math.toRadians(-horizontalAngle), 0, 1, 0);
|
poseStack.translate(0.5F, 0.5F, 0.5F);
|
||||||
|
poseStack.mulPose(Axis.YP.rotationDegrees(-horizontalAngle));
|
||||||
|
poseStack.translate(-0.5F, -0.5F, -0.5F);
|
||||||
|
|
||||||
DoubleBlockCombiner.NeighborCombineResult<? extends ChestBlockEntity> wrapper = chestBlock.combine(blockState, level, pos, true);
|
neighborCombineResult = chestBlock.combine(blockState, level, pos, true);
|
||||||
lidProgress = wrapper.apply(ChestBlock.opennessCombiner(blockEntity));
|
lidProgress = neighborCombineResult.apply(ChestBlock.opennessCombiner(blockEntity));
|
||||||
|
|
||||||
|
lastProgress = lidProgress.get(partialTick);
|
||||||
|
applyLidTransform(lastProgress);
|
||||||
} else {
|
} else {
|
||||||
baseRotation.identity();
|
instances = null;
|
||||||
lidProgress = $ -> 0f;
|
lid = null;
|
||||||
|
lock = null;
|
||||||
|
neighborCombineResult = null;
|
||||||
|
lidProgress = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
bottom.rotation(baseRotation);
|
|
||||||
bottom.setChanged();
|
|
||||||
|
|
||||||
applyLidTransform(lidProgress.get(partialTick));
|
|
||||||
}
|
|
||||||
|
|
||||||
private OrientedInstance createBottomInstance(Material texture) {
|
|
||||||
return instancerProvider.instancer(InstanceTypes.ORIENTED, BOTTOM_MODELS.get(Pair.of(chestType, texture)))
|
|
||||||
.createInstance();
|
|
||||||
}
|
|
||||||
|
|
||||||
private TransformedInstance createLidInstance(Material texture) {
|
|
||||||
return instancerProvider.instancer(InstanceTypes.TRANSFORMED, LID_MODELS.get(Pair.of(chestType, texture)))
|
|
||||||
.createInstance();
|
|
||||||
}
|
|
||||||
|
|
||||||
private TransformedInstance createLockInstance(Material texture) {
|
|
||||||
return instancerProvider.instancer(InstanceTypes.TRANSFORMED, LOCK_MODELS.get(Pair.of(chestType, texture)))
|
|
||||||
.createInstance();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isChristmas() {
|
private static boolean isChristmas() {
|
||||||
|
@ -117,8 +108,23 @@ public class ChestVisual<T extends BlockEntity & LidBlockEntity> extends Abstrac
|
||||||
return calendar.get(Calendar.MONTH) + 1 == 12 && calendar.get(Calendar.DATE) >= 24 && calendar.get(Calendar.DATE) <= 26;
|
return calendar.get(Calendar.MONTH) + 1 == 12 && calendar.get(Calendar.DATE) >= 24 && calendar.get(Calendar.DATE) <= 26;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setSectionCollector(SectionCollector sectionCollector) {
|
||||||
|
this.lightSections = sectionCollector;
|
||||||
|
|
||||||
|
if (neighborCombineResult != null) {
|
||||||
|
lightSections.sections(neighborCombineResult.apply(new SectionPosCombiner()));
|
||||||
|
} else {
|
||||||
|
lightSections.sections(LongSet.of(SectionPos.asLong(pos)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void beginFrame(Context context) {
|
public void beginFrame(Context context) {
|
||||||
|
if (instances == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (doDistanceLimitThisFrame(context) || !isVisible(context.frustum())) {
|
if (doDistanceLimitThisFrame(context) || !isVisible(context.frustum())) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -136,41 +142,80 @@ public class ChestVisual<T extends BlockEntity & LidBlockEntity> extends Abstrac
|
||||||
progress = 1.0F - progress;
|
progress = 1.0F - progress;
|
||||||
progress = 1.0F - progress * progress * progress;
|
progress = 1.0F - progress * progress * progress;
|
||||||
|
|
||||||
float angleX = -(progress * ((float) Math.PI / 2F));
|
lid.xRot = -(progress * ((float) Math.PI / 2F));
|
||||||
|
lock.xRot = lid.xRot;
|
||||||
lid.setIdentityTransform()
|
instances.updateInstances(poseStack);
|
||||||
.translate(getVisualPosition())
|
|
||||||
.rotateCentered(baseRotation)
|
|
||||||
.translate(0, 9f / 16f, 1f / 16f)
|
|
||||||
.rotateX(angleX)
|
|
||||||
.translate(0, -9f / 16f, -1f / 16f)
|
|
||||||
.setChanged();
|
|
||||||
|
|
||||||
lock.setIdentityTransform()
|
|
||||||
.translate(getVisualPosition())
|
|
||||||
.rotateCentered(baseRotation)
|
|
||||||
.translate(0, 8f / 16f, 0)
|
|
||||||
.rotateX(angleX)
|
|
||||||
.translate(0, -8f / 16f, 0)
|
|
||||||
.setChanged();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateLight(float partialTick) {
|
public void updateLight(float partialTick) {
|
||||||
relight(bottom, lid, lock);
|
if (instances != null) {
|
||||||
|
int packedLight = neighborCombineResult.apply(brightnessCombiner);
|
||||||
|
instances.traverse(instance -> {
|
||||||
|
instance.light(packedLight)
|
||||||
|
.setChanged();
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void collectCrumblingInstances(Consumer<Instance> consumer) {
|
public void collectCrumblingInstances(Consumer<Instance> consumer) {
|
||||||
consumer.accept(bottom);
|
if (instances != null) {
|
||||||
consumer.accept(lid);
|
instances.traverse(consumer);
|
||||||
consumer.accept(lock);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void _delete() {
|
protected void _delete() {
|
||||||
bottom.delete();
|
if (instances != null) {
|
||||||
lid.delete();
|
instances.delete();
|
||||||
lock.delete();
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class SectionPosCombiner implements DoubleBlockCombiner.Combiner<BlockEntity, LongSet> {
|
||||||
|
@Override
|
||||||
|
public LongSet acceptDouble(BlockEntity first, BlockEntity second) {
|
||||||
|
long firstSection = SectionPos.asLong(first.getBlockPos());
|
||||||
|
long secondSection = SectionPos.asLong(second.getBlockPos());
|
||||||
|
|
||||||
|
if (firstSection == secondSection) {
|
||||||
|
return LongSet.of(firstSection);
|
||||||
|
} else {
|
||||||
|
return LongSet.of(firstSection, secondSection);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LongSet acceptSingle(BlockEntity single) {
|
||||||
|
return LongSet.of(SectionPos.asLong(single.getBlockPos()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LongSet acceptNone() {
|
||||||
|
return LongSet.of(SectionPos.asLong(pos));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class BrightnessCombiner implements DoubleBlockCombiner.Combiner<BlockEntity, Integer> {
|
||||||
|
@Override
|
||||||
|
public Integer acceptDouble(BlockEntity first, BlockEntity second) {
|
||||||
|
int firstLight = LevelRenderer.getLightColor(first.getLevel(), first.getBlockPos());
|
||||||
|
int secondLight = LevelRenderer.getLightColor(second.getLevel(), second.getBlockPos());
|
||||||
|
int firstBlockLight = LightTexture.block(firstLight);
|
||||||
|
int secondBlockLight = LightTexture.block(secondLight);
|
||||||
|
int firstSkyLight = LightTexture.sky(firstLight);
|
||||||
|
int secondSkyLight = LightTexture.sky(secondLight);
|
||||||
|
return LightTexture.pack(Math.max(firstBlockLight, secondBlockLight), Math.max(firstSkyLight, secondSkyLight));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Integer acceptSingle(BlockEntity single) {
|
||||||
|
return LevelRenderer.getLightColor(single.getLevel(), single.getBlockPos());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Integer acceptNone() {
|
||||||
|
return LevelRenderer.getLightColor(level, pos);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
"LevelMixin",
|
"LevelMixin",
|
||||||
"LevelRendererMixin",
|
"LevelRendererMixin",
|
||||||
"MinecraftMixin",
|
"MinecraftMixin",
|
||||||
|
"ModelPartAccessor",
|
||||||
"PoseStackMixin",
|
"PoseStackMixin",
|
||||||
"fix.FixFabulousDepthMixin",
|
"fix.FixFabulousDepthMixin",
|
||||||
"fix.FixNormalScalingMixin",
|
"fix.FixNormalScalingMixin",
|
||||||
|
|
|
@ -12,6 +12,7 @@ import dev.engine_room.flywheel.impl.visualization.VisualizationEventHandler;
|
||||||
import dev.engine_room.flywheel.lib.model.ModelCache;
|
import dev.engine_room.flywheel.lib.model.ModelCache;
|
||||||
import dev.engine_room.flywheel.lib.model.ModelHolder;
|
import dev.engine_room.flywheel.lib.model.ModelHolder;
|
||||||
import dev.engine_room.flywheel.lib.model.baked.PartialModelEventHandler;
|
import dev.engine_room.flywheel.lib.model.baked.PartialModelEventHandler;
|
||||||
|
import dev.engine_room.flywheel.lib.model.part.MeshTree;
|
||||||
import net.fabricmc.api.ClientModInitializer;
|
import net.fabricmc.api.ClientModInitializer;
|
||||||
import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback;
|
import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback;
|
||||||
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientEntityEvents;
|
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientEntityEvents;
|
||||||
|
@ -71,6 +72,8 @@ public final class FlywheelFabric implements ClientModInitializer {
|
||||||
ModelCache.onEndClientResourceReload());
|
ModelCache.onEndClientResourceReload());
|
||||||
EndClientResourceReloadCallback.EVENT.register((minecraft, resourceManager, initialReload, error) ->
|
EndClientResourceReloadCallback.EVENT.register((minecraft, resourceManager, initialReload, error) ->
|
||||||
ModelHolder.onEndClientResourceReload());
|
ModelHolder.onEndClientResourceReload());
|
||||||
|
EndClientResourceReloadCallback.EVENT.register((minecraft, resourceManager, initialReload, error) ->
|
||||||
|
MeshTree.onEndClientResourceReload());
|
||||||
|
|
||||||
ModelLoadingPlugin.register(ctx -> {
|
ModelLoadingPlugin.register(ctx -> {
|
||||||
ctx.addModels(PartialModelEventHandler.onRegisterAdditional());
|
ctx.addModels(PartialModelEventHandler.onRegisterAdditional());
|
||||||
|
|
|
@ -13,6 +13,7 @@ import dev.engine_room.flywheel.impl.visualization.VisualizationEventHandler;
|
||||||
import dev.engine_room.flywheel.lib.model.ModelCache;
|
import dev.engine_room.flywheel.lib.model.ModelCache;
|
||||||
import dev.engine_room.flywheel.lib.model.ModelHolder;
|
import dev.engine_room.flywheel.lib.model.ModelHolder;
|
||||||
import dev.engine_room.flywheel.lib.model.baked.PartialModelEventHandler;
|
import dev.engine_room.flywheel.lib.model.baked.PartialModelEventHandler;
|
||||||
|
import dev.engine_room.flywheel.lib.model.part.MeshTree;
|
||||||
import dev.engine_room.flywheel.lib.util.LevelAttached;
|
import dev.engine_room.flywheel.lib.util.LevelAttached;
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.commands.synchronization.ArgumentTypeInfos;
|
import net.minecraft.commands.synchronization.ArgumentTypeInfos;
|
||||||
|
@ -111,6 +112,7 @@ public final class FlywheelForge {
|
||||||
|
|
||||||
modEventBus.addListener((EndClientResourceReloadEvent e) -> ModelCache.onEndClientResourceReload());
|
modEventBus.addListener((EndClientResourceReloadEvent e) -> ModelCache.onEndClientResourceReload());
|
||||||
modEventBus.addListener((EndClientResourceReloadEvent e) -> ModelHolder.onEndClientResourceReload());
|
modEventBus.addListener((EndClientResourceReloadEvent e) -> ModelHolder.onEndClientResourceReload());
|
||||||
|
modEventBus.addListener((EndClientResourceReloadEvent e) -> MeshTree.onEndClientResourceReload());
|
||||||
|
|
||||||
modEventBus.addListener(PartialModelEventHandler::onRegisterAdditional);
|
modEventBus.addListener(PartialModelEventHandler::onRegisterAdditional);
|
||||||
modEventBus.addListener(PartialModelEventHandler::onBakingCompleted);
|
modEventBus.addListener(PartialModelEventHandler::onBakingCompleted);
|
||||||
|
|
|
@ -19,7 +19,7 @@ forge_version_range = [47.0.0,)
|
||||||
|
|
||||||
# General build dependency versions
|
# General build dependency versions
|
||||||
java_version = 17
|
java_version = 17
|
||||||
arch_loom_version=1.7.412
|
arch_loom_version = 1.7.412
|
||||||
cursegradle_version = 1.4.0
|
cursegradle_version = 1.4.0
|
||||||
parchment_version = 2023.09.03
|
parchment_version = 2023.09.03
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue