Strip all Phase references, TODO/FUTURE roadmap notes, and internal planning comments from the codebase. Run Prettier for consistent formatting across all Java files.
245 lines
8.2 KiB
Java
245 lines
8.2 KiB
Java
package com.tiedup.remake.items;
|
|
|
|
import com.tiedup.remake.core.SystemMessageManager;
|
|
import com.tiedup.remake.core.TiedUpMod;
|
|
import com.tiedup.remake.items.base.ILockable;
|
|
import com.tiedup.remake.state.IBondageState;
|
|
import com.tiedup.remake.util.KidnappedHelper;
|
|
import com.tiedup.remake.util.TiedUpSounds;
|
|
import com.tiedup.remake.v2.BodyRegionV2;
|
|
import java.util.UUID;
|
|
import net.minecraft.network.chat.Component;
|
|
import net.minecraft.world.InteractionHand;
|
|
import net.minecraft.world.InteractionResult;
|
|
import net.minecraft.world.entity.LivingEntity;
|
|
import net.minecraft.world.entity.player.Player;
|
|
import net.minecraft.world.item.Item;
|
|
import net.minecraft.world.item.ItemStack;
|
|
import net.minecraftforge.api.distmarker.Dist;
|
|
import net.minecraftforge.api.distmarker.OnlyIn;
|
|
|
|
/**
|
|
* Master Key - Universal key that opens any padlock.
|
|
*
|
|
*
|
|
* Behavior:
|
|
* - Right-click: Opens Slave Management GUI (can unlock any lock)
|
|
* - Shift+Right-click: Quick unlock all restraints on target
|
|
* - Does not consume the key (reusable)
|
|
* - Cannot lock items (unlock only)
|
|
*/
|
|
public class ItemMasterKey extends Item {
|
|
|
|
public ItemMasterKey() {
|
|
super(new Item.Properties().stacksTo(8));
|
|
}
|
|
|
|
/**
|
|
* Called when player right-clicks another entity with the master key.
|
|
* Opens the Slave Item Management GUI or quick-unlocks all if sneaking.
|
|
*
|
|
* @param stack The item stack
|
|
* @param player The player using the key
|
|
* @param target The entity being interacted with
|
|
* @param hand The hand holding the key
|
|
* @return SUCCESS if action taken, PASS otherwise
|
|
*/
|
|
@Override
|
|
public InteractionResult interactLivingEntity(
|
|
ItemStack stack,
|
|
Player player,
|
|
LivingEntity target,
|
|
InteractionHand hand
|
|
) {
|
|
// Check if target can be restrained
|
|
IBondageState targetState = KidnappedHelper.getKidnappedState(target);
|
|
if (targetState == null) {
|
|
return InteractionResult.PASS;
|
|
}
|
|
|
|
// Target must have a collar
|
|
if (!targetState.hasCollar()) {
|
|
if (!player.level().isClientSide) {
|
|
SystemMessageManager.sendToPlayer(
|
|
player,
|
|
SystemMessageManager.MessageCategory.ERROR,
|
|
"Target is not wearing a collar!"
|
|
);
|
|
}
|
|
return InteractionResult.FAIL;
|
|
}
|
|
|
|
// Server-side: Handle Shift+click quick unlock
|
|
if (!player.level().isClientSide) {
|
|
if (player.isShiftKeyDown()) {
|
|
// Quick unlock all - original behavior
|
|
int unlocked = unlockAllRestraints(targetState, target);
|
|
|
|
if (unlocked > 0) {
|
|
TiedUpSounds.playUnlockSound(target);
|
|
SystemMessageManager.sendToPlayer(
|
|
player,
|
|
SystemMessageManager.MessageCategory.INFO,
|
|
"Unlocked " +
|
|
unlocked +
|
|
" restraint(s) on " +
|
|
target.getName().getString()
|
|
);
|
|
TiedUpMod.LOGGER.info(
|
|
"[ItemMasterKey] {} quick-unlocked {} restraints on {}",
|
|
player.getName().getString(),
|
|
unlocked,
|
|
target.getName().getString()
|
|
);
|
|
} else {
|
|
SystemMessageManager.sendToPlayer(
|
|
player,
|
|
SystemMessageManager.MessageCategory.INFO,
|
|
"No locked restraints found"
|
|
);
|
|
}
|
|
return InteractionResult.SUCCESS;
|
|
}
|
|
// Normal click - validation only, client opens GUI
|
|
return InteractionResult.SUCCESS;
|
|
}
|
|
|
|
// Client-side: Open GUI (normal click only)
|
|
if (!player.isShiftKeyDown()) {
|
|
openUnifiedBondageScreen(target);
|
|
}
|
|
|
|
return InteractionResult.SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* Opens the UnifiedBondageScreen in master mode targeting a specific entity.
|
|
*
|
|
* @param target The living entity to manage bondage for
|
|
*/
|
|
@OnlyIn(Dist.CLIENT)
|
|
private void openUnifiedBondageScreen(
|
|
net.minecraft.world.entity.LivingEntity target
|
|
) {
|
|
net.minecraft.client.Minecraft.getInstance().setScreen(
|
|
new com.tiedup.remake.client.gui.screens.UnifiedBondageScreen(
|
|
target
|
|
)
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Unlock all locked restraints on the target.
|
|
* Uses setLockedByKeyUUID(null) to properly clear the lock.
|
|
* Optionally drops padlocks if the item's dropLockOnUnlock() returns true.
|
|
*
|
|
* @param targetState The target's IBondageState state
|
|
* @param target The target entity (for dropping items)
|
|
* @return Number of items unlocked
|
|
*/
|
|
private int unlockAllRestraints(
|
|
IBondageState targetState,
|
|
LivingEntity target
|
|
) {
|
|
int unlocked = 0;
|
|
|
|
// Unlock bind
|
|
ItemStack bind = targetState.getEquipment(BodyRegionV2.ARMS);
|
|
if (!bind.isEmpty() && bind.getItem() instanceof ILockable lockable) {
|
|
if (lockable.isLocked(bind)) {
|
|
lockable.setLockedByKeyUUID(bind, null); // Clear lock with keyUUID system
|
|
unlocked++;
|
|
if (lockable.dropLockOnUnlock()) {
|
|
dropPadlock(targetState);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Unlock gag
|
|
ItemStack gag = targetState.getEquipment(BodyRegionV2.MOUTH);
|
|
if (!gag.isEmpty() && gag.getItem() instanceof ILockable lockable) {
|
|
if (lockable.isLocked(gag)) {
|
|
lockable.setLockedByKeyUUID(gag, null);
|
|
unlocked++;
|
|
if (lockable.dropLockOnUnlock()) {
|
|
dropPadlock(targetState);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Unlock blindfold
|
|
ItemStack blindfold = targetState.getEquipment(BodyRegionV2.EYES);
|
|
if (
|
|
!blindfold.isEmpty() &&
|
|
blindfold.getItem() instanceof ILockable lockable
|
|
) {
|
|
if (lockable.isLocked(blindfold)) {
|
|
lockable.setLockedByKeyUUID(blindfold, null);
|
|
unlocked++;
|
|
if (lockable.dropLockOnUnlock()) {
|
|
dropPadlock(targetState);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Unlock earplugs
|
|
ItemStack earplugs = targetState.getEquipment(BodyRegionV2.EARS);
|
|
if (
|
|
!earplugs.isEmpty() &&
|
|
earplugs.getItem() instanceof ILockable lockable
|
|
) {
|
|
if (lockable.isLocked(earplugs)) {
|
|
lockable.setLockedByKeyUUID(earplugs, null);
|
|
unlocked++;
|
|
if (lockable.dropLockOnUnlock()) {
|
|
dropPadlock(targetState);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Unlock collar
|
|
ItemStack collar = targetState.getEquipment(BodyRegionV2.NECK);
|
|
if (
|
|
!collar.isEmpty() && collar.getItem() instanceof ILockable lockable
|
|
) {
|
|
if (lockable.isLocked(collar)) {
|
|
lockable.setLockedByKeyUUID(collar, null);
|
|
unlocked++;
|
|
if (lockable.dropLockOnUnlock()) {
|
|
dropPadlock(targetState);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Unlock mittens
|
|
ItemStack mittens = targetState.getEquipment(BodyRegionV2.HANDS);
|
|
if (
|
|
!mittens.isEmpty() &&
|
|
mittens.getItem() instanceof ILockable lockable
|
|
) {
|
|
if (lockable.isLocked(mittens)) {
|
|
lockable.setLockedByKeyUUID(mittens, null);
|
|
unlocked++;
|
|
if (lockable.dropLockOnUnlock()) {
|
|
dropPadlock(targetState);
|
|
}
|
|
}
|
|
}
|
|
|
|
return unlocked;
|
|
}
|
|
|
|
/**
|
|
* Drop a padlock item near the target.
|
|
*
|
|
* @param targetState The target's IBondageState state
|
|
*/
|
|
private void dropPadlock(IBondageState targetState) {
|
|
// Create a padlock item to drop
|
|
ItemStack padlock = new ItemStack(
|
|
com.tiedup.remake.items.ModItems.PADLOCK.get()
|
|
);
|
|
targetState.kidnappedDropItem(padlock);
|
|
}
|
|
}
|