Files
TiedUp-/src/main/java/com/tiedup/remake/util/KidnappedHelper.java
NotEvil f6466360b6 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.
2026-04-12 00:51:22 +02:00

176 lines
6.2 KiB
Java

package com.tiedup.remake.util;
import com.tiedup.remake.compat.mca.MCACompat;
import com.tiedup.remake.v2.BodyRegionV2;
import com.tiedup.remake.state.IRestrainable;
import com.tiedup.remake.state.PlayerBindState;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.player.Player;
import org.jetbrains.annotations.Nullable;
/**
* Phase 14.1: Helper utility for working with IRestrainable entities.
*
* Provides convenient methods for obtaining IRestrainable instances from various entity types.
*
* <h2>Purpose</h2>
* This helper abstracts the complexity of determining whether an entity can be kidnapped/restrained
* and provides a unified way to access the IRestrainable interface across different entity types.
*
* <h2>Supported Entity Types</h2>
* <ul>
* <li><b>Player</b>: Uses {@link PlayerBindState} singleton</li>
* <li><b>EntityDamsel</b> (Phase 14.2): Implements IRestrainable directly</li>
* <li><b>EntityKidnapper</b> (Phase 14.2): Implements IRestrainable directly</li>
* <li><b>Other entities</b>: Returns null (not kidnappable)</li>
* </ul>
*
* <h2>Usage Example</h2>
* <pre>{@code
* public InteractionResult interactLivingEntity(ItemStack stack, Player user,
* LivingEntity target, InteractionHand hand) {
* IRestrainable state = KidnappedHelper.getKidnappedState(target);
* if (state == null) {
* return InteractionResult.PASS; // Entity cannot be restrained
* }
*
* if (state.isTiedUp()) {
* user.sendSystemMessage(Component.literal("Already tied up!"));
* return InteractionResult.FAIL;
* }
*
* state.equip(BodyRegionV2.ARMS, stack.copy());
* return InteractionResult.SUCCESS;
* }
* }</pre>
*/
public class KidnappedHelper {
/**
* Get the IRestrainable instance for any living entity.
*
* <p>This method determines the appropriate IRestrainable implementation based on entity type:
* <ul>
* <li><b>Player</b>: Returns {@link PlayerBindState#getInstance(Player)}</li>
* <li><b>IRestrainable implementer</b> (NPCs): Returns the entity itself (cast to IRestrainable)</li>
* <li><b>Other entities</b>: Returns null (entity cannot be kidnapped)</li>
* </ul>
*
* @param entity The living entity to check
* @return The IRestrainable instance, or null if entity cannot be kidnapped
*/
@Nullable
public static IRestrainable getKidnappedState(LivingEntity entity) {
if (entity == null) {
return null;
}
// For Players: Use PlayerBindState singleton
if (entity instanceof Player player) {
return PlayerBindState.getInstance(player);
}
// For NPCs that implement IRestrainable (EntityDamsel, EntityKidnapper, etc.)
if (entity instanceof IRestrainable kidnapped) {
return kidnapped;
}
// MCA Compatibility: Check if entity is an MCA villager
if (MCACompat.isMCALoaded() && MCACompat.isMCAVillager(entity)) {
IRestrainable mcaState = MCACompat.getKidnappedState(entity);
com.tiedup.remake.core.TiedUpMod.LOGGER.debug(
"[KidnappedHelper] MCA villager {} -> state: {}",
entity.getName().getString(),
mcaState != null ? mcaState.getClass().getSimpleName() : "null"
);
return mcaState;
}
// Entity cannot be kidnapped
return null;
}
/**
* Check if an entity can be kidnapped/restrained.
*
* @param entity The living entity to check
* @return true if the entity implements IRestrainable or is a Player
*/
public static boolean canBeKidnapped(LivingEntity entity) {
return getKidnappedState(entity) != null;
}
/**
* Check if an entity is currently tied up.
*
* <p>Convenience method that combines {@link #getKidnappedState(LivingEntity)}
* and {@link IRestrainable#isTiedUp()}.
*
* @param entity The living entity to check
* @return true if the entity is tied up, false otherwise
*/
public static boolean isTiedUp(LivingEntity entity) {
IRestrainable state = getKidnappedState(entity);
return state != null && state.isTiedUp();
}
/**
* Check if an entity is currently gagged.
*
* <p>Convenience method that combines {@link #getKidnappedState(LivingEntity)}
* and {@link IRestrainable#isGagged()}.
*
* @param entity The living entity to check
* @return true if the entity is gagged, false otherwise
*/
public static boolean isGagged(LivingEntity entity) {
IRestrainable state = getKidnappedState(entity);
return state != null && state.isGagged();
}
/**
* Check if an entity is currently blindfolded.
*
* <p>Convenience method that combines {@link #getKidnappedState(LivingEntity)}
* and {@link IRestrainable#isBlindfolded()}.
*
* @param entity The living entity to check
* @return true if the entity is blindfolded, false otherwise
*/
public static boolean isBlindfolded(LivingEntity entity) {
IRestrainable state = getKidnappedState(entity);
return state != null && state.isBlindfolded();
}
/**
* Check if an entity has a collar.
*
* <p>Convenience method that combines {@link #getKidnappedState(LivingEntity)}
* and {@link IRestrainable#hasCollar()}.
*
* @param entity The living entity to check
* @return true if the entity has a collar, false otherwise
*/
public static boolean hasCollar(LivingEntity entity) {
IRestrainable state = getKidnappedState(entity);
return state != null && state.hasCollar();
}
/**
* Check if an entity is enslaved.
*
* <p>Convenience method that combines {@link #getKidnappedState(LivingEntity)}
* and {@link IRestrainable#isSlave()}.
*
* @param entity The living entity to check
* @return true if the entity is enslaved, false otherwise
*/
/**
* Phase 17: Renamed from isSlave to isCaptive
*/
public static boolean isCaptive(LivingEntity entity) {
IRestrainable state = getKidnappedState(entity);
return state != null && state.isCaptive();
}
}