Package deal

- Add package entity visual
- Add packager visual
  - Don't render the box model in the visual because it relies on item
    transforms
- Bump flywheel build
- Upgrade to some of the newer Affine functions where applicable
This commit is contained in:
Jozufozu 2025-01-19 14:58:51 -06:00
parent f98a8f7efb
commit 153c63f1c8
7 changed files with 223 additions and 30 deletions

View file

@ -22,7 +22,7 @@ use_parchment = true
# dependency versions
registrate_version = MC1.20-1.3.3
flywheel_minecraft_version = 1.20.1
flywheel_version = 1.0.0-beta-182
flywheel_version = 1.0.0-beta-184
jei_minecraft_version = 1.20.1
jei_version = 15.10.0.39
curios_minecraft_version = 1.20.1

View file

@ -174,6 +174,7 @@ import com.simibubi.create.content.logistics.packagePort.postbox.PostboxBlockEnt
import com.simibubi.create.content.logistics.packagePort.postbox.PostboxRenderer;
import com.simibubi.create.content.logistics.packager.PackagerBlockEntity;
import com.simibubi.create.content.logistics.packager.PackagerRenderer;
import com.simibubi.create.content.logistics.packager.PackagerVisual;
import com.simibubi.create.content.logistics.packager.repackager.RepackagerBlockEntity;
import com.simibubi.create.content.logistics.packagerLink.PackagerLinkBlockEntity;
import com.simibubi.create.content.logistics.redstoneRequester.RedstoneRequesterBlockEntity;
@ -497,12 +498,14 @@ public class AllBlockEntityTypes {
public static final BlockEntityEntry<PackagerBlockEntity> PACKAGER = REGISTRATE
.blockEntity("packager", PackagerBlockEntity::new)
.visual(() -> PackagerVisual::new, true)
.validBlocks(AllBlocks.PACKAGER)
.renderer(() -> PackagerRenderer::new)
.register();
public static final BlockEntityEntry<RepackagerBlockEntity> REPACKAGER = REGISTRATE
.blockEntity("repackager", RepackagerBlockEntity::new)
.visual(() -> PackagerVisual::new, true)
.validBlocks(AllBlocks.REPACKAGER)
.renderer(() -> PackagerRenderer::new)
.register();

View file

@ -16,6 +16,7 @@ import com.simibubi.create.content.equipment.potatoCannon.PotatoProjectileEntity
import com.simibubi.create.content.equipment.potatoCannon.PotatoProjectileRenderer;
import com.simibubi.create.content.logistics.box.PackageEntity;
import com.simibubi.create.content.logistics.box.PackageRenderer;
import com.simibubi.create.content.logistics.box.PackageVisual;
import com.simibubi.create.content.trains.entity.CarriageContraptionEntity;
import com.simibubi.create.content.trains.entity.CarriageContraptionEntityRenderer;
import com.simibubi.create.content.trains.entity.CarriageContraptionVisual;
@ -71,7 +72,9 @@ public class AllEntityTypes {
MobCategory.MISC, 5, Integer.MAX_VALUE, false, true, SeatEntity::build).register();
public static final EntityEntry<PackageEntity> PACKAGE = register("package", PackageEntity::new, () -> PackageRenderer::new,
MobCategory.MISC, 10, 3, true, false, PackageEntity::build).register();
MobCategory.MISC, 10, 3, true, false, PackageEntity::build)
.visual(() -> PackageVisual::new, true)
.register();
//

View file

@ -4,6 +4,7 @@ import com.mojang.blaze3d.vertex.PoseStack;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllPartialModels;
import dev.engine_room.flywheel.api.backend.BackendManager;
import dev.engine_room.flywheel.lib.model.baked.PartialModel;
import net.createmod.catnip.render.CachedBuffers;
import net.createmod.catnip.render.SuperByteBuffer;
@ -28,11 +29,12 @@ public class PackageRenderer extends EntityRenderer<PackageEntity> {
@Override
public void render(PackageEntity entity, float yaw, float pt, PoseStack ms, MultiBufferSource buffer, int light) {
ItemStack box = entity.box;
if (box.isEmpty() || !PackageItem.isPackage(box))
box = AllBlocks.CARDBOARD_BLOCK.asStack();
PartialModel model = AllPartialModels.PACKAGES.get(ForgeRegistries.ITEMS.getKey(box.getItem()));
renderBox(entity, yaw, ms, buffer, light, model);
if (!BackendManager.isBackendOn()) {
ItemStack box = entity.box;
if (box.isEmpty() || !PackageItem.isPackage(box)) box = AllBlocks.CARDBOARD_BLOCK.asStack();
PartialModel model = AllPartialModels.PACKAGES.get(ForgeRegistries.ITEMS.getKey(box.getItem()));
renderBox(entity, yaw, ms, buffer, light, model);
}
super.render(entity, yaw, pt, ms, buffer, light);
}

View file

@ -0,0 +1,69 @@
package com.simibubi.create.content.logistics.box;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllPartialModels;
import dev.engine_room.flywheel.api.visualization.VisualizationContext;
import dev.engine_room.flywheel.lib.instance.InstanceTypes;
import dev.engine_room.flywheel.lib.instance.TransformedInstance;
import dev.engine_room.flywheel.lib.model.Models;
import dev.engine_room.flywheel.lib.model.baked.PartialModel;
import dev.engine_room.flywheel.lib.transform.Translate;
import dev.engine_room.flywheel.lib.visual.AbstractEntityVisual;
import dev.engine_room.flywheel.lib.visual.SimpleDynamicVisual;
import net.minecraft.util.Mth;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.phys.Vec3;
import net.minecraftforge.registries.ForgeRegistries;
public class PackageVisual extends AbstractEntityVisual<PackageEntity> implements SimpleDynamicVisual {
public final TransformedInstance instance;
public PackageVisual(VisualizationContext ctx, PackageEntity entity, float partialTick) {
super(ctx, entity, partialTick);
ItemStack box = entity.box;
if (box.isEmpty() || !PackageItem.isPackage(box))
box = AllBlocks.CARDBOARD_BLOCK.asStack();
PartialModel model = AllPartialModels.PACKAGES.get(ForgeRegistries.ITEMS.getKey(box.getItem()));
instance = instancerProvider().instancer(InstanceTypes.TRANSFORMED, Models.partial(model))
.createInstance();
animate(partialTick);
}
@Override
public void beginFrame(Context ctx) {
animate(ctx.partialTick());
}
private void animate(float partialTick) {
float yaw = Mth.lerp(partialTick, entity.yRotO, entity.getYRot());
Vec3 pos = PackageVisual.this.entity.position();
var renderOrigin = renderOrigin();
var x = (float) (Mth.lerp(partialTick, this.entity.xo, pos.x) - renderOrigin.getX());
var y = (float) (Mth.lerp(partialTick, this.entity.yo, pos.y) - renderOrigin.getY());
var z = (float) (Mth.lerp(partialTick, this.entity.zo, pos.z) - renderOrigin.getZ());
long randomBits = (long) entity.getId() * 31L * 493286711L;
randomBits = randomBits * randomBits * 4392167121L + randomBits * 98761L;
float xNudge = (((float) (randomBits >> 16 & 7L) + 0.5F) / 8.0F - 0.5F) * 0.004F;
float yNudge = (((float) (randomBits >> 20 & 7L) + 0.5F) / 8.0F - 0.5F) * 0.004F;
float zNudge = (((float) (randomBits >> 24 & 7L) + 0.5F) / 8.0F - 0.5F) * 0.004F;
instance.setIdentityTransform()
.translate(x - 0.5 + xNudge, y + yNudge, z - 0.5 + zNudge)
.rotateYCenteredDegrees(yaw)
.light(computePackedLight(partialTick))
.setChanged();
}
@Override
protected void _delete() {
instance.delete();
}
}

View file

@ -5,6 +5,8 @@ import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllPartialModels;
import com.simibubi.create.foundation.blockEntity.renderer.SmartBlockEntityRenderer;
import dev.engine_room.flywheel.api.backend.BackendManager;
import dev.engine_room.flywheel.api.model.Model;
import dev.engine_room.flywheel.lib.model.baked.PartialModel;
import dev.engine_room.flywheel.lib.transform.TransformStack;
import net.createmod.catnip.render.CachedBuffers;
@ -33,36 +35,35 @@ public class PackagerRenderer extends SmartBlockEntityRenderer<PackagerBlockEnti
ItemStack renderedBox = be.getRenderedBox();
float trayOffset = be.getTrayOffset(partialTicks);
boolean hatchOpen = be.animationTicks > (be.animationInward ? 1 : 5)
&& be.animationTicks < PackagerBlockEntity.CYCLE - (be.animationInward ? 5 : 1);
BlockState blockState = be.getBlockState();
Direction facing = blockState.getValue(PackagerBlock.FACING)
.getOpposite();
PartialModel hatchModel =
hatchOpen ? AllPartialModels.PACKAGER_HATCH_OPEN : AllPartialModels.PACKAGER_HATCH_CLOSED;
if (!BackendManager.isBackendOn()) {
var hatchModel = getHatchModel(be);
SuperByteBuffer sbb = CachedBuffers.partial(hatchModel, blockState);
sbb.translate(Vec3.atLowerCornerOf(facing.getNormal())
.scale(.49999f))
.rotateCentered(AngleHelper.rad(AngleHelper.horizontalAngle(facing)), Direction.UP)
.rotateCentered(AngleHelper.rad(AngleHelper.verticalAngle(facing)), Direction.EAST)
.light(light)
.renderInto(ms, buffer.getBuffer(RenderType.solid()));
SuperByteBuffer sbb = CachedBuffers.partial(hatchModel, blockState);
sbb.translate(Vec3.atLowerCornerOf(facing.getNormal())
.scale(.49999f))
.rotateYCenteredDegrees(AngleHelper.horizontalAngle(facing))
.rotateXCenteredDegrees(AngleHelper.verticalAngle(facing))
.light(light)
.renderInto(ms, buffer.getBuffer(RenderType.solid()));
ms.pushPose();
var msr = TransformStack.of(ms);
msr.translate(Vec3.atLowerCornerOf(facing.getNormal())
.scale(trayOffset));
sbb = CachedBuffers.partial(AllBlocks.PACKAGER.has(blockState) ? AllPartialModels.PACKAGER_TRAY_REGULAR
: AllPartialModels.PACKAGER_TRAY_DEFRAG, blockState);
sbb.rotateCentered(AngleHelper.rad(facing.toYRot()), Direction.UP)
.light(light)
.renderInto(ms, buffer.getBuffer(RenderType.cutoutMipped()));
sbb = CachedBuffers.partial(getTrayModel(blockState), blockState);
sbb.translate(Vec3.atLowerCornerOf(facing.getNormal())
.scale(trayOffset))
.rotateYCenteredDegrees(facing.toYRot())
.light(light)
.renderInto(ms, buffer.getBuffer(RenderType.cutoutMipped()));
}
if (!renderedBox.isEmpty()) {
msr.translate(.5f, .5f, .5f)
ms.pushPose();
var msr = TransformStack.of(ms);
msr.translate(Vec3.atLowerCornerOf(facing.getNormal())
.scale(trayOffset))
.translate(.5f, .5f, .5f)
.rotateYDegrees(facing.toYRot())
.translate(0, 2 / 16f, 0)
.scale(1.49f, 1.49f, 1.49f);
@ -70,9 +71,22 @@ public class PackagerRenderer extends SmartBlockEntityRenderer<PackagerBlockEnti
.getItemRenderer()
.renderStatic(null, renderedBox, ItemDisplayContext.FIXED, false, ms, buffer, be.getLevel(), light,
overlay, 0);
ms.popPose();
}
}
ms.popPose();
public static PartialModel getTrayModel(BlockState blockState) {
return AllBlocks.PACKAGER.has(blockState) ? AllPartialModels.PACKAGER_TRAY_REGULAR
: AllPartialModels.PACKAGER_TRAY_DEFRAG;
}
public static PartialModel getHatchModel(PackagerBlockEntity be) {
return isHatchOpen(be) ? AllPartialModels.PACKAGER_HATCH_OPEN : AllPartialModels.PACKAGER_HATCH_CLOSED;
}
public static boolean isHatchOpen(PackagerBlockEntity be) {
return be.animationTicks > (be.animationInward ? 1 : 5)
&& be.animationTicks < PackagerBlockEntity.CYCLE - (be.animationInward ? 5 : 1);
}
}

View file

@ -0,0 +1,102 @@
package com.simibubi.create.content.logistics.packager;
import java.util.function.Consumer;
import org.jetbrains.annotations.Nullable;
import dev.engine_room.flywheel.api.instance.Instance;
import dev.engine_room.flywheel.api.visualization.VisualizationContext;
import dev.engine_room.flywheel.lib.instance.InstanceTypes;
import dev.engine_room.flywheel.lib.instance.TransformedInstance;
import dev.engine_room.flywheel.lib.model.Models;
import dev.engine_room.flywheel.lib.model.baked.PartialModel;
import dev.engine_room.flywheel.lib.visual.AbstractBlockEntityVisual;
import dev.engine_room.flywheel.lib.visual.SimpleDynamicVisual;
import net.createmod.catnip.math.AngleHelper;
import net.minecraft.core.Direction;
import net.minecraft.world.phys.Vec3;
public class PackagerVisual<T extends PackagerBlockEntity> extends AbstractBlockEntityVisual<T> implements SimpleDynamicVisual {
public final TransformedInstance hatch;
public final TransformedInstance tray;
public float lastTrayOffset = Float.NaN;
public PartialModel lastHatchPartial;
public PackagerVisual(VisualizationContext ctx, T blockEntity, float partialTick) {
super(ctx, blockEntity, partialTick);
lastHatchPartial = PackagerRenderer.getHatchModel(blockEntity);
hatch = instancerProvider().instancer(InstanceTypes.TRANSFORMED, Models.partial(lastHatchPartial))
.createInstance();
tray = instancerProvider().instancer(InstanceTypes.TRANSFORMED, Models.partial(PackagerRenderer.getTrayModel(blockState)))
.createInstance();
Direction facing = blockState.getValue(PackagerBlock.FACING)
.getOpposite();
var lowerCorner = Vec3.atLowerCornerOf(facing.getNormal());
hatch.setIdentityTransform()
.translate(getVisualPosition())
.translate(lowerCorner
.scale(.49999f))
.rotateYCenteredDegrees(AngleHelper.horizontalAngle(facing))
.rotateXCenteredDegrees(AngleHelper.verticalAngle(facing))
.setChanged();
// TODO: I think we need proper ItemVisuals to handle rendering the boxes in here
animate(partialTick);
}
@Override
public void beginFrame(Context ctx) {
animate(ctx.partialTick());
}
public void animate(float partialTick) {
var hatchPartial = PackagerRenderer.getHatchModel(blockEntity);
if (hatchPartial != this.lastHatchPartial) {
instancerProvider().instancer(InstanceTypes.TRANSFORMED, Models.partial(hatchPartial))
.stealInstance(hatch);
this.lastHatchPartial = hatchPartial;
}
float trayOffset = blockEntity.getTrayOffset(partialTick);
if (trayOffset != lastTrayOffset) {
Direction facing = blockState.getValue(PackagerBlock.FACING)
.getOpposite();
var lowerCorner = Vec3.atLowerCornerOf(facing.getNormal());
tray.setIdentityTransform()
.translate(getVisualPosition())
.translate(lowerCorner.scale(trayOffset))
.rotateYCenteredDegrees(facing.toYRot())
.setChanged();
lastTrayOffset = trayOffset;
}
}
@Override
public void updateLight(float partialTick) {
relight(hatch, tray);
}
@Override
protected void _delete() {
hatch.delete();
tray.delete();
}
@Override
public void collectCrumblingInstances(Consumer<@Nullable Instance> consumer) {
}
}