Skip to content

Commit

Permalink
Added Elytra Pivot
Browse files Browse the repository at this point in the history
  • Loading branch information
UnlikePaladin committed Oct 2, 2023
1 parent 7d468bf commit 4b27c92
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 9 deletions.
@@ -1,16 +1,28 @@
package org.figuramc.figura.mixin.render.layers.elytra;

import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.blaze3d.vertex.VertexConsumer;
import com.mojang.math.Axis;
import net.minecraft.client.model.ElytraModel;
import net.minecraft.client.model.EntityModel;
import net.minecraft.client.player.AbstractClientPlayer;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.entity.ItemRenderer;
import net.minecraft.client.renderer.entity.RenderLayerParent;
import net.minecraft.client.renderer.entity.layers.ElytraLayer;
import net.minecraft.client.renderer.entity.layers.RenderLayer;
import net.minecraft.client.renderer.texture.OverlayTexture;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.entity.EquipmentSlot;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.player.PlayerModelPart;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import org.figuramc.figura.avatar.Avatar;
import org.figuramc.figura.avatar.AvatarManager;
import org.figuramc.figura.lua.api.vanilla_model.VanillaPart;
import org.figuramc.figura.model.ParentType;
import org.figuramc.figura.permissions.Permissions;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
Expand All @@ -28,33 +40,69 @@ public ElytraLayerMixin(RenderLayerParent<T, M> context) {
}

@Shadow @Final private ElytraModel<T> elytraModel;
@Shadow @Final private static ResourceLocation WINGS_LOCATION;
@Unique
private VanillaPart vanillaPart;
@Unique
private Avatar figura$avatar;

@Unique
private boolean renderedPivot;

@Inject(at = @At(value = "HEAD"), method = "render(Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;ILnet/minecraft/world/entity/LivingEntity;FFFFFF)V")
public void renderElytra(PoseStack poseStack, MultiBufferSource multiBufferSource, int i, T livingEntity, float f, float g, float h, float j, float k, float l, CallbackInfo ci) {
figura$avatar = AvatarManager.getAvatar(livingEntity);

if (figura$avatar == null) return;

ItemStack itemStack = livingEntity.getItemBySlot(EquipmentSlot.CHEST);
if (!itemStack.is(Items.ELYTRA)) {
return;
}

// Try to render the pivot part
renderedPivot = figura$avatar.pivotPartRender(ParentType.ElytraPivot, stack -> {
stack.pushPose();
stack.scale(16, 16, 16);
stack.mulPose(Axis.XP.rotationDegrees(180f));
stack.mulPose(Axis.YP.rotationDegrees(180f));
stack.translate(0.0f, 0.0f, 0.125f);
this.elytraModel.setupAnim(livingEntity, f, g, h, i, j);
ResourceLocation resourceLocation = livingEntity instanceof AbstractClientPlayer abstractClientPlayer ? (abstractClientPlayer.isElytraLoaded() && abstractClientPlayer.getElytraTextureLocation() != null ? abstractClientPlayer.getElytraTextureLocation() : (abstractClientPlayer.isCapeLoaded() && abstractClientPlayer.getCloakTextureLocation() != null && abstractClientPlayer.isModelPartShown(PlayerModelPart.CAPE) ? abstractClientPlayer.getCloakTextureLocation() : WINGS_LOCATION)) : WINGS_LOCATION;
VertexConsumer vertexConsumer = ItemRenderer.getArmorFoilBuffer(multiBufferSource, RenderType.armorCutoutNoCull(resourceLocation), false, itemStack.hasFoil());
this.elytraModel.renderToBuffer(stack, vertexConsumer, i, OverlayTexture.NO_OVERLAY, 1.0f, 1.0f, 1.0f, 1.0f);
stack.popPose();
});
}

@Inject(at = @At(value = "INVOKE", target = "Lnet/minecraft/client/model/ElytraModel;setupAnim(Lnet/minecraft/world/entity/LivingEntity;FFFFF)V", shift = At.Shift.AFTER), method = "render(Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;ILnet/minecraft/world/entity/LivingEntity;FFFFFF)V")
@Inject(at = @At(value = "INVOKE", target = "Lnet/minecraft/client/model/ElytraModel;setupAnim(Lnet/minecraft/world/entity/LivingEntity;FFFFF)V", shift = At.Shift.AFTER), method = "render(Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;ILnet/minecraft/world/entity/LivingEntity;FFFFFF)V", cancellable = true)
public void onRender(PoseStack poseStack, MultiBufferSource multiBufferSource, int light, T livingEntity, float limbAngle, float limbDistance, float tickDelta, float animationProgress, float headYaw, float headPitch, CallbackInfo ci) {
vanillaPart = null;
Avatar avatar = AvatarManager.getAvatar(livingEntity);
if (avatar == null)
if (figura$avatar == null)
return;

if (avatar.luaRuntime != null) {
VanillaPart part = avatar.luaRuntime.vanilla_model.ELYTRA;
if (figura$avatar.luaRuntime != null) {
VanillaPart part = figura$avatar.luaRuntime.vanilla_model.ELYTRA;
part.save(elytraModel);
if (avatar.permissions.get(Permissions.VANILLA_MODEL_EDIT) == 1) {
if (figura$avatar.permissions.get(Permissions.VANILLA_MODEL_EDIT) == 1) {
vanillaPart = part;
vanillaPart.preTransform(elytraModel);
}
}

avatar.elytraRender(livingEntity, multiBufferSource, poseStack, light, tickDelta, elytraModel);
figura$avatar.elytraRender(livingEntity, multiBufferSource, poseStack, light, tickDelta, elytraModel);

if (vanillaPart != null)
vanillaPart.posTransform(elytraModel);

if (renderedPivot) {
poseStack.popPose();
ci.cancel();
}
}

@Inject(at = @At("RETURN"), method = "render(Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;ILnet/minecraft/world/entity/LivingEntity;FFFFFF)V")
public void postRender(PoseStack poseStack, MultiBufferSource multiBufferSource, int i, T livingEntity, float f, float g, float h, float j, float k, float l, CallbackInfo ci) {
@Inject(at = @At(value = "INVOKE", target = "Lnet/minecraft/client/model/ElytraModel;renderToBuffer(Lcom/mojang/blaze3d/vertex/PoseStack;Lcom/mojang/blaze3d/vertex/VertexConsumer;IIFFFF)V"), method = "render(Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;ILnet/minecraft/world/entity/LivingEntity;FFFFFF)V")
public void cancelVanillaPart(PoseStack poseStack, MultiBufferSource multiBufferSource, int i, T livingEntity, float f, float g, float h, float j, float k, float l, CallbackInfo ci) {
if (vanillaPart != null)
vanillaPart.restore(elytraModel);
}
Expand Down
Expand Up @@ -45,6 +45,7 @@ public enum ParentType {
HelmetItemPivot(false, true,"HELMET_ITEM_PIVOT"),
HelmetPivot(false, true, "HELMET_PIVOT", "HelmetPivot"),
ChestplatePivot(false, true, "CHESTPLATE_PIVOT", "ChestplatePivot"),
ElytraPivot(false, true, "ELYTRA_PIVOT", "ElytraPivot"),
LeftShoulderPivot(false, true, "LEFT_SHOULDER_PIVOT", "LeftShoulderPivot"),
RightShoulderPivot(false, true, "RIGHT_SHOULDER_PIVOT", "RightShoulderPivot"),
LeggingsPivot(false, true, "LEGGINGS_PIVOT", "LeggingsPivot"),
Expand Down
Expand Up @@ -314,6 +314,7 @@ else if (hasCapeOrElytra)
if (hasArmor) {
model.addGroup(HelmetPivot, FiguraVec3.of(0, 24, 0), head);
model.addGroup(ChestplatePivot, FiguraVec3.of(0, 24, 0), body);
model.addGroup(ElytraPivot, FiguraVec3.of(0, 24, 0), body);
model.addGroup(LeftShoulderPivot, FiguraVec3.of(-6, 24, 0), leftArm);
model.addGroup(RightShoulderPivot, FiguraVec3.of(6, 24, 0), rightArm);
model.addGroup(LeggingsPivot, FiguraVec3.of(0, 12, 0), body);
Expand Down

0 comments on commit 4b27c92

Please sign in to comment.