Use the entity's own model for rendering skulls

This commit is contained in:
Sollace 2022-06-11 20:46:24 +02:00
parent 06328583e3
commit 0c54bdd911
16 changed files with 175 additions and 165 deletions

View file

@ -107,6 +107,12 @@ public abstract class AbstractPonyModel<T extends LivingEntity> extends ClientPo
upperTorsoOverlay.copyTransform(upperTorso);
}
public void setHeadRotation(float animationProgress, float yaw, float pitch) {
head.yaw = yaw * ((float)Math.PI / 180);
head.pitch = pitch * ((float)Math.PI / 180);
hat.copyTransform(head);
}
/**
* Aligns legs to a sneaky position.
*/
@ -548,11 +554,11 @@ public abstract class AbstractPonyModel<T extends LivingEntity> extends ClientPo
stack.pop();
}
protected void renderHead(MatrixStack stack, VertexConsumer vertices, int overlayUv, int lightUv, float red, float green, float blue, float alpha) {
public void renderHead(MatrixStack stack, VertexConsumer vertices, int overlayUv, int lightUv, float red, float green, float blue, float alpha) {
head.render(stack, vertices, overlayUv, lightUv, red, green, blue, alpha);
}
protected void renderHelmet(MatrixStack stack, VertexConsumer vertices, int overlayUv, int lightUv, float red, float green, float blue, float alpha) {
public void renderHelmet(MatrixStack stack, VertexConsumer vertices, int overlayUv, int lightUv, float red, float green, float blue, float alpha) {
hat.render(stack, vertices, overlayUv, lightUv, red, green, blue, alpha);
}

View file

@ -72,7 +72,6 @@ public final class ModelType {
public static final ModelKey<ParaspriteModel> PARASPRITE = register("parasprite", ParaspriteModel::new);
public static final ModelKey<PonyElytra<?>> ELYTRA = register("elytra", PonyElytra::new);
public static final ModelKey<PonySkullModel> SKULL = register("skull", PonySkullModel::new);
public static final ModelKey<ArmorStandEntityModel> ARMOUR_STAND = register("armour_stand", PonyArmourStandModel::new);
public static final ModelKey<PonyArmourModel<?>> ARMOUR_INNER = register("armour_inner", PonyArmourModel::new);

View file

@ -12,24 +12,23 @@ import com.minelittlepony.mson.api.ModelKey;
/**
* Container class for the various models and their associated piece of armour.
*/
public class ModelWrapper<T extends LivingEntity, M extends IModel> implements IModelWrapper {
private final M body;
private final IArmour<?> armor;
public record ModelWrapper<T extends LivingEntity, M extends IModel> (
M body,
IArmour<?> armor
) implements IModelWrapper {
/**
* Creates a new model wrapper to contain the given pony.
*/
@SuppressWarnings("unchecked")
public ModelWrapper(ModelKey<?> key) {
body = (M)key.createModel();
armor = body.createArmour();
public static <T extends LivingEntity, M extends IModel> ModelWrapper<T, M> of(ModelKey<?> key) {
M body = key.createModel();
IArmour<?> armor = body.createArmour();
armor.applyMetadata(body.getMetadata());
return new ModelWrapper<>(body, armor);
}
public M getBody() {
return body;
return body();
}
/**
@ -37,7 +36,7 @@ public class ModelWrapper<T extends LivingEntity, M extends IModel> implements I
*/
@SuppressWarnings("unchecked")
public <V extends IArmourModel> IArmour<V> getArmor() {
return (IArmour<V>)armor;
return (IArmour<V>)armor();
}
@Override

View file

@ -44,8 +44,8 @@ public class PonySkullModel extends SkullEntityModel implements MsonModel, ICapi
}
@Override
public void setHeadRotation(float poweredTicks, float yaw, float pitch) {
super.setHeadRotation(poweredTicks, yaw, pitch);
public void setHeadRotation(float animationProgress, float yaw, float pitch) {
super.setHeadRotation(animationProgress, yaw, pitch);
hair.yaw = head.yaw;
hair.pitch = head.pitch;
}

View file

@ -39,6 +39,12 @@ public class EarthPonyModel<T extends LivingEntity> extends AbstractPonyModel<T>
cape.pivotY = sneaking ? 2 : riding ? -4 : 0;
}
@Override
public void setHeadRotation(float animationProgress, float yaw, float pitch) {
super.setHeadRotation(animationProgress, yaw, pitch);
snout.setGender(getMetadata().getGender());
}
@Override
protected void shakeBody(float move, float swing, float bodySwing, float ticks) {
super.shakeBody(move, swing, bodySwing, ticks);

View file

@ -64,7 +64,7 @@ public class UnicornModel<T extends LivingEntity> extends EarthPonyModel<T> impl
}
@Override
protected void renderHead(MatrixStack stack, VertexConsumer vertices, int overlayUv, int lightUv, float red, float green, float blue, float alpha) {
public void renderHead(MatrixStack stack, VertexConsumer vertices, int overlayUv, int lightUv, float red, float green, float blue, float alpha) {
super.renderHead(stack, vertices, overlayUv, lightUv, red, green, blue, alpha);
if (hasHorn()) {

View file

@ -6,6 +6,7 @@ import com.google.common.cache.LoadingCache;
import com.minelittlepony.api.pony.IPony;
import com.minelittlepony.api.pony.IPonyManager;
import com.minelittlepony.client.MineLittlePony;
import com.minelittlepony.client.render.blockentity.skull.PonySkullRenderer;
import com.minelittlepony.settings.PonyConfig;
import com.minelittlepony.settings.PonyLevel;
import org.jetbrains.annotations.Nullable;
@ -128,6 +129,7 @@ public class PonyManager implements IPonyManager, IdentifiableResourceReloadList
clientProfiler.push("Reloading all background ponies");
poniesCache.invalidateAll();
backgroundPonyList.reloadAll(sender);
PonySkullRenderer.reload();
clientProfiler.pop();
clientProfiler.endTick();
}, clientExecutor);

View file

@ -137,8 +137,7 @@ public class EquineRenderManager<T extends LivingEntity, M extends EntityModel<T
}
public ModelWrapper<T, M> setModel(ModelKey<?> key) {
playerModel = new ModelWrapper<>(key);
playerModel = ModelWrapper.of(key);
return playerModel;
}

View file

@ -1,29 +0,0 @@
package com.minelittlepony.client.render.blockentity.skull;
import net.minecraft.client.render.VertexConsumer;
import net.minecraft.client.util.math.MatrixStack;
import com.minelittlepony.client.model.PonySkullModel;
import com.minelittlepony.client.render.blockentity.skull.PonySkullRenderer.ISkull;
import com.minelittlepony.api.pony.IPony;
import com.minelittlepony.client.model.ModelType;
public abstract class AbstractPonySkull implements ISkull {
private PonySkullModel ponyHead = ModelType.SKULL.createModel();
@Override
public void setAngles(float angle, float poweredTicks) {
ponyHead.setHeadRotation(poweredTicks, angle, 0);
}
@Override
public void bindPony(IPony pony) {
ponyHead.metadata = pony.getMetadata();
}
@Override
public void render(MatrixStack stack, VertexConsumer vertices, int lightUv, int overlayUv, float red, float green, float blue, float alpha) {
ponyHead.render(stack, vertices, lightUv, overlayUv, red, green, blue, alpha);
}
}

View file

@ -1,20 +1,34 @@
package com.minelittlepony.client.render.blockentity.skull;
import com.google.common.base.Suppliers;
import com.minelittlepony.api.pony.IPony;
import com.minelittlepony.client.model.AbstractPonyModel;
import com.minelittlepony.client.render.MobRenderers;
import com.minelittlepony.client.render.blockentity.skull.PonySkullRenderer.ISkull;
import com.minelittlepony.mson.api.ModelKey;
import com.minelittlepony.settings.PonyConfig;
import com.mojang.authlib.GameProfile;
import java.util.function.Supplier;
import net.minecraft.client.model.ModelPart;
import net.minecraft.client.render.VertexConsumer;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.Vec3f;
import org.jetbrains.annotations.Nullable;
public class MobSkull extends AbstractPonySkull {
public class MobSkull implements ISkull {
private final Identifier texture;
private final MobRenderers type;
MobSkull(Identifier texture, MobRenderers type) {
private final Supplier<AbstractPonyModel<?>> ponyHead;
MobSkull(Identifier texture, MobRenderers type, ModelKey<? extends AbstractPonyModel<?>> modelKey) {
this.texture = texture;
this.type = type;
this.ponyHead = Suppliers.memoize(modelKey::createModel);
}
@Override
@ -26,4 +40,28 @@ public class MobSkull extends AbstractPonySkull {
public Identifier getSkinResource(@Nullable GameProfile profile) {
return texture;
}
@Override
public boolean bindPony(IPony pony) {
ponyHead.get().setMetadata(pony.getMetadata());
return true;
}
@Override
public void setAngles(float yaw, float animationProgress) {
Vec3f v = new Vec3f(0, -2, 1.99F);
v.rotate(Vec3f.POSITIVE_Y.getDegreesQuaternion(yaw));
ModelPart head = ponyHead.get().getHead();
head.pivotX = v.getX();
head.pivotY = v.getY();
head.pivotZ = v.getZ();
ponyHead.get().setVisible(true);
ponyHead.get().setHeadRotation(animationProgress, yaw, 0);
}
@Override
public void render(MatrixStack stack, VertexConsumer vertices, int lightUv, int overlayUv, float red, float green, float blue, float alpha) {
ponyHead.get().renderHead(stack, vertices, lightUv, overlayUv, red, green, blue, alpha);
ponyHead.get().renderHelmet(stack, vertices, lightUv, overlayUv, red, green, blue, alpha);
}
}

View file

@ -0,0 +1,82 @@
package com.minelittlepony.client.render.blockentity.skull;
import com.google.common.base.Suppliers;
import com.minelittlepony.api.pony.IPony;
import com.minelittlepony.api.pony.meta.Race;
import com.minelittlepony.client.SkinsProxy;
import com.minelittlepony.client.model.*;
import com.minelittlepony.client.render.blockentity.skull.PonySkullRenderer.ISkull;
import com.minelittlepony.settings.PonyConfig;
import com.minelittlepony.settings.PonyLevel;
import com.mojang.authlib.GameProfile;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Supplier;
import net.minecraft.client.render.VertexConsumer;
import net.minecraft.client.util.DefaultSkinHelper;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.util.Identifier;
import net.minecraft.util.dynamic.DynamicSerializableUuid;
import net.minecraft.util.math.Vec3f;
import org.jetbrains.annotations.Nullable;
public class PlayerPonySkull implements ISkull {
private AbstractPonyModel<?> ponyHead;
private final Map<PlayerModelKey<?, AbstractPonyModel<?>>, AbstractPonyModel<?>> modelCache = new HashMap<>();
private final Supplier<DJPon3EarsModel> deadMau5 = Suppliers.memoize(ModelType.DJ_PON_3::createModel);
@Override
public boolean canRender(PonyConfig config) {
return config.ponyskulls.get() && config.ponyLevel.get() != PonyLevel.HUMANS;
}
@Override
public Identifier getSkinResource(@Nullable GameProfile profile) {
deadMau5.get().setVisible(profile != null && "deadmau5".equals(profile.getName()));
if (profile != null) {
Identifier skin = SkinsProxy.instance.getSkinTexture(profile);
if (skin != null) {
return skin;
}
return DefaultSkinHelper.getTexture(DynamicSerializableUuid.getUuidFromProfile(profile));
}
return DefaultSkinHelper.getTexture();
}
@Override
public boolean bindPony(IPony pony) {
Race race = pony.getRace(false);
if (race.isHuman()) {
return false;
}
ponyHead = modelCache.computeIfAbsent(ModelType.getPlayerModel(race), key -> key.getKey(false).createModel());
ponyHead.setMetadata(pony.getMetadata());
return true;
}
@Override
public void setAngles(float yaw, float animationProgress) {
Vec3f v = new Vec3f(0, -2, 2);
v.rotate(Vec3f.POSITIVE_Y.getDegreesQuaternion(yaw));
ponyHead.getHead().pivotX = v.getX();
ponyHead.getHead().pivotY = v.getY();
ponyHead.getHead().pivotZ = v.getZ();
ponyHead.setVisible(true);
ponyHead.setHeadRotation(animationProgress, yaw, 0);
}
@Override
public void render(MatrixStack stack, VertexConsumer vertices, int lightUv, int overlayUv, float red, float green, float blue, float alpha) {
ponyHead.renderHead(stack, vertices, lightUv, overlayUv, red, green, blue, alpha);
ponyHead.renderHelmet(stack, vertices, lightUv, overlayUv, red, green, blue, alpha);
deadMau5.get().render(stack, vertices, overlayUv, lightUv, red, green, blue, alpha);
}
}

View file

@ -1,49 +0,0 @@
package com.minelittlepony.client.render.blockentity.skull;
import com.minelittlepony.client.SkinsProxy;
import com.minelittlepony.client.model.DJPon3EarsModel;
import com.minelittlepony.client.model.ModelType;
import com.minelittlepony.settings.PonyConfig;
import com.minelittlepony.settings.PonyLevel;
import com.mojang.authlib.GameProfile;
import net.minecraft.client.render.VertexConsumer;
import net.minecraft.client.util.DefaultSkinHelper;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.util.Identifier;
import net.minecraft.util.dynamic.DynamicSerializableUuid;
import org.jetbrains.annotations.Nullable;
public class PonySkull extends AbstractPonySkull {
private final DJPon3EarsModel deadMau5 = ModelType.DJ_PON_3.createModel();
@Override
public boolean canRender(PonyConfig config) {
return config.ponyLevel.get() != PonyLevel.HUMANS;
}
@Override
public Identifier getSkinResource(@Nullable GameProfile profile) {
deadMau5.setVisible(profile != null && "deadmau5".equals(profile.getName()));
if (profile != null) {
Identifier skin = SkinsProxy.instance.getSkinTexture(profile);
if (skin != null) {
return skin;
}
return DefaultSkinHelper.getTexture(DynamicSerializableUuid.getUuidFromProfile(profile));
}
return DefaultSkinHelper.getTexture();
}
@Override
public void render(MatrixStack stack, VertexConsumer vertices, int overlayUv, int lightUv, float red, float green, float blue, float alpha) {
super.render(stack, vertices, overlayUv, lightUv, red, green, blue, alpha);
deadMau5.render(stack, vertices, overlayUv, lightUv, red, green, blue, alpha);
}
}

View file

@ -3,6 +3,7 @@ package com.minelittlepony.client.render.blockentity.skull;
import com.google.common.collect.Maps;
import com.minelittlepony.api.pony.IPony;
import com.minelittlepony.client.MineLittlePony;
import com.minelittlepony.client.model.ModelType;
import com.minelittlepony.client.render.LevitatingItemRenderer;
import com.minelittlepony.client.render.MobRenderers;
import com.minelittlepony.client.render.entity.SkeleponyRenderer;
@ -17,7 +18,6 @@ import net.minecraft.client.render.VertexConsumer;
import net.minecraft.client.render.VertexConsumerProvider;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.util.Identifier;
import net.minecraft.util.Util;
import net.minecraft.util.math.Direction;
import java.util.Map;
@ -28,17 +28,23 @@ import org.jetbrains.annotations.Nullable;
*/
public class PonySkullRenderer {
private static final Map<SkullBlock.SkullType, ISkull> SKULLS = Util.make(Maps.newHashMap(), (skullMap) -> {
skullMap.put(SkullBlock.Type.SKELETON, new MobSkull(SkeleponyRenderer.SKELETON, MobRenderers.SKELETON));
skullMap.put(SkullBlock.Type.WITHER_SKELETON, new MobSkull(SkeleponyRenderer.WITHER, MobRenderers.SKELETON));
skullMap.put(SkullBlock.Type.ZOMBIE, new MobSkull(ZomponyRenderer.ZOMBIE, MobRenderers.ZOMBIE));
skullMap.put(SkullBlock.Type.PLAYER, new PonySkull());
});
private static final Map<SkullBlock.SkullType, ISkull> SKULLS = Maps.newHashMap();
private static ISkull selectedSkull;
private static Identifier selectedSkin;
public static void reload() {
SKULLS.clear();
loadSkulls(SKULLS);
}
private static void loadSkulls(Map<SkullBlock.SkullType, ISkull> skullMap) {
skullMap.put(SkullBlock.Type.SKELETON, new MobSkull(SkeleponyRenderer.SKELETON, MobRenderers.SKELETON, ModelType.SKELETON));
skullMap.put(SkullBlock.Type.WITHER_SKELETON, new MobSkull(SkeleponyRenderer.WITHER, MobRenderers.SKELETON, ModelType.ENDERMAN));
skullMap.put(SkullBlock.Type.ZOMBIE, new MobSkull(ZomponyRenderer.ZOMBIE, MobRenderers.ZOMBIE, ModelType.ZOMBIE));
skullMap.put(SkullBlock.Type.PLAYER, new PlayerPonySkull());
}
public static RenderLayer getSkullRenderLayer(SkullBlock.SkullType skullType, @Nullable GameProfile profile) {
selectedSkull = null;
selectedSkin = null;
@ -55,7 +61,7 @@ public class PonySkullRenderer {
}
public static boolean renderSkull(@Nullable Direction direction,
float angle, float poweredTicks,
float yaw, float animationProgress,
MatrixStack stack, VertexConsumerProvider renderContext, RenderLayer layer,
int lightUv) {
@ -63,7 +69,9 @@ public class PonySkullRenderer {
return false;
}
selectedSkull.bindPony(MineLittlePony.getInstance().getManager().getPony(selectedSkin));
if (!selectedSkull.bindPony(MineLittlePony.getInstance().getManager().getPony(selectedSkin))) {
return false;
}
stack.push();
@ -82,7 +90,7 @@ public class PonySkullRenderer {
VertexConsumer vertices = renderContext.getBuffer(layer);
selectedSkull.setAngles(angle, poweredTicks);
selectedSkull.setAngles(yaw, animationProgress);
selectedSkull.render(stack, vertices, lightUv, OverlayTexture.DEFAULT_UV, 1, 1, 1, 1);
stack.pop();
@ -105,6 +113,6 @@ public class PonySkullRenderer {
Identifier getSkinResource(@Nullable GameProfile profile);
void bindPony(IPony pony);
boolean bindPony(IPony pony);
}
}

View file

@ -22,7 +22,7 @@ public class PlayerSeaponyRenderer extends PlayerPonyRenderer {
public PlayerSeaponyRenderer(EntityRendererFactory.Context context, boolean slim, ModelKey<? extends ClientPonyModel<AbstractClientPlayerEntity>> key) {
super(context, slim, key);
normalPony = new ModelWrapper<>(ModelType.<AbstractClientPlayerEntity, ClientPonyModel<AbstractClientPlayerEntity>>getPlayerModel(Race.UNICORN).getKey(slim));
normalPony = ModelWrapper.of(ModelType.<AbstractClientPlayerEntity, ClientPonyModel<AbstractClientPlayerEntity>>getPlayerModel(Race.UNICORN).getKey(slim));
seapony = this.manager.getModelWrapper();
}

View file

@ -54,7 +54,7 @@ public class PonyStandRenderer extends ArmorStandEntityRenderer {
}
class Armour extends ArmorFeatureRenderer<ArmorStandEntity, ArmorStandArmorEntityModel, ArmorStandArmorEntityModel> {
private final ModelWrapper<ArmorStandEntity, EarthPonyModel<ArmorStandEntity>> pony = new ModelWrapper<>(ModelType.EARTH_PONY.getKey(false));
private final ModelWrapper<ArmorStandEntity, EarthPonyModel<ArmorStandEntity>> pony = ModelWrapper.of(ModelType.EARTH_PONY.getKey(false));
public Armour(FeatureRendererContext<ArmorStandEntity, ArmorStandArmorEntityModel> renderer, EntityRendererFactory.Context context) {
super(renderer,

View file

@ -1,51 +0,0 @@
{
"texture": {"w": 64, "h": 64},
"data": {
"head": {
"cubes": [
{"from": [-4, -8, -4], "size": [8, 8, 8]}
],
"children": {
"snout": {
"type": "mson:slot",
"name": "snout",
"locals": {
"x": 0,
"y": -2,
"z": 2
},
"implementation": "com.minelittlepony.client.model.part.PonySnout",
"data": "minelittlepony:components/snout"
},
"ears": {
"type": "mson:slot",
"name": "ears",
"locals": {
"x": 0,
"y": -2,
"z": 2
},
"implementation": "com.minelittlepony.client.model.part.PonyEars",
"data": "minelittlepony:components/ears"
},
"horn": {
"type": "mson:slot",
"name": "horn",
"locals": {
"x": 0,
"y": -2,
"z": 2
},
"implementation": "com.minelittlepony.client.model.part.UnicornHorn",
"data": "minelittlepony:components/horn"
}
}
},
"hair": {
"texture": {"u": 32},
"cubes": [
{"from": [-4, -8, -4], "size": [8, 8, 8], "dilate": 0.25}
]
}
}
}