package com.tiedup.remake.dispenser; import com.tiedup.remake.state.IBondageState; import com.tiedup.remake.v2.BodyRegionV2; import com.tiedup.remake.v2.bondage.BindModeHelper; import com.tiedup.remake.v2.bondage.CollarHelper; import com.tiedup.remake.v2.bondage.component.ComponentType; import com.tiedup.remake.v2.bondage.component.GaggingComponent; import com.tiedup.remake.v2.bondage.datadriven.DataDrivenBondageItem; import com.tiedup.remake.v2.bondage.datadriven.DataDrivenItemDefinition; import com.tiedup.remake.v2.bondage.datadriven.DataDrivenItemRegistry; import java.util.function.BiConsumer; import java.util.function.Predicate; import net.minecraft.world.item.ItemStack; /** * Generic dispenser behavior for equipping bondage items. * Uses V2 data-driven item detection instead of V1 class checks. * * Use factory methods to create instances for each bondage type. */ public class GenericBondageDispenseBehavior extends EquipBondageDispenseBehavior { private final Predicate itemCheck; private final Predicate canEquipCheck; private final BiConsumer equipAction; private GenericBondageDispenseBehavior( Predicate itemCheck, Predicate canEquipCheck, BiConsumer equipAction ) { this.itemCheck = itemCheck; this.canEquipCheck = canEquipCheck; this.equipAction = equipAction; } @Override protected boolean isValidItem(ItemStack stack) { return !stack.isEmpty() && itemCheck.test(stack); } @Override protected boolean canEquip(IBondageState state) { return state != null && canEquipCheck.test(state); } @Override protected void equip(IBondageState state, ItemStack stack) { if (state != null) { equipAction.accept(state, stack); } } // Factory Methods public static GenericBondageDispenseBehavior forBind() { return new GenericBondageDispenseBehavior( BindModeHelper::isBindItem, state -> !state.isTiedUp(), (s, i) -> s.equip(BodyRegionV2.ARMS, i) ); } public static GenericBondageDispenseBehavior forGag() { return new GenericBondageDispenseBehavior( stack -> DataDrivenBondageItem.getComponent(stack, ComponentType.GAGGING, GaggingComponent.class) != null, state -> !state.isGagged(), (s, i) -> s.equip(BodyRegionV2.MOUTH, i) ); } public static GenericBondageDispenseBehavior forBlindfold() { return new GenericBondageDispenseBehavior( stack -> { DataDrivenItemDefinition def = DataDrivenItemRegistry.get(stack); return def != null && def.occupiedRegions().contains(BodyRegionV2.EYES); }, state -> !state.isBlindfolded(), (s, i) -> s.equip(BodyRegionV2.EYES, i) ); } public static GenericBondageDispenseBehavior forCollar() { return new GenericBondageDispenseBehavior( CollarHelper::isCollar, state -> !state.hasCollar(), (s, i) -> s.equip(BodyRegionV2.NECK, i) ); } public static GenericBondageDispenseBehavior forEarplugs() { return new GenericBondageDispenseBehavior( stack -> { DataDrivenItemDefinition def = DataDrivenItemRegistry.get(stack); return def != null && def.occupiedRegions().contains(BodyRegionV2.EARS); }, state -> !state.hasEarplugs(), (s, i) -> s.equip(BodyRegionV2.EARS, i) ); } }