diff --git a/src/main/java/twilightforest/block/entity/ReactorDebrisBlockEntity.java b/src/main/java/twilightforest/block/entity/ReactorDebrisBlockEntity.java index ecd5806385..0dfe1ed52b 100644 --- a/src/main/java/twilightforest/block/entity/ReactorDebrisBlockEntity.java +++ b/src/main/java/twilightforest/block/entity/ReactorDebrisBlockEntity.java @@ -1,6 +1,7 @@ package twilightforest.block.entity; import com.google.common.base.MoreObjects; +import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.core.BlockPos; import net.minecraft.core.HolderLookup; import net.minecraft.nbt.CompoundTag; @@ -17,6 +18,8 @@ import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.shapes.Shapes; import net.minecraft.world.phys.shapes.VoxelShape; +import net.neoforged.neoforge.model.data.ModelData; +import net.neoforged.neoforge.model.data.ModelProperty; import org.joml.Vector3f; import twilightforest.init.TFBlockEntities; @@ -30,6 +33,7 @@ public class ReactorDebrisBlockEntity extends BlockEntity { Identifier.withDefaultNamespace("block/nether_portal"), Identifier.withDefaultNamespace("block/obsidian"), }; + public static final ModelProperty TEXTURE_FOR_PARTICLE = new ModelProperty<>(); public static final Identifier DEFAULT_TEXTURE = TEXTURES[0]; private static final float Z_FIGHTING_MIN = 0.008F; private static final float Z_FIGHTING_MAX = 1 - 0.008F; @@ -153,4 +157,12 @@ public ClientboundBlockEntityDataPacket getUpdatePacket() { public CompoundTag getUpdateTag(HolderLookup.Provider registries) { return this.saveCustomOnly(registries); } + + @Override + public ModelData getModelData() { + if (!(this.level instanceof ClientLevel clientLevel)) + return ModelData.EMPTY.derive().with(TEXTURE_FOR_PARTICLE, ReactorDebrisBlockEntity.DEFAULT_TEXTURE).build(); + final Identifier textureForParticle = this.textures[clientLevel.getRandom().nextInt(this.textures.length)]; + return ModelData.EMPTY.derive().with(TEXTURE_FOR_PARTICLE, textureForParticle).build(); + } } diff --git a/src/main/java/twilightforest/client/model/armor/TravellersWingsModel.java b/src/main/java/twilightforest/client/model/armor/TravellersWingsModel.java index 935db1e795..34c576e6d1 100644 --- a/src/main/java/twilightforest/client/model/armor/TravellersWingsModel.java +++ b/src/main/java/twilightforest/client/model/armor/TravellersWingsModel.java @@ -7,6 +7,7 @@ import net.minecraft.client.model.geom.ModelPart; import net.minecraft.client.model.geom.PartPose; import net.minecraft.client.model.geom.builders.*; +import net.minecraft.client.renderer.entity.state.HumanoidRenderState; import net.minecraft.util.Mth; import net.minecraft.world.entity.LivingEntity; import org.joml.Vector3f; @@ -15,10 +16,9 @@ import twilightforest.init.TFDataAttachments; import twilightforest.util.TFMathUtil; -import java.util.Collections; import java.util.List; -public class TravellersWingsModel extends HumanoidModel { +public class TravellersWingsModel extends HumanoidModel { private static final double TAU = 4; // Time (in ticks) in which distance reduces in e times private static final float ANGLE_10_DEG = Mth.PI / 18; private static final Vector3f SMALL_SWING = new Vector3f(8.0F, 8.0F, 8.0F); @@ -167,9 +167,21 @@ protected static void createBelt(PartDefinition root, float deformation) { ); } - public void setupModelAnimations(LivingEntity entity, float f, float f1, double ageInTicks, float netHeadYaw, float headPitch) { + // [VanillaCopy] this method should be removed when IClientItemExtensions fully switches to HumanoidRenderState + private HumanoidRenderState createRendererState(LivingEntity entity, float walkAnimationPos, float walkAnimationSpeed, double ageInTicks, float netHeadYaw, float headPitch) { + HumanoidRenderState state = new HumanoidRenderState(); + state.entityType = entity.getType(); + state.walkAnimationPos = walkAnimationPos; + state.walkAnimationSpeed = walkAnimationSpeed; + state.ageInTicks = (float) ageInTicks; + state.yRot = netHeadYaw; + state.xRot = headPitch; + return state; + } + + public void setupModelAnimations(LivingEntity entity, float walkAnimationPos, float walkAnimationSpeed, double ageInTicks, float netHeadYaw, float headPitch) { this.bodyParts().forEach(modelPart -> modelPart.getAllParts().forEach(ModelPart::resetPose)); - super.setupAnim(entity, f, f1, (float) ageInTicks, netHeadYaw, headPitch); + super.setupAnim(createRendererState(entity, walkAnimationPos, walkAnimationSpeed, ageInTicks, netHeadYaw, headPitch)); TravellersWingsAnimAttachment animAttachment = entity.getData(TFDataAttachments.TRAVELLERS_WINGS_ANIM); TravellersWingsAttachment attachment = entity.getData(TFDataAttachments.TRAVELLERS_WINGS); @@ -220,7 +232,7 @@ public void setupModelAnimations(LivingEntity entity, float f, float f1, double animAttachment.zRotOld = this.wingBaseRight.zRot; // If the wing model keeps a non-changing offset then looking at it with a spyglass even 4 chunks away will reveal Z-fighting. - float distance = (float) (Math.sqrt(entity.distanceToSqr(this.mainCamera.getPosition())) * PART_OFFSET); + float distance = (float) (Math.sqrt(entity.distanceToSqr(this.mainCamera.position())) * PART_OFFSET); // The below solution is to animate its offset based off of camera distance. The animation is not time-based. int partCount = Math.min(this.wingPartsLeft.size(), this.wingPartsRight.size()); for (int partIndex = 0; partIndex < partCount; partIndex++) { @@ -240,12 +252,6 @@ private Vector3f calculateRotations(TravellersWingsAnimAttachment attachment, do ); } - @Override - protected Iterable headParts() { - return Collections.emptyList(); - } - - @Override protected Iterable bodyParts() { return ImmutableList.of(body, leftLeg, rightLeg); } diff --git a/src/main/java/twilightforest/client/model/block/ReactorDebrisModel.java b/src/main/java/twilightforest/client/model/block/ReactorDebrisModel.java deleted file mode 100644 index 25d2195401..0000000000 --- a/src/main/java/twilightforest/client/model/block/ReactorDebrisModel.java +++ /dev/null @@ -1,39 +0,0 @@ -package twilightforest.client.model.block; - -import com.google.common.base.MoreObjects; -import net.minecraft.client.multiplayer.ClientLevel; -import net.minecraft.client.renderer.texture.TextureAtlasSprite; -import net.minecraft.client.resources.model.BakedModel; -import net.minecraft.client.resources.model.DelegateBakedModel; -import net.minecraft.core.BlockPos; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.level.BlockAndTintGetter; -import net.minecraft.world.level.block.state.BlockState; -import net.neoforged.neoforge.client.model.data.ModelData; -import net.neoforged.neoforge.client.model.data.ModelProperty; -import org.jetbrains.annotations.NotNull; -import twilightforest.block.entity.ReactorDebrisBlockEntity; -import twilightforest.client.renderer.block.ReactorDebrisRenderer; - - -public class ReactorDebrisModel extends DelegateBakedModel { - public static final ModelProperty TEXTURE_FOR_PARTICLE = new ModelProperty<>(); - public ReactorDebrisModel(BakedModel defaultModel) { - super(defaultModel); - } - - @Override - public @NotNull ModelData getModelData(BlockAndTintGetter level, BlockPos pos, BlockState state, ModelData modelData) { - if (!(level.getBlockEntity(pos) instanceof ReactorDebrisBlockEntity reactorDebrisBlockEntity) - || !(level instanceof ClientLevel clientLevel)) - return modelData.derive().with(TEXTURE_FOR_PARTICLE, ReactorDebrisBlockEntity.DEFAULT_TEXTURE).build(); - final ResourceLocation textureForParticle = reactorDebrisBlockEntity.textures[clientLevel.random.nextInt(reactorDebrisBlockEntity.textures.length)]; - return modelData.derive().with(TEXTURE_FOR_PARTICLE, textureForParticle).build(); - } - - @Override - public @NotNull TextureAtlasSprite getParticleIcon(ModelData data) { - ResourceLocation texturePath = MoreObjects.firstNonNull(data.get(TEXTURE_FOR_PARTICLE), ReactorDebrisBlockEntity.DEFAULT_TEXTURE); - return ReactorDebrisRenderer.getSprite(texturePath); - } -} diff --git a/src/main/java/twilightforest/client/model/block/connected/ConnectedTextureModelLoader.java b/src/main/java/twilightforest/client/model/block/connected/ConnectedTextureModelLoader.java index ed8e9188ea..44b5c47c7d 100644 --- a/src/main/java/twilightforest/client/model/block/connected/ConnectedTextureModelLoader.java +++ b/src/main/java/twilightforest/client/model/block/connected/ConnectedTextureModelLoader.java @@ -5,7 +5,7 @@ import net.minecraft.core.Direction; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.core.registries.Registries; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.tags.TagKey; import net.minecraft.util.GsonHelper; import net.minecraft.world.level.block.Block; @@ -75,14 +75,14 @@ private List parseConnnectableBlocks(JsonObject object) { for (JsonElement element : object.getAsJsonArray("connectable_blocks")) { if (element.getAsString().startsWith("#")) { - ResourceLocation tag = ResourceLocation.tryParse(element.getAsString().substring(1)); + Identifier tag = Identifier.tryParse(element.getAsString().substring(1)); if (tag != null) { BuiltInRegistries.BLOCK.getTagOrEmpty(TagKey.create(Registries.BLOCK, tag)).forEach(blockHolder -> blocks.add(blockHolder.value())); } else { throw new JsonParseException("Invalid block tag: " + element.getAsString()); } } else { - Block block = BuiltInRegistries.BLOCK.getValue(ResourceLocation.tryParse(element.getAsString())); + Block block = BuiltInRegistries.BLOCK.getValue(Identifier.tryParse(element.getAsString())); if (block == Blocks.AIR) { throw new JsonParseException("Invalid block: " + element.getAsString()); } diff --git a/src/main/java/twilightforest/client/model/block/forcefield/ForceFieldModelBuilder.java b/src/main/java/twilightforest/client/model/block/forcefield/ForceFieldModelBuilder.java index 67a6b97846..536bd46915 100644 --- a/src/main/java/twilightforest/client/model/block/forcefield/ForceFieldModelBuilder.java +++ b/src/main/java/twilightforest/client/model/block/forcefield/ForceFieldModelBuilder.java @@ -5,21 +5,23 @@ import com.google.gson.JsonArray; import com.google.gson.JsonObject; import com.mojang.datafixers.util.Pair; -import net.minecraft.client.renderer.block.model.BlockElement; -import net.minecraft.client.renderer.block.model.BlockElementFace; -import net.minecraft.client.renderer.block.model.BlockElementRotation; -import net.minecraft.client.renderer.block.model.BlockFaceUV; +import com.mojang.math.Quadrant; import net.minecraft.client.renderer.texture.MissingTextureAtlasSprite; +import net.minecraft.client.resources.model.cuboid.CuboidFace; +import net.minecraft.client.resources.model.cuboid.CuboidModelElement; +import net.minecraft.client.resources.model.cuboid.CuboidRotation; import net.minecraft.core.Direction; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.util.Mth; import net.neoforged.neoforge.client.model.ExtraFaceData; import net.neoforged.neoforge.client.model.generators.template.CustomLoaderBuilder; import org.apache.commons.lang3.mutable.MutableObject; import org.jetbrains.annotations.Nullable; import org.joml.Vector3f; +import org.joml.Vector3fc; import twilightforest.TwilightForestMod; import twilightforest.client.model.block.forcefield.ForceFieldModel.ExtraDirection; +import twilightforest.util.UnbakedGeometryUtil; import java.util.*; import java.util.function.BiConsumer; @@ -81,7 +83,7 @@ public JsonObject toJson(JsonObject json) { if (!this.elements.isEmpty()) { JsonArray elements = new JsonArray(); this.elements.forEach(forceFieldElementBuilder -> { - BlockElement part = forceFieldElementBuilder.build(); + CuboidModelElement part = forceFieldElementBuilder.build(); JsonObject partObj = new JsonObject(); if (forceFieldElementBuilder.condition != null) { @@ -98,50 +100,50 @@ public JsonObject toJson(JsonObject json) { partObj.add("condition", condition); } - partObj.add("from", serializeVector3f(part.from)); - partObj.add("to", serializeVector3f(part.to)); + partObj.add("from", serializeVector3fc(part.from())); + partObj.add("to", serializeVector3fc(part.to())); - if (part.rotation != null) { + if (part.rotation() != null) { JsonObject rotation = new JsonObject(); - rotation.add("origin", serializeVector3f(part.rotation.origin())); + rotation.add("origin", serializeVector3fc(part.rotation().origin())); rotation.addProperty("axis", part.rotation.axis().getSerializedName()); rotation.addProperty("angle", part.rotation.angle()); - if (part.rotation.rescale()) { + if (part.rotation().rescale()) { rotation.addProperty("rescale", true); } partObj.add("rotation", rotation); } - if (!part.shade) { - partObj.addProperty("shade", part.shade); + if (!part.shade()) { + partObj.addProperty("shade", part.shade()); } - if (part.lightEmission != 0) { - partObj.addProperty("light_emission", part.lightEmission); + if (part.lightEmission() != 0) { + partObj.addProperty("light_emission", part.lightEmission()); } JsonObject faces = new JsonObject(); for (Direction dir : Direction.values()) { - BlockElementFace face = part.faces.get(dir); + CuboidFace face = part.faces().get(dir); if (face == null) continue; JsonObject faceObj = new JsonObject(); faceObj.addProperty("texture", serializeLocOrKey(face.texture())); - if (!Arrays.equals(face.uv().uvs, part.uvsByFace(dir))) { - faceObj.add("uv", new Gson().toJsonTree(face.uv().uvs)); + if (!UnbakedGeometryUtil.areUVsEqual(face.uvs(), UnbakedGeometryUtil.uvsByFace(dir, part))) { + faceObj.add("uv", new Gson().toJsonTree(face.uvs())); } if (face.cullForDirection() != null) { faceObj.addProperty("cullface", face.cullForDirection().getSerializedName()); } - if (face.uv().rotation != 0) { - faceObj.addProperty("rotation", face.uv().rotation); + if (face.rotation() != Quadrant.R0) { + faceObj.addProperty("rotation", UnbakedGeometryUtil.angleFromQuadrant(face.rotation())); } if (face.tintIndex() != -1) { faceObj.addProperty("tintindex", face.tintIndex()); } faces.add(dir.getSerializedName(), faceObj); } - if (!part.faces.isEmpty()) { + if (!part.faces().isEmpty()) { partObj.add("faces", faces); } elements.add(partObj); @@ -155,10 +157,10 @@ private static String serializeLocOrKey(String tex) { if (tex.charAt(0) == '#') { return tex; } - return ResourceLocation.parse(tex).toString(); + return Identifier.parse(tex).toString(); } - private static JsonArray serializeVector3f(Vector3f vec) { + private static JsonArray serializeVector3fc(Vector3fc vec) { JsonArray ret = new JsonArray(); ret.add(serializeFloat(vec.x())); ret.add(serializeFloat(vec.y())); @@ -288,12 +290,12 @@ private BiConsumer addTexture(S return (direction, builder) -> builder.texture(texture); } - BlockElement build() { - Map faces = this.faces.entrySet().stream() + CuboidModelElement build() { + Map faces = this.faces.entrySet().stream() .collect(Collectors.toMap(Map.Entry::getKey, entry -> entry.getValue().build(), (direction, face) -> { throw new IllegalArgumentException(); }, LinkedHashMap::new)); - return new BlockElement(this.from, this.to, faces, this.rotation == null ? null : this.rotation.build(), this.shade, this.light, ExtraFaceData.DEFAULT); + return new CuboidModelElement(this.from, this.to, faces, this.rotation == null ? null : this.rotation.build(), this.shade, this.light, ExtraFaceData.DEFAULT); } public ForceFieldModelBuilder end() { @@ -340,11 +342,11 @@ public ForceFieldElementBuilder.FaceBuilder rotation(FaceRotation rot) { return this; } - BlockElementFace build() { + CuboidFace build() { if (this.texture == null) { throw new IllegalStateException("A model face must have a texture"); } - return new BlockElementFace(this.cullface, this.tintindex, this.texture, new BlockFaceUV(this.uvs, this.rotation.rotation), ExtraFaceData.DEFAULT, new MutableObject<>()); + return new CuboidFace(this.cullface, this.tintindex, this.texture, this.uvs == null ? new CuboidFace.UVs(0, 0, 16, 16) : UnbakedGeometryUtil.uvsFromArray(this.uvs), UnbakedGeometryUtil.quadrantFromAngle(this.rotation.rotation), ExtraFaceData.DEFAULT, new MutableObject<>()); } public ForceFieldElementBuilder end() { @@ -384,10 +386,10 @@ public ForceFieldElementBuilder.RotationBuilder rescale(boolean rescale) { return this; } - BlockElementRotation build() { + CuboidRotation build() { Preconditions.checkNotNull(this.origin, "No origin specified"); Preconditions.checkNotNull(this.axis, "No axis specified"); - return new BlockElementRotation(this.origin, this.axis, this.angle, this.rescale); + return new CuboidRotation(this.origin, new CuboidRotation.SingleAxisRotation(this.axis, this.angle), this.rescale); } public ForceFieldElementBuilder end() { diff --git a/src/main/java/twilightforest/client/model/block/forcefield/ForceFieldModelLoader.java b/src/main/java/twilightforest/client/model/block/forcefield/ForceFieldModelLoader.java index 46bb236fb5..cdf18cd0d2 100644 --- a/src/main/java/twilightforest/client/model/block/forcefield/ForceFieldModelLoader.java +++ b/src/main/java/twilightforest/client/model/block/forcefield/ForceFieldModelLoader.java @@ -4,9 +4,8 @@ import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParseException; -import net.minecraft.client.renderer.block.model.BlockElement; +import net.minecraft.client.resources.model.cuboid.CuboidModelElement; import net.minecraft.util.GsonHelper; -import net.neoforged.neoforge.client.model.NeoForgeModelProperties; import net.neoforged.neoforge.client.model.StandardModelParameters; import net.neoforged.neoforge.client.model.UnbakedModelLoader; import org.jetbrains.annotations.Nullable; @@ -24,7 +23,7 @@ public class ForceFieldModelLoader implements UnbakedModelLoader elementsAndConditions = new HashMap<>(); + Map elementsAndConditions = new HashMap<>(); if (json.has("elements")) { for (JsonElement jsonElement : GsonHelper.getAsJsonArray(json, "elements")) { @@ -41,7 +40,7 @@ public UnbakedForceFieldModel read(JsonObject json, JsonDeserializationContext c } } } - elementsAndConditions.put(context.deserialize(jsonElement, BlockElement.class), new Condition(direction, b, parents)); + elementsAndConditions.put(context.deserialize(jsonElement, CuboidModelElement.class), new Condition(direction, b, parents)); } } diff --git a/src/main/java/twilightforest/client/model/block/forcefield/UnbakedForceFieldModel.java b/src/main/java/twilightforest/client/model/block/forcefield/UnbakedForceFieldModel.java index 4c2cf16f46..b382165d1b 100644 --- a/src/main/java/twilightforest/client/model/block/forcefield/UnbakedForceFieldModel.java +++ b/src/main/java/twilightforest/client/model/block/forcefield/UnbakedForceFieldModel.java @@ -1,22 +1,20 @@ package twilightforest.client.model.block.forcefield; -import net.minecraft.client.renderer.block.model.BlockElement; import net.minecraft.client.renderer.block.model.ItemTransforms; import net.minecraft.client.renderer.block.model.TextureSlots; import net.minecraft.client.resources.model.*; +import net.minecraft.client.resources.model.cuboid.CuboidModelElement; import net.minecraft.util.context.ContextMap; -import net.neoforged.neoforge.client.RenderTypeGroup; import net.neoforged.neoforge.client.model.AbstractUnbakedModel; -import net.neoforged.neoforge.client.model.ExtendedUnbakedModel; import net.neoforged.neoforge.client.model.StandardModelParameters; import java.util.Map; public class UnbakedForceFieldModel extends AbstractUnbakedModel { - private final Map elementsAndConditions; + private final Map elementsAndConditions; - public UnbakedForceFieldModel(Map elementsAndConditions, StandardModelParameters parameters) { + public UnbakedForceFieldModel(Map elementsAndConditions, StandardModelParameters parameters) { super(parameters); this.elementsAndConditions = elementsAndConditions; } diff --git a/src/main/java/twilightforest/client/model/block/patch/PatchBuilder.java b/src/main/java/twilightforest/client/model/block/patch/PatchBuilder.java index 5160a6db0c..c60e278071 100644 --- a/src/main/java/twilightforest/client/model/block/patch/PatchBuilder.java +++ b/src/main/java/twilightforest/client/model/block/patch/PatchBuilder.java @@ -1,6 +1,5 @@ package twilightforest.client.model.block.patch; -import com.google.gson.JsonArray; import com.google.gson.JsonObject; import net.neoforged.neoforge.client.model.generators.template.CustomLoaderBuilder; import twilightforest.TwilightForestMod; diff --git a/src/main/java/twilightforest/client/model/block/patch/PatchModelLoader.java b/src/main/java/twilightforest/client/model/block/patch/PatchModelLoader.java index 0d6db0059c..4599a7d9e5 100644 --- a/src/main/java/twilightforest/client/model/block/patch/PatchModelLoader.java +++ b/src/main/java/twilightforest/client/model/block/patch/PatchModelLoader.java @@ -4,8 +4,6 @@ import com.google.gson.JsonObject; import com.google.gson.JsonParseException; import com.mojang.realmsclient.util.JsonUtils; -import net.minecraft.resources.ResourceLocation; -import net.neoforged.neoforge.client.model.NeoForgeModelProperties; import net.neoforged.neoforge.client.model.StandardModelParameters; import net.neoforged.neoforge.client.model.UnbakedModelLoader; diff --git a/src/main/java/twilightforest/client/model/block/patch/UnbakedPatchModel.java b/src/main/java/twilightforest/client/model/block/patch/UnbakedPatchModel.java index 0def27c9a2..0ca1c5a901 100644 --- a/src/main/java/twilightforest/client/model/block/patch/UnbakedPatchModel.java +++ b/src/main/java/twilightforest/client/model/block/patch/UnbakedPatchModel.java @@ -4,7 +4,6 @@ import net.minecraft.client.renderer.block.model.TextureSlots; import net.minecraft.client.resources.model.*; import net.minecraft.util.context.ContextMap; -import net.neoforged.neoforge.client.RenderTypeGroup; import net.neoforged.neoforge.client.model.AbstractUnbakedModel; import net.neoforged.neoforge.client.model.StandardModelParameters; diff --git a/src/main/java/twilightforest/client/model/entity/HostileWolfModel.java b/src/main/java/twilightforest/client/model/entity/HostileWolfModel.java index a810bb836c..171b98b04a 100644 --- a/src/main/java/twilightforest/client/model/entity/HostileWolfModel.java +++ b/src/main/java/twilightforest/client/model/entity/HostileWolfModel.java @@ -26,7 +26,7 @@ public HostileWolfModel(ModelPart root) { } public HostileWolfModel(Function type, ModelPart root) { - super(type, false, 5.0F, 2.0F, 2.0F, 2.0F, 24.0F); + super(root, type); this.head = root.getChild("head"); this.body = root.getChild("body"); this.upperBody = root.getChild("upper_body"); diff --git a/src/main/java/twilightforest/client/model/item/TrollsteinnModel.java b/src/main/java/twilightforest/client/model/item/TrollsteinnModel.java deleted file mode 100644 index d880eab3e9..0000000000 --- a/src/main/java/twilightforest/client/model/item/TrollsteinnModel.java +++ /dev/null @@ -1,50 +0,0 @@ -package twilightforest.client.model.item; - -import net.minecraft.client.Minecraft; -import net.minecraft.client.multiplayer.ClientLevel; -import net.minecraft.client.renderer.block.model.ItemOverrides; -import net.minecraft.client.resources.model.BakedModel; -import net.minecraft.client.resources.model.ModelResourceLocation; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.item.ItemStack; -import net.neoforged.neoforge.client.model.BakedModelWrapper; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import twilightforest.TwilightForestMod; -import twilightforest.block.TrollsteinnBlock; - -public class TrollsteinnModel extends BakedModelWrapper { - public static final ModelResourceLocation LIT_TROLLSTEINN = ModelResourceLocation.standalone(TwilightForestMod.prefix("item/trollsteinn_light")); - @Nullable - private BakedModel litTrollsteinnModel; - private final ItemOverrides overrides = new ItemOverrides() { - @Override - public BakedModel resolve(@NotNull BakedModel model, @NotNull ItemStack stack, @Nullable ClientLevel level, @Nullable LivingEntity entity, int seed) { - if (TrollsteinnModel.this.litTrollsteinnModel == null) - TrollsteinnModel.this.litTrollsteinnModel = Minecraft.getInstance().getModelManager().getModel(LIT_TROLLSTEINN); - - Entity itemEntity = (entity == null) ? stack.getEntityRepresentation() : entity; - - if (level == null || itemEntity == null) { - return super.resolve(TrollsteinnModel.this.originalModel, stack, level, entity, seed); - } - - int brightness = level.getMaxLocalRawBrightness(itemEntity.blockPosition(), level.getSkyDarken()); - if (brightness > TrollsteinnBlock.LIGHT_THRESHOLD) { - return super.resolve(TrollsteinnModel.this.litTrollsteinnModel, stack, level, entity, seed); - } else { - return super.resolve(TrollsteinnModel.this.originalModel, stack, level, entity, seed); - } - } - }; - - public TrollsteinnModel(BakedModel originalModel) { - super(originalModel); - } - - @Override - public ItemOverrides getOverrides() { - return overrides; - } -} diff --git a/src/main/java/twilightforest/client/state/entity/LichMinionRenderState.java b/src/main/java/twilightforest/client/state/entity/LichMinionRenderState.java new file mode 100644 index 0000000000..8426cd207c --- /dev/null +++ b/src/main/java/twilightforest/client/state/entity/LichMinionRenderState.java @@ -0,0 +1,7 @@ +package twilightforest.client.state.entity; + +import net.minecraft.client.renderer.entity.state.ZombieRenderState; + +public class LichMinionRenderState extends ZombieRenderState { + public boolean hasStrength; +} \ No newline at end of file diff --git a/src/main/java/twilightforest/client/state/entity/LoyalZombieRenderState.java b/src/main/java/twilightforest/client/state/entity/LoyalZombieRenderState.java new file mode 100644 index 0000000000..e1a23174d1 --- /dev/null +++ b/src/main/java/twilightforest/client/state/entity/LoyalZombieRenderState.java @@ -0,0 +1,7 @@ +package twilightforest.client.state.entity; + +import net.minecraft.client.renderer.entity.state.HumanoidRenderState; + +public class LoyalZombieRenderState extends HumanoidRenderState { + public boolean isAggressive; +} \ No newline at end of file diff --git a/src/main/java/twilightforest/util/UnbakedGeometryUtil.java b/src/main/java/twilightforest/util/UnbakedGeometryUtil.java new file mode 100644 index 0000000000..890c8075b2 --- /dev/null +++ b/src/main/java/twilightforest/util/UnbakedGeometryUtil.java @@ -0,0 +1,59 @@ +package twilightforest.util; + +import com.mojang.math.Quadrant; +import net.minecraft.client.renderer.block.dispatch.ModelState; +import net.minecraft.client.resources.model.ModelBaker; +import net.minecraft.client.resources.model.cuboid.CuboidFace; +import net.minecraft.client.resources.model.cuboid.CuboidModelElement; +import net.minecraft.client.resources.model.cuboid.FaceBakery; +import net.minecraft.client.resources.model.geometry.BakedQuad; +import net.minecraft.client.resources.model.sprite.Material; +import net.minecraft.core.Direction; + +public class UnbakedGeometryUtil { + // [VanillaCopy] returned back this method from 1.21.1 Vanilla Sources + public static CuboidFace.UVs uvsByFace(Direction face, CuboidModelElement element) { + return switch (face) { + case DOWN -> new CuboidFace.UVs(element.from().x(), 16.0F - element.to().z(), element.to().x(), 16.0F - element.from().z()); + case UP -> new CuboidFace.UVs(element.from().x(), element.from().z(), element.to().x(), element.to().z()); + case SOUTH -> new CuboidFace.UVs(element.from().x(), 16.0F - element.to().y(), element.to().x(), 16.0F - element.from().y()); + case WEST -> new CuboidFace.UVs(element.from().z(), 16.0F - element.to().y(), element.to().z(), 16.0F - element.from().y()); + case EAST -> new CuboidFace.UVs(16.0F - element.to().z(), 16.0F - element.to().y(), 16.0F - element.from().z(), 16.0F - element.from().y()); + default -> new CuboidFace.UVs(16.0F - element.to().x(), 16.0F - element.to().y(), 16.0F - element.from().x(), 16.0F - element.from().y()); + }; + } + + // [VanillaCopy] returned back this method from 1.21.1 Vanilla Sources + public static BakedQuad bakeElementFace(ModelBaker baker, CuboidModelElement element, CuboidFace face, Material.Baked sprite, Direction direction, ModelState state) { + return FaceBakery.bakeQuad(baker, element.from(), element.to(), face, sprite, direction, state, null, element.shade(), 0); + } + + public static boolean areUVsEqual(CuboidFace.UVs first, CuboidFace.UVs second) { + return first.minU() == second.minU() && first.minV() == second.minV() && first.maxU() == second.maxU() && first.maxV() == second.maxV(); + } + + public static int angleFromQuadrant(Quadrant quadrant) { + return switch (quadrant) { + case R90 -> 90; + case R180 -> 180; + case R270 -> 270; + default -> 0; + }; + } + + public static Quadrant quadrantFromAngle(int angle) { + if (angle >= 0 && angle < 90) { + return Quadrant.R90; + } else if (angle >= 90 && angle < 180) { + return Quadrant.R180; + } else if (angle >= 180 && angle < 270) { + return Quadrant.R270; + } else { + return Quadrant.R0; + } + } + + public static CuboidFace.UVs uvsFromArray(float[] array) { + return new CuboidFace.UVs(array[0], array[1], array[2], array[3]); + } +}