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.mixin.client;
|
||||
|
||||
import com.tiedup.remake.client.animation.BondageAnimationManager;
|
||||
import com.tiedup.remake.client.animation.StaticPoseApplier;
|
||||
import com.tiedup.remake.client.animation.util.AnimationIdBuilder;
|
||||
import com.tiedup.remake.compat.mca.MCACompat;
|
||||
import com.tiedup.remake.items.base.ItemBind;
|
||||
import com.tiedup.remake.items.base.PoseType;
|
||||
import com.tiedup.remake.v2.BodyRegionV2;
|
||||
import com.tiedup.remake.v2.bondage.capability.V2EquipmentHelper;
|
||||
import com.tiedup.remake.state.IBondageState;
|
||||
import dev.kosmx.playerAnim.impl.IAnimatedPlayer;
|
||||
import dev.kosmx.playerAnim.impl.animation.AnimationApplier;
|
||||
import java.util.UUID;
|
||||
import net.minecraft.client.model.HumanoidModel;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Pseudo;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
/**
|
||||
* Mixin for MCA's VillagerEntityBaseModelMCA to apply tied poses.
|
||||
*
|
||||
* <p>This mixin injects at the end of setupAnim (m_6973_) to override MCA's default
|
||||
* animations when a villager is tied up. Without this, the bondage render layer
|
||||
* shows the tied pose but the underlying MCA model still shows normal walking/idle
|
||||
* animations.
|
||||
*
|
||||
* <p>Uses @Pseudo annotation - mixin is optional and will be skipped if MCA is not installed.
|
||||
*
|
||||
* <p>Target class: net.mca.client.model.VillagerEntityBaseModelMCA
|
||||
* <p>Target method: setupAnim (MCP name, remapped from Yarn by Architectury)
|
||||
*/
|
||||
@Pseudo
|
||||
@Mixin(
|
||||
targets = "forge.net.mca.client.model.VillagerEntityBaseModelMCA",
|
||||
remap = false
|
||||
)
|
||||
public class MixinVillagerEntityBaseModelMCA<T extends LivingEntity> {
|
||||
|
||||
// Note: Tick tracking moved to MCAAnimationTickCache for cleanup on world unload
|
||||
|
||||
/**
|
||||
* Inject at the end of setupAnim to apply tied pose after MCA has set its animations.
|
||||
*
|
||||
* <p>This completely overrides arm/leg positions when the villager is tied up.
|
||||
*
|
||||
* <p>Method signature: void setupAnim(T entity, float limbSwing, float limbSwingAmount, float ageInTicks, float netHeadYaw, float headPitch)
|
||||
* <p>Note: MCA uses Architectury which remaps Yarn's method names to Forge/MCP names
|
||||
*/
|
||||
@Inject(method = "m_6973_", at = @At("TAIL"), remap = false)
|
||||
private void tiedup$applyTiedPose(
|
||||
T villager,
|
||||
float limbSwing,
|
||||
float limbSwingAmount,
|
||||
float ageInTicks,
|
||||
float netHeadYaw,
|
||||
float headPitch,
|
||||
CallbackInfo ci
|
||||
) {
|
||||
// Only process on client side
|
||||
if (villager.level() == null || !villager.level().isClientSide()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if MCA is loaded and this villager is tied
|
||||
if (!MCACompat.isMCALoaded()) {
|
||||
return;
|
||||
}
|
||||
|
||||
IBondageState state = MCACompat.getKidnappedState(villager);
|
||||
if (state == null || !state.isTiedUp()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Get pose info from bind item
|
||||
ItemStack bind = state.getEquipment(BodyRegionV2.ARMS);
|
||||
PoseType poseType = PoseType.STANDARD;
|
||||
|
||||
if (bind.getItem() instanceof ItemBind itemBind) {
|
||||
poseType = itemBind.getPoseType();
|
||||
}
|
||||
|
||||
// Derive bound state from V2 regions, fallback to V1 bind mode NBT
|
||||
boolean armsBound = V2EquipmentHelper.isRegionOccupied(villager, BodyRegionV2.ARMS);
|
||||
boolean legsBound = V2EquipmentHelper.isRegionOccupied(villager, BodyRegionV2.LEGS);
|
||||
|
||||
if (!armsBound && !legsBound && bind.getItem() instanceof ItemBind) {
|
||||
armsBound = ItemBind.hasArmsBound(bind);
|
||||
legsBound = ItemBind.hasLegsBound(bind);
|
||||
}
|
||||
|
||||
// MCA doesn't track struggling state - use false for now
|
||||
// TODO: Add struggling support to MCA integration
|
||||
boolean isStruggling = false;
|
||||
|
||||
// Cast this mixin to HumanoidModel to apply pose
|
||||
// MCA's VillagerEntityBaseModelMCA extends HumanoidModel
|
||||
@SuppressWarnings("unchecked")
|
||||
HumanoidModel<?> model = (HumanoidModel<?>) (Object) this;
|
||||
|
||||
// Check if villager supports PlayerAnimator (via our mixin)
|
||||
if (villager instanceof IAnimatedPlayer animated) {
|
||||
// Build animation ID and play animation
|
||||
String animId = AnimationIdBuilder.build(
|
||||
poseType,
|
||||
armsBound,
|
||||
legsBound,
|
||||
null,
|
||||
isStruggling,
|
||||
true
|
||||
);
|
||||
BondageAnimationManager.playAnimation(villager, animId);
|
||||
|
||||
// Tick the animation stack only once per game tick (not every render frame)
|
||||
// ageInTicks increments by 1 each game tick, with fractional values between ticks
|
||||
int currentTick = (int) ageInTicks;
|
||||
UUID entityId = villager.getUUID();
|
||||
int lastTick =
|
||||
com.tiedup.remake.client.animation.tick.MCAAnimationTickCache.getLastTick(
|
||||
entityId
|
||||
);
|
||||
|
||||
if (lastTick != currentTick) {
|
||||
// New game tick - tick the animation
|
||||
animated.getAnimationStack().tick();
|
||||
com.tiedup.remake.client.animation.tick.MCAAnimationTickCache.setLastTick(
|
||||
entityId,
|
||||
currentTick
|
||||
);
|
||||
}
|
||||
|
||||
// Apply animation transforms to model parts
|
||||
AnimationApplier emote = animated.playerAnimator_getAnimation();
|
||||
if (emote != null && emote.isActive()) {
|
||||
// Use correct PlayerAnimator part names (torso, not body)
|
||||
emote.updatePart("head", model.head);
|
||||
emote.updatePart("torso", model.body);
|
||||
emote.updatePart("leftArm", model.leftArm);
|
||||
emote.updatePart("rightArm", model.rightArm);
|
||||
emote.updatePart("leftLeg", model.leftLeg);
|
||||
emote.updatePart("rightLeg", model.rightLeg);
|
||||
|
||||
// Force rotations using setRotation to ensure they're applied
|
||||
model.rightArm.setRotation(
|
||||
model.rightArm.xRot,
|
||||
model.rightArm.yRot,
|
||||
model.rightArm.zRot
|
||||
);
|
||||
model.leftArm.setRotation(
|
||||
model.leftArm.xRot,
|
||||
model.leftArm.yRot,
|
||||
model.leftArm.zRot
|
||||
);
|
||||
model.rightLeg.setRotation(
|
||||
model.rightLeg.xRot,
|
||||
model.rightLeg.yRot,
|
||||
model.rightLeg.zRot
|
||||
);
|
||||
model.leftLeg.setRotation(
|
||||
model.leftLeg.xRot,
|
||||
model.leftLeg.yRot,
|
||||
model.leftLeg.zRot
|
||||
);
|
||||
model.body.setRotation(
|
||||
model.body.xRot,
|
||||
model.body.yRot,
|
||||
model.body.zRot
|
||||
);
|
||||
model.head.setRotation(
|
||||
model.head.xRot,
|
||||
model.head.yRot,
|
||||
model.head.zRot
|
||||
);
|
||||
} else {
|
||||
// Fallback to static poses if animation not active
|
||||
StaticPoseApplier.applyStaticPose(
|
||||
model,
|
||||
poseType,
|
||||
armsBound,
|
||||
legsBound
|
||||
);
|
||||
}
|
||||
} else {
|
||||
// Fallback: entity doesn't support PlayerAnimator, use static poses
|
||||
StaticPoseApplier.applyStaticPose(model, poseType, armsBound, legsBound);
|
||||
}
|
||||
|
||||
// Hide arms for WRAP/LATEX_SACK poses (like DamselModel does)
|
||||
if (poseType == PoseType.WRAP || poseType == PoseType.LATEX_SACK) {
|
||||
model.leftArm.visible = false;
|
||||
model.rightArm.visible = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user