Phase 1 (state): PlayerBindState, PlayerCaptorManager, PlayerEquipment, PlayerDataRetrieval, PlayerLifecycle, PlayerShockCollar, StruggleAccessory Phase 2 (client): AnimationTickHandler, NpcAnimationTickHandler, 5 render handlers, DamselModel, 3 client mixins, SelfBondageInputHandler, SlaveManagementScreen, ActionPanel, SlaveEntryWidget, ModKeybindings Phase 3 (entities): 28 entity/AI files migrated to CollarHelper, BindModeHelper, PoseTypeHelper, createStack() Phase 4 (network): PacketSlaveAction, PacketMasterEquip, PacketAssignCellToCollar, PacketNpcCommand, PacketFurnitureForcemount Phase 5 (events): RestraintTaskTickHandler, PetPlayRestrictionHandler, PlayerEnslavementHandler, ChatEventHandler, LaborAttackPunishmentHandler Phase 6 (commands): BondageSubCommand, CollarCommand, NPCCommand, KidnapSetCommand Phase 7 (compat): MCAKidnappedAdapter, MCA mixins Phase 8 (misc): GagTalkManager, PetRequestManager, HangingCagePiece, BondageItemBlockEntity, TrappedChestBlockEntity, DispenserBehaviors, BondageItemLoaderUtility, RestraintApplicator, StruggleSessionManager, MovementStyleResolver, CampLifecycleManager Some files retain dual V1/V2 checks (instanceof V1 || V2Helper) for coexistence — V1-only branches removed in Branch D.
85 lines
2.7 KiB
Java
85 lines
2.7 KiB
Java
package com.tiedup.remake.mixin;
|
|
|
|
import com.tiedup.remake.compat.mca.MCACompat;
|
|
import com.tiedup.remake.v2.bondage.CollarHelper;
|
|
import com.tiedup.remake.state.IBondageState;
|
|
import com.tiedup.remake.v2.BodyRegionV2;
|
|
import net.minecraft.world.entity.LivingEntity;
|
|
import net.minecraft.world.entity.Mob;
|
|
import net.minecraft.world.entity.player.Player;
|
|
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.CallbackInfoReturnable;
|
|
|
|
/**
|
|
* Mixin to allow vanilla leash attachment to MCA villagers when tied or collar owner.
|
|
*
|
|
* <p>By default, MCA villagers cannot be leashed. This mixin overrides
|
|
* the canBeLeashed check to allow leashing when:
|
|
* <ul>
|
|
* <li>The villager is tied up (any bind), OR</li>
|
|
* <li>The player is a collar owner</li>
|
|
* </ul>
|
|
*
|
|
* <p>Uses @Pseudo annotation - mixin is optional and will be skipped if MCA is not installed.
|
|
*/
|
|
@Pseudo
|
|
@Mixin(targets = "forge.net.mca.entity.VillagerEntityMCA", remap = false)
|
|
public class MixinMCAVillagerLeash {
|
|
|
|
/**
|
|
* Override canBeLeashed to allow TiedUp leash mechanics.
|
|
*
|
|
* <p>The canBeLeashed method is a vanilla method (remapped), so we use remap = true.
|
|
*
|
|
* @param player The player trying to leash
|
|
* @param cir Callback info for returning the result
|
|
*/
|
|
@Inject(
|
|
method = "canBeLeashed",
|
|
at = @At("HEAD"),
|
|
cancellable = true,
|
|
remap = true
|
|
)
|
|
private void tiedup$overrideCanBeLeashed(
|
|
Player player,
|
|
CallbackInfoReturnable<Boolean> cir
|
|
) {
|
|
LivingEntity entity = (LivingEntity) (Object) this;
|
|
IBondageState state = MCACompat.getKidnappedState(entity);
|
|
|
|
// No TiedUp state - let vanilla/MCA handle it
|
|
if (state == null) {
|
|
return;
|
|
}
|
|
|
|
// Already leashed - cannot leash again
|
|
if (entity instanceof Mob mob && mob.isLeashed()) {
|
|
cir.setReturnValue(false);
|
|
return;
|
|
}
|
|
|
|
// Can be leashed if tied up
|
|
if (state.isTiedUp()) {
|
|
cir.setReturnValue(true);
|
|
return;
|
|
}
|
|
|
|
// Can be leashed if player is collar owner
|
|
if (state.hasCollar()) {
|
|
ItemStack collar = state.getEquipment(BodyRegionV2.NECK);
|
|
if (CollarHelper.isCollar(collar)) {
|
|
if (CollarHelper.isOwner(collar, player)) {
|
|
cir.setReturnValue(true);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Default: let MCA handle it (usually returns false)
|
|
}
|
|
}
|