Layered with mixins
- Render netherite diving gear with both layers properly - Mixin to HumanoidArmorLayer to render both layers for all slots
This commit is contained in:
parent
3d74c41c2d
commit
53cc386b86
10 changed files with 158 additions and 8 deletions
|
@ -252,32 +252,32 @@ public class AllItems {
|
|||
.model((c, p) -> p.withExistingParent(c.getName(), p.mcLoc("item/barrier")))
|
||||
.register();
|
||||
|
||||
public static final ItemEntry<BacktankItem>
|
||||
public static final ItemEntry<? extends BacktankItem>
|
||||
|
||||
COPPER_BACKTANK = REGISTRATE.item("copper_backtank", p -> new BacktankItem(AllArmorMaterials.COPPER, p, Create.asResource("copper_diving"), COPPER_BACKTANK_PLACEABLE))
|
||||
.model(AssetLookup.customGenericItemModel("_", "item"))
|
||||
.tag(AllItemTags.PRESSURIZED_AIR_SOURCES.tag)
|
||||
.register(),
|
||||
|
||||
NETHERITE_BACKTANK = REGISTRATE.item("netherite_backtank", p -> new BacktankItem(ArmorMaterials.NETHERITE, p, Create.asResource("netherite_diving"), NETHERITE_BACKTANK_PLACEABLE))
|
||||
NETHERITE_BACKTANK = REGISTRATE.item("netherite_backtank", p -> new BacktankItem.MultiLayered(ArmorMaterials.NETHERITE, p, Create.asResource("netherite_diving"), NETHERITE_BACKTANK_PLACEABLE))
|
||||
.model(AssetLookup.customGenericItemModel("_", "item"))
|
||||
.tag(AllItemTags.PRESSURIZED_AIR_SOURCES.tag)
|
||||
.register();
|
||||
|
||||
public static final ItemEntry<DivingHelmetItem>
|
||||
public static final ItemEntry<? extends DivingHelmetItem>
|
||||
|
||||
COPPER_DIVING_HELMET = REGISTRATE.item("copper_diving_helmet", p -> new DivingHelmetItem(AllArmorMaterials.COPPER, p, Create.asResource("copper_diving")))
|
||||
.register(),
|
||||
|
||||
NETHERITE_DIVING_HELMET = REGISTRATE.item("netherite_diving_helmet", p -> new DivingHelmetItem(ArmorMaterials.NETHERITE, p, Create.asResource("netherite_diving")))
|
||||
NETHERITE_DIVING_HELMET = REGISTRATE.item("netherite_diving_helmet", p -> new DivingHelmetItem.MultiLayered(ArmorMaterials.NETHERITE, p, Create.asResource("netherite_diving")))
|
||||
.register();
|
||||
|
||||
public static final ItemEntry<DivingBootsItem>
|
||||
public static final ItemEntry<? extends DivingBootsItem>
|
||||
|
||||
COPPER_DIVING_BOOTS = REGISTRATE.item("copper_diving_boots", p -> new DivingBootsItem(AllArmorMaterials.COPPER, p, Create.asResource("copper_diving")))
|
||||
.register(),
|
||||
|
||||
NETHERITE_DIVING_BOOTS = REGISTRATE.item("netherite_diving_boots", p -> new DivingBootsItem(ArmorMaterials.NETHERITE, p, Create.asResource("netherite_diving")))
|
||||
NETHERITE_DIVING_BOOTS = REGISTRATE.item("netherite_diving_boots", p -> new DivingBootsItem.MultiLayered(ArmorMaterials.NETHERITE, p, Create.asResource("netherite_diving")))
|
||||
.register();
|
||||
|
||||
public static final ItemEntry<SandPaperItem> SAND_PAPER = REGISTRATE.item("sand_paper", SandPaperItem::new)
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
package com.simibubi.create.content.curiosities.armor;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import com.simibubi.create.content.curiosities.armor.CapacityEnchantment.ICapacityEnchantable;
|
||||
import com.simibubi.create.foundation.item.MultiLayeredArmorItem;
|
||||
|
||||
import net.minecraft.core.NonNullList;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
|
@ -27,9 +29,9 @@ public class BacktankItem extends BaseArmorItem implements ICapacityEnchantable
|
|||
|
||||
private final Supplier<BacktankBlockItem> blockItem;
|
||||
|
||||
public BacktankItem(ArmorMaterial material, Properties properties, ResourceLocation textureLoc, Supplier<BacktankBlockItem> copperBacktankPlaceable) {
|
||||
public BacktankItem(ArmorMaterial material, Properties properties, ResourceLocation textureLoc, Supplier<BacktankBlockItem> placeable) {
|
||||
super(material, SLOT, properties, textureLoc);
|
||||
this.blockItem = copperBacktankPlaceable;
|
||||
this.blockItem = placeable;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
@ -108,4 +110,15 @@ public class BacktankItem extends BaseArmorItem implements ICapacityEnchantable
|
|||
return this.getOrCreateDescriptionId();
|
||||
}
|
||||
}
|
||||
|
||||
public static class MultiLayered extends BacktankItem implements MultiLayeredArmorItem {
|
||||
public MultiLayered(ArmorMaterial material, Properties properties, ResourceLocation textureLoc, Supplier<BacktankBlockItem> placeable) {
|
||||
super(material, properties, textureLoc, placeable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getArmorTexture(ItemStack stack, Entity entity, EquipmentSlot slot, String layer) {
|
||||
return String.format(Locale.ROOT, "%s:textures/models/armor/%s_layer_%s.png", textureLoc.getNamespace(), textureLoc.getPath(), layer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
package com.simibubi.create.content.curiosities.armor;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
import com.simibubi.create.foundation.item.MultiLayeredArmorItem;
|
||||
import com.simibubi.create.foundation.utility.NBTHelper;
|
||||
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
|
@ -9,6 +12,7 @@ import net.minecraft.world.entity.LivingEntity;
|
|||
import net.minecraft.world.entity.Pose;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.item.ArmorMaterial;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import net.minecraftforge.event.entity.living.LivingEvent.LivingUpdateEvent;
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
|
@ -72,4 +76,15 @@ public class DivingBootsItem extends BaseArmorItem {
|
|||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static class MultiLayered extends DivingBootsItem implements MultiLayeredArmorItem {
|
||||
public MultiLayered(ArmorMaterial material, Properties properties, ResourceLocation textureLoc) {
|
||||
super(material, properties, textureLoc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getArmorTexture(ItemStack stack, Entity entity, EquipmentSlot slot, String layer) {
|
||||
return String.format(Locale.ROOT, "%s:textures/models/armor/%s_layer_%s.png", textureLoc.getNamespace(), textureLoc.getPath(), layer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
package com.simibubi.create.content.curiosities.armor;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
import com.simibubi.create.foundation.advancement.AllAdvancements;
|
||||
import com.simibubi.create.foundation.item.MultiLayeredArmorItem;
|
||||
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
|
@ -82,4 +85,15 @@ public class DivingHelmetItem extends BaseArmorItem {
|
|||
entity.addEffect(new MobEffectInstance(MobEffects.WATER_BREATHING, 30, 0, true, false, true));
|
||||
BacktankUtil.consumeAir(entity, backtank, 1);
|
||||
}
|
||||
|
||||
public static class MultiLayered extends DivingHelmetItem implements MultiLayeredArmorItem {
|
||||
public MultiLayered(ArmorMaterial material, Properties properties, ResourceLocation textureLoc) {
|
||||
super(material, properties, textureLoc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getArmorTexture(ItemStack stack, Entity entity, EquipmentSlot slot, String layer) {
|
||||
return String.format(Locale.ROOT, "%s:textures/models/armor/%s_layer_%s.png", textureLoc.getNamespace(), textureLoc.getPath(), layer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
package com.simibubi.create.foundation.item;
|
||||
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.EquipmentSlot;
|
||||
import net.minecraft.world.item.ArmorItem;
|
||||
import net.minecraft.world.item.DyeableLeatherItem;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraftforge.common.extensions.IForgeItem;
|
||||
|
||||
/**
|
||||
* This interface is meant to be implemented on {@link ArmorItem}s, which will allow them to be rendered on both the inner model and outer model.
|
||||
*
|
||||
* <p>Classes implementing this interface <b>must not</b> also implement {@link DyeableLeatherItem}.
|
||||
*
|
||||
* <p>Classes that implement this interface and override {@link IForgeItem#getArmorTexture(ItemStack, Entity, EquipmentSlot, String) getArmorTexture}
|
||||
* must note that the {@code String} argument will be used for layer context instead of the type.
|
||||
* This string will always be {@code "1"} when querying the location for the outer model or {@code "2"} when querying the location for the inner model.
|
||||
*/
|
||||
public interface MultiLayeredArmorItem {
|
||||
}
|
|
@ -0,0 +1,87 @@
|
|||
package com.simibubi.create.foundation.mixin;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.ModifyVariable;
|
||||
import org.spongepowered.asm.mixin.injection.At.Shift;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.simibubi.create.foundation.item.MultiLayeredArmorItem;
|
||||
|
||||
import net.minecraft.client.model.HumanoidModel;
|
||||
import net.minecraft.client.renderer.MultiBufferSource;
|
||||
import net.minecraft.client.renderer.entity.layers.HumanoidArmorLayer;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.EquipmentSlot;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.item.ArmorItem;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
|
||||
@Mixin(HumanoidArmorLayer.class)
|
||||
public class HumanoidArmorLayerMixin {
|
||||
@Shadow
|
||||
@Final
|
||||
private HumanoidModel<?> innerModel;
|
||||
@Shadow
|
||||
@Final
|
||||
private HumanoidModel<?> outerModel;
|
||||
|
||||
@Unique
|
||||
private boolean intercepted;
|
||||
@Unique
|
||||
private Boolean useInnerTexture;
|
||||
|
||||
@Shadow
|
||||
private void renderArmorPiece(PoseStack poseStack, MultiBufferSource buffer, LivingEntity livingEntity, EquipmentSlot slot, int packedLight, HumanoidModel<?> model) {
|
||||
}
|
||||
|
||||
@Shadow
|
||||
private boolean usesInnerModel(EquipmentSlot slot) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Inject(method = "renderArmorPiece", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/entity/layers/HumanoidArmorLayer;getParentModel()Lnet/minecraft/client/model/EntityModel;"), locals = LocalCapture.CAPTURE_FAILHARD, cancellable = true)
|
||||
private void onRenderArmorPiece(PoseStack poseStack, MultiBufferSource buffer, LivingEntity livingEntity, EquipmentSlot slot, int packedLight, HumanoidModel<?> model, CallbackInfo ci, ItemStack stack, ArmorItem armorItem) {
|
||||
if (intercepted) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (armorItem instanceof MultiLayeredArmorItem) {
|
||||
intercepted = true;
|
||||
|
||||
useInnerTexture = true;
|
||||
renderArmorPiece(poseStack, buffer, livingEntity, slot, packedLight, innerModel);
|
||||
useInnerTexture = false;
|
||||
renderArmorPiece(poseStack, buffer, livingEntity, slot, packedLight, outerModel);
|
||||
|
||||
useInnerTexture = null;
|
||||
intercepted = false;
|
||||
ci.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(method = "usesInnerModel", at = @At("HEAD"), cancellable = true)
|
||||
private void onUsesInnerModel(EquipmentSlot slot, CallbackInfoReturnable<Boolean> cir) {
|
||||
if (useInnerTexture != null) {
|
||||
cir.setReturnValue(useInnerTexture);
|
||||
}
|
||||
}
|
||||
|
||||
@ModifyVariable(method = "getArmorResource", at = @At(value = "INVOKE", target = "Lnet/minecraftforge/client/ForgeHooksClient;getArmorTexture(Lnet/minecraft/world/entity/Entity;Lnet/minecraft/world/item/ItemStack;Ljava/lang/String;Lnet/minecraft/world/entity/EquipmentSlot;Ljava/lang/String;)Ljava/lang/String;", shift = Shift.BEFORE), ordinal = 0)
|
||||
private String modifyType(@Nullable String type, Entity entity, ItemStack stack, EquipmentSlot slot, @Nullable String typeArg) {
|
||||
if (stack.getItem() instanceof MultiLayeredArmorItem) {
|
||||
return usesInnerModel(slot) ? "2" : "1";
|
||||
}
|
||||
|
||||
return type;
|
||||
}
|
||||
}
|
Binary file not shown.
Before Width: | Height: | Size: 9.8 KiB After Width: | Height: | Size: 8.7 KiB |
Binary file not shown.
Before Width: | Height: | Size: 8.5 KiB |
Before Width: | Height: | Size: 9 KiB After Width: | Height: | Size: 9 KiB |
|
@ -7,6 +7,7 @@
|
|||
"mixins": [
|
||||
"CustomItemUseEffectsMixin",
|
||||
"EntityMixin",
|
||||
"HumanoidArmorLayerMixin",
|
||||
"MapItemSavedDataMixin",
|
||||
"ContraptionDriverInteractMixin",
|
||||
"accessor.AbstractProjectileDispenseBehaviorAccessor",
|
||||
|
|
Loading…
Reference in a new issue