mirror of
https://github.com/MineLittlePony/MineLittlePony.git
synced 2025-02-13 08:14:23 +01:00
(Backport) Add support for rendering modded armor
# Conflicts: # src/main/java/com/minelittlepony/client/model/armour/PonifiedEquipmentRenderer.java # src/main/java/com/minelittlepony/client/render/entity/feature/ArmourFeature.java
This commit is contained in:
parent
74090596ff
commit
3284669e24
4 changed files with 95 additions and 0 deletions
|
@ -77,6 +77,15 @@ public class PonyConfig extends Config {
|
||||||
.addComment("Disables certain easter eggs and secrets (party pooper)")
|
.addComment("Disables certain easter eggs and secrets (party pooper)")
|
||||||
.addComment("Turning this off may help with compatibility in some cases");
|
.addComment("Turning this off may help with compatibility in some cases");
|
||||||
|
|
||||||
|
public final Setting<Boolean> enableFabricModelsApiSupport = value("settings", "enableFabricModelsApiSupport", false)
|
||||||
|
.addComment("Enables rendering of modded armour registered via the fabric api")
|
||||||
|
.addComment("Note that since any armour registered in this way is designed to work for the human model, pieces may not fit exactly.")
|
||||||
|
.addComment("i.e. Anything that goes on the plyer's backs needs to be rotated by the mod developer when rendered on a pony")
|
||||||
|
.addComment("Developers: To know if you're being rendered on a pony model, check the renderstate or model class with")
|
||||||
|
.addComment(" state instanceof com.minelittlepony.api.model.PonyModel$AttributedHolder or model instanceof com.minelittlepony.api.model.PonyModel")
|
||||||
|
.addComment(" Note that the matrix stack your receieve is pre-transformed for the body part your model is attached to, so if you intend to call model.transform(state, part, matrices)")
|
||||||
|
.addComment(" with a different part (ie BACK) you must pop the stack to revert to the previous first.");
|
||||||
|
|
||||||
public final Setting<VisibilityMode> horseButton = value("horseButton", VisibilityMode.AUTO)
|
public final Setting<VisibilityMode> horseButton = value("horseButton", VisibilityMode.AUTO)
|
||||||
.addComment("Whether to show the mine little pony settings button on the main menu")
|
.addComment("Whether to show the mine little pony settings button on the main menu")
|
||||||
.addComment("AUTO (default) - only show when HDSkins is not installed")
|
.addComment("AUTO (default) - only show when HDSkins is not installed")
|
||||||
|
|
|
@ -8,9 +8,17 @@ import com.minelittlepony.common.util.Color;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
|
import com.minelittlepony.api.config.PonyConfig;
|
||||||
|
import com.minelittlepony.api.model.*;
|
||||||
|
import com.minelittlepony.client.model.ClientPonyModel;
|
||||||
|
import com.minelittlepony.client.util.render.MatrixStackUtil;
|
||||||
|
|
||||||
|
import net.fabricmc.fabric.api.client.rendering.v1.ArmorRenderer;
|
||||||
|
import net.fabricmc.fabric.impl.client.rendering.ArmorRendererRegistryImpl;
|
||||||
import net.minecraft.client.render.*;
|
import net.minecraft.client.render.*;
|
||||||
import net.minecraft.client.render.entity.model.*;
|
import net.minecraft.client.render.entity.model.*;
|
||||||
import net.minecraft.client.render.model.BakedModelManager;
|
import net.minecraft.client.render.model.BakedModelManager;
|
||||||
|
import net.minecraft.client.render.entity.model.BipedEntityModel;
|
||||||
import net.minecraft.client.util.math.MatrixStack;
|
import net.minecraft.client.util.math.MatrixStack;
|
||||||
import net.minecraft.component.DataComponentTypes;
|
import net.minecraft.component.DataComponentTypes;
|
||||||
import net.minecraft.entity.EquipmentSlot;
|
import net.minecraft.entity.EquipmentSlot;
|
||||||
|
@ -18,8 +26,16 @@ import net.minecraft.entity.LivingEntity;
|
||||||
import net.minecraft.item.*;
|
import net.minecraft.item.*;
|
||||||
import net.minecraft.item.trim.ArmorTrim;
|
import net.minecraft.item.trim.ArmorTrim;
|
||||||
import net.minecraft.util.Colors;
|
import net.minecraft.util.Colors;
|
||||||
|
import net.minecraft.util.Unit;
|
||||||
|
|
||||||
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
import org.apache.logging.log4j.Logger;
|
||||||
|
|
||||||
public class ArmourFeature<T extends LivingEntity, M extends EntityModel<T> & PonyModel<T>> extends AbstractPonyFeature<T, M> {
|
public class ArmourFeature<T extends LivingEntity, M extends EntityModel<T> & PonyModel<T>> extends AbstractPonyFeature<T, M> {
|
||||||
|
private static final Logger LOGGER = LogManager.getLogger("PonifiedEquipmentRenderer");
|
||||||
|
|
||||||
|
private static boolean FABRIC_API_FAILURE;
|
||||||
|
|
||||||
public ArmourFeature(PonyRenderContext<T, M> context, BakedModelManager bakery) {
|
public ArmourFeature(PonyRenderContext<T, M> context, BakedModelManager bakery) {
|
||||||
super(context);
|
super(context);
|
||||||
}
|
}
|
||||||
|
@ -56,6 +72,17 @@ public class ArmourFeature<T extends LivingEntity, M extends EntityModel<T> & Po
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!FABRIC_API_FAILURE && PonyConfig.getInstance().enableFabricModelsApiSupport.get()) {
|
||||||
|
try {
|
||||||
|
if (FabricArmorRendererInvoker.renderArmor(stack, pony, matrices, provider, light, entity, armorSlot)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} catch (Throwable t) {
|
||||||
|
LOGGER.error("Failure calling fabric armor rendering api", t);
|
||||||
|
FABRIC_API_FAILURE = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
float glintAlpha = plugin.getGlintAlpha(armorSlot, stack);
|
float glintAlpha = plugin.getGlintAlpha(armorSlot, stack);
|
||||||
boolean glint = glintAlpha > 0;
|
boolean glint = glintAlpha > 0;
|
||||||
int color = plugin.getDyeColor(armorSlot, stack);
|
int color = plugin.getDyeColor(armorSlot, stack);
|
||||||
|
@ -118,4 +145,43 @@ public class ArmourFeature<T extends LivingEntity, M extends EntityModel<T> & Po
|
||||||
|
|
||||||
plugin.onArmourRendered(entity, matrices, provider, armorSlot, layer, ArmourRendererPlugin.ArmourType.ARMOUR);
|
plugin.onArmourRendered(entity, matrices, provider, armorSlot, layer, ArmourRendererPlugin.ArmourType.ARMOUR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static final class FabricArmorRendererInvoker {
|
||||||
|
private static final Map<ArmorRenderer, Unit> FAILING_RENDERERS = new WeakHashMap<>();
|
||||||
|
|
||||||
|
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||||
|
private static <T extends LivingEntity, V extends ClientPonyModel<T>> boolean renderArmor(
|
||||||
|
ItemStack stack,
|
||||||
|
Models<T, ? extends PonyModel<T>> models, MatrixStack matrices,
|
||||||
|
VertexConsumerProvider vertices, int light, T entity,
|
||||||
|
EquipmentSlot armorSlot) {
|
||||||
|
ArmorRenderer renderer = ArmorRendererRegistryImpl.get(stack.getItem());
|
||||||
|
|
||||||
|
if (renderer != null && !FAILING_RENDERERS.containsKey(renderer)) {
|
||||||
|
MatrixStack isolation = MatrixStackUtil.pushIsolation(matrices);
|
||||||
|
try {
|
||||||
|
isolation.push();
|
||||||
|
models.body().transform(getBodyPart(armorSlot), isolation);
|
||||||
|
renderer.render(isolation, vertices, stack, entity, armorSlot, light, (BipedEntityModel)models.body());
|
||||||
|
isolation.pop();
|
||||||
|
} catch (Throwable t) {
|
||||||
|
LOGGER.error("Exception occured whilst rendering custom armor via fabric api. Renderer {} has been disabled", renderer, t);
|
||||||
|
FAILING_RENDERERS.put(renderer, Unit.INSTANCE);
|
||||||
|
} finally {
|
||||||
|
MatrixStackUtil.popIsolation();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static BodyPart getBodyPart(EquipmentSlot slot) {
|
||||||
|
return switch (slot) {
|
||||||
|
case HEAD -> BodyPart.HEAD;
|
||||||
|
case CHEST, BODY -> BodyPart.BODY;
|
||||||
|
case LEGS, FEET, MAINHAND, OFFHAND -> BodyPart.LEGS;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
package com.minelittlepony.client.util.render;
|
||||||
|
|
||||||
|
import net.minecraft.client.util.math.MatrixStack;
|
||||||
|
|
||||||
|
public class MatrixStackUtil {
|
||||||
|
static final MatrixStack ISOLATION_STACK = new MatrixStack();
|
||||||
|
|
||||||
|
public static MatrixStack pushIsolation(MatrixStack matrices) {
|
||||||
|
ISOLATION_STACK.peek().getNormalMatrix().set(matrices.peek().getNormalMatrix());
|
||||||
|
ISOLATION_STACK.peek().getPositionMatrix().set(matrices.peek().getPositionMatrix());
|
||||||
|
return ISOLATION_STACK;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void popIsolation() {
|
||||||
|
while (!ISOLATION_STACK.isEmpty()) {
|
||||||
|
ISOLATION_STACK.pop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -14,6 +14,7 @@
|
||||||
"minelp.options.skins.hdskins.open": "Open HD Skins",
|
"minelp.options.skins.hdskins.open": "Open HD Skins",
|
||||||
"minelp.options.skins.hdskins.disabled": "HD Skins is not installed\n\nThe HD Skins mod is required to upload skins from in-game and to use custom skin servers.\n\nIf you cannot use that you will have to go to www.minecraft.net to upload your skin there.",
|
"minelp.options.skins.hdskins.disabled": "HD Skins is not installed\n\nThe HD Skins mod is required to upload skins from in-game and to use custom skin servers.\n\nIf you cannot use that you will have to go to www.minecraft.net to upload your skin there.",
|
||||||
"minelp.options.snuzzles": "Show Snuzzles",
|
"minelp.options.snuzzles": "Show Snuzzles",
|
||||||
|
"minelp.options.enablefabricmodelsapisupport": "(Experimental) Show Modded Armor",
|
||||||
"minelp.options.fillycam": "Filly Cam",
|
"minelp.options.fillycam": "Filly Cam",
|
||||||
"minelp.options.showscale": "Show-accurate scaling",
|
"minelp.options.showscale": "Show-accurate scaling",
|
||||||
"minelp.options.fpsmagic": "Magic in first-person",
|
"minelp.options.fpsmagic": "Magic in first-person",
|
||||||
|
|
Loading…
Reference in a new issue