Clean repo for open source release
Remove build artifacts, dev tool configs, unused dependencies, and third-party source dumps. Add proper README, update .gitignore, clean up Makefile.
This commit is contained in:
@@ -0,0 +1,198 @@
|
||||
package com.tiedup.remake.client.animation.render;
|
||||
|
||||
import com.tiedup.remake.core.TiedUpMod;
|
||||
import com.tiedup.remake.v2.BodyRegionV2;
|
||||
import com.tiedup.remake.items.base.ItemBind;
|
||||
import com.tiedup.remake.items.base.PoseType;
|
||||
import com.tiedup.remake.state.HumanChairHelper;
|
||||
import com.tiedup.remake.state.PlayerBindState;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||
import net.minecraft.client.player.AbstractClientPlayer;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||
import net.minecraftforge.client.event.RenderPlayerEvent;
|
||||
import net.minecraftforge.eventbus.api.EventPriority;
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
|
||||
/**
|
||||
* Handles DOG and HUMAN_CHAIR pose rendering adjustments.
|
||||
*
|
||||
* <p>Applies vertical offset and smooth body rotation for DOG/HUMAN_CHAIR poses.
|
||||
* Runs at HIGH priority to ensure transforms are applied before other Pre handlers.
|
||||
*
|
||||
* <p>Extracted from PlayerArmHideEventHandler for single-responsibility.
|
||||
*/
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
@Mod.EventBusSubscriber(
|
||||
modid = TiedUpMod.MOD_ID,
|
||||
bus = Mod.EventBusSubscriber.Bus.FORGE,
|
||||
value = Dist.CLIENT
|
||||
)
|
||||
public class DogPoseRenderHandler {
|
||||
|
||||
/**
|
||||
* DOG pose state tracking per player.
|
||||
* Stores: [0: smoothedTarget, 1: currentRot, 2: appliedDelta, 3: isMoving (0/1)]
|
||||
*/
|
||||
private static final Int2ObjectMap<float[]> dogPoseState =
|
||||
new Int2ObjectOpenHashMap<>();
|
||||
|
||||
// Array indices for dogPoseState
|
||||
private static final int IDX_TARGET = 0;
|
||||
private static final int IDX_CURRENT = 1;
|
||||
private static final int IDX_DELTA = 2;
|
||||
private static final int IDX_MOVING = 3;
|
||||
|
||||
/**
|
||||
* Get the rotation delta applied to a player's render for DOG pose.
|
||||
* Used by MixinPlayerModel to compensate head rotation.
|
||||
*/
|
||||
public static float getAppliedRotationDelta(int playerId) {
|
||||
float[] state = dogPoseState.get(playerId);
|
||||
return state != null ? state[IDX_DELTA] : 0f;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a player is currently moving in DOG pose.
|
||||
*/
|
||||
public static boolean isDogPoseMoving(int playerId) {
|
||||
float[] state = dogPoseState.get(playerId);
|
||||
return state != null && state[IDX_MOVING] > 0.5f;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear all DOG pose state data.
|
||||
* Called on world unload to prevent memory leaks.
|
||||
*/
|
||||
public static void clearState() {
|
||||
dogPoseState.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Before player render: Apply vertical offset and rotation for DOG/HUMAN_CHAIR poses.
|
||||
* HIGH priority ensures this runs before arm/item hiding handlers.
|
||||
*/
|
||||
@SubscribeEvent(priority = EventPriority.HIGH)
|
||||
public static void onRenderPlayerPre(RenderPlayerEvent.Pre event) {
|
||||
Player player = event.getEntity();
|
||||
if (!(player instanceof AbstractClientPlayer)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (player.isRemoved() || !player.isAlive()) {
|
||||
return;
|
||||
}
|
||||
|
||||
PlayerBindState state = PlayerBindState.getInstance(player);
|
||||
if (state == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
ItemStack bindForPose = state.getEquipment(BodyRegionV2.ARMS);
|
||||
if (
|
||||
bindForPose.isEmpty() ||
|
||||
!(bindForPose.getItem() instanceof ItemBind itemBind)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
PoseType bindPoseType = itemBind.getPoseType();
|
||||
// Check for humanChairMode NBT override
|
||||
bindPoseType = HumanChairHelper.resolveEffectivePose(
|
||||
bindPoseType,
|
||||
bindForPose
|
||||
);
|
||||
|
||||
if (
|
||||
bindPoseType != PoseType.DOG && bindPoseType != PoseType.HUMAN_CHAIR
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Lower player by 6 model units (6/16 = 0.375 blocks)
|
||||
event
|
||||
.getPoseStack()
|
||||
.translate(0, RenderConstants.DOG_AND_PETBED_Y_OFFSET, 0);
|
||||
|
||||
int playerId = player.getId();
|
||||
net.minecraft.world.phys.Vec3 movement = player.getDeltaMovement();
|
||||
boolean isMoving = movement.horizontalDistanceSqr() > 0.0001;
|
||||
|
||||
// Get or create state - initialize to current body rotation
|
||||
float[] s = dogPoseState.get(playerId);
|
||||
if (s == null) {
|
||||
s = new float[] { player.yBodyRot, player.yBodyRot, 0f, 0f };
|
||||
dogPoseState.put(playerId, s);
|
||||
}
|
||||
|
||||
// Human chair: lock rotation state — body must not turn
|
||||
if (bindPoseType == PoseType.HUMAN_CHAIR) {
|
||||
s[IDX_CURRENT] = player.yBodyRot;
|
||||
s[IDX_TARGET] = player.yBodyRot;
|
||||
s[IDX_DELTA] = 0f;
|
||||
s[IDX_MOVING] = 0f;
|
||||
} else {
|
||||
// Determine target rotation
|
||||
float rawTarget;
|
||||
if (isMoving) {
|
||||
// Moving: face movement direction
|
||||
rawTarget = (float) Math.toDegrees(
|
||||
Math.atan2(-movement.x, movement.z)
|
||||
);
|
||||
} else {
|
||||
// Stationary: face where head is looking
|
||||
rawTarget = player.yHeadRot;
|
||||
}
|
||||
|
||||
// Check if head would be clamped (body lagging behind head)
|
||||
float predictedHeadYaw = net.minecraft.util.Mth.wrapDegrees(
|
||||
player.yHeadRot - s[IDX_CURRENT]
|
||||
);
|
||||
float maxYaw = isMoving
|
||||
? RenderConstants.HEAD_MAX_YAW_MOVING
|
||||
: RenderConstants.HEAD_MAX_YAW_STATIONARY;
|
||||
boolean headAtLimit =
|
||||
Math.abs(predictedHeadYaw) >
|
||||
maxYaw * RenderConstants.HEAD_AT_LIMIT_RATIO;
|
||||
|
||||
if (headAtLimit && !isMoving) {
|
||||
// Head at limit while stationary: snap body to release head
|
||||
float sign = predictedHeadYaw > 0 ? 1f : -1f;
|
||||
s[IDX_CURRENT] =
|
||||
player.yHeadRot -
|
||||
sign * maxYaw * RenderConstants.HEAD_SNAP_RELEASE_RATIO;
|
||||
s[IDX_TARGET] = s[IDX_CURRENT];
|
||||
} else {
|
||||
// Normal smoothing
|
||||
float targetDelta = net.minecraft.util.Mth.wrapDegrees(
|
||||
rawTarget - s[IDX_TARGET]
|
||||
);
|
||||
float targetSpeed = isMoving
|
||||
? RenderConstants.DOG_TARGET_SPEED_MOVING
|
||||
: RenderConstants.DOG_TARGET_SPEED_STATIONARY;
|
||||
s[IDX_TARGET] += targetDelta * targetSpeed;
|
||||
|
||||
float rotDelta = net.minecraft.util.Mth.wrapDegrees(
|
||||
s[IDX_TARGET] - s[IDX_CURRENT]
|
||||
);
|
||||
float speed = isMoving
|
||||
? RenderConstants.DOG_ROT_SPEED_MOVING
|
||||
: RenderConstants.DOG_ROT_SPEED_STATIONARY;
|
||||
s[IDX_CURRENT] += rotDelta * speed;
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate and store the delta we apply to poseStack
|
||||
s[IDX_DELTA] = player.yBodyRot - s[IDX_CURRENT];
|
||||
s[IDX_MOVING] = isMoving ? 1f : 0f;
|
||||
|
||||
// Apply rotation to make body face our custom direction
|
||||
event
|
||||
.getPoseStack()
|
||||
.mulPose(com.mojang.math.Axis.YP.rotationDegrees(s[IDX_DELTA]));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package com.tiedup.remake.client.animation.render;
|
||||
|
||||
import com.tiedup.remake.core.TiedUpMod;
|
||||
import com.tiedup.remake.state.PlayerBindState;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.player.LocalPlayer;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||
import net.minecraftforge.client.event.RenderHandEvent;
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
|
||||
/**
|
||||
* Hide first-person hand/item rendering based on bondage state.
|
||||
*
|
||||
* Behavior:
|
||||
* - Tied up: Hide hands completely (hands are behind back)
|
||||
* - Mittens: Hide hands + items (Forge limitation - can't separate them)
|
||||
*/
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
@Mod.EventBusSubscriber(
|
||||
modid = TiedUpMod.MOD_ID,
|
||||
bus = Mod.EventBusSubscriber.Bus.FORGE,
|
||||
value = Dist.CLIENT
|
||||
)
|
||||
public class FirstPersonHandHideHandler {
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onRenderHand(RenderHandEvent event) {
|
||||
Minecraft mc = Minecraft.getInstance();
|
||||
if (mc == null) {
|
||||
return;
|
||||
}
|
||||
LocalPlayer player = mc.player;
|
||||
|
||||
if (player == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
PlayerBindState state = PlayerBindState.getInstance(player);
|
||||
if (state == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Tied or Mittens: hide hands completely
|
||||
// (Forge limitation: RenderHandEvent controls hand + item together)
|
||||
if (state.isTiedUp() || state.hasMittens()) {
|
||||
event.setCanceled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
package com.tiedup.remake.client.animation.render;
|
||||
|
||||
import com.tiedup.remake.core.TiedUpMod;
|
||||
import com.tiedup.remake.state.PlayerBindState;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||
import net.minecraft.client.player.AbstractClientPlayer;
|
||||
import net.minecraft.world.InteractionHand;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||
import net.minecraftforge.client.event.RenderPlayerEvent;
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
|
||||
/**
|
||||
* Hides held items when player has arms bound or is wearing mittens.
|
||||
*
|
||||
* <p>Uses Pre/Post pattern to temporarily replace held items with empty
|
||||
* stacks for rendering, then restore them after.
|
||||
*
|
||||
* <p>Extracted from PlayerArmHideEventHandler for single-responsibility.
|
||||
*/
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
@Mod.EventBusSubscriber(
|
||||
modid = TiedUpMod.MOD_ID,
|
||||
bus = Mod.EventBusSubscriber.Bus.FORGE,
|
||||
value = Dist.CLIENT
|
||||
)
|
||||
public class HeldItemHideHandler {
|
||||
|
||||
/**
|
||||
* Stored items to restore after rendering.
|
||||
* Key: Player entity ID (int), Value: [mainHand, offHand]
|
||||
*/
|
||||
private static final Int2ObjectMap<ItemStack[]> storedItems =
|
||||
new Int2ObjectOpenHashMap<>();
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onRenderPlayerPre(RenderPlayerEvent.Pre event) {
|
||||
Player player = event.getEntity();
|
||||
if (!(player instanceof AbstractClientPlayer)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (player.isRemoved() || !player.isAlive()) {
|
||||
return;
|
||||
}
|
||||
|
||||
PlayerBindState state = PlayerBindState.getInstance(player);
|
||||
if (state == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
boolean hasArmsBound = state.hasArmsBound();
|
||||
boolean hasMittens = state.hasMittens();
|
||||
|
||||
if (hasArmsBound || hasMittens) {
|
||||
ItemStack mainHand = player.getItemInHand(
|
||||
InteractionHand.MAIN_HAND
|
||||
);
|
||||
ItemStack offHand = player.getItemInHand(InteractionHand.OFF_HAND);
|
||||
|
||||
if (!mainHand.isEmpty() || !offHand.isEmpty()) {
|
||||
storedItems.put(
|
||||
player.getId(),
|
||||
new ItemStack[] { mainHand.copy(), offHand.copy() }
|
||||
);
|
||||
|
||||
player.setItemInHand(
|
||||
InteractionHand.MAIN_HAND,
|
||||
ItemStack.EMPTY
|
||||
);
|
||||
player.setItemInHand(InteractionHand.OFF_HAND, ItemStack.EMPTY);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onRenderPlayerPost(RenderPlayerEvent.Post event) {
|
||||
Player player = event.getEntity();
|
||||
if (!(player instanceof AbstractClientPlayer)) {
|
||||
return;
|
||||
}
|
||||
|
||||
ItemStack[] items = storedItems.remove(player.getId());
|
||||
if (items != null) {
|
||||
player.setItemInHand(InteractionHand.MAIN_HAND, items[0]);
|
||||
player.setItemInHand(InteractionHand.OFF_HAND, items[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
package com.tiedup.remake.client.animation.render;
|
||||
|
||||
import com.tiedup.remake.client.state.PetBedClientState;
|
||||
import com.tiedup.remake.v2.BodyRegionV2;
|
||||
import com.tiedup.remake.core.TiedUpMod;
|
||||
import com.tiedup.remake.items.base.ItemBind;
|
||||
import com.tiedup.remake.items.base.PoseType;
|
||||
import com.tiedup.remake.state.HumanChairHelper;
|
||||
import com.tiedup.remake.state.PlayerBindState;
|
||||
import net.minecraft.client.player.AbstractClientPlayer;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||
import net.minecraftforge.client.event.RenderPlayerEvent;
|
||||
import net.minecraftforge.eventbus.api.EventPriority;
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
|
||||
/**
|
||||
* Handles pet bed render adjustments (SIT and SLEEP modes).
|
||||
*
|
||||
* <p>Applies vertical offset and forced standing pose for pet bed states.
|
||||
* Runs at HIGH priority alongside DogPoseRenderHandler.
|
||||
*
|
||||
* <p>Extracted from PlayerArmHideEventHandler for single-responsibility.
|
||||
*/
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
@Mod.EventBusSubscriber(
|
||||
modid = TiedUpMod.MOD_ID,
|
||||
bus = Mod.EventBusSubscriber.Bus.FORGE,
|
||||
value = Dist.CLIENT
|
||||
)
|
||||
public class PetBedRenderHandler {
|
||||
|
||||
/**
|
||||
* Before player render: Apply vertical offset and forced pose for pet bed.
|
||||
*/
|
||||
@SubscribeEvent(priority = EventPriority.HIGH)
|
||||
public static void onRenderPlayerPre(RenderPlayerEvent.Pre event) {
|
||||
Player player = event.getEntity();
|
||||
if (!(player instanceof AbstractClientPlayer)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (player.isRemoved() || !player.isAlive()) {
|
||||
return;
|
||||
}
|
||||
|
||||
java.util.UUID petBedUuid = player.getUUID();
|
||||
byte petBedMode = PetBedClientState.get(petBedUuid);
|
||||
|
||||
if (petBedMode == 1 || petBedMode == 2) {
|
||||
// Skip Y-offset if DogPoseRenderHandler already applies it
|
||||
// (DOG/HUMAN_CHAIR pose uses the same offset amount)
|
||||
if (!isDogOrChairPose(player)) {
|
||||
event
|
||||
.getPoseStack()
|
||||
.translate(0, RenderConstants.DOG_AND_PETBED_Y_OFFSET, 0);
|
||||
}
|
||||
}
|
||||
if (petBedMode == 2) {
|
||||
// SLEEP: force STANDING pose to prevent vanilla sleeping rotation
|
||||
player.setForcedPose(net.minecraft.world.entity.Pose.STANDING);
|
||||
|
||||
// Compensate for vanilla sleeping Y offset
|
||||
player
|
||||
.getSleepingPos()
|
||||
.ifPresent(pos -> {
|
||||
double yOffset = player.getY() - pos.getY();
|
||||
if (yOffset > 0.01) {
|
||||
event.getPoseStack().translate(0, -yOffset, 0);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the player is in DOG or HUMAN_CHAIR pose.
|
||||
* Used to avoid double Y-offset with DogPoseRenderHandler.
|
||||
*/
|
||||
private static boolean isDogOrChairPose(Player player) {
|
||||
PlayerBindState state = PlayerBindState.getInstance(player);
|
||||
if (state == null) return false;
|
||||
ItemStack bind = state.getEquipment(BodyRegionV2.ARMS);
|
||||
if (
|
||||
bind.isEmpty() || !(bind.getItem() instanceof ItemBind itemBind)
|
||||
) return false;
|
||||
PoseType pose = HumanChairHelper.resolveEffectivePose(
|
||||
itemBind.getPoseType(),
|
||||
bind
|
||||
);
|
||||
return pose == PoseType.DOG || pose == PoseType.HUMAN_CHAIR;
|
||||
}
|
||||
|
||||
/**
|
||||
* After player render: Restore forced pose for pet bed SLEEP mode.
|
||||
*/
|
||||
@SubscribeEvent
|
||||
public static void onRenderPlayerPost(RenderPlayerEvent.Post event) {
|
||||
Player player = event.getEntity();
|
||||
if (!(player instanceof AbstractClientPlayer)) {
|
||||
return;
|
||||
}
|
||||
|
||||
byte petBedMode = PetBedClientState.get(player.getUUID());
|
||||
if (petBedMode == 2) {
|
||||
player.setForcedPose(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,135 @@
|
||||
package com.tiedup.remake.client.animation.render;
|
||||
|
||||
import com.tiedup.remake.client.renderer.layers.ClothesRenderHelper;
|
||||
import com.tiedup.remake.v2.BodyRegionV2;
|
||||
import com.tiedup.remake.core.TiedUpMod;
|
||||
import com.tiedup.remake.items.base.ItemBind;
|
||||
import com.tiedup.remake.items.base.PoseType;
|
||||
import com.tiedup.remake.items.clothes.ClothesProperties;
|
||||
import com.tiedup.remake.state.PlayerBindState;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||
import net.minecraft.client.model.PlayerModel;
|
||||
import net.minecraft.client.player.AbstractClientPlayer;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||
import net.minecraftforge.client.event.RenderPlayerEvent;
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
|
||||
/**
|
||||
* Hide player arms and outer layers based on bondage/clothes state.
|
||||
*
|
||||
* <p>Responsibilities (after extraction of dog pose, pet bed, and held items):
|
||||
* <ul>
|
||||
* <li>Hide arms for wrap/latex_sack poses</li>
|
||||
* <li>Hide outer layers (hat, jacket, sleeves, pants) based on clothes settings</li>
|
||||
* </ul>
|
||||
*
|
||||
* <p>Uses Pre/Post pattern to temporarily modify and restore state.
|
||||
*/
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
@Mod.EventBusSubscriber(
|
||||
modid = TiedUpMod.MOD_ID,
|
||||
bus = Mod.EventBusSubscriber.Bus.FORGE,
|
||||
value = Dist.CLIENT
|
||||
)
|
||||
public class PlayerArmHideEventHandler {
|
||||
|
||||
/**
|
||||
* Stored layer visibility to restore after rendering.
|
||||
* Key: Player entity ID (int), Value: [hat, jacket, leftSleeve, rightSleeve, leftPants, rightPants]
|
||||
*/
|
||||
private static final Int2ObjectMap<boolean[]> storedLayers =
|
||||
new Int2ObjectOpenHashMap<>();
|
||||
|
||||
/**
|
||||
* Before player render:
|
||||
* - Hide arms for wrap/latex_sack poses
|
||||
* - Hide outer layers based on clothes settings (Phase 19)
|
||||
*/
|
||||
@SubscribeEvent
|
||||
public static void onRenderPlayerPre(RenderPlayerEvent.Pre event) {
|
||||
Player player = event.getEntity();
|
||||
if (!(player instanceof AbstractClientPlayer clientPlayer)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (player.isRemoved() || !player.isAlive()) {
|
||||
return;
|
||||
}
|
||||
|
||||
PlayerBindState state = PlayerBindState.getInstance(player);
|
||||
if (state == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
PlayerModel<?> model = event.getRenderer().getModel();
|
||||
|
||||
// === HIDE ARMS (wrap/latex_sack poses) ===
|
||||
if (state.hasArmsBound()) {
|
||||
ItemStack bind = state.getEquipment(BodyRegionV2.ARMS);
|
||||
if (
|
||||
!bind.isEmpty() && bind.getItem() instanceof ItemBind itemBind
|
||||
) {
|
||||
PoseType poseType = itemBind.getPoseType();
|
||||
|
||||
// Only hide arms for wrap/sack poses (arms are covered by the item)
|
||||
if (
|
||||
poseType == PoseType.WRAP || poseType == PoseType.LATEX_SACK
|
||||
) {
|
||||
model.leftArm.visible = false;
|
||||
model.rightArm.visible = false;
|
||||
model.leftSleeve.visible = false;
|
||||
model.rightSleeve.visible = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// === HIDE WEARER LAYERS (clothes settings) - Phase 19 ===
|
||||
ItemStack clothes = state.getEquipment(BodyRegionV2.TORSO);
|
||||
if (!clothes.isEmpty()) {
|
||||
ClothesProperties props =
|
||||
ClothesRenderHelper.getPropsForLayerHiding(
|
||||
clothes,
|
||||
clientPlayer
|
||||
);
|
||||
if (props != null) {
|
||||
boolean[] savedLayers = ClothesRenderHelper.hideWearerLayers(
|
||||
model,
|
||||
props
|
||||
);
|
||||
if (savedLayers != null) {
|
||||
storedLayers.put(player.getId(), savedLayers);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* After player render: Restore arm visibility and layer visibility.
|
||||
*/
|
||||
@SubscribeEvent
|
||||
public static void onRenderPlayerPost(RenderPlayerEvent.Post event) {
|
||||
Player player = event.getEntity();
|
||||
if (!(player instanceof AbstractClientPlayer)) {
|
||||
return;
|
||||
}
|
||||
|
||||
PlayerModel<?> model = event.getRenderer().getModel();
|
||||
|
||||
// === RESTORE ARM VISIBILITY ===
|
||||
model.leftArm.visible = true;
|
||||
model.rightArm.visible = true;
|
||||
model.leftSleeve.visible = true;
|
||||
model.rightSleeve.visible = true;
|
||||
|
||||
// === RESTORE WEARER LAYERS - Phase 19 ===
|
||||
boolean[] savedLayers = storedLayers.remove(player.getId());
|
||||
if (savedLayers != null) {
|
||||
ClothesRenderHelper.restoreWearerLayers(model, savedLayers);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package com.tiedup.remake.client.animation.render;
|
||||
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||
|
||||
/**
|
||||
* Centralizes magic numbers used across render handlers.
|
||||
*
|
||||
* <p>DOG pose rotation smoothing, head clamp limits, and vertical offsets
|
||||
* that were previously scattered as unnamed literals.
|
||||
*/
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
public final class RenderConstants {
|
||||
|
||||
private RenderConstants() {}
|
||||
|
||||
// === DOG pose rotation smoothing speeds ===
|
||||
|
||||
/** Speed for smoothing body rotation toward target while moving */
|
||||
public static final float DOG_ROT_SPEED_MOVING = 0.15f;
|
||||
|
||||
/** Speed for smoothing body rotation toward target while stationary */
|
||||
public static final float DOG_ROT_SPEED_STATIONARY = 0.12f;
|
||||
|
||||
/** Speed for smoothing target rotation while moving */
|
||||
public static final float DOG_TARGET_SPEED_MOVING = 0.2f;
|
||||
|
||||
/** Speed for smoothing target rotation while stationary */
|
||||
public static final float DOG_TARGET_SPEED_STATIONARY = 0.3f;
|
||||
|
||||
// === Head clamp limits ===
|
||||
|
||||
/** Maximum head yaw relative to body while moving (degrees) */
|
||||
public static final float HEAD_MAX_YAW_MOVING = 60f;
|
||||
|
||||
/** Maximum head yaw relative to body while stationary (degrees) */
|
||||
public static final float HEAD_MAX_YAW_STATIONARY = 90f;
|
||||
|
||||
/** Threshold ratio for detecting head-at-limit (triggers body snap) */
|
||||
public static final float HEAD_AT_LIMIT_RATIO = 0.85f;
|
||||
|
||||
/** Ratio of max yaw to snap body to when releasing head */
|
||||
public static final float HEAD_SNAP_RELEASE_RATIO = 0.7f;
|
||||
|
||||
// === Vertical offsets (model units, 16 = 1 block) ===
|
||||
|
||||
/** Y offset for DOG and PET BED poses (6/16 = 0.375 blocks) */
|
||||
public static final double DOG_AND_PETBED_Y_OFFSET = -6.0 / 16.0;
|
||||
|
||||
/** Y offset for Damsel sitting pose (model units) */
|
||||
public static final float DAMSEL_SIT_OFFSET = -10.0f;
|
||||
|
||||
/** Y offset for Damsel kneeling pose (model units) */
|
||||
public static final float DAMSEL_KNEEL_OFFSET = -5.0f;
|
||||
|
||||
/** Y offset for Damsel dog pose (model units) */
|
||||
public static final float DAMSEL_DOG_OFFSET = -7.0f;
|
||||
}
|
||||
Reference in New Issue
Block a user