package com.tiedup.remake.util; import com.tiedup.remake.core.TiedUpMod; import com.tiedup.remake.items.base.IHasResistance; import com.tiedup.remake.state.IBondageState; import com.tiedup.remake.v2.bondage.CollarHelper; import com.tiedup.remake.v2.BodyRegionV2; import java.util.UUID; import net.minecraft.ChatFormatting; import net.minecraft.network.chat.Component; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.item.ItemStack; import org.jetbrains.annotations.Nullable; /** * Utility class for applying restraints to entities. * * * This class provides methods for applying various restraints (binds, gags, * blindfolds, etc.) to targets with consistent validation. Used by: * - KidnapperCaptureGoal * - KidnapperPunishGoal * - EntityRopeArrow * - Other capture/restraint mechanics */ public final class RestraintApplicator { private RestraintApplicator() { // Utility class - no instantiation } // ==================== BIND ==================== /** * Apply a bind or tighten existing binds. * * @param target The target entity * @param bind The bind item to apply if needed * @return true if bind was applied or tightened */ public static boolean applyOrTightenBind( LivingEntity target, ItemStack bind ) { IBondageState state = KidnappedHelper.getKidnappedState(target); if (state == null) { return false; } ItemStack currentBind = state.getEquipment(BodyRegionV2.ARMS); if (currentBind.isEmpty()) { // No bind - apply new one if (bind != null && !bind.isEmpty()) { state.equip(BodyRegionV2.ARMS, bind.copy()); return true; } return false; } // Tighten existing bind - reset resistance to max if (currentBind.getItem() instanceof IHasResistance bindItem) { int maxResistance = bindItem.getBaseResistance(target); state.setCurrentBindResistance(maxResistance); return true; } return false; } /** * Tighten an entity's binds, resetting resistance to max. * This happens when a guard catches someone struggling. * *
Consolidated from EntityKidnapper, EntityMaid, EntitySlaveTrader, KidnapperPunishGoal.
* * @param state The prisoner's kidnapped state * @param prisoner The prisoner entity * @return true if binds were tightened, false if no binds equipped */ public static boolean tightenBind( IBondageState state, LivingEntity prisoner ) { if (state == null) return false; ItemStack bind = state.getEquipment(BodyRegionV2.ARMS); if (bind.isEmpty()) { return false; } if (bind.getItem() instanceof IHasResistance resistItem) { int baseResistance = resistItem.getBaseResistance(prisoner); resistItem.setCurrentResistance(bind, baseResistance); // Notify the prisoner if (prisoner instanceof ServerPlayer serverPlayer) { serverPlayer.sendSystemMessage( Component.literal( "Your restraints have been tightened!" ).withStyle(ChatFormatting.RED) ); } TiedUpMod.LOGGER.debug( "[RestraintApplicator] Tightened {}'s binds (resistance reset to {})", prisoner.getName().getString(), baseResistance ); return true; } return false; } // ==================== GAG ==================== /** * Apply a gag to the target. * * @param target The target entity * @param gag The gag item to apply * @return true if successfully applied, false if already gagged or invalid */ public static boolean applyGag(LivingEntity target, ItemStack gag) { IBondageState state = KidnappedHelper.getKidnappedState(target); if (state == null || gag == null || gag.isEmpty()) { return false; } if (state.isGagged()) { return false; // Already gagged } state.equip(BodyRegionV2.MOUTH, gag.copy()); return true; } /** * Apply a gag only if the target doesn't have one. * * @param target The target entity * @param gag The gag item to apply * @return true if gag was applied */ public static boolean applyGagIfMissing( LivingEntity target, ItemStack gag ) { IBondageState state = KidnappedHelper.getKidnappedState(target); if (state == null || gag == null || gag.isEmpty()) { return false; } ItemStack currentGag = state.getEquipment(BodyRegionV2.MOUTH); if (!currentGag.isEmpty()) { return false; // Already has gag } state.equip(BodyRegionV2.MOUTH, gag.copy()); return true; } // ==================== BLINDFOLD ==================== /** * Apply a blindfold to the target. * * @param target The target entity * @param blindfold The blindfold item to apply * @return true if successfully applied, false if already blindfolded or invalid */ public static boolean applyBlindfold( LivingEntity target, ItemStack blindfold ) { IBondageState state = KidnappedHelper.getKidnappedState(target); if (state == null || blindfold == null || blindfold.isEmpty()) { return false; } if (state.isBlindfolded()) { return false; // Already blindfolded } state.equip(BodyRegionV2.EYES, blindfold.copy()); return true; } /** * Apply a blindfold only if the target doesn't have one. * * @param target The target entity * @param blindfold The blindfold item to apply * @return true if blindfold was applied */ public static boolean applyBlindfoldIfMissing( LivingEntity target, ItemStack blindfold ) { IBondageState state = KidnappedHelper.getKidnappedState(target); if (state == null || blindfold == null || blindfold.isEmpty()) { return false; } ItemStack currentBlindfold = state.getEquipment(BodyRegionV2.EYES); if (!currentBlindfold.isEmpty()) { return false; // Already has blindfold } state.equip(BodyRegionV2.EYES, blindfold.copy()); return true; } // ==================== MITTENS ==================== /** * Apply mittens to the target. * * @param target The target entity * @param mittens The mittens item to apply * @return true if successfully applied, false if already has mittens or invalid */ public static boolean applyMittens(LivingEntity target, ItemStack mittens) { IBondageState state = KidnappedHelper.getKidnappedState(target); if (state == null || mittens == null || mittens.isEmpty()) { return false; } if (state.hasMittens()) { return false; // Already has mittens } state.equip(BodyRegionV2.HANDS, mittens.copy()); return true; } // ==================== EARPLUGS ==================== /** * Apply earplugs to the target. * * @param target The target entity * @param earplugs The earplugs item to apply * @return true if successfully applied, false if already has earplugs or invalid */ public static boolean applyEarplugs( LivingEntity target, ItemStack earplugs ) { IBondageState state = KidnappedHelper.getKidnappedState(target); if (state == null || earplugs == null || earplugs.isEmpty()) { return false; } if (state.hasEarplugs()) { return false; // Already has earplugs } state.equip(BodyRegionV2.EARS, earplugs.copy()); return true; } // ==================== COLLAR ==================== /** * Apply a collar to the target with owner information. * * @param target The target entity * @param collar The collar item to apply * @param ownerUUID The owner's UUID (can be null) * @param ownerName The owner's name (can be null) * @return true if successfully applied, false if already has collar or invalid */ public static boolean applyCollar( LivingEntity target, ItemStack collar, @Nullable UUID ownerUUID, @Nullable String ownerName ) { IBondageState state = KidnappedHelper.getKidnappedState(target); if (state == null || collar == null || collar.isEmpty()) { return false; } if (state.hasCollar()) { return false; // Already has collar } ItemStack collarCopy = collar.copy(); // Add owner if provided if (ownerUUID != null && CollarHelper.isCollar(collarCopy)) { CollarHelper.addOwner( collarCopy, ownerUUID, ownerName != null ? ownerName : "Unknown" ); } state.equip(BodyRegionV2.NECK, collarCopy); return true; } /** * Apply a collar without owner information. * * @param target The target entity * @param collar The collar item to apply * @return true if successfully applied */ public static boolean applyCollar(LivingEntity target, ItemStack collar) { return applyCollar(target, collar, null, null); } // ==================== BULK OPERATIONS ==================== /** * Check if target has any restraints. * * @param target The target entity * @return true if target has any restraints */ public static boolean hasAnyRestraint(LivingEntity target) { IBondageState state = KidnappedHelper.getKidnappedState(target); if (state == null) { return false; } return ( state.isTiedUp() || state.isGagged() || state.isBlindfolded() || state.hasMittens() || state.hasEarplugs() || state.hasCollar() ); } /** * Get the kidnapped state for an entity. * * @param target The target entity * @return The IBondageState state, or null if not available */ @Nullable public static IBondageState getState(LivingEntity target) { return KidnappedHelper.getKidnappedState(target); } }