Material refactor pt 1

- User no longer needs to supply a key object to get an instancer
 - Move memoization logic outside of MaterialManager
 - Provide utility class for memoizing models
 - Vanilla instances use static objects for their models
 - PartialModels don't actually need reference states, use air instead
 - Move RenderLayer to api package
 - Kill lazy killable
This commit is contained in:
Jozufozu 2022-04-10 17:02:28 -07:00
parent e762d69d0b
commit ec92fef445
24 changed files with 190 additions and 111 deletions

View File

@ -59,6 +59,7 @@ body:
label: Mod Version
description: The version of the mod you were using when the bug occured
options:
- "0.7.0"
- "0.6.2"
- "0.6.1"
- "0.6.0"

View File

@ -2,7 +2,7 @@ org.gradle.jvmargs = -Xmx3G
org.gradle.daemon = false
# mod version info
mod_version = 0.6.2
mod_version = 0.7.0
mc_update_version = 1.18
minecraft_version = 1.18.2
forge_version = 40.0.15

View File

@ -2,44 +2,37 @@ package com.jozufozu.flywheel.api;
import java.util.function.Supplier;
import com.jozufozu.flywheel.core.Models;
import com.jozufozu.flywheel.core.PartialModel;
import com.jozufozu.flywheel.core.model.BlockModel;
import com.jozufozu.flywheel.core.model.Model;
import com.jozufozu.flywheel.core.model.ModelUtil;
import com.jozufozu.flywheel.util.Pair;
import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.core.Direction;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.state.BlockState;
public interface Material<D extends InstanceData> {
/**
* Get an instancer for the given model. Calling this method twice with the same key will return the same instancer.
*
* @param key An object that uniquely identifies the model.
* @param modelSupplier A factory that creates the Model that you want to render.
* @param modelKey An object that uniquely identifies and provides the model.
* @return An instancer for the given model, capable of rendering many copies for little cost.
*/
Instancer<D> model(Object key, Supplier<Model> modelSupplier);
default Instancer<D> getModel(PartialModel partial, BlockState referenceState) {
return model(partial, () -> new BlockModel(partial.get(), referenceState));
}
Instancer<D> model(ModelSupplier modelKey);
default Instancer<D> getModel(PartialModel partial) {
return model(partial, () -> new BlockModel(partial.get(), Blocks.AIR.defaultBlockState()));
return model(Models.partial(partial));
}
default Instancer<D> getModel(PartialModel partial, BlockState referenceState, Direction dir) {
return getModel(partial, referenceState, dir, ModelUtil.rotateToFace(dir));
default Instancer<D> getModel(PartialModel partial, Direction dir) {
return model(Models.partial(partial, dir, () -> ModelUtil.rotateToFace(dir)));
}
default Instancer<D> getModel(PartialModel partial, BlockState referenceState, Direction dir, Supplier<PoseStack> modelTransform) {
return model(Pair.of(dir, partial), () -> new BlockModel(partial.get(), referenceState, modelTransform.get()));
default Instancer<D> getModel(PartialModel partial, Direction dir, Supplier<PoseStack> modelTransform) {
return model(Models.partial(partial, dir, modelTransform));
}
default Instancer<D> getModel(BlockState toRender) {
return model(toRender, () -> new BlockModel(toRender));
return model(Models.block(toRender));
}
}

View File

@ -1,7 +1,5 @@
package com.jozufozu.flywheel.api;
import com.jozufozu.flywheel.backend.RenderLayer;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.core.Vec3i;
@ -11,10 +9,10 @@ public interface MaterialManager {
* Get a material group that will render in the given layer with the given state.
*
* @param layer The {@link RenderLayer} you want to draw in.
* @param state The {@link RenderType} you need to draw with.
* @param type The {@link RenderType} you need to draw with.
* @return A material group whose children will
*/
MaterialGroup state(RenderLayer layer, RenderType state);
MaterialGroup state(RenderLayer layer, RenderType type);
Vec3i getOriginCoordinate();

View File

@ -0,0 +1,11 @@
package com.jozufozu.flywheel.api;
import javax.annotation.Nonnull;
import com.jozufozu.flywheel.core.model.Model;
public interface ModelSupplier {
@Nonnull
Model get();
}

View File

@ -1,4 +1,4 @@
package com.jozufozu.flywheel.backend;
package com.jozufozu.flywheel.api;
import javax.annotation.Nullable;

View File

@ -7,6 +7,7 @@ import java.util.function.Supplier;
import com.jozufozu.flywheel.api.InstanceData;
import com.jozufozu.flywheel.api.Instancer;
import com.jozufozu.flywheel.api.Material;
import com.jozufozu.flywheel.api.ModelSupplier;
import com.jozufozu.flywheel.api.struct.Batched;
import com.jozufozu.flywheel.core.model.Model;
import com.mojang.blaze3d.vertex.PoseStack;
@ -14,7 +15,7 @@ import com.mojang.blaze3d.vertex.VertexConsumer;
public class BatchedMaterial<D extends InstanceData> implements Material<D> {
protected final Map<Object, CPUInstancer<D>> models;
protected final Map<ModelSupplier, CPUInstancer<D>> models;
private final Batched<D> type;
public BatchedMaterial(Batched<D> type) {
@ -24,8 +25,8 @@ public class BatchedMaterial<D extends InstanceData> implements Material<D> {
}
@Override
public Instancer<D> model(Object key, Supplier<Model> modelSupplier) {
return models.computeIfAbsent(key, $ -> new CPUInstancer<>(type, modelSupplier.get()));
public Instancer<D> model(ModelSupplier modelKey) {
return models.computeIfAbsent(modelKey, k -> new CPUInstancer<>(type, k.get()));
}
public void setupAndRenderInto(PoseStack stack, VertexConsumer buffer) {

View File

@ -6,7 +6,7 @@ import java.util.List;
import java.util.Map;
import com.jozufozu.flywheel.api.MaterialGroup;
import com.jozufozu.flywheel.backend.RenderLayer;
import com.jozufozu.flywheel.api.RenderLayer;
import com.jozufozu.flywheel.backend.instancing.BatchDrawingTracker;
import com.jozufozu.flywheel.backend.instancing.Engine;
import com.jozufozu.flywheel.backend.instancing.TaskEngine;
@ -33,8 +33,8 @@ public class BatchingEngine implements Engine {
}
@Override
public MaterialGroup state(RenderLayer layer, RenderType state) {
return layers.get(layer).computeIfAbsent(state, BatchedMaterialGroup::new);
public MaterialGroup state(RenderLayer layer, RenderType type) {
return layers.get(layer).computeIfAbsent(type, BatchedMaterialGroup::new);
}
@Override

View File

@ -10,6 +10,7 @@ import java.util.function.Supplier;
import com.jozufozu.flywheel.api.InstanceData;
import com.jozufozu.flywheel.api.Instancer;
import com.jozufozu.flywheel.api.Material;
import com.jozufozu.flywheel.api.ModelSupplier;
import com.jozufozu.flywheel.api.struct.Instanced;
import com.jozufozu.flywheel.core.model.Model;
@ -19,7 +20,7 @@ import com.jozufozu.flywheel.core.model.Model;
*/
public class InstancedMaterial<D extends InstanceData> implements Material<D> {
protected final Map<Object, GPUInstancer<D>> models = new HashMap<>();
protected final Map<ModelSupplier, GPUInstancer<D>> models = new HashMap<>();
protected final Instanced<D> type;
protected final List<GPUInstancer<D>> uninitialized = new ArrayList<>();
@ -27,17 +28,10 @@ public class InstancedMaterial<D extends InstanceData> implements Material<D> {
this.type = type;
}
/**
* Get an instancer for the given model. Calling this method twice with the same key will return the same instancer.
*
* @param key An object that uniquely identifies the model.
* @param modelSupplier A factory that creates the IModel that you want to render.
* @return An instancer for the given model, capable of rendering many copies for little cost.
*/
@Override
public Instancer<D> model(Object key, Supplier<Model> modelSupplier) {
return models.computeIfAbsent(key, $ -> {
GPUInstancer<D> instancer = new GPUInstancer<>(type, modelSupplier.get());
public Instancer<D> model(ModelSupplier modelKey) {
return models.computeIfAbsent(modelKey, k -> {
GPUInstancer<D> instancer = new GPUInstancer<>(type, k.get());
uninitialized.add(instancer);
return instancer;
});

View File

@ -7,7 +7,7 @@ import com.jozufozu.flywheel.api.InstanceData;
import com.jozufozu.flywheel.api.MaterialGroup;
import com.jozufozu.flywheel.api.struct.Instanced;
import com.jozufozu.flywheel.api.struct.StructType;
import com.jozufozu.flywheel.backend.RenderLayer;
import com.jozufozu.flywheel.api.RenderLayer;
import com.jozufozu.flywheel.backend.gl.versioned.GlCompat;
import com.jozufozu.flywheel.backend.model.FallbackAllocator;
import com.jozufozu.flywheel.backend.model.ModelAllocator;

View File

@ -9,7 +9,7 @@ import java.util.stream.Stream;
import javax.annotation.Nullable;
import com.jozufozu.flywheel.api.MaterialGroup;
import com.jozufozu.flywheel.backend.RenderLayer;
import com.jozufozu.flywheel.api.RenderLayer;
import com.jozufozu.flywheel.backend.instancing.Engine;
import com.jozufozu.flywheel.backend.instancing.TaskEngine;
import com.jozufozu.flywheel.core.compile.ProgramCompiler;
@ -59,7 +59,7 @@ public class InstancingEngine<P extends WorldProgram> implements Engine {
/**
* Get a material group that will render in the given layer with the given type.
*
* @param layer The {@link RenderLayer} you want to draw in.
* @param layer
* @param type The {@link RenderType} you need to draw with.
* @return A material group whose children will
*/

View File

@ -0,0 +1,37 @@
package com.jozufozu.flywheel.core;
import java.util.HashMap;
import java.util.Map;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.function.Supplier;
import com.jozufozu.flywheel.api.ModelSupplier;
import com.jozufozu.flywheel.core.model.BlockModel;
import com.jozufozu.flywheel.util.Pair;
import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.Util;
import net.minecraft.core.Direction;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.state.BlockState;
public class Models {
public static ModelSupplier block(BlockState state) {
return BLOCK_STATE.apply(state);
}
public static ModelSupplier partial(PartialModel partial) {
return PARTIAL.apply(partial);
}
public static ModelSupplier partial(PartialModel partial, Direction dir, Supplier<PoseStack> modelTransform) {
return PARTIAL_DIR.computeIfAbsent(Pair.of(dir, partial), $ -> new SimpleModelSupplier(() -> new BlockModel(partial.get(), Blocks.AIR.defaultBlockState(), modelTransform.get())));
}
private static final Function<BlockState, ModelSupplier> BLOCK_STATE = Util.memoize(it -> new SimpleModelSupplier(() -> new BlockModel(it)));
private static final Function<PartialModel, ModelSupplier> PARTIAL = Util.memoize(it -> new SimpleModelSupplier(() -> new BlockModel(it.get(), Blocks.AIR.defaultBlockState())));
private static final Map<Pair<Direction, PartialModel>, ModelSupplier> PARTIAL_DIR = new HashMap<>();
}

View File

@ -0,0 +1,25 @@
package com.jozufozu.flywheel.core;
import java.util.function.Supplier;
import javax.annotation.Nonnull;
import com.jozufozu.flywheel.api.ModelSupplier;
import com.jozufozu.flywheel.core.model.Model;
import com.jozufozu.flywheel.util.Lazy;
import com.jozufozu.flywheel.util.NonNullSupplier;
public class SimpleModelSupplier implements ModelSupplier {
private final Lazy<Model> supplier;
public SimpleModelSupplier(NonNullSupplier<Model> supplier) {
this.supplier = Lazy.of(supplier);
}
@Nonnull
@Override
public Model get() {
return supplier.get();
}
}

View File

@ -6,7 +6,7 @@ import javax.annotation.Nullable;
import com.jozufozu.flywheel.api.vertex.VertexType;
import com.jozufozu.flywheel.backend.Backend;
import com.jozufozu.flywheel.backend.RenderLayer;
import com.jozufozu.flywheel.api.RenderLayer;
import com.jozufozu.flywheel.core.GameStateRegistry;
import com.jozufozu.flywheel.core.shader.ProgramSpec;
import com.jozufozu.flywheel.core.shader.StateSnapshot;

View File

@ -1,6 +1,6 @@
package com.jozufozu.flywheel.core.crumbling;
import com.jozufozu.flywheel.backend.RenderLayer;
import com.jozufozu.flywheel.api.RenderLayer;
import com.jozufozu.flywheel.backend.instancing.instancing.InstancedMaterialGroup;
import com.jozufozu.flywheel.backend.instancing.instancing.InstancingEngine;
import com.jozufozu.flywheel.util.Textures;

View File

@ -44,14 +44,10 @@ public class CrumblingRenderer {
static RenderType _currentLayer;
private static final Lazy<State> STATE;
private static final Lazy.KillSwitch<State> INVALIDATOR;
private static Lazy<State> STATE;
static {
Pair<Lazy<State>, Lazy.KillSwitch<State>> state = Lazy.ofKillable(State::new, State::kill);
STATE = state.first();
INVALIDATOR = state.second();
_init();
}
public static void renderBreaking(RenderLayerEvent event) {
@ -126,7 +122,12 @@ public class CrumblingRenderer {
}
public static void reset() {
INVALIDATOR.killValue();
STATE.ifPresent(State::kill);
_init();
}
private static void _init() {
STATE = Lazy.of(State::new);
}
private static class State {

View File

@ -2,8 +2,8 @@ package com.jozufozu.flywheel.core.model;
import java.lang.reflect.Field;
import java.util.Collection;
import java.util.EnumMap;
import java.util.Random;
import java.util.function.Supplier;
import com.jozufozu.flywheel.Flywheel;
import com.jozufozu.flywheel.core.virtual.VirtualEmptyBlockGetter;
@ -127,18 +127,28 @@ public class ModelUtil {
return builder;
}
public static Supplier<PoseStack> rotateToFace(Direction facing) {
return () -> {
PoseStack stack = new PoseStack();
TransformStack.cast(stack)
.centre()
.rotateToFace(facing.getOpposite())
.unCentre();
return stack;
};
private static PoseStack createRotation(Direction facing) {
PoseStack stack = new PoseStack();
TransformStack.cast(stack)
.centre()
.rotateToFace(facing.getOpposite())
.unCentre();
return stack;
}
private static class ThreadLocalObjects {
public static PoseStack rotateToFace(Direction facing) {
return TRANSFORMS.get(facing);
}
private static final EnumMap<Direction, PoseStack> TRANSFORMS = new EnumMap<>(Direction.class);
static {
for (Direction value : Direction.values()) {
TRANSFORMS.put(value, createRotation(value));
}
}
private static class ThreadLocalObjects {
public final Random random = new Random();
public final ShadeSeparatingVertexConsumer shadeSeparatingWrapper = new ShadeSeparatingVertexConsumer();
public final BufferBuilder unshadedBuilder = new BufferBuilder(512);

View File

@ -2,7 +2,7 @@ package com.jozufozu.flywheel.event;
import javax.annotation.Nullable;
import com.jozufozu.flywheel.backend.RenderLayer;
import com.jozufozu.flywheel.api.RenderLayer;
import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.math.Matrix4f;

View File

@ -1,10 +1,11 @@
package com.jozufozu.flywheel.util;
import java.util.function.Consumer;
import java.util.function.Supplier;
import javax.annotation.Nonnull;
public class Lazy<T> {
public class Lazy<T> implements Supplier<T> {
private final NonNullSupplier<T> supplier;
@ -23,36 +24,13 @@ public class Lazy<T> {
return value;
}
/**
* Provides an external facing API safe way of invalidating lazy values.
*/
public static <T> Pair<Lazy<T>, KillSwitch<T>> ofKillable(NonNullSupplier<T> factory, Consumer<T> destructor) {
Lazy<T> lazy = new Lazy<>(factory);
KillSwitch<T> killSwitch = new KillSwitch<>(lazy, destructor);
return Pair.of(lazy, killSwitch);
}
public static <T> Lazy<T> of(NonNullSupplier<T> factory) {
return new Lazy<>(factory);
}
public static class KillSwitch<T> {
private final Lazy<T> lazy;
private final Consumer<T> finalizer;
private KillSwitch(Lazy<T> lazy, Consumer<T> finalizer) {
this.lazy = lazy;
this.finalizer = finalizer;
}
public void killValue() {
if (lazy.value != null) {
finalizer.accept(lazy.value);
lazy.value = null;
}
public void ifPresent(Consumer<T> func) {
if (value != null) {
func.accept(value);
}
}
}

View File

@ -5,5 +5,6 @@ import javax.annotation.Nonnull;
@FunctionalInterface
public interface NonNullSupplier<T> {
@Nonnull T get();
@Nonnull
T get();
}

View File

@ -1,9 +1,13 @@
package com.jozufozu.flywheel.vanilla;
import javax.annotation.Nonnull;
import com.jozufozu.flywheel.api.MaterialManager;
import com.jozufozu.flywheel.api.ModelSupplier;
import com.jozufozu.flywheel.api.instance.DynamicInstance;
import com.jozufozu.flywheel.backend.instancing.blockentity.BlockEntityInstance;
import com.jozufozu.flywheel.core.Materials;
import com.jozufozu.flywheel.core.SimpleModelSupplier;
import com.jozufozu.flywheel.core.hardcoded.ModelPart;
import com.jozufozu.flywheel.core.materials.oriented.OrientedData;
import com.jozufozu.flywheel.util.AnimationTickHolder;
@ -16,6 +20,8 @@ import net.minecraft.world.level.block.entity.BellBlockEntity;
public class BellInstance extends BlockEntityInstance<BellBlockEntity> implements DynamicInstance {
private static final ModelSupplier MODEL = new SimpleModelSupplier(BellInstance::createBellModel);
private final OrientedData bell;
private float lastRingTime = Float.NaN;
@ -59,10 +65,11 @@ public class BellInstance extends BlockEntityInstance<BellBlockEntity> implement
private OrientedData createBellInstance() {
return materialManager.defaultCutout()
.material(Materials.ORIENTED)
.model(blockEntity.getType(), BellInstance::createBellModel)
.model(MODEL)
.createInstance();
}
@Nonnull
private static ModelPart createBellModel() {
return ModelPart.builder("bell", 32, 32)
.sprite(BellRenderer.BELL_RESOURCE_LOCATION.sprite())

View File

@ -1,13 +1,16 @@
package com.jozufozu.flywheel.vanilla;
import java.util.Calendar;
import java.util.function.BiFunction;
import javax.annotation.Nonnull;
import com.jozufozu.flywheel.api.MaterialManager;
import com.jozufozu.flywheel.api.ModelSupplier;
import com.jozufozu.flywheel.api.instance.DynamicInstance;
import com.jozufozu.flywheel.backend.instancing.blockentity.BlockEntityInstance;
import com.jozufozu.flywheel.core.Materials;
import com.jozufozu.flywheel.core.SimpleModelSupplier;
import com.jozufozu.flywheel.core.hardcoded.ModelPart;
import com.jozufozu.flywheel.core.materials.model.ModelData;
import com.jozufozu.flywheel.core.materials.oriented.OrientedData;
@ -16,8 +19,10 @@ import com.mojang.math.Quaternion;
import com.mojang.math.Vector3f;
import it.unimi.dsi.fastutil.floats.Float2FloatFunction;
import net.minecraft.Util;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.Sheets;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.resources.model.Material;
import net.minecraft.world.level.block.AbstractChestBlock;
import net.minecraft.world.level.block.Block;
@ -30,6 +35,9 @@ import net.minecraft.world.level.block.state.properties.ChestType;
public class ChestInstance<T extends BlockEntity & LidBlockEntity> extends BlockEntityInstance<T> implements DynamicInstance {
private static final BiFunction<ChestType, TextureAtlasSprite, ModelSupplier> LID = Util.memoize((type, sprite) -> new SimpleModelSupplier(() -> createLidModel(type, sprite)));
private static final BiFunction<ChestType, TextureAtlasSprite, ModelSupplier> BASE = Util.memoize((type, sprite) -> new SimpleModelSupplier(() -> createBaseModel(type, sprite)));
private final OrientedData body;
private final ModelData lid;
@ -111,7 +119,7 @@ public class ChestInstance<T extends BlockEntity & LidBlockEntity> extends Block
return materialManager.solid(RenderType.entitySolid(renderMaterial.atlasLocation()))
.material(Materials.ORIENTED)
.model("base_" + renderMaterial.texture(), this::getBaseModel)
.model(BASE.apply(chestType, renderMaterial.sprite()))
.createInstance();
}
@ -119,15 +127,15 @@ public class ChestInstance<T extends BlockEntity & LidBlockEntity> extends Block
return materialManager.solid(RenderType.entitySolid(renderMaterial.atlasLocation()))
.material(Materials.TRANSFORMED)
.model("lid_" + renderMaterial.texture(), this::getLidModel)
.model(LID.apply(chestType, renderMaterial.sprite()))
.createInstance();
}
private ModelPart getBaseModel() {
private static ModelPart createBaseModel(ChestType type, TextureAtlasSprite sprite) {
return switch (chestType) {
return switch (type) {
case LEFT -> ModelPart.builder("chest_base_left", 64, 64)
.sprite(renderMaterial.sprite())
.sprite(sprite)
.cuboid()
.textureOffset(0, 19)
.start(0, 0, 1)
@ -135,7 +143,7 @@ public class ChestInstance<T extends BlockEntity & LidBlockEntity> extends Block
.endCuboid()
.build();
case RIGHT -> ModelPart.builder("chest_base_right", 64, 64)
.sprite(renderMaterial.sprite())
.sprite(sprite)
.cuboid()
.textureOffset(0, 19)
.start(1, 0, 1)
@ -143,7 +151,7 @@ public class ChestInstance<T extends BlockEntity & LidBlockEntity> extends Block
.endCuboid()
.build();
default -> ModelPart.builder("chest_base", 64, 64)
.sprite(renderMaterial.sprite())
.sprite(sprite)
.cuboid()
.textureOffset(0, 19)
.start(1, 0, 1)
@ -154,11 +162,11 @@ public class ChestInstance<T extends BlockEntity & LidBlockEntity> extends Block
}
private ModelPart getLidModel() {
private static ModelPart createLidModel(ChestType type, TextureAtlasSprite sprite) {
return switch (chestType) {
return switch (type) {
case LEFT -> ModelPart.builder("chest_lid_left", 64, 64)
.sprite(renderMaterial.sprite())
.sprite(sprite)
.cuboid()
.textureOffset(0, 0)
.start(0, 0, 1)
@ -170,7 +178,7 @@ public class ChestInstance<T extends BlockEntity & LidBlockEntity> extends Block
.endCuboid()
.build();
case RIGHT -> ModelPart.builder("chest_lid_right", 64, 64)
.sprite(renderMaterial.sprite())
.sprite(sprite)
.cuboid()
.textureOffset(0, 0)
.start(1, 0, 1)
@ -182,7 +190,7 @@ public class ChestInstance<T extends BlockEntity & LidBlockEntity> extends Block
.endCuboid()
.build();
default -> ModelPart.builder("chest_lid", 64, 64)
.sprite(renderMaterial.sprite())
.sprite(sprite)
.cuboid()
.textureOffset(0, 0)
.start(1, 0, 1)

View File

@ -1,10 +1,14 @@
package com.jozufozu.flywheel.vanilla;
import javax.annotation.Nonnull;
import com.jozufozu.flywheel.api.MaterialManager;
import com.jozufozu.flywheel.api.ModelSupplier;
import com.jozufozu.flywheel.api.instance.DynamicInstance;
import com.jozufozu.flywheel.api.instance.TickableInstance;
import com.jozufozu.flywheel.backend.instancing.entity.EntityInstance;
import com.jozufozu.flywheel.core.Materials;
import com.jozufozu.flywheel.core.SimpleModelSupplier;
import com.jozufozu.flywheel.core.hardcoded.ModelPart;
import com.jozufozu.flywheel.core.materials.model.ModelData;
import com.jozufozu.flywheel.core.model.Model;
@ -25,6 +29,7 @@ import net.minecraft.world.phys.Vec3;
public class MinecartInstance<T extends AbstractMinecart> extends EntityInstance<T> implements DynamicInstance, TickableInstance {
private static final ResourceLocation MINECART_LOCATION = new ResourceLocation("textures/entity/minecart.png");
private static final ModelSupplier MODEL = new SimpleModelSupplier(MinecartInstance::getBodyModel);
private final PoseStack stack = new PoseStack();
@ -151,11 +156,12 @@ public class MinecartInstance<T extends AbstractMinecart> extends EntityInstance
private ModelData getBody() {
return materialManager.solid(RenderType.entitySolid(MINECART_LOCATION))
.material(Materials.TRANSFORMED)
.model(entity.getType(), this::getBodyModel)
.model(MODEL)
.createInstance();
}
private Model getBodyModel() {
@Nonnull
private static Model getBodyModel() {
int y = -3;
return ModelPart.builder("minecart", 64, 32)
.cuboid().invertYZ().start(-10, -8, -y).size(20, 16, 2).textureOffset(0, 10).rotateZ((float) Math.PI).rotateX(((float)Math.PI / 2F)).endCuboid()

View File

@ -1,9 +1,13 @@
package com.jozufozu.flywheel.vanilla;
import java.util.function.Function;
import com.jozufozu.flywheel.api.MaterialManager;
import com.jozufozu.flywheel.api.ModelSupplier;
import com.jozufozu.flywheel.api.instance.DynamicInstance;
import com.jozufozu.flywheel.backend.instancing.blockentity.BlockEntityInstance;
import com.jozufozu.flywheel.core.Materials;
import com.jozufozu.flywheel.core.SimpleModelSupplier;
import com.jozufozu.flywheel.core.hardcoded.ModelPart;
import com.jozufozu.flywheel.core.materials.model.ModelData;
import com.jozufozu.flywheel.util.AnimationTickHolder;
@ -12,6 +16,7 @@ import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.math.Quaternion;
import com.mojang.math.Vector3f;
import net.minecraft.Util;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.Sheets;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
@ -22,6 +27,9 @@ import net.minecraft.world.level.block.entity.ShulkerBoxBlockEntity;
public class ShulkerBoxInstance extends BlockEntityInstance<ShulkerBoxBlockEntity> implements DynamicInstance {
private static final Function<TextureAtlasSprite, ModelSupplier> BASE = Util.memoize(it -> new SimpleModelSupplier(() -> makeBaseModel(it)));
private static final Function<TextureAtlasSprite, ModelSupplier> LID = Util.memoize(it -> new SimpleModelSupplier(() -> makeLidModel(it)));
private final TextureAtlasSprite texture;
private final ModelData base;
@ -93,18 +101,18 @@ public class ShulkerBoxInstance extends BlockEntityInstance<ShulkerBoxBlockEntit
private ModelData makeBaseInstance() {
return materialManager.cutout(RenderType.entityCutoutNoCull(Sheets.SHULKER_SHEET))
.material(Materials.TRANSFORMED)
.model("base_" + texture.getName(), this::makeBaseModel)
.model(BASE.apply(texture))
.createInstance();
}
private ModelData makeLidInstance() {
return materialManager.cutout(RenderType.entityCutoutNoCull(Sheets.SHULKER_SHEET))
.material(Materials.TRANSFORMED)
.model("lid_" + texture.getName(), this::makeLidModel)
.model(LID.apply(texture))
.createInstance();
}
private ModelPart makeBaseModel() {
private static ModelPart makeBaseModel(TextureAtlasSprite texture) {
return ModelPart.builder("shulker_base", 64, 64)
.sprite(texture)
.cuboid()
@ -115,7 +123,7 @@ public class ShulkerBoxInstance extends BlockEntityInstance<ShulkerBoxBlockEntit
.build();
}
private ModelPart makeLidModel() {
private static ModelPart makeLidModel(TextureAtlasSprite texture) {
return ModelPart.builder("shulker_lid", 64, 64)
.sprite(texture)
.cuboid()