Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions src/main/java/dev/tr7zw/firstperson/FirstPersonModelCore.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,16 @@
@Deprecated
public static boolean enabled = true;
@Deprecated
public static boolean isRenderingPlayer = false;

Check failure on line 26 in src/main/java/dev/tr7zw/firstperson/FirstPersonModelCore.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Rename field "isRenderingPlayer" to prevent any misunderstanding/clash with method "isRenderingPlayer".

See more on https://sonarcloud.io/project/issues?id=tr7zw_FirstPersonModel&issues=AaB4YGSPRV0_tXUKmMkD&open=AaB4YGSPRV0_tXUKmMkD&pullRequest=659
/**
* True while the render state of the camera entity is being extracted and
* the mod is active. Widens {@link #isRenderingPlayer()} for mods that build
* their render data at extraction time (e.g. YSM), without marking the
* extracted states themselves, so captures of other mods (RealCamera, GUIs)
* evaluate with the flag down and keep rendering the full model with its
* head.
*/
public static boolean cameraEntityExtract = false;
private CameraType lastCameraType = null;
@Deprecated
private int tickCounterWorkaround = 0;
Expand Down Expand Up @@ -96,6 +105,19 @@
tickCounterWorkaround++;
}

@Override
public boolean isRenderingPlayer() {
return super.isRenderingPlayer() || cameraEntityExtract;
}

/**
* The un-widened flag. Only true while FirstPerson itself extracts/renders
* the camera entity, not for third party extractions.
*/
public boolean isRenderingPlayerRaw() {
return super.isRenderingPlayer();
}

@Override
public void setRenderingPlayer(boolean isRenderingPlayer) {
super.setRenderingPlayer(isRenderingPlayer);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -181,8 +181,10 @@ public void renderPostAnim(LivingEntity livingEntity, float f, float g, PoseStac
@Inject(method = "extractRenderState(Lnet/minecraft/world/entity/LivingEntity;Lnet/minecraft/client/renderer/entity/state/LivingEntityRenderState;F)V", at = @At("HEAD"))
private void checkIfCameraEntity(LivingEntity livingEntity, LivingEntityRenderState livingEntityRenderState,
float f, CallbackInfo ci) {
// Raw flag: only states extracted by FirstPerson itself are marked, so
// third party captures (RealCamera, GUIs) keep rendering the head.
((LivingEntityRenderStateAccess) livingEntityRenderState)
.setIsCameraEntity(FirstPersonModelCore.instance.isRenderingPlayer());
.setIsCameraEntity(FirstPersonModelCore.instance.isRenderingPlayerRaw());
}
//? }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public class PlayerMixin {

@Inject(method = "getItemBySlot", at = @At("HEAD"), cancellable = true)
public void getItemBySlot(EquipmentSlot slot, CallbackInfoReturnable<ItemStack> ci) {
if (FirstPersonModelCore.instance.isRenderingPlayer() && Minecraft.getInstance().isSameThread()
if (FirstPersonModelCore.instance.isRenderingPlayerRaw() && Minecraft.getInstance().isSameThread()
&& (Object) this instanceof Player player) {
if (slot == EquipmentSlot.HEAD) {
ci.setReturnValue(ItemStack.EMPTY);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,16 @@

import com.mojang.blaze3d.vertex.*;
import dev.tr7zw.firstperson.*;
import dev.tr7zw.firstperson.access.*;
import lombok.*;
import net.minecraft.client.*;
import net.minecraft.client.renderer.*;
import net.minecraft.client.renderer.entity.*;
//? if >= 1.21.2
import net.minecraft.client.renderer.entity.state.*;
//? if >= 26.1 {
import net.minecraft.client.renderer.state.level.*;
//? }
import net.minecraft.world.level.*;
import org.spongepowered.asm.mixin.*;
import org.spongepowered.asm.mixin.injection.*;
Expand All @@ -33,8 +37,60 @@

private static Minecraft fpmMcInstance = Minecraft.getInstance();

//? if >= 1.21.9 {
//? if >= 26.1 {

private boolean fpmSubmittingCameraEntity = false;

/**
* YSM (and potentially other mods) defer their animation evaluation to the
* submit of the render state and check {@link FirstPersonModelCore#isRenderingPlayer()}
* at that point to decide when to hide the head. Two windows keep the flag
* up for exactly those moments:
* - extraction of the camera entity: widens the flag (without marking the
* states themselves, so third party captures stay unflagged) which makes
* YSM attach its first person context and re-evaluate the head visibility
* on every submit,
* - the submit of the state FPM extracted (marked via isCameraEntity): the
* only evaluation that must see the flag up, hiding the head for the
* actual frame render. Evaluations triggered by other mods (RealCamera,
* GUIs) run with the flag down and keep the model headed.
*/
@Inject(method = "extractEntity(Lnet/minecraft/world/entity/Entity;F)Lnet/minecraft/client/renderer/entity/state/EntityRenderState;",
at = @At("HEAD"), expect = 0, require = 0)
private void fpmExtractStart(Entity entity, float f, CallbackInfoReturnable<EntityRenderState> cir) {
Minecraft mc = Minecraft.getInstance();
if (entity == mc.getCameraEntity() && mc.options.getCameraType() == CameraType.FIRST_PERSON
&& FirstPersonModelCore.instance.getLogicHandler().shouldApplyThirdPerson(false)) {
FirstPersonModelCore.cameraEntityExtract = true;

Check failure on line 64 in src/main/java/dev/tr7zw/firstperson/mixins/RenderDispatcherMixin.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Make the enclosing method "static" or remove this set.

See more on https://sonarcloud.io/project/issues?id=tr7zw_FirstPersonModel&issues=AaB4YGPpRV0_tXUKmMkB&open=AaB4YGPpRV0_tXUKmMkB&pullRequest=659
}
}

@Inject(method = "extractEntity(Lnet/minecraft/world/entity/Entity;F)Lnet/minecraft/client/renderer/entity/state/EntityRenderState;",
at = @At("TAIL"), expect = 0, require = 0)
private void fpmExtractEnd(Entity entity, float f, CallbackInfoReturnable<EntityRenderState> cir) {
FirstPersonModelCore.cameraEntityExtract = false;

Check failure on line 71 in src/main/java/dev/tr7zw/firstperson/mixins/RenderDispatcherMixin.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Make the enclosing method "static" or remove this set.

See more on https://sonarcloud.io/project/issues?id=tr7zw_FirstPersonModel&issues=AaB4YGPpRV0_tXUKmMkC&open=AaB4YGPpRV0_tXUKmMkC&pullRequest=659
}

@Inject(method = "submit(Lnet/minecraft/client/renderer/entity/state/EntityRenderState;Lnet/minecraft/client/renderer/state/level/CameraRenderState;DDDLcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/SubmitNodeCollector;)V",
at = @At("HEAD"), expect = 0, require = 0)
private void fpmSubmitStart(EntityRenderState renderState, CameraRenderState camera, double x, double y, double z,
PoseStack poseStack, SubmitNodeCollector submitNodeCollector, CallbackInfo ci) {
if (renderState instanceof LivingEntityRenderState livingState
&& ((LivingEntityRenderStateAccess) (Object) livingState).isCameraEntity()) {
fpmSubmittingCameraEntity = true;
FirstPersonModelCore.instance.setRenderingPlayer(true);
}
}

@Inject(method = "submit(Lnet/minecraft/client/renderer/entity/state/EntityRenderState;Lnet/minecraft/client/renderer/state/level/CameraRenderState;DDDLcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/SubmitNodeCollector;)V",
at = @At("TAIL"), expect = 0, require = 0)
private void fpmSubmitEnd(EntityRenderState renderState, CameraRenderState camera, double x, double y, double z,
PoseStack poseStack, SubmitNodeCollector submitNodeCollector, CallbackInfo ci) {
if (fpmSubmittingCameraEntity) {
fpmSubmittingCameraEntity = false;
FirstPersonModelCore.instance.setRenderingPlayer(false);
}
}
//? } else if >= 1.21.3 {
/*

Expand Down