fix: Re-implement head_model with the new model format
This commit is contained in:
@@ -26,3 +26,5 @@ accessible method net/minecraft/client/render/RenderPhase$Texture getId ()Ljava/
|
|||||||
accessible field net/minecraft/client/render/RenderLayer$MultiPhase phases Lnet/minecraft/client/render/RenderLayer$MultiPhaseParameters;
|
accessible field net/minecraft/client/render/RenderLayer$MultiPhase phases Lnet/minecraft/client/render/RenderLayer$MultiPhaseParameters;
|
||||||
accessible field net/minecraft/client/render/RenderLayer$MultiPhaseParameters texture Lnet/minecraft/client/render/RenderPhase$TextureBase;
|
accessible field net/minecraft/client/render/RenderLayer$MultiPhaseParameters texture Lnet/minecraft/client/render/RenderPhase$TextureBase;
|
||||||
accessible field net/minecraft/client/network/ClientPlayerInteractionManager currentBreakingPos Lnet/minecraft/util/math/BlockPos;
|
accessible field net/minecraft/client/network/ClientPlayerInteractionManager currentBreakingPos Lnet/minecraft/util/math/BlockPos;
|
||||||
|
|
||||||
|
mutable field net/minecraft/client/render/entity/state/LivingEntityRenderState headItemRenderState Lnet/minecraft/client/render/item/ItemRenderState;
|
||||||
|
|||||||
@@ -110,6 +110,10 @@ object CustomModelOverrideParser {
|
|||||||
Firmament.identifier("predicates/legacy"),
|
Firmament.identifier("predicates/legacy"),
|
||||||
PredicateModel.Unbaked.CODEC
|
PredicateModel.Unbaked.CODEC
|
||||||
)
|
)
|
||||||
|
ItemModelTypes.ID_MAPPER.put(
|
||||||
|
Firmament.identifier("head_model"),
|
||||||
|
HeadModelChooser.Unbaked.CODEC
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,90 @@
|
|||||||
|
package moe.nea.firmament.features.texturepack
|
||||||
|
|
||||||
|
import com.google.gson.JsonObject
|
||||||
|
import com.mojang.serialization.MapCodec
|
||||||
|
import com.mojang.serialization.codecs.RecordCodecBuilder
|
||||||
|
import net.minecraft.client.item.ItemModelManager
|
||||||
|
import net.minecraft.client.render.item.ItemRenderState
|
||||||
|
import net.minecraft.client.render.item.model.BasicItemModel
|
||||||
|
import net.minecraft.client.render.item.model.ItemModel
|
||||||
|
import net.minecraft.client.render.item.model.ItemModelTypes
|
||||||
|
import net.minecraft.client.render.model.ResolvableModel
|
||||||
|
import net.minecraft.client.world.ClientWorld
|
||||||
|
import net.minecraft.entity.LivingEntity
|
||||||
|
import net.minecraft.item.ItemStack
|
||||||
|
import net.minecraft.item.ModelTransformationMode
|
||||||
|
import net.minecraft.util.Identifier
|
||||||
|
|
||||||
|
object HeadModelChooser {
|
||||||
|
val IS_CHOOSING_HEAD_MODEL = ThreadLocal.withInitial { false }
|
||||||
|
|
||||||
|
interface HasExplicitHeadModelMarker {
|
||||||
|
fun markExplicitHead_Firmament()
|
||||||
|
fun isExplicitHeadModel_Firmament(): Boolean
|
||||||
|
companion object{
|
||||||
|
@JvmStatic
|
||||||
|
fun cast(state: ItemRenderState) = state as HasExplicitHeadModelMarker
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data class Baked(val head: ItemModel, val regular: ItemModel) : ItemModel {
|
||||||
|
override fun update(
|
||||||
|
state: ItemRenderState,
|
||||||
|
stack: ItemStack?,
|
||||||
|
resolver: ItemModelManager?,
|
||||||
|
transformationMode: ModelTransformationMode?,
|
||||||
|
world: ClientWorld?,
|
||||||
|
user: LivingEntity?,
|
||||||
|
seed: Int
|
||||||
|
) {
|
||||||
|
val instance =
|
||||||
|
if (IS_CHOOSING_HEAD_MODEL.get()) {
|
||||||
|
HasExplicitHeadModelMarker.cast(state).markExplicitHead_Firmament()
|
||||||
|
head
|
||||||
|
} else {
|
||||||
|
regular
|
||||||
|
}
|
||||||
|
instance.update(state, stack, resolver, transformationMode, world, user, seed)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data class Unbaked(
|
||||||
|
val head: ItemModel.Unbaked,
|
||||||
|
val regular: ItemModel.Unbaked,
|
||||||
|
) : ItemModel.Unbaked {
|
||||||
|
override fun getCodec(): MapCodec<out ItemModel.Unbaked> {
|
||||||
|
return CODEC
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun bake(context: ItemModel.BakeContext): ItemModel {
|
||||||
|
return Baked(
|
||||||
|
head.bake(context),
|
||||||
|
regular.bake(context)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun resolve(resolver: ResolvableModel.Resolver) {
|
||||||
|
head.resolve(resolver)
|
||||||
|
regular.resolve(resolver)
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
@JvmStatic
|
||||||
|
fun fromLegacyJson(jsonObject: JsonObject, unbakedModel: ItemModel.Unbaked): ItemModel.Unbaked {
|
||||||
|
val model = jsonObject["firmament:head_model"] ?: return unbakedModel
|
||||||
|
val modelUrl = model.asJsonPrimitive.asString
|
||||||
|
val headModel = BasicItemModel.Unbaked(Identifier.of(modelUrl), listOf())
|
||||||
|
return Unbaked(headModel, unbakedModel)
|
||||||
|
}
|
||||||
|
|
||||||
|
val CODEC = RecordCodecBuilder.mapCodec {
|
||||||
|
it.group(
|
||||||
|
ItemModelTypes.CODEC.fieldOf("head")
|
||||||
|
.forGetter(Unbaked::head),
|
||||||
|
ItemModelTypes.CODEC.fieldOf("regular")
|
||||||
|
.forGetter(Unbaked::regular),
|
||||||
|
).apply(it, ::Unbaked)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
package moe.nea.firmament.mixins.custommodels;
|
||||||
|
|
||||||
|
import moe.nea.firmament.features.texturepack.HeadModelChooser;
|
||||||
|
import net.minecraft.client.render.item.ItemRenderState;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
|
|
||||||
|
@Mixin(ItemRenderState.class)
|
||||||
|
public class ItemRenderStateExtraInfo implements HeadModelChooser.HasExplicitHeadModelMarker {
|
||||||
|
boolean hasExplicitHead_firmament = false;
|
||||||
|
|
||||||
|
@Inject(method = "clear", at = @At("HEAD"))
|
||||||
|
private void clear(CallbackInfo ci) {
|
||||||
|
hasExplicitHead_firmament = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void markExplicitHead_Firmament() {
|
||||||
|
hasExplicitHead_firmament = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isExplicitHeadModel_Firmament() {
|
||||||
|
return hasExplicitHead_firmament;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
package moe.nea.firmament.mixins.custommodels;
|
||||||
|
|
||||||
|
import moe.nea.firmament.features.texturepack.HeadModelChooser;
|
||||||
|
import net.minecraft.client.item.ItemModelManager;
|
||||||
|
import net.minecraft.client.render.entity.LivingEntityRenderer;
|
||||||
|
import net.minecraft.client.render.entity.model.EntityModel;
|
||||||
|
import net.minecraft.client.render.entity.state.LivingEntityRenderState;
|
||||||
|
import net.minecraft.client.render.item.ItemRenderState;
|
||||||
|
import net.minecraft.entity.EquipmentSlot;
|
||||||
|
import net.minecraft.entity.LivingEntity;
|
||||||
|
import net.minecraft.item.ModelTransformationMode;
|
||||||
|
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.callback.CallbackInfo;
|
||||||
|
|
||||||
|
@Mixin(LivingEntityRenderer.class)
|
||||||
|
public class ReplaceHeadModel<T extends LivingEntity, S extends LivingEntityRenderState, M extends EntityModel<? super S>> {
|
||||||
|
@Shadow
|
||||||
|
@Final
|
||||||
|
protected ItemModelManager itemModelResolver;
|
||||||
|
|
||||||
|
@Unique
|
||||||
|
private ItemRenderState tempRenderState = new ItemRenderState();
|
||||||
|
|
||||||
|
@Inject(
|
||||||
|
method = "updateRenderState(Lnet/minecraft/entity/LivingEntity;Lnet/minecraft/client/render/entity/state/LivingEntityRenderState;F)V",
|
||||||
|
at = @At("TAIL")
|
||||||
|
)
|
||||||
|
private void replaceHeadModel(
|
||||||
|
T livingEntity, S livingEntityRenderState, float f, CallbackInfo ci
|
||||||
|
) {
|
||||||
|
var headItemStack = livingEntity.getEquippedStack(EquipmentSlot.HEAD);
|
||||||
|
|
||||||
|
HeadModelChooser.INSTANCE.getIS_CHOOSING_HEAD_MODEL().set(true);
|
||||||
|
tempRenderState.clear();
|
||||||
|
this.itemModelResolver.updateForLivingEntity(tempRenderState, headItemStack, ModelTransformationMode.HEAD, false, livingEntity);
|
||||||
|
HeadModelChooser.INSTANCE.getIS_CHOOSING_HEAD_MODEL().set(false);
|
||||||
|
|
||||||
|
if (HeadModelChooser.HasExplicitHeadModelMarker.cast(tempRenderState)
|
||||||
|
.isExplicitHeadModel_Firmament()) {
|
||||||
|
livingEntityRenderState.wearingSkullType = null;
|
||||||
|
var temp = livingEntityRenderState.headItemRenderState;
|
||||||
|
livingEntityRenderState.headItemRenderState = tempRenderState;
|
||||||
|
tempRenderState = temp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,6 +5,7 @@ import com.llamalad7.mixinextras.injector.ModifyReturnValue;
|
|||||||
import com.llamalad7.mixinextras.sugar.Local;
|
import com.llamalad7.mixinextras.sugar.Local;
|
||||||
import moe.nea.firmament.Firmament;
|
import moe.nea.firmament.Firmament;
|
||||||
import moe.nea.firmament.features.texturepack.CustomSkyBlockTextures;
|
import moe.nea.firmament.features.texturepack.CustomSkyBlockTextures;
|
||||||
|
import moe.nea.firmament.features.texturepack.HeadModelChooser;
|
||||||
import moe.nea.firmament.features.texturepack.PredicateModel;
|
import moe.nea.firmament.features.texturepack.PredicateModel;
|
||||||
import moe.nea.firmament.util.ErrorUtil;
|
import moe.nea.firmament.util.ErrorUtil;
|
||||||
import net.minecraft.client.item.ItemAsset;
|
import net.minecraft.client.item.ItemAsset;
|
||||||
@@ -61,6 +62,7 @@ public class SupplyFakeModelPatch {
|
|||||||
try (var is = resource.getInputStream()) {
|
try (var is = resource.getInputStream()) {
|
||||||
var jsonObject = Firmament.INSTANCE.getGson().fromJson(new InputStreamReader(is), JsonObject.class);
|
var jsonObject = Firmament.INSTANCE.getGson().fromJson(new InputStreamReader(is), JsonObject.class);
|
||||||
unbakedModel = PredicateModel.Unbaked.fromLegacyJson(jsonObject, unbakedModel);
|
unbakedModel = PredicateModel.Unbaked.fromLegacyJson(jsonObject, unbakedModel);
|
||||||
|
unbakedModel = HeadModelChooser.Unbaked.fromLegacyJson(jsonObject, unbakedModel);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
ErrorUtil.INSTANCE.softError("Could not create resource for fake model supplication: " + model.getKey(), e);
|
ErrorUtil.INSTANCE.softError("Could not create resource for fake model supplication: " + model.getKey(), e);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user