Home alone

- Remove LoweringVisitor
- Move functionality of four main static methods in LoweringVisitor to new ModelTrees class
  - Return ModelTree directly
  - Accept Material instead of TextureAtlasSprite for efficiency, so visuals don't need to look up the sprite to get the ModelTree
- Use ResourceReloadCache for MeshTree.CACHE
This commit is contained in:
PepperCode1 2024-09-19 11:40:41 -07:00
parent 5a75fe972f
commit 62a0954381
11 changed files with 146 additions and 267 deletions

View file

@ -1,128 +0,0 @@
package dev.engine_room.flywheel.lib.model.part;
import java.util.ArrayList;
import java.util.Set;
import org.jetbrains.annotations.Nullable;
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.model.RetexturedMesh;
import dev.engine_room.flywheel.lib.model.SingleMeshModel;
import net.minecraft.client.model.geom.PartPose;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
/**
* A tree walking visitor that lowers a MeshTree to a ModelTree.
*/
public interface LoweringVisitor {
static ModelTree leaf(Model model) {
return leaf(model, PartPose.ZERO);
}
static ModelTree leaf(Model model, PartPose initialPose) {
return ModelTree.create(model, initialPose, new ModelTree[0], new String[0]);
}
static LoweringVisitor create(Material material) {
return (path, mesh) -> new SingleMeshModel(mesh, material);
}
static LoweringVisitor create(Material material, TextureAtlasSprite sprite) {
return (path, mesh) -> new SingleMeshModel(new RetexturedMesh(mesh, sprite), material);
}
static LoweringVisitor pruning(Set<String> prune, Material material) {
return new LoweringVisitor() {
@Override
public @Nullable ModelTree visit(String path, MeshTree meshTree) {
if (prune.contains(path)) {
return null;
}
return LoweringVisitor.super.visit(path, meshTree);
}
@Override
public Model visit(String path, Mesh mesh) {
return new SingleMeshModel(mesh, material);
}
};
}
static LoweringVisitor pruning(Set<String> prune, Material material, TextureAtlasSprite sprite) {
return new LoweringVisitor() {
@Override
public @Nullable ModelTree visit(String path, MeshTree meshTree) {
if (prune.contains(path)) {
return null;
}
return LoweringVisitor.super.visit(path, meshTree);
}
@Override
public Model visit(String path, Mesh mesh) {
return new SingleMeshModel(new RetexturedMesh(mesh, sprite), material);
}
};
}
static String append(String path, String child) {
if (path.isEmpty()) {
return child;
}
return path + "/" + child;
}
/**
* Walk the given MeshTree, lowering its Mesh to a Model, and lowering all children using the given visitor.
*
* @param path The absolute path to the MeshTree node.
* @param meshTree The MeshTree to walk.
* @param loweringVisitor The visitor to use to lower the Mesh and MeshTree nodes.
* @return The lowered ModelTree.
*/
static ModelTree walk(String path, MeshTree meshTree, LoweringVisitor loweringVisitor) {
Model out = null;
if (meshTree.mesh() != null) {
out = loweringVisitor.visit(path, meshTree.mesh());
}
ArrayList<ModelTree> children = new ArrayList<>();
ArrayList<String> childNames = new ArrayList<>();
for (int i = 0; i < meshTree.childCount(); i++) {
var child = loweringVisitor.visit(append(path, meshTree.childName(i)), meshTree.child(i));
if (child != null) {
children.add(child);
childNames.add(meshTree.childName(i));
}
}
return ModelTree.create(out, meshTree.initialPose(), children.toArray(new ModelTree[0]), childNames.toArray(new String[0]));
}
/**
* Visit the given Mesh, converting it to a Model.
*
* @param path The absolute path to the MeshTree node containing the Mesh.
* @param mesh The Mesh to lower.
* @return The lowered Model, or null if the Model should be omitted.
*/
@Nullable Model visit(String path, Mesh mesh);
/**
* Visit the given MeshTree, converting it to a ModelTree.
*
* @param path The absolute path to the MeshTree node.
* @param meshTree The MeshTree to lower.
* @return The lowered ModelTree, or null if the ModelTree should be omitted.
*/
@Nullable
default ModelTree visit(String path, MeshTree meshTree) {
return walk(path, meshTree, this);
}
}

View file

@ -1,12 +1,8 @@
package dev.engine_room.flywheel.lib.model.part;
import java.util.Arrays;
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 com.mojang.blaze3d.vertex.PoseStack;
@ -14,6 +10,7 @@ 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.ResourceReloadCache;
import dev.engine_room.flywheel.lib.model.SimpleQuadMesh;
import dev.engine_room.flywheel.lib.vertex.PosTexNormalVertexView;
import dev.engine_room.flywheel.lib.vertex.VertexView;
@ -28,7 +25,7 @@ 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<>();
private static final ResourceReloadCache<ModelLayerLocation, MeshTree> CACHE = new ResourceReloadCache<>(MeshTree::convert);
@Nullable
private final Mesh mesh;
@ -44,7 +41,7 @@ public final class MeshTree {
}
public static MeshTree of(ModelLayerLocation layer) {
return CACHE.computeIfAbsent(layer, MeshTree::convert);
return CACHE.get(layer);
}
private static MeshTree convert(ModelLayerLocation layer) {
@ -58,9 +55,9 @@ public final class MeshTree {
private static MeshTree convert(ModelPart modelPart, ThreadLocalObjects objects) {
var modelPartChildren = FlwLibLink.INSTANCE.getModelPartChildren(modelPart);
// Freeze the ordering here. Maybe we want to sort this?
String[] childNames = modelPartChildren.keySet()
.toArray(String[]::new);
Arrays.sort(childNames);
MeshTree[] children = new MeshTree[childNames.length];
for (int i = 0; i < childNames.length; i++) {
@ -135,20 +132,6 @@ public final class MeshTree {
return child;
}
public void traverse(Consumer<Mesh> consumer) {
if (mesh != null) {
consumer.accept(mesh);
}
for (MeshTree child : children) {
child.traverse(consumer);
}
}
@ApiStatus.Internal
public static void onEndClientResourceReload() {
CACHE.clear();
}
private static class ThreadLocalObjects {
public final VertexWriter vertexWriter = new VertexWriter();
}

View file

@ -2,74 +2,50 @@ package dev.engine_room.flywheel.lib.model.part;
import java.util.Arrays;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.NoSuchElementException;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.Nullable;
import dev.engine_room.flywheel.api.model.Model;
import net.minecraft.client.model.geom.ModelLayerLocation;
import net.minecraft.client.model.geom.PartPose;
public class ModelTree {
private static final Map<ModelTreeKey, ModelTree> CACHE = new ConcurrentHashMap<>();
public final class ModelTree {
@Nullable
private final Model model;
private final PartPose initialPose;
private final ModelTree[] children;
private final String[] childNames;
private ModelTree(@Nullable Model model, PartPose initialPose, ModelTree[] children, String[] childNames) {
this.model = model;
this.initialPose = initialPose;
this.children = children;
this.childNames = childNames;
}
/**
* Create and memoize a ModelTree root.
*
* <p>This method is intended for use by Visuals.
*
* @param modelLayerLocation The model location to lower.
* @param loweringVisitor The visitor to use to lower the model.
* @return The cached ModelTree root.
*/
public static ModelTree of(ModelLayerLocation modelLayerLocation, LoweringVisitor loweringVisitor) {
return CACHE.computeIfAbsent(new ModelTreeKey(modelLayerLocation, loweringVisitor), k -> {
var meshTree = MeshTree.of(k.modelLayerLocation());
var out = k.loweringVisitor()
.visit("", meshTree);
if (out == null) {
// Should this be an error, or a missing model?
return ModelTree.create(null, PartPose.ZERO, new ModelTree[0], new String[0]);
}
return out;
});
}
/**
* Create a new ModelTree node.
*
* <p>This method is intended for use by {@link LoweringVisitor} implementations.
*
* @param model The model to associate with this node, or null if this node does not render.
* @param initialPose The initial pose of this node.
* @param children The children of this node.
* @param childNames The names of the children of this node.
* @return A new ModelTree node.
* @throws IllegalArgumentException if children and childNames have different lengths.
*/
public static ModelTree create(@Nullable Model model, PartPose initialPose, ModelTree[] children, String[] childNames) {
if (children.length != childNames.length) {
throw new IllegalArgumentException("children and childNames must have the same length (%s != %s)".formatted(children.length, childNames.length));
public ModelTree(@Nullable Model model, PartPose initialPose, Map<String, ModelTree> children) {
this.model = model;
this.initialPose = initialPose;
String[] childNames = children.keySet().toArray(String[]::new);
Arrays.sort(childNames);
ModelTree[] childArray = new ModelTree[childNames.length];
for (int i = 0; i < childNames.length; i++) {
childArray[i] = children.get(childNames[i]);
}
return new ModelTree(model, initialPose, children, childNames);
this.children = childArray;
this.childNames = childNames;
}
@Nullable
public Model model() {
return model;
}
public PartPose initialPose() {
return initialPose;
}
public int childCount() {
@ -84,24 +60,32 @@ public class ModelTree {
return childNames[index];
}
public PartPose initialPose() {
return initialPose;
}
@Nullable
public Model model() {
return model;
}
public int childIndex(String name) {
return Arrays.binarySearch(childNames, name);
}
@ApiStatus.Internal
public static void onEndClientResourceReload() {
CACHE.clear();
public boolean hasChild(String name) {
return childIndex(name) >= 0;
}
private record ModelTreeKey(ModelLayerLocation modelLayerLocation, LoweringVisitor loweringVisitor) {
@Nullable
public ModelTree child(String name) {
int index = childIndex(name);
if (index < 0) {
return null;
}
return child(index);
}
public ModelTree childOrThrow(String name) {
ModelTree child = child(name);
if (child == null) {
throw new NoSuchElementException("Can't find part " + name);
}
return child;
}
}

View file

@ -1,15 +0,0 @@
package dev.engine_room.flywheel.lib.model.part;
import java.util.function.Function;
import dev.engine_room.flywheel.lib.model.ResourceReloadCache;
/**
* If the lookup to create your model tree directly through {@link ModelTree#of} is particularly expensive,
* you can memoize the arguments here to hide the cost.
*/
public class ModelTreeCache<T> extends ResourceReloadCache<T, ModelTree> {
public ModelTreeCache(Function<T, ModelTree> factory) {
super(factory);
}
}

View file

@ -0,0 +1,83 @@
package dev.engine_room.flywheel.lib.model.part;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import org.jetbrains.annotations.Nullable;
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.model.ResourceReloadCache;
import dev.engine_room.flywheel.lib.model.RetexturedMesh;
import dev.engine_room.flywheel.lib.model.SingleMeshModel;
import net.minecraft.client.model.geom.ModelLayerLocation;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
public final class ModelTrees {
private static final ResourceReloadCache<ModelTreeKey, ModelTree> CACHE = new ResourceReloadCache<>(k -> {
ModelTree tree = convert("", MeshTree.of(k.layer), k.pathsToPrune, k.texture != null ? k.texture.sprite() : null, k.material);
if (tree == null) {
throw new IllegalArgumentException("Cannot prune root node!");
}
return tree;
});
private ModelTrees() {
}
public static ModelTree of(ModelLayerLocation layer, Material material) {
return CACHE.get(new ModelTreeKey(layer, Collections.emptySet(), null, material));
}
public static ModelTree of(ModelLayerLocation layer, net.minecraft.client.resources.model.Material texture, Material material) {
return CACHE.get(new ModelTreeKey(layer, Collections.emptySet(), texture, material));
}
public static ModelTree of(ModelLayerLocation layer, Set<String> pathsToPrune, Material material) {
return CACHE.get(new ModelTreeKey(layer, Set.copyOf(pathsToPrune), null, material));
}
public static ModelTree of(ModelLayerLocation layer, Set<String> pathsToPrune, net.minecraft.client.resources.model.Material texture, Material material) {
return CACHE.get(new ModelTreeKey(layer, Set.copyOf(pathsToPrune), texture, material));
}
@Nullable
private static ModelTree convert(String path, MeshTree meshTree, Set<String> pathsToPrune, @Nullable TextureAtlasSprite sprite, Material material) {
if (pathsToPrune.contains(path)) {
return null;
}
Model model = null;
Mesh mesh = meshTree.mesh();
if (mesh != null) {
if (sprite != null) {
mesh = new RetexturedMesh(mesh, sprite);
}
model = new SingleMeshModel(mesh, material);
}
Map<String, ModelTree> children = new HashMap<>();
String pathSlash = path + "/";
for (int i = 0; i < meshTree.childCount(); i++) {
String childName = meshTree.childName(i);
var child = convert(pathSlash + childName, meshTree.child(i), pathsToPrune, sprite, material);
if (child != null) {
children.put(childName, child);
}
}
return new ModelTree(model, meshTree.initialPose(), children);
}
private record ModelTreeKey(ModelLayerLocation layer, Set<String> pathsToPrune, @Nullable net.minecraft.client.resources.model.Material texture, Material material) {
}
}

View file

@ -9,10 +9,8 @@ import dev.engine_room.flywheel.api.instance.Instance;
import dev.engine_room.flywheel.api.material.Material;
import dev.engine_room.flywheel.api.visualization.VisualizationContext;
import dev.engine_room.flywheel.lib.material.SimpleMaterial;
import dev.engine_room.flywheel.lib.model.ResourceReloadHolder;
import dev.engine_room.flywheel.lib.model.part.InstanceTree;
import dev.engine_room.flywheel.lib.model.part.LoweringVisitor;
import dev.engine_room.flywheel.lib.model.part.ModelTree;
import dev.engine_room.flywheel.lib.model.part.ModelTrees;
import dev.engine_room.flywheel.lib.visual.AbstractBlockEntityVisual;
import dev.engine_room.flywheel.lib.visual.SimpleDynamicVisual;
import net.minecraft.client.model.geom.ModelLayers;
@ -26,9 +24,6 @@ public class BellVisual extends AbstractBlockEntityVisual<BellBlockEntity> imple
.mipmap(false)
.build();
// Need to hold the visitor in a ResourceReloadHolder to ensure we have a valid sprite.
private static final ResourceReloadHolder<LoweringVisitor> VISITOR = new ResourceReloadHolder<>(() -> LoweringVisitor.create(MATERIAL, BellRenderer.BELL_RESOURCE_LOCATION.sprite()));
private final InstanceTree instances;
private final InstanceTree bellBody;
@ -39,7 +34,7 @@ public class BellVisual extends AbstractBlockEntityVisual<BellBlockEntity> imple
public BellVisual(VisualizationContext ctx, BellBlockEntity blockEntity, float partialTick) {
super(ctx, blockEntity, partialTick);
instances = InstanceTree.create(instancerProvider(), ModelTree.of(ModelLayers.BELL, VISITOR.get()));
instances = InstanceTree.create(instancerProvider(), ModelTrees.of(ModelLayers.BELL, BellRenderer.BELL_RESOURCE_LOCATION, MATERIAL));
bellBody = instances.childOrThrow("bell_body");
BlockPos visualPos = getVisualPosition();

View file

@ -4,7 +4,6 @@ import java.util.Calendar;
import java.util.EnumMap;
import java.util.Map;
import java.util.function.Consumer;
import java.util.function.Function;
import org.jetbrains.annotations.Nullable;
import org.joml.Matrix4f;
@ -15,10 +14,8 @@ import dev.engine_room.flywheel.api.material.Material;
import dev.engine_room.flywheel.api.visualization.VisualizationContext;
import dev.engine_room.flywheel.lib.material.CutoutShaders;
import dev.engine_room.flywheel.lib.material.SimpleMaterial;
import dev.engine_room.flywheel.lib.model.ResourceReloadCache;
import dev.engine_room.flywheel.lib.model.part.InstanceTree;
import dev.engine_room.flywheel.lib.model.part.LoweringVisitor;
import dev.engine_room.flywheel.lib.model.part.ModelTree;
import dev.engine_room.flywheel.lib.model.part.ModelTrees;
import dev.engine_room.flywheel.lib.visual.AbstractBlockEntityVisual;
import dev.engine_room.flywheel.lib.visual.SimpleDynamicVisual;
import it.unimi.dsi.fastutil.floats.Float2FloatFunction;
@ -28,7 +25,6 @@ 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.texture.TextureAtlasSprite;
import net.minecraft.core.BlockPos;
import net.minecraft.core.SectionPos;
import net.minecraft.util.Mth;
@ -55,8 +51,6 @@ public class ChestVisual<T extends BlockEntity & LidBlockEntity> extends Abstrac
LAYER_LOCATIONS.put(ChestType.RIGHT, ModelLayers.DOUBLE_CHEST_RIGHT);
}
private static final Function<TextureAtlasSprite, LoweringVisitor> VISITOR = new ResourceReloadCache<>(s -> LoweringVisitor.create(MATERIAL, s));
@Nullable
private final InstanceTree instances;
@Nullable
@ -80,8 +74,8 @@ public class ChestVisual<T extends BlockEntity & LidBlockEntity> extends Abstrac
Block block = blockState.getBlock();
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(), ModelTree.of(LAYER_LOCATIONS.get(chestType), VISITOR.apply(sprite)));
net.minecraft.client.resources.model.Material texture = Sheets.chooseMaterial(blockEntity, chestType, isChristmas());
instances = InstanceTree.create(instancerProvider(), ModelTrees.of(LAYER_LOCATIONS.get(chestType), texture, MATERIAL));
lid = instances.childOrThrow("lid");
lock = instances.childOrThrow("lock");

View file

@ -14,8 +14,7 @@ import dev.engine_room.flywheel.lib.instance.TransformedInstance;
import dev.engine_room.flywheel.lib.material.SimpleMaterial;
import dev.engine_room.flywheel.lib.model.Models;
import dev.engine_room.flywheel.lib.model.part.InstanceTree;
import dev.engine_room.flywheel.lib.model.part.LoweringVisitor;
import dev.engine_room.flywheel.lib.model.part.ModelTree;
import dev.engine_room.flywheel.lib.model.part.ModelTrees;
import dev.engine_room.flywheel.lib.visual.ComponentEntityVisual;
import dev.engine_room.flywheel.lib.visual.SimpleDynamicVisual;
import dev.engine_room.flywheel.lib.visual.SimpleTickableVisual;
@ -36,7 +35,6 @@ public class MinecartVisual<T extends AbstractMinecart> extends ComponentEntityV
.texture(TEXTURE)
.mipmap(false)
.build();
private static final LoweringVisitor VISITOR = LoweringVisitor.create(MATERIAL);
private final InstanceTree instances;
@Nullable
@ -50,7 +48,7 @@ public class MinecartVisual<T extends AbstractMinecart> extends ComponentEntityV
public MinecartVisual(VisualizationContext ctx, T entity, float partialTick, ModelLayerLocation layerLocation) {
super(ctx, entity, partialTick);
instances = InstanceTree.create(instancerProvider(), ModelTree.of(layerLocation, VISITOR));
instances = InstanceTree.create(instancerProvider(), ModelTrees.of(layerLocation, MATERIAL));
blockState = entity.getDisplayBlockState();
contents = createContentsInstance();

View file

@ -2,23 +2,20 @@ package dev.engine_room.flywheel.vanilla;
import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Function;
import org.joml.Matrix4f;
import dev.engine_room.flywheel.api.instance.Instance;
import dev.engine_room.flywheel.api.material.Material;
import dev.engine_room.flywheel.api.visualization.VisualizationContext;
import dev.engine_room.flywheel.lib.material.CutoutShaders;
import dev.engine_room.flywheel.lib.material.SimpleMaterial;
import dev.engine_room.flywheel.lib.model.ResourceReloadCache;
import dev.engine_room.flywheel.lib.model.part.InstanceTree;
import dev.engine_room.flywheel.lib.model.part.LoweringVisitor;
import dev.engine_room.flywheel.lib.model.part.ModelTree;
import dev.engine_room.flywheel.lib.model.part.ModelTrees;
import dev.engine_room.flywheel.lib.visual.AbstractBlockEntityVisual;
import dev.engine_room.flywheel.lib.visual.SimpleDynamicVisual;
import net.minecraft.client.model.geom.ModelLayers;
import net.minecraft.client.renderer.Sheets;
import net.minecraft.client.resources.model.Material;
import net.minecraft.core.Direction;
import net.minecraft.util.Mth;
import net.minecraft.world.item.DyeColor;
@ -26,15 +23,13 @@ import net.minecraft.world.level.block.ShulkerBoxBlock;
import net.minecraft.world.level.block.entity.ShulkerBoxBlockEntity;
public class ShulkerBoxVisual extends AbstractBlockEntityVisual<ShulkerBoxBlockEntity> implements SimpleDynamicVisual {
private static final dev.engine_room.flywheel.api.material.Material MATERIAL = SimpleMaterial.builder()
private static final Material MATERIAL = SimpleMaterial.builder()
.cutout(CutoutShaders.ONE_TENTH)
.texture(Sheets.SHULKER_SHEET)
.mipmap(false)
.backfaceCulling(false)
.build();
private static final Function<Material, LoweringVisitor> VISITORS = new ResourceReloadCache<>(m -> LoweringVisitor.pruning(Set.of("head"), MATERIAL, m.sprite()));
private static final Set<String> PATHS_TO_PRUNE = Set.of("/head");
private final InstanceTree instances;
private final InstanceTree lid;
@ -47,23 +42,22 @@ public class ShulkerBoxVisual extends AbstractBlockEntityVisual<ShulkerBoxBlockE
super(ctx, blockEntity, partialTick);
DyeColor color = blockEntity.getColor();
Material texture;
net.minecraft.client.resources.model.Material texture;
if (color == null) {
texture = Sheets.DEFAULT_SHULKER_TEXTURE_LOCATION;
} else {
texture = Sheets.SHULKER_TEXTURE_LOCATION.get(color.getId());
}
instances = InstanceTree.create(instancerProvider(), ModelTree.of(ModelLayers.SHULKER, VISITORS.apply(texture)));
instances = InstanceTree.create(instancerProvider(), ModelTrees.of(ModelLayers.SHULKER, PATHS_TO_PRUNE, texture, MATERIAL));
lid = instances.childOrThrow("lid");
initialPose = createInitialPose();
lid = instances.childOrThrow("lid");
}
private Matrix4f createInitialPose() {
var rotation = getDirection().getRotation();
var visualPosition = getVisualPosition();
var rotation = getDirection().getRotation();
return new Matrix4f().translate(visualPosition.getX(), visualPosition.getY(), visualPosition.getZ())
.translate(0.5f, 0.5f, 0.5f)
.scale(0.9995f)

View file

@ -12,8 +12,6 @@ import dev.engine_room.flywheel.impl.visualization.VisualizationEventHandler;
import dev.engine_room.flywheel.lib.model.ResourceReloadCache;
import dev.engine_room.flywheel.lib.model.ResourceReloadHolder;
import dev.engine_room.flywheel.lib.model.baked.PartialModelEventHandler;
import dev.engine_room.flywheel.lib.model.part.MeshTree;
import dev.engine_room.flywheel.lib.model.part.ModelTree;
import net.fabricmc.api.ClientModInitializer;
import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback;
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientEntityEvents;
@ -71,9 +69,6 @@ public final class FlywheelFabric implements ClientModInitializer {
private static void setupLib() {
EndClientResourceReloadCallback.EVENT.register((minecraft, resourceManager, initialReload, error) -> ResourceReloadCache.onEndClientResourceReload());
EndClientResourceReloadCallback.EVENT.register((minecraft, resourceManager, initialReload, error) -> ResourceReloadHolder.onEndClientResourceReload());
EndClientResourceReloadCallback.EVENT.register((minecraft, resourceManager, initialReload, error) ->
MeshTree.onEndClientResourceReload());
EndClientResourceReloadCallback.EVENT.register((minecraft, resourceManager, initialReload, error) -> ModelTree.onEndClientResourceReload());
ModelLoadingPlugin.register(ctx -> {
ctx.addModels(PartialModelEventHandler.onRegisterAdditional());

View file

@ -13,8 +13,6 @@ import dev.engine_room.flywheel.impl.visualization.VisualizationEventHandler;
import dev.engine_room.flywheel.lib.model.ResourceReloadCache;
import dev.engine_room.flywheel.lib.model.ResourceReloadHolder;
import dev.engine_room.flywheel.lib.model.baked.PartialModelEventHandler;
import dev.engine_room.flywheel.lib.model.part.MeshTree;
import dev.engine_room.flywheel.lib.model.part.ModelTree;
import dev.engine_room.flywheel.lib.util.LevelAttached;
import net.minecraft.client.Minecraft;
import net.minecraft.commands.synchronization.ArgumentTypeInfos;
@ -113,8 +111,6 @@ public final class FlywheelForge {
modEventBus.addListener((EndClientResourceReloadEvent e) -> ResourceReloadCache.onEndClientResourceReload());
modEventBus.addListener((EndClientResourceReloadEvent e) -> ResourceReloadHolder.onEndClientResourceReload());
modEventBus.addListener((EndClientResourceReloadEvent e) -> MeshTree.onEndClientResourceReload());
modEventBus.addListener((EndClientResourceReloadEvent e) -> ModelTree.onEndClientResourceReload());
modEventBus.addListener(PartialModelEventHandler::onRegisterAdditional);
modEventBus.addListener(PartialModelEventHandler::onBakingCompleted);