package com.minelittlepony.client.render; import com.minelittlepony.api.config.PonyConfig; import com.minelittlepony.api.events.Channel; import com.minelittlepony.api.events.PonyDataCallback; import com.minelittlepony.api.model.*; import com.minelittlepony.api.pony.Pony; import com.minelittlepony.client.MineLittlePony; import com.minelittlepony.client.transform.PonyPosture; import com.minelittlepony.mson.api.ModelKey; import com.minelittlepony.util.MathUtil; import com.mojang.blaze3d.systems.RenderSystem; import java.util.Objects; import net.fabricmc.api.EnvType; import net.minecraft.client.MinecraftClient; import net.minecraft.client.render.Frustum; import net.minecraft.client.render.entity.model.EntityModel; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.entity.Entity; import net.minecraft.entity.LivingEntity; import net.minecraft.entity.player.PlayerEntity; public class EquineRenderManager & PonyModel> { private ModelWrapper playerModel; private final IPonyRenderContext renderer; private final FrustrumCheck frustrum = new FrustrumCheck<>(this); public static void disableModelRenderProfile() { RenderSystem.disableBlend(); } public EquineRenderManager(IPonyRenderContext renderer) { this.renderer = renderer; } public IPonyRenderContext getContext() { return renderer; } public ModelWrapper getModelWrapper() { return playerModel; } public M getModel() { return playerModel.body(); } @SuppressWarnings({"rawtypes", "unchecked"}) public ModelWrapper setModel(ModelKey key) { return setModel(new ModelWrapper(key)); } public ModelWrapper setModel(ModelWrapper wrapper) { playerModel = wrapper; return wrapper; } public Frustum getFrustrum(T entity, Frustum vanilla) { if (RenderPass.getCurrent() == RenderPass.HUD) { return FrustrumCheck.ALWAYS_VISIBLE; } if (entity.isSleeping() || !PonyConfig.getInstance().frustrum.get()) { return vanilla; } return frustrum.withCamera(entity, vanilla); } public float getRenderYaw(T entity, float rotationYaw, float partialTicks) { if (entity.hasVehicle()) { Entity mount = entity.getVehicle(); if (mount instanceof LivingEntity) { return MathUtil.interpolateDegress(((LivingEntity) mount).prevBodyYaw, ((LivingEntity) mount).bodyYaw, partialTicks); } } return rotationYaw; } public void preRenderCallback(T entity, MatrixStack stack, float ticks) { updateModel(entity, ModelAttributes.Mode.THIRD_PERSON); float s = getScaleFactor(); stack.scale(s, s, s); translateRider(entity, stack, ticks); } private void translateRider(T entity, MatrixStack stack, float ticks) { if (entity.hasVehicle() && entity.getVehicle() instanceof LivingEntity) { LivingEntity ridingEntity = (LivingEntity) entity.getVehicle(); IPonyRenderContext renderer = MineLittlePony.getInstance().getRenderDispatcher().getPonyRenderer(ridingEntity); if (renderer != null) { // negate vanilla translations so the rider begins at the ridees feet. stack.translate(0, -ridingEntity.getHeight(), 0); Pony riderPony = renderer.getEntityPony(ridingEntity); renderer.translateRider(ridingEntity, riderPony, entity, renderer.getEntityPony(entity), stack, ticks); } } } public void setupTransforms(T entity, MatrixStack stack, float yaw, float tickDelta) { PonyPosture.of(getModel().getAttributes()).apply(entity, getModel(), stack, yaw, tickDelta, 1); } public void applyPostureRiding(T entity, MatrixStack stack, float yaw, float tickDelta) { PonyPosture.of(getModel().getAttributes()).apply(entity, getModel(), stack, yaw, tickDelta, -1); } public Pony updateModel(T entity, ModelAttributes.Mode mode) { Pony pony = renderer.getEntityPony(entity); playerModel.applyMetadata(pony.metadata()); if (pony.hasMetadata() && entity instanceof RegistrationHandler && ((RegistrationHandler)entity).shouldUpdateRegistration(pony)) { entity.calculateDimensions(); PlayerEntity clientPlayer = MinecraftClient.getInstance().player; if (clientPlayer != null) { if (Objects.equals(entity, clientPlayer) || Objects.equals(((PlayerEntity)entity).getGameProfile(), clientPlayer.getGameProfile())) { Channel.broadcastPonyData(pony.metadata()); } } PonyDataCallback.EVENT.invoker().onPonyDataAvailable((PlayerEntity)entity, pony.metadata(), EnvType.CLIENT); } getModel().updateLivingState(entity, pony, mode); return pony; } public float getScaleFactor() { return getModel().getSize().scaleFactor(); } public double getNamePlateYOffset(T entity) { // We start by negating the height calculation done by mahjong. float y = -(entity.getHeight() + 0.5F); // Then we add our own offsets. y += getModel().getAttributes().visualHeight * getScaleFactor() + 0.25F; if (entity.isSneaking()) { y -= 0.25F; } if (entity.hasVehicle()) { y += entity.getVehicle().getEyeHeight(entity.getPose()); } if (entity.isSleeping()) { y /= 2; } return y; } public interface RegistrationHandler { boolean shouldUpdateRegistration(Pony pony); } }