package com.minelittlepony.client.render; import com.minelittlepony.client.MineLittlePony; import com.minelittlepony.client.model.IPonyModel; import com.minelittlepony.client.model.ModelWrapper; import com.minelittlepony.client.transform.PonyPosture; import com.minelittlepony.mson.api.ModelKey; import com.minelittlepony.pony.IPony; import com.minelittlepony.util.MathUtil; import com.mojang.blaze3d.platform.GlStateManager.DestFactor; import com.mojang.blaze3d.platform.GlStateManager.SourceFactor; import com.mojang.blaze3d.systems.RenderSystem; import javax.annotation.Nonnull; 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.util.Identifier; public class EquineRenderManager & IPonyModel> { public ModelWrapper playerModel; private IPony pony; private final IPonyRenderContext renderer; private boolean skipBlend; private final FrustrumCheck frustrum = new FrustrumCheck<>(this); public static void enableModelRenderProfile(boolean skipBlend) { RenderSystem.enableBlend(); if (!skipBlend) { RenderSystem.blendFunc(SourceFactor.SRC_ALPHA, DestFactor.ONE_MINUS_SRC_ALPHA); } RenderSystem.alphaFunc(516, 0.003921569F); } public static void disableModelRenderProfile() { RenderSystem.disableBlend(); } public EquineRenderManager(IPonyRenderContext renderer) { this.renderer = renderer; } public void setSkipBlend() { skipBlend = true; } public Frustum getFrustrum(T entity, Frustum vanilla) { if (entity.isSleeping() || !MineLittlePony.getInstance().getConfig().frustrum.get()) { return vanilla; } return frustrum.withCamera(entity, vanilla); } public void preRenderCallback(T entity, MatrixStack stack, float ticks) { updateModel(entity, Mode.THIRD_PERSON); float s = getScaleFactor(); stack.scale(s, s, s); enableModelRenderProfile(skipBlend); translateRider(entity, stack, ticks); } 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; } protected void translateRider(T entity, MatrixStack stack, float ticks) { if (entity.hasVehicle() && entity.getVehicle() instanceof LivingEntity) { LivingEntity ridingEntity = (LivingEntity) entity.getVehicle(); IPonyRenderContext renderer = PonyRenderDispatcher.getInstance().getPonyRenderer(ridingEntity); if (renderer != null) { // negate vanilla translations so the rider begins at the ridees feet. stack.translate(0, -ridingEntity.getHeight(), 0); IPony riderPony = renderer.getEntityPony(ridingEntity); renderer.translateRider(ridingEntity, riderPony, entity, pony, stack, ticks); } } } @SuppressWarnings("unchecked") public void applyPostureTransform(T player, MatrixStack stack, float yaw, float ticks) { ((PonyPosture) getPosture(player)).apply(player, getModel(), stack, yaw, ticks, 1); } @SuppressWarnings("unchecked") public void applyPostureRiding(T player, MatrixStack stack, float yaw, float ticks) { ((PonyPosture) getPosture(player)).apply(player, getModel(), stack, yaw, ticks, -1); } @Nonnull private PonyPosture getPosture(T entity) { if (entity.isFallFlying()) { return PonyPosture.ELYTRA; } if (entity.isAlive() && entity.isSleeping()) { return PonyPosture.DEFAULT; } if (getModel().getAttributes().isSwimming) { return PonyPosture.SWIMMING; } if (getModel().getAttributes().isGoingFast) { return PonyPosture.FLIGHT; } return PonyPosture.FALLING; } public M getModel() { return playerModel.getBody(); } public ModelWrapper setModel(ModelKey key) { playerModel = new ModelWrapper<>(key); return playerModel; } public void updateMetadata(Identifier texture) { pony = MineLittlePony.getInstance().getManager().getPony(texture); playerModel.apply(pony.getMetadata()); } public void updateModel(T entity, Mode mode) { pony = renderer.getEntityPony(entity); playerModel.apply(pony.getMetadata()); pony.updateForEntity(entity); getModel().updateLivingState(entity, pony, mode); } public IPony getPony(T entity) { updateModel(entity, Mode.THIRD_PERSON); return pony; } public float getShadowScale() { return getModel().getSize().getShadowSize(); } public float getScaleFactor() { return getModel().getSize().getScaleFactor(); } public double getNamePlateYOffset(T entity) { // We start by negating the height calculation done by mahjong. float y = -(entity.getHeight() + 0.5F - (entity.isInSneakingPose() ? 0.25F : 0)); // 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 enum Mode { FIRST_PERSON, THIRD_PERSON } }