feature/d01-branch-c-migration #8

Merged
NotEvil merged 3 commits from feature/d01-branch-c-migration into develop 2026-04-14 22:57:06 +00:00
78 changed files with 729 additions and 763 deletions

View File

@@ -6,6 +6,14 @@ import com.tiedup.remake.items.base.ItemCollar;
import com.tiedup.remake.items.base.ItemEarplugs; import com.tiedup.remake.items.base.ItemEarplugs;
import com.tiedup.remake.items.base.ItemGag; import com.tiedup.remake.items.base.ItemGag;
import com.tiedup.remake.items.clothes.GenericClothes; import com.tiedup.remake.items.clothes.GenericClothes;
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 javax.annotation.Nullable; import javax.annotation.Nullable;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
@@ -191,55 +199,45 @@ public abstract class BondageItemBlockEntity
@Override @Override
public void readBondageData(CompoundTag tag) { public void readBondageData(CompoundTag tag) {
// Read bind with type validation // Read bind with type validation (V1 ItemBind or V2 ARMS-region item)
if (tag.contains("bind")) { if (tag.contains("bind")) {
ItemStack bindStack = ItemStack.of(tag.getCompound("bind")); ItemStack bindStack = ItemStack.of(tag.getCompound("bind"));
if ( if (!bindStack.isEmpty() && (bindStack.getItem() instanceof ItemBind || BindModeHelper.isBindItem(bindStack))) {
!bindStack.isEmpty() && bindStack.getItem() instanceof ItemBind
) {
this.bind = bindStack; this.bind = bindStack;
} }
} }
// Read gag with type validation // Read gag with type validation (V1 ItemGag or V2 GAGGING component)
if (tag.contains("gag")) { if (tag.contains("gag")) {
ItemStack gagStack = ItemStack.of(tag.getCompound("gag")); ItemStack gagStack = ItemStack.of(tag.getCompound("gag"));
if (!gagStack.isEmpty() && gagStack.getItem() instanceof ItemGag) { if (!gagStack.isEmpty() && (gagStack.getItem() instanceof ItemGag
|| DataDrivenBondageItem.getComponent(gagStack, ComponentType.GAGGING, GaggingComponent.class) != null)) {
this.gag = gagStack; this.gag = gagStack;
} }
} }
// Read blindfold with type validation // Read blindfold with type validation (V1 ItemBlindfold or V2 EYES-region item)
if (tag.contains("blindfold")) { if (tag.contains("blindfold")) {
ItemStack blindfoldStack = ItemStack.of( ItemStack blindfoldStack = ItemStack.of(tag.getCompound("blindfold"));
tag.getCompound("blindfold") if (!blindfoldStack.isEmpty() && (blindfoldStack.getItem() instanceof ItemBlindfold
); || isDataDrivenForRegion(blindfoldStack, BodyRegionV2.EYES))) {
if (
!blindfoldStack.isEmpty() &&
blindfoldStack.getItem() instanceof ItemBlindfold
) {
this.blindfold = blindfoldStack; this.blindfold = blindfoldStack;
} }
} }
// Read earplugs with type validation // Read earplugs with type validation (V1 ItemEarplugs or V2 EARS-region item)
if (tag.contains("earplugs")) { if (tag.contains("earplugs")) {
ItemStack earplugsStack = ItemStack.of(tag.getCompound("earplugs")); ItemStack earplugsStack = ItemStack.of(tag.getCompound("earplugs"));
if ( if (!earplugsStack.isEmpty() && (earplugsStack.getItem() instanceof ItemEarplugs
!earplugsStack.isEmpty() && || isDataDrivenForRegion(earplugsStack, BodyRegionV2.EARS))) {
earplugsStack.getItem() instanceof ItemEarplugs
) {
this.earplugs = earplugsStack; this.earplugs = earplugsStack;
} }
} }
// Read collar with type validation // Read collar with type validation (V1 ItemCollar or V2 collar)
if (tag.contains("collar")) { if (tag.contains("collar")) {
ItemStack collarStack = ItemStack.of(tag.getCompound("collar")); ItemStack collarStack = ItemStack.of(tag.getCompound("collar"));
if ( if (!collarStack.isEmpty() && (collarStack.getItem() instanceof ItemCollar || CollarHelper.isCollar(collarStack))) {
!collarStack.isEmpty() &&
collarStack.getItem() instanceof ItemCollar
) {
this.collar = collarStack; this.collar = collarStack;
} }
} }
@@ -279,6 +277,14 @@ public abstract class BondageItemBlockEntity
return tag; return tag;
} }
// V2 HELPERS
/** Check if a stack is a data-driven item occupying the given body region. */
private static boolean isDataDrivenForRegion(ItemStack stack, BodyRegionV2 region) {
DataDrivenItemDefinition def = DataDrivenItemRegistry.get(stack);
return def != null && def.occupiedRegions().contains(region);
}
// NETWORK SYNC // NETWORK SYNC
/** /**

View File

@@ -1,7 +1,19 @@
package com.tiedup.remake.blocks.entity; package com.tiedup.remake.blocks.entity;
import com.tiedup.remake.items.base.*; import com.tiedup.remake.items.base.ItemBind;
import com.tiedup.remake.items.base.ItemBlindfold;
import com.tiedup.remake.items.base.ItemCollar;
import com.tiedup.remake.items.base.ItemEarplugs;
import com.tiedup.remake.items.base.ItemGag;
import com.tiedup.remake.items.clothes.GenericClothes; import com.tiedup.remake.items.clothes.GenericClothes;
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 javax.annotation.Nullable; import javax.annotation.Nullable;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
@@ -45,7 +57,7 @@ public class TrappedChestBlockEntity
@Override @Override
public void setBind(ItemStack stack) { public void setBind(ItemStack stack) {
if (stack.isEmpty() || stack.getItem() instanceof ItemBind) { if (stack.isEmpty() || stack.getItem() instanceof ItemBind || BindModeHelper.isBindItem(stack)) {
this.bind = stack; this.bind = stack;
setChangedAndSync(); setChangedAndSync();
} }
@@ -58,7 +70,8 @@ public class TrappedChestBlockEntity
@Override @Override
public void setGag(ItemStack stack) { public void setGag(ItemStack stack) {
if (stack.isEmpty() || stack.getItem() instanceof ItemGag) { if (stack.isEmpty() || stack.getItem() instanceof ItemGag
|| DataDrivenBondageItem.getComponent(stack, ComponentType.GAGGING, GaggingComponent.class) != null) {
this.gag = stack; this.gag = stack;
setChangedAndSync(); setChangedAndSync();
} }
@@ -71,7 +84,8 @@ public class TrappedChestBlockEntity
@Override @Override
public void setBlindfold(ItemStack stack) { public void setBlindfold(ItemStack stack) {
if (stack.isEmpty() || stack.getItem() instanceof ItemBlindfold) { if (stack.isEmpty() || stack.getItem() instanceof ItemBlindfold
|| isDataDrivenForRegion(stack, BodyRegionV2.EYES)) {
this.blindfold = stack; this.blindfold = stack;
setChangedAndSync(); setChangedAndSync();
} }
@@ -84,7 +98,8 @@ public class TrappedChestBlockEntity
@Override @Override
public void setEarplugs(ItemStack stack) { public void setEarplugs(ItemStack stack) {
if (stack.isEmpty() || stack.getItem() instanceof ItemEarplugs) { if (stack.isEmpty() || stack.getItem() instanceof ItemEarplugs
|| isDataDrivenForRegion(stack, BodyRegionV2.EARS)) {
this.earplugs = stack; this.earplugs = stack;
setChangedAndSync(); setChangedAndSync();
} }
@@ -97,7 +112,7 @@ public class TrappedChestBlockEntity
@Override @Override
public void setCollar(ItemStack stack) { public void setCollar(ItemStack stack) {
if (stack.isEmpty() || stack.getItem() instanceof ItemCollar) { if (stack.isEmpty() || stack.getItem() instanceof ItemCollar || CollarHelper.isCollar(stack)) {
this.collar = stack; this.collar = stack;
setChangedAndSync(); setChangedAndSync();
} }
@@ -183,6 +198,14 @@ public class TrappedChestBlockEntity
writeBondageData(tag); writeBondageData(tag);
} }
// V2 HELPERS
/** Check if a stack is a data-driven item occupying the given body region. */
private static boolean isDataDrivenForRegion(ItemStack stack, BodyRegionV2 region) {
DataDrivenItemDefinition def = DataDrivenItemRegistry.get(stack);
return def != null && def.occupiedRegions().contains(region);
}
// NETWORK SYNC // NETWORK SYNC
/** /**

View File

@@ -2,8 +2,8 @@ package com.tiedup.remake.cells;
import com.tiedup.remake.core.TiedUpMod; import com.tiedup.remake.core.TiedUpMod;
import com.tiedup.remake.items.base.ILockable; import com.tiedup.remake.items.base.ILockable;
import com.tiedup.remake.items.base.ItemCollar;
import com.tiedup.remake.prison.PrisonerManager; import com.tiedup.remake.prison.PrisonerManager;
import com.tiedup.remake.v2.bondage.CollarHelper;
import com.tiedup.remake.state.IRestrainable; import com.tiedup.remake.state.IRestrainable;
import com.tiedup.remake.util.KidnappedHelper; import com.tiedup.remake.util.KidnappedHelper;
import com.tiedup.remake.v2.BodyRegionV2; import com.tiedup.remake.v2.BodyRegionV2;
@@ -231,7 +231,7 @@ public final class CampLifecycleManager {
} }
// Suppress collar removal alerts - this is a legitimate release (camp death) // Suppress collar removal alerts - this is a legitimate release (camp death)
ItemCollar.runWithSuppressedAlert(() -> { CollarHelper.runWithSuppressedAlert(() -> {
// Unlock collar if owned by the dead camp/trader // Unlock collar if owned by the dead camp/trader
unlockCollarIfOwnedBy(prisoner, state, traderUUID); unlockCollarIfOwnedBy(prisoner, state, traderUUID);
@@ -285,8 +285,8 @@ public final class CampLifecycleManager {
return; return;
} }
if (collar.getItem() instanceof ItemCollar collarItem) { if (CollarHelper.isCollar(collar)) {
List<UUID> owners = collarItem.getOwners(collar); List<UUID> owners = CollarHelper.getOwners(collar);
// If the dead trader/camp is an owner, unlock the collar // If the dead trader/camp is an owner, unlock the collar
if (owners.contains(ownerUUID)) { if (owners.contains(ownerUUID)) {

View File

@@ -3,8 +3,8 @@ package com.tiedup.remake.client;
import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.blaze3d.vertex.VertexConsumer; import com.mojang.blaze3d.vertex.VertexConsumer;
import com.tiedup.remake.core.TiedUpMod; import com.tiedup.remake.core.TiedUpMod;
import com.tiedup.remake.items.GenericBind; import com.tiedup.remake.items.base.PoseType;
import com.tiedup.remake.items.base.BindVariant; import com.tiedup.remake.v2.bondage.PoseTypeHelper;
import com.tiedup.remake.state.PlayerBindState; import com.tiedup.remake.state.PlayerBindState;
import com.tiedup.remake.v2.BodyRegionV2; import com.tiedup.remake.v2.BodyRegionV2;
import com.tiedup.remake.v2.bondage.capability.V2EquipmentHelper; import com.tiedup.remake.v2.bondage.capability.V2EquipmentHelper;
@@ -141,12 +141,7 @@ public class FirstPersonMittensRenderer {
net.minecraft.world.item.ItemStack bindStack = net.minecraft.world.item.ItemStack bindStack =
V2EquipmentHelper.getInRegion(player, BodyRegionV2.ARMS); V2EquipmentHelper.getInRegion(player, BodyRegionV2.ARMS);
if (bindStack.isEmpty()) return false; if (bindStack.isEmpty()) return false;
if (bindStack.getItem() instanceof GenericBind bind) { PoseType poseType = PoseTypeHelper.getPoseType(bindStack);
BindVariant variant = bind.getVariant(); return poseType == PoseType.WRAP || poseType == PoseType.LATEX_SACK;
return (
variant == BindVariant.WRAP || variant == BindVariant.LATEX_SACK
);
}
return false;
} }
} }

View File

@@ -6,7 +6,7 @@ import com.tiedup.remake.client.gui.screens.UnifiedBondageScreen;
import com.tiedup.remake.core.ModConfig; import com.tiedup.remake.core.ModConfig;
import com.tiedup.remake.core.TiedUpMod; import com.tiedup.remake.core.TiedUpMod;
import com.tiedup.remake.items.base.ILockable; import com.tiedup.remake.items.base.ILockable;
import com.tiedup.remake.items.base.ItemCollar; import com.tiedup.remake.v2.bondage.CollarHelper;
import com.tiedup.remake.network.ModNetwork; import com.tiedup.remake.network.ModNetwork;
import com.tiedup.remake.network.action.PacketForceSeatModifier; import com.tiedup.remake.network.action.PacketForceSeatModifier;
import com.tiedup.remake.network.action.PacketStruggle; import com.tiedup.remake.network.action.PacketStruggle;
@@ -428,11 +428,8 @@ public class ModKeybindings {
target, target,
BodyRegionV2.NECK BodyRegionV2.NECK
); );
if ( if (!collarStack.isEmpty() && CollarHelper.isCollar(collarStack)) {
!collarStack.isEmpty() && return CollarHelper.isOwner(collarStack, player);
collarStack.getItem() instanceof ItemCollar collar
) {
return collar.isOwner(collarStack, player);
} }
return false; return false;
} }

View File

@@ -1,8 +1,8 @@
package com.tiedup.remake.client.animation.render; package com.tiedup.remake.client.animation.render;
import com.tiedup.remake.core.TiedUpMod; import com.tiedup.remake.core.TiedUpMod;
import com.tiedup.remake.items.base.ItemBind;
import com.tiedup.remake.items.base.PoseType; import com.tiedup.remake.items.base.PoseType;
import com.tiedup.remake.v2.bondage.PoseTypeHelper;
import com.tiedup.remake.state.HumanChairHelper; import com.tiedup.remake.state.HumanChairHelper;
import com.tiedup.remake.state.PlayerBindState; import com.tiedup.remake.state.PlayerBindState;
import com.tiedup.remake.v2.BodyRegionV2; import com.tiedup.remake.v2.BodyRegionV2;
@@ -93,14 +93,11 @@ public class DogPoseRenderHandler {
} }
ItemStack bindForPose = state.getEquipment(BodyRegionV2.ARMS); ItemStack bindForPose = state.getEquipment(BodyRegionV2.ARMS);
if ( if (bindForPose.isEmpty()) {
bindForPose.isEmpty() ||
!(bindForPose.getItem() instanceof ItemBind itemBind)
) {
return; return;
} }
PoseType bindPoseType = itemBind.getPoseType(); PoseType bindPoseType = PoseTypeHelper.getPoseType(bindForPose);
// Check for humanChairMode NBT override // Check for humanChairMode NBT override
bindPoseType = HumanChairHelper.resolveEffectivePose( bindPoseType = HumanChairHelper.resolveEffectivePose(
bindPoseType, bindPoseType,

View File

@@ -2,8 +2,8 @@ package com.tiedup.remake.client.animation.render;
import com.tiedup.remake.client.state.PetBedClientState; import com.tiedup.remake.client.state.PetBedClientState;
import com.tiedup.remake.core.TiedUpMod; import com.tiedup.remake.core.TiedUpMod;
import com.tiedup.remake.items.base.ItemBind;
import com.tiedup.remake.items.base.PoseType; import com.tiedup.remake.items.base.PoseType;
import com.tiedup.remake.v2.bondage.PoseTypeHelper;
import com.tiedup.remake.state.HumanChairHelper; import com.tiedup.remake.state.HumanChairHelper;
import com.tiedup.remake.state.PlayerBindState; import com.tiedup.remake.state.PlayerBindState;
import com.tiedup.remake.v2.BodyRegionV2; import com.tiedup.remake.v2.BodyRegionV2;
@@ -83,11 +83,9 @@ public class PetBedRenderHandler {
PlayerBindState state = PlayerBindState.getInstance(player); PlayerBindState state = PlayerBindState.getInstance(player);
if (state == null) return false; if (state == null) return false;
ItemStack bind = state.getEquipment(BodyRegionV2.ARMS); ItemStack bind = state.getEquipment(BodyRegionV2.ARMS);
if ( if (bind.isEmpty()) return false;
bind.isEmpty() || !(bind.getItem() instanceof ItemBind itemBind)
) return false;
PoseType pose = HumanChairHelper.resolveEffectivePose( PoseType pose = HumanChairHelper.resolveEffectivePose(
itemBind.getPoseType(), PoseTypeHelper.getPoseType(bind),
bind bind
); );
return pose == PoseType.DOG || pose == PoseType.HUMAN_CHAIR; return pose == PoseType.DOG || pose == PoseType.HUMAN_CHAIR;

View File

@@ -2,8 +2,8 @@ package com.tiedup.remake.client.animation.render;
import com.tiedup.remake.client.renderer.layers.ClothesRenderHelper; import com.tiedup.remake.client.renderer.layers.ClothesRenderHelper;
import com.tiedup.remake.core.TiedUpMod; import com.tiedup.remake.core.TiedUpMod;
import com.tiedup.remake.items.base.ItemBind;
import com.tiedup.remake.items.base.PoseType; import com.tiedup.remake.items.base.PoseType;
import com.tiedup.remake.v2.bondage.PoseTypeHelper;
import com.tiedup.remake.items.clothes.ClothesProperties; import com.tiedup.remake.items.clothes.ClothesProperties;
import com.tiedup.remake.state.PlayerBindState; import com.tiedup.remake.state.PlayerBindState;
import com.tiedup.remake.v2.BodyRegionV2; import com.tiedup.remake.v2.BodyRegionV2;
@@ -71,10 +71,8 @@ public class PlayerArmHideEventHandler {
// === HIDE ARMS (wrap/latex_sack poses) === // === HIDE ARMS (wrap/latex_sack poses) ===
if (state.hasArmsBound()) { if (state.hasArmsBound()) {
ItemStack bind = state.getEquipment(BodyRegionV2.ARMS); ItemStack bind = state.getEquipment(BodyRegionV2.ARMS);
if ( if (!bind.isEmpty()) {
!bind.isEmpty() && bind.getItem() instanceof ItemBind itemBind PoseType poseType = PoseTypeHelper.getPoseType(bind);
) {
PoseType poseType = itemBind.getPoseType();
// Only hide arms for wrap/sack poses (arms are covered by the item) // Only hide arms for wrap/sack poses (arms are covered by the item)
if ( if (

View File

@@ -14,8 +14,9 @@ import com.tiedup.remake.client.gltf.GltfAnimationApplier;
import com.tiedup.remake.client.state.ClothesClientCache; import com.tiedup.remake.client.state.ClothesClientCache;
import com.tiedup.remake.client.state.MovementStyleClientState; import com.tiedup.remake.client.state.MovementStyleClientState;
import com.tiedup.remake.client.state.PetBedClientState; import com.tiedup.remake.client.state.PetBedClientState;
import com.tiedup.remake.items.base.ItemBind;
import com.tiedup.remake.items.base.PoseType; import com.tiedup.remake.items.base.PoseType;
import com.tiedup.remake.v2.bondage.BindModeHelper;
import com.tiedup.remake.v2.bondage.PoseTypeHelper;
import com.tiedup.remake.state.HumanChairHelper; import com.tiedup.remake.state.HumanChairHelper;
import com.tiedup.remake.state.PlayerBindState; import com.tiedup.remake.state.PlayerBindState;
import com.tiedup.remake.v2.BodyRegionV2; import com.tiedup.remake.v2.BodyRegionV2;
@@ -249,14 +250,10 @@ public class AnimationTickHandler {
PlayerBindState state PlayerBindState state
) { ) {
ItemStack bind = state.getEquipment(BodyRegionV2.ARMS); ItemStack bind = state.getEquipment(BodyRegionV2.ARMS);
PoseType poseType = PoseType.STANDARD; PoseType poseType = PoseTypeHelper.getPoseType(bind);
if (bind.getItem() instanceof ItemBind itemBind) {
poseType = itemBind.getPoseType();
// Human chair mode: override DOG pose to HUMAN_CHAIR (straight limbs) // Human chair mode: override DOG pose to HUMAN_CHAIR (straight limbs)
poseType = HumanChairHelper.resolveEffectivePose(poseType, bind); poseType = HumanChairHelper.resolveEffectivePose(poseType, bind);
}
// Derive bound state from V2 regions (works client-side, synced via capability) // Derive bound state from V2 regions (works client-side, synced via capability)
boolean armsBound = V2EquipmentHelper.isRegionOccupied( boolean armsBound = V2EquipmentHelper.isRegionOccupied(
@@ -268,10 +265,10 @@ public class AnimationTickHandler {
BodyRegionV2.LEGS BodyRegionV2.LEGS
); );
// V1 fallback: if no V2 regions are set but player is tied, derive from ItemBind NBT // V1 fallback: if no V2 regions are set but player is tied, derive from bind mode NBT
if (!armsBound && !legsBound && bind.getItem() instanceof ItemBind) { if (!armsBound && !legsBound && BindModeHelper.isBindItem(bind)) {
armsBound = ItemBind.hasArmsBound(bind); armsBound = BindModeHelper.hasArmsBound(bind);
legsBound = ItemBind.hasLegsBound(bind); legsBound = BindModeHelper.hasLegsBound(bind);
} }
boolean isStruggling = state.isStruggling(); boolean isStruggling = state.isStruggling();

View File

@@ -9,8 +9,9 @@ import com.tiedup.remake.client.gltf.GltfAnimationApplier;
import com.tiedup.remake.entities.AbstractTiedUpNpc; import com.tiedup.remake.entities.AbstractTiedUpNpc;
import com.tiedup.remake.entities.EntityMaster; import com.tiedup.remake.entities.EntityMaster;
import com.tiedup.remake.entities.ai.master.MasterState; import com.tiedup.remake.entities.ai.master.MasterState;
import com.tiedup.remake.items.base.ItemBind;
import com.tiedup.remake.items.base.PoseType; import com.tiedup.remake.items.base.PoseType;
import com.tiedup.remake.v2.bondage.BindModeHelper;
import com.tiedup.remake.v2.bondage.PoseTypeHelper;
import com.tiedup.remake.v2.BodyRegionV2; import com.tiedup.remake.v2.BodyRegionV2;
import com.tiedup.remake.v2.bondage.IV2BondageEquipment; import com.tiedup.remake.v2.bondage.IV2BondageEquipment;
import com.tiedup.remake.v2.bondage.capability.V2EquipmentHelper; import com.tiedup.remake.v2.bondage.capability.V2EquipmentHelper;
@@ -161,13 +162,8 @@ public class NpcAnimationTickHandler {
net.minecraft.world.item.ItemStack bind = entity.getEquipment( net.minecraft.world.item.ItemStack bind = entity.getEquipment(
BodyRegionV2.ARMS BodyRegionV2.ARMS
); );
PoseType poseType = PoseType.STANDARD; PoseType poseType = PoseTypeHelper.getPoseType(bind);
boolean hasBind = false; boolean hasBind = BindModeHelper.isBindItem(bind);
if (bind.getItem() instanceof ItemBind itemBind) {
poseType = itemBind.getPoseType();
hasBind = true;
}
// Derive bound state from V2 regions (AbstractTiedUpNpc implements IV2EquipmentHolder) // Derive bound state from V2 regions (AbstractTiedUpNpc implements IV2EquipmentHolder)
boolean armsBound = V2EquipmentHelper.isRegionOccupied( boolean armsBound = V2EquipmentHelper.isRegionOccupied(
@@ -179,10 +175,10 @@ public class NpcAnimationTickHandler {
BodyRegionV2.LEGS BodyRegionV2.LEGS
); );
// V1 fallback: if no V2 regions set but NPC has a bind, derive from ItemBind NBT // V1 fallback: if no V2 regions set but NPC has a bind, derive from bind mode NBT
if (!armsBound && !legsBound && bind.getItem() instanceof ItemBind) { if (!armsBound && !legsBound && BindModeHelper.isBindItem(bind)) {
armsBound = ItemBind.hasArmsBound(bind); armsBound = BindModeHelper.hasArmsBound(bind);
legsBound = ItemBind.hasLegsBound(bind); legsBound = BindModeHelper.hasLegsBound(bind);
} }
boolean isStruggling = entity.isStruggling(); boolean isStruggling = entity.isStruggling();

View File

@@ -1,8 +1,8 @@
package com.tiedup.remake.client.events; package com.tiedup.remake.client.events;
import com.tiedup.remake.core.TiedUpMod; import com.tiedup.remake.core.TiedUpMod;
import com.tiedup.remake.items.ModItems; import com.tiedup.remake.items.base.PoseType;
import com.tiedup.remake.items.base.BindVariant; import com.tiedup.remake.v2.bondage.PoseTypeHelper;
import com.tiedup.remake.state.IBondageState; import com.tiedup.remake.state.IBondageState;
import com.tiedup.remake.util.KidnappedHelper; import com.tiedup.remake.util.KidnappedHelper;
import com.tiedup.remake.v2.BodyRegionV2; import com.tiedup.remake.v2.BodyRegionV2;
@@ -138,7 +138,7 @@ public class LeashProxyClientHandler {
ItemStack bind = state.getEquipment(BodyRegionV2.ARMS); ItemStack bind = state.getEquipment(BodyRegionV2.ARMS);
if ( if (
!bind.isEmpty() && !bind.isEmpty() &&
bind.getItem() == ModItems.getBind(BindVariant.DOGBINDER) PoseTypeHelper.getPoseType(bind) == PoseType.DOG
) { ) {
return DOGWALK_Y_OFFSET; return DOGWALK_Y_OFFSET;
} }

View File

@@ -1,13 +1,20 @@
package com.tiedup.remake.client.events; package com.tiedup.remake.client.events;
import com.tiedup.remake.items.base.*; import com.tiedup.remake.items.base.ItemCollar;
import com.tiedup.remake.network.ModNetwork; import com.tiedup.remake.network.ModNetwork;
import com.tiedup.remake.network.selfbondage.PacketSelfBondage; import com.tiedup.remake.network.selfbondage.PacketSelfBondage;
import com.tiedup.remake.v2.bondage.BindModeHelper;
import com.tiedup.remake.v2.bondage.CollarHelper;
import com.tiedup.remake.v2.bondage.IV2BondageItem; import com.tiedup.remake.v2.bondage.IV2BondageItem;
import com.tiedup.remake.v2.bondage.component.BlindingComponent;
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 net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.player.LocalPlayer; import net.minecraft.client.player.LocalPlayer;
import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionHand;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.api.distmarker.OnlyIn;
@@ -70,7 +77,7 @@ public class SelfBondageInputHandler {
if (!event.getLevel().isClientSide()) return; if (!event.getLevel().isClientSide()) return;
ItemStack stack = event.getItemStack(); ItemStack stack = event.getItemStack();
if (isSelfBondageItem(stack.getItem())) { if (isSelfBondageItem(stack)) {
event.setCanceled(true); event.setCanceled(true);
startSelfBondage(); startSelfBondage();
} }
@@ -87,11 +94,11 @@ public class SelfBondageInputHandler {
InteractionHand hand = InteractionHand.MAIN_HAND; InteractionHand hand = InteractionHand.MAIN_HAND;
ItemStack stack = player.getMainHandItem(); ItemStack stack = player.getMainHandItem();
if (!isSelfBondageItem(stack.getItem())) { if (!isSelfBondageItem(stack)) {
stack = player.getOffhandItem(); stack = player.getOffhandItem();
hand = InteractionHand.OFF_HAND; hand = InteractionHand.OFF_HAND;
if (!isSelfBondageItem(stack.getItem())) { if (!isSelfBondageItem(stack)) {
return; // No bondage item in either hand return; // No bondage item in either hand
} }
} }
@@ -130,7 +137,7 @@ public class SelfBondageInputHandler {
// Check if still holding bondage item in the active hand // Check if still holding bondage item in the active hand
ItemStack stack = player.getItemInHand(activeHand); ItemStack stack = player.getItemInHand(activeHand);
if (!isSelfBondageItem(stack.getItem())) { if (!isSelfBondageItem(stack)) {
stopSelfBondage(); stopSelfBondage();
return; return;
} }
@@ -153,27 +160,31 @@ public class SelfBondageInputHandler {
} }
/** /**
* Check if an item supports self-bondage. * Check if a stack supports self-bondage.
* Collar is explicitly excluded. * Collar is explicitly excluded.
*/ */
private static boolean isSelfBondageItem(Item item) { private static boolean isSelfBondageItem(ItemStack stack) {
// Collar cannot be self-equipped (V1 collar guard) if (stack.isEmpty()) return false;
if (item instanceof ItemCollar) {
// Collar cannot be self-equipped (V1 collar guard + V2 ownership component)
if (stack.getItem() instanceof ItemCollar || CollarHelper.isCollar(stack)) {
return false; return false;
} }
// V2 bondage items support self-bondage (left-click hold with tying duration) // V2 bondage items support self-bondage (left-click hold with tying duration)
if (item instanceof IV2BondageItem) { if (stack.getItem() instanceof IV2BondageItem) {
return true; return true;
} }
// V1 bondage items (legacy) // V2 data-driven items: check if it occupies any bondage region
return ( DataDrivenItemDefinition def = DataDrivenItemRegistry.get(stack);
item instanceof ItemBind || if (def != null) {
item instanceof ItemGag || return true;
item instanceof ItemBlindfold || }
item instanceof ItemMittens ||
item instanceof ItemEarplugs // V1 fallback: bind items
); return BindModeHelper.isBindItem(stack)
|| DataDrivenBondageItem.getComponent(stack, ComponentType.GAGGING, GaggingComponent.class) != null
|| DataDrivenBondageItem.getComponent(stack, ComponentType.BLINDING, BlindingComponent.class) != null;
} }
} }

View File

@@ -3,7 +3,7 @@ package com.tiedup.remake.client.gui.screens;
import com.tiedup.remake.client.gui.util.GuiColors; import com.tiedup.remake.client.gui.util.GuiColors;
import com.tiedup.remake.client.gui.util.GuiLayoutConstants; import com.tiedup.remake.client.gui.util.GuiLayoutConstants;
import com.tiedup.remake.client.gui.widgets.SlaveEntryWidget; import com.tiedup.remake.client.gui.widgets.SlaveEntryWidget;
import com.tiedup.remake.items.base.ItemCollar; import com.tiedup.remake.v2.bondage.CollarHelper;
import com.tiedup.remake.network.ModNetwork; import com.tiedup.remake.network.ModNetwork;
import com.tiedup.remake.network.slave.PacketSlaveAction; import com.tiedup.remake.network.slave.PacketSlaveAction;
import com.tiedup.remake.state.IBondageState; import com.tiedup.remake.state.IBondageState;
@@ -145,8 +145,8 @@ public class SlaveManagementScreen extends BaseScreen {
ItemStack collarStack = kidnapped.getEquipment( ItemStack collarStack = kidnapped.getEquipment(
BodyRegionV2.NECK BodyRegionV2.NECK
); );
if (collarStack.getItem() instanceof ItemCollar collar) { if (CollarHelper.isCollar(collarStack)) {
if (collar.isOwner(collarStack, player)) { if (CollarHelper.isOwner(collarStack, player)) {
addSlaveEntry(kidnapped); addSlaveEntry(kidnapped);
addedUUIDs.add(entity.getUUID()); addedUUIDs.add(entity.getUUID());
} }

View File

@@ -7,7 +7,7 @@ import com.tiedup.remake.items.ItemLockpick;
import com.tiedup.remake.items.ModItems; import com.tiedup.remake.items.ModItems;
import com.tiedup.remake.items.base.IHasResistance; import com.tiedup.remake.items.base.IHasResistance;
import com.tiedup.remake.items.base.ILockable; import com.tiedup.remake.items.base.ILockable;
import com.tiedup.remake.items.base.ItemCollar; import com.tiedup.remake.v2.bondage.CollarHelper;
import com.tiedup.remake.network.ModNetwork; import com.tiedup.remake.network.ModNetwork;
import com.tiedup.remake.network.action.PacketSetKnifeCutTarget; import com.tiedup.remake.network.action.PacketSetKnifeCutTarget;
import com.tiedup.remake.network.minigame.PacketLockpickMiniGameStart; import com.tiedup.remake.network.minigame.PacketLockpickMiniGameStart;
@@ -474,10 +474,10 @@ public class ActionPanel extends AbstractWidget {
// Bondage Service toggle (NECK collar only, prison configured) // Bondage Service toggle (NECK collar only, prison configured)
if ( if (
selectedRegion == BodyRegionV2.NECK && selectedRegion == BodyRegionV2.NECK &&
selectedItem.getItem() instanceof ItemCollar collar CollarHelper.isCollar(selectedItem)
) { ) {
if (collar.hasCellAssigned(selectedItem)) { if (CollarHelper.hasCellAssigned(selectedItem)) {
boolean svcEnabled = collar.isBondageServiceEnabled( boolean svcEnabled = CollarHelper.isBondageServiceEnabled(
selectedItem selectedItem
); );
String svcKey = svcEnabled String svcKey = svcEnabled

View File

@@ -5,7 +5,7 @@ import static com.tiedup.remake.client.gui.util.GuiLayoutConstants.*;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.tiedup.remake.client.gui.util.GuiColors; import com.tiedup.remake.client.gui.util.GuiColors;
import com.tiedup.remake.items.ItemGpsCollar; import com.tiedup.remake.items.ItemGpsCollar;
import com.tiedup.remake.items.base.ItemCollar; import com.tiedup.remake.v2.bondage.CollarHelper;
import com.tiedup.remake.state.IBondageState; import com.tiedup.remake.state.IBondageState;
import com.tiedup.remake.v2.BodyRegionV2; import com.tiedup.remake.v2.BodyRegionV2;
import java.util.ArrayList; import java.util.ArrayList;
@@ -560,19 +560,13 @@ public class SlaveEntryWidget
private boolean hasShockCollar() { private boolean hasShockCollar() {
if (!slave.hasCollar()) return false; if (!slave.hasCollar()) return false;
ItemStack collar = slave.getEquipment(BodyRegionV2.NECK); ItemStack collar = slave.getEquipment(BodyRegionV2.NECK);
return ( return CollarHelper.canShock(collar);
collar.getItem() instanceof ItemCollar itemCollar &&
itemCollar.canShock()
);
} }
private boolean hasGPSCollar() { private boolean hasGPSCollar() {
if (!slave.hasCollar()) return false; if (!slave.hasCollar()) return false;
ItemStack collar = slave.getEquipment(BodyRegionV2.NECK); ItemStack collar = slave.getEquipment(BodyRegionV2.NECK);
return ( return CollarHelper.hasGPS(collar);
collar.getItem() instanceof ItemCollar itemCollar &&
itemCollar.hasGPS()
);
} }
private boolean isInAnySafeZone( private boolean isInAnySafeZone(
@@ -580,7 +574,7 @@ public class SlaveEntryWidget
ItemStack collarStack, ItemStack collarStack,
LivingEntity entity LivingEntity entity
) { ) {
if (!gps.isActive(collarStack)) return true; if (!CollarHelper.isActive(collarStack)) return true;
var safeSpots = gps.getSafeSpots(collarStack); var safeSpots = gps.getSafeSpots(collarStack);
if (safeSpots.isEmpty()) return true; if (safeSpots.isEmpty()) return true;

View File

@@ -9,8 +9,9 @@ import com.tiedup.remake.entities.AbstractTiedUpNpc;
import com.tiedup.remake.entities.EntityKidnapperArcher; import com.tiedup.remake.entities.EntityKidnapperArcher;
import com.tiedup.remake.entities.EntityMaster; import com.tiedup.remake.entities.EntityMaster;
import com.tiedup.remake.entities.ai.master.MasterState; import com.tiedup.remake.entities.ai.master.MasterState;
import com.tiedup.remake.items.base.ItemBind;
import com.tiedup.remake.items.base.PoseType; import com.tiedup.remake.items.base.PoseType;
import com.tiedup.remake.v2.bondage.BindModeHelper;
import com.tiedup.remake.v2.bondage.PoseTypeHelper;
import com.tiedup.remake.items.clothes.GenericClothes; import com.tiedup.remake.items.clothes.GenericClothes;
import com.tiedup.remake.v2.BodyRegionV2; import com.tiedup.remake.v2.BodyRegionV2;
import com.tiedup.remake.v2.bondage.capability.V2EquipmentHelper; import com.tiedup.remake.v2.bondage.capability.V2EquipmentHelper;
@@ -230,11 +231,7 @@ public class DamselModel
if (inPose) { if (inPose) {
ItemStack bind = entity.getEquipment(BodyRegionV2.ARMS); ItemStack bind = entity.getEquipment(BodyRegionV2.ARMS);
PoseType poseType = PoseType.STANDARD; PoseType poseType = PoseTypeHelper.getPoseType(bind);
if (bind.getItem() instanceof ItemBind itemBind) {
poseType = itemBind.getPoseType();
}
// Hide arms for wrap/latex_sack poses // Hide arms for wrap/latex_sack poses
if (poseType == PoseType.WRAP || poseType == PoseType.LATEX_SACK) { if (poseType == PoseType.WRAP || poseType == PoseType.LATEX_SACK) {
@@ -252,9 +249,7 @@ public class DamselModel
PoseType currentPoseType = PoseType.STANDARD; PoseType currentPoseType = PoseType.STANDARD;
if (inPose) { if (inPose) {
ItemStack bindForPoseType = entity.getEquipment(BodyRegionV2.ARMS); ItemStack bindForPoseType = entity.getEquipment(BodyRegionV2.ARMS);
if (bindForPoseType.getItem() instanceof ItemBind itemBindForType) { currentPoseType = PoseTypeHelper.getPoseType(bindForPoseType);
currentPoseType = itemBindForType.getPoseType();
}
} }
// Check if this is a Master in human chair mode (head should look around freely) // Check if this is a Master in human chair mode (head should look around freely)
@@ -306,11 +301,7 @@ public class DamselModel
// Animation not yet active (1-frame delay) - apply static pose as fallback // Animation not yet active (1-frame delay) - apply static pose as fallback
// This ensures immediate visual feedback when bind is applied // This ensures immediate visual feedback when bind is applied
ItemStack bind = entity.getEquipment(BodyRegionV2.ARMS); ItemStack bind = entity.getEquipment(BodyRegionV2.ARMS);
PoseType fallbackPoseType = PoseType.STANDARD; PoseType fallbackPoseType = PoseTypeHelper.getPoseType(bind);
if (bind.getItem() instanceof ItemBind itemBind) {
fallbackPoseType = itemBind.getPoseType();
}
// Derive bound state from V2 regions (AbstractTiedUpNpc implements IV2EquipmentHolder) // Derive bound state from V2 regions (AbstractTiedUpNpc implements IV2EquipmentHolder)
boolean armsBound = V2EquipmentHelper.isRegionOccupied( boolean armsBound = V2EquipmentHelper.isRegionOccupied(
@@ -323,10 +314,10 @@ public class DamselModel
); );
if ( if (
!armsBound && !legsBound && bind.getItem() instanceof ItemBind !armsBound && !legsBound && BindModeHelper.isBindItem(bind)
) { ) {
armsBound = ItemBind.hasArmsBound(bind); armsBound = BindModeHelper.hasArmsBound(bind);
legsBound = ItemBind.hasLegsBound(bind); legsBound = BindModeHelper.hasLegsBound(bind);
} }
// Apply static pose directly to model parts // Apply static pose directly to model parts

View File

@@ -7,8 +7,8 @@ import com.mojang.brigadier.context.CommandContext;
import com.mojang.brigadier.exceptions.CommandSyntaxException; import com.mojang.brigadier.exceptions.CommandSyntaxException;
import com.tiedup.remake.cells.CellDataV2; import com.tiedup.remake.cells.CellDataV2;
import com.tiedup.remake.cells.CellRegistryV2; import com.tiedup.remake.cells.CellRegistryV2;
import com.tiedup.remake.items.base.ItemCollar;
import com.tiedup.remake.state.PlayerBindState; import com.tiedup.remake.state.PlayerBindState;
import com.tiedup.remake.v2.bondage.CollarHelper;
import com.tiedup.remake.util.teleport.Position; import com.tiedup.remake.util.teleport.Position;
import com.tiedup.remake.util.teleport.TeleportHelper; import com.tiedup.remake.util.teleport.TeleportHelper;
import com.tiedup.remake.v2.BodyRegionV2; import com.tiedup.remake.v2.BodyRegionV2;
@@ -160,8 +160,8 @@ public class CollarCommand {
} }
if (source.getEntity() instanceof ServerPlayer executor) { if (source.getEntity() instanceof ServerPlayer executor) {
if (collar.getItem() instanceof ItemCollar collarItem) { if (CollarHelper.isCollar(collar)) {
collarItem.addOwner(collar, executor); CollarHelper.addOwner(collar, executor);
source.sendSuccess( source.sendSuccess(
() -> () ->
Component.literal( Component.literal(
@@ -195,8 +195,8 @@ public class CollarCommand {
} }
if (source.getEntity() instanceof ServerPlayer executor) { if (source.getEntity() instanceof ServerPlayer executor) {
if (collar.getItem() instanceof ItemCollar collarItem) { if (CollarHelper.isCollar(collar)) {
collarItem.removeOwner(collar, executor.getUUID()); CollarHelper.removeOwner(collar, executor.getUUID());
source.sendSuccess( source.sendSuccess(
() -> () ->
Component.literal( Component.literal(
@@ -230,8 +230,8 @@ public class CollarCommand {
return 0; return 0;
} }
if (collar.getItem() instanceof ItemCollar collarItem) { if (CollarHelper.isCollar(collar)) {
collarItem.setNickname(collar, name); CollarHelper.setNickname(collar, name);
source.sendSuccess( source.sendSuccess(
() -> () ->
Component.literal( Component.literal(
@@ -261,8 +261,8 @@ public class CollarCommand {
return 0; return 0;
} }
if (collar.getItem() instanceof ItemCollar collarItem) { if (CollarHelper.isCollar(collar)) {
collarItem.addOwner(collar, owner); CollarHelper.addOwner(collar, owner);
source.sendSuccess( source.sendSuccess(
() -> () ->
Component.literal( Component.literal(
@@ -296,8 +296,8 @@ public class CollarCommand {
return 0; return 0;
} }
if (collar.getItem() instanceof ItemCollar collarItem) { if (CollarHelper.isCollar(collar)) {
collarItem.removeOwner(collar, owner.getUUID()); CollarHelper.removeOwner(collar, owner.getUUID());
source.sendSuccess( source.sendSuccess(
() -> () ->
Component.literal( Component.literal(
@@ -348,8 +348,8 @@ public class CollarCommand {
return 0; return 0;
} }
if (collar.getItem() instanceof ItemCollar collarItem) { if (CollarHelper.isCollar(collar)) {
collarItem.setCellId(collar, cell.getId()); CollarHelper.setCellId(collar, cell.getId());
source.sendSuccess( source.sendSuccess(
() -> () ->
Component.literal( Component.literal(
@@ -388,8 +388,8 @@ public class CollarCommand {
return 0; return 0;
} }
if (collar.getItem() instanceof ItemCollar collarItem) { if (CollarHelper.isCollar(collar)) {
if (!collarItem.hasCellAssigned(collar)) { if (!CollarHelper.hasCellAssigned(collar)) {
source.sendFailure( source.sendFailure(
Component.literal("No cell assigned to collar") Component.literal("No cell assigned to collar")
); );
@@ -397,7 +397,7 @@ public class CollarCommand {
} }
// Get cell position and teleport // Get cell position and teleport
java.util.UUID cellId = collarItem.getCellId(collar); java.util.UUID cellId = CollarHelper.getCellId(collar);
ServerLevel serverLevel = source.getLevel(); ServerLevel serverLevel = source.getLevel();
CellDataV2 cell = CellRegistryV2.get(serverLevel).getCell(cellId); CellDataV2 cell = CellRegistryV2.get(serverLevel).getCell(cellId);
@@ -449,7 +449,7 @@ public class CollarCommand {
return 0; return 0;
} }
if (collar.getItem() instanceof ItemCollar collarItem) { if (CollarHelper.isCollar(collar)) {
source.sendSuccess( source.sendSuccess(
() -> () ->
Component.literal( Component.literal(
@@ -460,24 +460,24 @@ public class CollarCommand {
false false
); );
String nickname = collarItem.getNickname(collar); String nickname = CollarHelper.getNickname(collar);
source.sendSuccess( source.sendSuccess(
() -> () ->
Component.literal( Component.literal(
"§7Nickname: §f" + "§7Nickname: §f" +
(nickname.isEmpty() ? "None" : nickname) (nickname == null || nickname.isEmpty() ? "None" : nickname)
), ),
false false
); );
source.sendSuccess( source.sendSuccess(
() -> () ->
Component.literal( Component.literal(
"§7Has Owner: §f" + collarItem.hasOwner(collar) "§7Has Owner: §f" + CollarHelper.hasOwner(collar)
), ),
false false
); );
// Cell assignment // Cell assignment
java.util.UUID cellId = collarItem.getCellId(collar); java.util.UUID cellId = CollarHelper.getCellId(collar);
if (cellId != null) { if (cellId != null) {
ServerLevel serverLevel = source.getLevel(); ServerLevel serverLevel = source.getLevel();
CellRegistryV2 registry = CellRegistryV2.get(serverLevel); CellRegistryV2 registry = CellRegistryV2.get(serverLevel);
@@ -510,10 +510,12 @@ public class CollarCommand {
); );
} }
boolean locked = collar.getItem() instanceof com.tiedup.remake.items.base.ILockable lockable
&& lockable.isLocked(collar);
source.sendSuccess( source.sendSuccess(
() -> () ->
Component.literal( Component.literal(
"§7Locked: §f" + collarItem.isLocked(collar) "§7Locked: §f" + locked
), ),
false false
); );

View File

@@ -4,12 +4,10 @@ import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.context.CommandContext; import com.mojang.brigadier.context.CommandContext;
import com.mojang.brigadier.exceptions.CommandSyntaxException; import com.mojang.brigadier.exceptions.CommandSyntaxException;
import com.tiedup.remake.items.ModItems; import com.tiedup.remake.items.ModItems;
import com.tiedup.remake.items.base.BindVariant;
import com.tiedup.remake.items.base.BlindfoldVariant;
import com.tiedup.remake.items.base.EarplugsVariant;
import com.tiedup.remake.items.base.GagVariant;
import com.tiedup.remake.items.base.KnifeVariant; import com.tiedup.remake.items.base.KnifeVariant;
import com.tiedup.remake.v2.bondage.datadriven.DataDrivenBondageItem;
import java.util.Optional; import java.util.Optional;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.commands.CommandSourceStack; import net.minecraft.commands.CommandSourceStack;
import net.minecraft.commands.Commands; import net.minecraft.commands.Commands;
import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Component;
@@ -82,42 +80,18 @@ public class KidnapSetCommand {
int given = 0; int given = 0;
// Binds // Binds
given += giveItem( given += giveDataDrivenItems(player, "ropes", 8);
player, given += giveDataDrivenItems(player, "chain", 4);
new ItemStack(ModItems.getBind(BindVariant.ROPES), 8) given += giveDataDrivenItems(player, "leather_straps", 4);
);
given += giveItem(
player,
new ItemStack(ModItems.getBind(BindVariant.CHAIN), 4)
);
given += giveItem(
player,
new ItemStack(ModItems.getBind(BindVariant.LEATHER_STRAPS), 4)
);
// Gags // Gags
given += giveItem( given += giveDataDrivenItems(player, "cloth_gag", 4);
player, given += giveDataDrivenItems(player, "ball_gag", 4);
new ItemStack(ModItems.getGag(GagVariant.CLOTH_GAG), 4) given += giveDataDrivenItems(player, "tape_gag", 4);
);
given += giveItem(
player,
new ItemStack(ModItems.getGag(GagVariant.BALL_GAG), 4)
);
given += giveItem(
player,
new ItemStack(ModItems.getGag(GagVariant.TAPE_GAG), 4)
);
// Blindfolds // Blindfolds
given += giveItem( given += giveDataDrivenItems(player, "classic_blindfold", 4);
player, given += giveDataDrivenItems(player, "blindfold_mask", 2);
new ItemStack(ModItems.getBlindfold(BlindfoldVariant.CLASSIC), 4)
);
given += giveItem(
player,
new ItemStack(ModItems.getBlindfold(BlindfoldVariant.MASK), 2)
);
// Collars // Collars
given += giveItem( given += giveItem(
@@ -155,10 +129,7 @@ public class KidnapSetCommand {
given += giveItem(player, new ItemStack(ModItems.MASTER_KEY.get(), 1)); given += giveItem(player, new ItemStack(ModItems.MASTER_KEY.get(), 1));
// Earplugs // Earplugs
given += giveItem( given += giveDataDrivenItems(player, "classic_earplugs", 4);
player,
new ItemStack(ModItems.getEarplugs(EarplugsVariant.CLASSIC), 4)
);
// Rope arrows // Rope arrows
given += giveItem(player, new ItemStack(ModItems.ROPE_ARROW.get(), 16)); given += giveItem(player, new ItemStack(ModItems.ROPE_ARROW.get(), 16));
@@ -182,6 +153,18 @@ public class KidnapSetCommand {
return finalGiven; return finalGiven;
} }
private static int giveDataDrivenItems(ServerPlayer player, String itemName, int count) {
int given = 0;
for (int i = 0; i < count; i++) {
ItemStack stack = DataDrivenBondageItem.createStack(new ResourceLocation("tiedup", itemName));
if (!stack.isEmpty()) {
giveItem(player, stack);
given++;
}
}
return given;
}
private static int giveItem(ServerPlayer player, ItemStack stack) { private static int giveItem(ServerPlayer player, ItemStack stack) {
if (!player.getInventory().add(stack)) { if (!player.getInventory().add(stack)) {
// Drop on ground if inventory full // Drop on ground if inventory full

View File

@@ -7,11 +7,9 @@ import com.mojang.brigadier.exceptions.CommandSyntaxException;
import com.tiedup.remake.entities.*; import com.tiedup.remake.entities.*;
import com.tiedup.remake.entities.skins.EliteKidnapperSkinManager; import com.tiedup.remake.entities.skins.EliteKidnapperSkinManager;
import com.tiedup.remake.items.ModItems; import com.tiedup.remake.items.ModItems;
import com.tiedup.remake.items.base.BindVariant;
import com.tiedup.remake.items.base.BlindfoldVariant;
import com.tiedup.remake.items.base.EarplugsVariant;
import com.tiedup.remake.items.base.GagVariant;
import com.tiedup.remake.state.IBondageState; import com.tiedup.remake.state.IBondageState;
import com.tiedup.remake.v2.bondage.datadriven.DataDrivenBondageItem;
import net.minecraft.resources.ResourceLocation;
import com.tiedup.remake.v2.BodyRegionV2; import com.tiedup.remake.v2.BodyRegionV2;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
@@ -507,7 +505,7 @@ public class NPCCommand {
npc.equip( npc.equip(
BodyRegionV2.ARMS, BodyRegionV2.ARMS,
new ItemStack(ModItems.getBind(BindVariant.ROPES)) DataDrivenBondageItem.createStack(new ResourceLocation("tiedup", "ropes"))
); );
context context
.getSource() .getSource()
@@ -538,7 +536,7 @@ public class NPCCommand {
npc.equip( npc.equip(
BodyRegionV2.MOUTH, BodyRegionV2.MOUTH,
new ItemStack(ModItems.getGag(GagVariant.CLOTH_GAG)) DataDrivenBondageItem.createStack(new ResourceLocation("tiedup", "cloth_gag"))
); );
context context
.getSource() .getSource()
@@ -571,7 +569,7 @@ public class NPCCommand {
npc.equip( npc.equip(
BodyRegionV2.EYES, BodyRegionV2.EYES,
new ItemStack(ModItems.getBlindfold(BlindfoldVariant.CLASSIC)) DataDrivenBondageItem.createStack(new ResourceLocation("tiedup", "classic_blindfold"))
); );
context context
.getSource() .getSource()
@@ -656,10 +654,10 @@ public class NPCCommand {
com.tiedup.remake.entities.AbstractTiedUpNpc npcEntity com.tiedup.remake.entities.AbstractTiedUpNpc npcEntity
) { ) {
npcEntity.applyBondage( npcEntity.applyBondage(
new ItemStack(ModItems.getBind(BindVariant.ROPES)), DataDrivenBondageItem.createStack(new ResourceLocation("tiedup", "ropes")),
new ItemStack(ModItems.getGag(GagVariant.CLOTH_GAG)), DataDrivenBondageItem.createStack(new ResourceLocation("tiedup", "cloth_gag")),
new ItemStack(ModItems.getBlindfold(BlindfoldVariant.CLASSIC)), DataDrivenBondageItem.createStack(new ResourceLocation("tiedup", "classic_blindfold")),
new ItemStack(ModItems.getEarplugs(EarplugsVariant.CLASSIC)), DataDrivenBondageItem.createStack(new ResourceLocation("tiedup", "classic_earplugs")),
new ItemStack(ModItems.CLASSIC_COLLAR.get()), new ItemStack(ModItems.CLASSIC_COLLAR.get()),
ItemStack.EMPTY // No clothes ItemStack.EMPTY // No clothes
); );

View File

@@ -9,12 +9,10 @@ import com.tiedup.remake.commands.CommandHelper;
import com.tiedup.remake.core.SystemMessageManager; import com.tiedup.remake.core.SystemMessageManager;
import com.tiedup.remake.items.ModItems; import com.tiedup.remake.items.ModItems;
import com.tiedup.remake.items.base.AdjustmentHelper; import com.tiedup.remake.items.base.AdjustmentHelper;
import com.tiedup.remake.items.base.BindVariant;
import com.tiedup.remake.items.base.BlindfoldVariant;
import com.tiedup.remake.items.base.EarplugsVariant;
import com.tiedup.remake.items.base.GagVariant;
import com.tiedup.remake.items.base.ItemCollar;
import com.tiedup.remake.network.ModNetwork; import com.tiedup.remake.network.ModNetwork;
import com.tiedup.remake.v2.bondage.CollarHelper;
import com.tiedup.remake.v2.bondage.datadriven.DataDrivenBondageItem;
import net.minecraft.resources.ResourceLocation;
import com.tiedup.remake.network.sync.PacketSyncBindState; import com.tiedup.remake.network.sync.PacketSyncBindState;
import com.tiedup.remake.state.PlayerBindState; import com.tiedup.remake.state.PlayerBindState;
import net.minecraft.commands.CommandSourceStack; import net.minecraft.commands.CommandSourceStack;
@@ -256,7 +254,7 @@ public class BondageSubCommand {
return 0; return 0;
} }
ItemStack ropes = new ItemStack(ModItems.getBind(BindVariant.ROPES)); ItemStack ropes = DataDrivenBondageItem.createStack(new ResourceLocation("tiedup", "ropes"));
state.putBindOn(ropes); state.putBindOn(ropes);
CommandHelper.syncPlayerState(targetPlayer, state); CommandHelper.syncPlayerState(targetPlayer, state);
@@ -387,7 +385,7 @@ public class BondageSubCommand {
return 0; return 0;
} }
ItemStack gag = new ItemStack(ModItems.getGag(GagVariant.CLOTH_GAG)); ItemStack gag = DataDrivenBondageItem.createStack(new ResourceLocation("tiedup", "cloth_gag"));
state.putGagOn(gag); state.putGagOn(gag);
CommandHelper.syncPlayerState(targetPlayer, state); CommandHelper.syncPlayerState(targetPlayer, state);
@@ -440,9 +438,7 @@ public class BondageSubCommand {
return 0; return 0;
} }
ItemStack blindfold = new ItemStack( ItemStack blindfold = DataDrivenBondageItem.createStack(new ResourceLocation("tiedup", "classic_blindfold"));
ModItems.getBlindfold(BlindfoldVariant.CLASSIC)
);
state.putBlindfoldOn(blindfold); state.putBlindfoldOn(blindfold);
CommandHelper.syncPlayerState(targetPlayer, state); CommandHelper.syncPlayerState(targetPlayer, state);
@@ -500,8 +496,7 @@ public class BondageSubCommand {
ItemStack collar = new ItemStack(ModItems.CLASSIC_COLLAR.get()); ItemStack collar = new ItemStack(ModItems.CLASSIC_COLLAR.get());
if (context.getSource().getEntity() instanceof ServerPlayer executor) { if (context.getSource().getEntity() instanceof ServerPlayer executor) {
ItemCollar collarItem = (ItemCollar) collar.getItem(); CollarHelper.addOwner(collar, executor);
collarItem.addOwner(collar, executor);
} }
state.putCollarOn(collar); state.putCollarOn(collar);
@@ -1021,9 +1016,7 @@ public class BondageSubCommand {
return 0; return 0;
} }
ItemStack earplugs = new ItemStack( ItemStack earplugs = DataDrivenBondageItem.createStack(new ResourceLocation("tiedup", "classic_earplugs"));
ModItems.getEarplugs(EarplugsVariant.CLASSIC)
);
state.putEarplugsOn(earplugs); state.putEarplugsOn(earplugs);
CommandHelper.syncPlayerState(targetPlayer, state); CommandHelper.syncPlayerState(targetPlayer, state);
@@ -1067,25 +1060,19 @@ public class BondageSubCommand {
int applied = 0; int applied = 0;
if (!state.isTiedUp()) { if (!state.isTiedUp()) {
ItemStack ropes = new ItemStack( ItemStack ropes = DataDrivenBondageItem.createStack(new ResourceLocation("tiedup", "ropes"));
ModItems.getBind(BindVariant.ROPES)
);
state.putBindOn(ropes); state.putBindOn(ropes);
applied++; applied++;
} }
if (!state.isGagged()) { if (!state.isGagged()) {
ItemStack gag = new ItemStack( ItemStack gag = DataDrivenBondageItem.createStack(new ResourceLocation("tiedup", "cloth_gag"));
ModItems.getGag(GagVariant.CLOTH_GAG)
);
state.putGagOn(gag); state.putGagOn(gag);
applied++; applied++;
} }
if (!state.isBlindfolded()) { if (!state.isBlindfolded()) {
ItemStack blindfold = new ItemStack( ItemStack blindfold = DataDrivenBondageItem.createStack(new ResourceLocation("tiedup", "classic_blindfold"));
ModItems.getBlindfold(BlindfoldVariant.CLASSIC)
);
state.putBlindfoldOn(blindfold); state.putBlindfoldOn(blindfold);
applied++; applied++;
} }
@@ -1095,17 +1082,14 @@ public class BondageSubCommand {
if ( if (
context.getSource().getEntity() instanceof ServerPlayer executor context.getSource().getEntity() instanceof ServerPlayer executor
) { ) {
ItemCollar collarItem = (ItemCollar) collar.getItem(); CollarHelper.addOwner(collar, executor);
collarItem.addOwner(collar, executor);
} }
state.putCollarOn(collar); state.putCollarOn(collar);
applied++; applied++;
} }
if (!state.hasEarplugs()) { if (!state.hasEarplugs()) {
ItemStack earplugs = new ItemStack( ItemStack earplugs = DataDrivenBondageItem.createStack(new ResourceLocation("tiedup", "classic_earplugs"));
ModItems.getEarplugs(EarplugsVariant.CLASSIC)
);
state.putEarplugsOn(earplugs); state.putEarplugsOn(earplugs);
applied++; applied++;
} }
@@ -1167,21 +1151,15 @@ public class BondageSubCommand {
// First fully restrain // First fully restrain
if (!state.isTiedUp()) { if (!state.isTiedUp()) {
ItemStack ropes = new ItemStack( ItemStack ropes = DataDrivenBondageItem.createStack(new ResourceLocation("tiedup", "ropes"));
ModItems.getBind(BindVariant.ROPES)
);
state.putBindOn(ropes); state.putBindOn(ropes);
} }
if (!state.isGagged()) { if (!state.isGagged()) {
ItemStack gag = new ItemStack( ItemStack gag = DataDrivenBondageItem.createStack(new ResourceLocation("tiedup", "cloth_gag"));
ModItems.getGag(GagVariant.CLOTH_GAG)
);
state.putGagOn(gag); state.putGagOn(gag);
} }
if (!state.isBlindfolded()) { if (!state.isBlindfolded()) {
ItemStack blindfold = new ItemStack( ItemStack blindfold = DataDrivenBondageItem.createStack(new ResourceLocation("tiedup", "classic_blindfold"));
ModItems.getBlindfold(BlindfoldVariant.CLASSIC)
);
state.putBlindfoldOn(blindfold); state.putBlindfoldOn(blindfold);
} }
if (!state.hasCollar()) { if (!state.hasCollar()) {
@@ -1189,15 +1167,12 @@ public class BondageSubCommand {
if ( if (
context.getSource().getEntity() instanceof ServerPlayer executor context.getSource().getEntity() instanceof ServerPlayer executor
) { ) {
ItemCollar collarItem = (ItemCollar) collar.getItem(); CollarHelper.addOwner(collar, executor);
collarItem.addOwner(collar, executor);
} }
state.putCollarOn(collar); state.putCollarOn(collar);
} }
if (!state.hasEarplugs()) { if (!state.hasEarplugs()) {
ItemStack earplugs = new ItemStack( ItemStack earplugs = DataDrivenBondageItem.createStack(new ResourceLocation("tiedup", "classic_earplugs"));
ModItems.getEarplugs(EarplugsVariant.CLASSIC)
);
state.putEarplugsOn(earplugs); state.putEarplugsOn(earplugs);
} }

View File

@@ -2,8 +2,10 @@ package com.tiedup.remake.compat.mca.capability;
import com.tiedup.remake.compat.mca.MCABondageManager; import com.tiedup.remake.compat.mca.MCABondageManager;
import com.tiedup.remake.compat.mca.MCACompat; import com.tiedup.remake.compat.mca.MCACompat;
import com.tiedup.remake.items.base.IHasBlindingEffect; import com.tiedup.remake.v2.bondage.component.BlindingComponent;
import com.tiedup.remake.items.base.IHasGaggingEffect; 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.items.base.IHasResistance; import com.tiedup.remake.items.base.IHasResistance;
import com.tiedup.remake.items.base.ILockable; import com.tiedup.remake.items.base.ILockable;
import com.tiedup.remake.items.base.ItemBind; import com.tiedup.remake.items.base.ItemBind;
@@ -277,16 +279,17 @@ public class MCAKidnappedAdapter implements IRestrainable {
@Override @Override
public boolean hasGaggingEffect() { public boolean hasGaggingEffect() {
ItemStack gag = cap.getGag(); ItemStack gag = cap.getGag();
return !gag.isEmpty() && gag.getItem() instanceof IHasGaggingEffect; if (gag.isEmpty()) return false;
if (DataDrivenBondageItem.getComponent(gag, ComponentType.GAGGING, GaggingComponent.class) != null) return true;
return gag.getItem() instanceof com.tiedup.remake.items.base.IHasGaggingEffect;
} }
@Override @Override
public boolean hasBlindingEffect() { public boolean hasBlindingEffect() {
ItemStack blindfold = cap.getBlindfold(); ItemStack blindfold = cap.getBlindfold();
return ( if (blindfold.isEmpty()) return false;
!blindfold.isEmpty() && if (DataDrivenBondageItem.getComponent(blindfold, ComponentType.BLINDING, BlindingComponent.class) != null) return true;
blindfold.getItem() instanceof IHasBlindingEffect return blindfold.getItem() instanceof com.tiedup.remake.items.base.IHasBlindingEffect;
);
} }
@Override @Override

View File

@@ -5,6 +5,9 @@ import static com.tiedup.remake.util.GameConstants.*;
import com.tiedup.remake.dialogue.EmotionalContext.EmotionType; import com.tiedup.remake.dialogue.EmotionalContext.EmotionType;
import com.tiedup.remake.items.base.ItemGag; import com.tiedup.remake.items.base.ItemGag;
import com.tiedup.remake.state.IBondageState; import com.tiedup.remake.state.IBondageState;
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.util.GagMaterial; import com.tiedup.remake.util.GagMaterial;
import com.tiedup.remake.util.PhoneticMapper; import com.tiedup.remake.util.PhoneticMapper;
import com.tiedup.remake.util.SyllableAnalyzer; import com.tiedup.remake.util.SyllableAnalyzer;
@@ -58,7 +61,12 @@ public class GagTalkManager {
) { ) {
LivingEntity entity = kidnapped.asLivingEntity(); LivingEntity entity = kidnapped.asLivingEntity();
GagMaterial material = GagMaterial.CLOTH; GagMaterial material = GagMaterial.CLOTH;
if (gagStack.getItem() instanceof ItemGag gag) { // V2: check data-driven GaggingComponent first
GaggingComponent gaggingComp = DataDrivenBondageItem.getComponent(
gagStack, ComponentType.GAGGING, GaggingComponent.class);
if (gaggingComp != null && gaggingComp.getMaterial() != null) {
material = gaggingComp.getMaterial();
} else if (gagStack.getItem() instanceof ItemGag gag) {
material = gag.getGagMaterial(); material = gag.getGagMaterial();
} }
@@ -514,9 +522,16 @@ public class GagTalkManager {
} }
GagMaterial material = GagMaterial.CLOTH; GagMaterial material = GagMaterial.CLOTH;
if (gagStack != null && gagStack.getItem() instanceof ItemGag gag) { if (gagStack != null && !gagStack.isEmpty()) {
// V2: check data-driven GaggingComponent first
GaggingComponent comp = DataDrivenBondageItem.getComponent(
gagStack, ComponentType.GAGGING, GaggingComponent.class);
if (comp != null && comp.getMaterial() != null) {
material = comp.getMaterial();
} else if (gagStack.getItem() instanceof ItemGag gag) {
material = gag.getGagMaterial(); material = gag.getGagMaterial();
} }
}
StringBuilder muffled = new StringBuilder(); StringBuilder muffled = new StringBuilder();
String[] words = originalMessage.split("\\s+"); String[] words = originalMessage.split("\\s+");

View File

@@ -5,9 +5,9 @@ import com.tiedup.remake.dialogue.DialogueBridge;
import com.tiedup.remake.entities.EntityMaster; import com.tiedup.remake.entities.EntityMaster;
import com.tiedup.remake.entities.ai.master.MasterPlaceBlockGoal; import com.tiedup.remake.entities.ai.master.MasterPlaceBlockGoal;
import com.tiedup.remake.entities.ai.master.MasterState; import com.tiedup.remake.entities.ai.master.MasterState;
import com.tiedup.remake.items.ModItems;
import com.tiedup.remake.items.base.BindVariant;
import com.tiedup.remake.network.ModNetwork; import com.tiedup.remake.network.ModNetwork;
import com.tiedup.remake.v2.bondage.datadriven.DataDrivenBondageItem;
import net.minecraft.resources.ResourceLocation;
import com.tiedup.remake.network.master.PacketOpenPetRequestMenu; import com.tiedup.remake.network.master.PacketOpenPetRequestMenu;
import com.tiedup.remake.state.PlayerBindState; import com.tiedup.remake.state.PlayerBindState;
import com.tiedup.remake.v2.BodyRegionV2; import com.tiedup.remake.v2.BodyRegionV2;
@@ -171,9 +171,7 @@ public class PetRequestManager {
// Put dogbind on player (if not already tied) // Put dogbind on player (if not already tied)
if (!state.isTiedUp()) { if (!state.isTiedUp()) {
ItemStack dogbind = new ItemStack( ItemStack dogbind = DataDrivenBondageItem.createStack(new ResourceLocation("tiedup", "dogbinder"));
ModItems.getBind(BindVariant.DOGBINDER)
);
state.equip(BodyRegionV2.ARMS, dogbind); state.equip(BodyRegionV2.ARMS, dogbind);
TiedUpMod.LOGGER.debug( TiedUpMod.LOGGER.debug(
"[PetRequestManager] Equipped dogbind on {} for walk", "[PetRequestManager] Equipped dogbind on {} for walk",
@@ -228,7 +226,7 @@ public class PetRequestManager {
} }
// Master equips armbinder on pet (classic pet play restraint) // Master equips armbinder on pet (classic pet play restraint)
ItemStack bind = new ItemStack(ModItems.getBind(BindVariant.ARMBINDER)); ItemStack bind = DataDrivenBondageItem.createStack(new ResourceLocation("tiedup", "armbinder"));
state.equip(BodyRegionV2.ARMS, bind); state.equip(BodyRegionV2.ARMS, bind);
DialogueBridge.talkTo(master, pet, "petplay.tie_accept"); DialogueBridge.talkTo(master, pet, "petplay.tie_accept");

View File

@@ -4,7 +4,12 @@ import com.tiedup.remake.core.TiedUpMod;
import com.tiedup.remake.entities.damsel.components.*; import com.tiedup.remake.entities.damsel.components.*;
import com.tiedup.remake.entities.skins.Gender; import com.tiedup.remake.entities.skins.Gender;
import com.tiedup.remake.items.base.ILockable; import com.tiedup.remake.items.base.ILockable;
import com.tiedup.remake.items.base.ItemCollar; import com.tiedup.remake.v2.bondage.CollarHelper;
import com.tiedup.remake.v2.bondage.PoseTypeHelper;
import com.tiedup.remake.v2.bondage.datadriven.DataDrivenBondageItem;
import com.tiedup.remake.v2.bondage.component.ComponentType;
import com.tiedup.remake.v2.bondage.component.GaggingComponent;
import com.tiedup.remake.v2.bondage.component.BlindingComponent;
import com.tiedup.remake.state.ICaptor; import com.tiedup.remake.state.ICaptor;
import com.tiedup.remake.state.IRestrainable; import com.tiedup.remake.state.IRestrainable;
import com.tiedup.remake.state.IRestrainableEntity; import com.tiedup.remake.state.IRestrainableEntity;
@@ -455,16 +460,8 @@ public abstract class AbstractTiedUpNpc
*/ */
public boolean isDogPose() { public boolean isDogPose() {
ItemStack bind = this.getEquipment(BodyRegionV2.ARMS); ItemStack bind = this.getEquipment(BodyRegionV2.ARMS);
if ( if (bind.isEmpty()) return false;
bind.getItem() instanceof return PoseTypeHelper.getPoseType(bind) == com.tiedup.remake.items.base.PoseType.DOG;
com.tiedup.remake.items.base.ItemBind itemBind
) {
return (
itemBind.getPoseType() ==
com.tiedup.remake.items.base.PoseType.DOG
);
}
return false;
} }
/** /**
@@ -679,12 +676,10 @@ public abstract class AbstractTiedUpNpc
// Exception: collar owner can leash even if not tied // Exception: collar owner can leash even if not tied
if (this.hasCollar()) { if (this.hasCollar()) {
ItemStack collar = this.getEquipment(BodyRegionV2.NECK); ItemStack collar = this.getEquipment(BodyRegionV2.NECK);
if (collar.getItem() instanceof ItemCollar collarItem) { if (CollarHelper.isOwner(collar, player)) {
if (collarItem.getOwners(collar).contains(player.getUUID())) {
return true; return true;
} }
} }
}
return false; return false;
} }
@@ -801,20 +796,16 @@ public abstract class AbstractTiedUpNpc
public boolean hasGaggingEffect() { public boolean hasGaggingEffect() {
ItemStack gag = this.getEquipment(BodyRegionV2.MOUTH); ItemStack gag = this.getEquipment(BodyRegionV2.MOUTH);
if (gag.isEmpty()) return false; if (gag.isEmpty()) return false;
return ( if (DataDrivenBondageItem.getComponent(gag, ComponentType.GAGGING, GaggingComponent.class) != null) return true;
gag.getItem() instanceof return gag.getItem() instanceof com.tiedup.remake.items.base.IHasGaggingEffect;
com.tiedup.remake.items.base.IHasGaggingEffect
);
} }
@Override @Override
public boolean hasBlindingEffect() { public boolean hasBlindingEffect() {
ItemStack blindfold = this.getEquipment(BodyRegionV2.EYES); ItemStack blindfold = this.getEquipment(BodyRegionV2.EYES);
if (blindfold.isEmpty()) return false; if (blindfold.isEmpty()) return false;
return ( if (DataDrivenBondageItem.getComponent(blindfold, ComponentType.BLINDING, BlindingComponent.class) != null) return true;
blindfold.getItem() instanceof return blindfold.getItem() instanceof com.tiedup.remake.items.base.IHasBlindingEffect;
com.tiedup.remake.items.base.IHasBlindingEffect
);
} }
@Override @Override
@@ -990,9 +981,9 @@ public abstract class AbstractTiedUpNpc
ItemStack collar = this.getEquipment(BodyRegionV2.NECK); ItemStack collar = this.getEquipment(BodyRegionV2.NECK);
if (collar.isEmpty()) return false; if (collar.isEmpty()) return false;
if (!(collar.getItem() instanceof ItemCollar itemCollar)) return false; if (!CollarHelper.isCollar(collar)) return false;
java.util.UUID cellId = itemCollar.getCellId(collar); java.util.UUID cellId = CollarHelper.getCellId(collar);
if (cellId == null) return false; if (cellId == null) return false;
// Get cell position from registry // Get cell position from registry

View File

@@ -1,10 +1,9 @@
package com.tiedup.remake.entities; package com.tiedup.remake.entities;
import com.tiedup.remake.core.SystemMessageManager; import com.tiedup.remake.core.SystemMessageManager;
import com.tiedup.remake.items.ModItems; import com.tiedup.remake.v2.bondage.CollarHelper;
import com.tiedup.remake.items.base.BindVariant; import com.tiedup.remake.v2.bondage.datadriven.DataDrivenBondageItem;
import com.tiedup.remake.items.base.GagVariant; import net.minecraft.resources.ResourceLocation;
import com.tiedup.remake.items.base.ItemCollar;
import com.tiedup.remake.state.PlayerBindState; import com.tiedup.remake.state.PlayerBindState;
import com.tiedup.remake.util.MessageDispatcher; import com.tiedup.remake.util.MessageDispatcher;
import com.tiedup.remake.util.teleport.Position; import com.tiedup.remake.util.teleport.Position;
@@ -53,14 +52,11 @@ public class BondageServiceHandler {
if (!npc.hasCollar()) return false; if (!npc.hasCollar()) return false;
ItemStack collar = npc.getEquipment(BodyRegionV2.NECK); ItemStack collar = npc.getEquipment(BodyRegionV2.NECK);
if (collar.getItem() instanceof ItemCollar itemCollar) {
return ( return (
itemCollar.hasCellAssigned(collar) && CollarHelper.hasCellAssigned(collar) &&
itemCollar.isBondageServiceEnabled(collar) CollarHelper.isBondageServiceEnabled(collar)
); );
} }
return false;
}
/** /**
* Get the custom bondage service message from the collar. * Get the custom bondage service message from the collar.
@@ -70,13 +66,11 @@ public class BondageServiceHandler {
public String getMessage() { public String getMessage() {
if (npc.hasCollar()) { if (npc.hasCollar()) {
ItemStack collar = npc.getEquipment(BodyRegionV2.NECK); ItemStack collar = npc.getEquipment(BodyRegionV2.NECK);
if (collar.getItem() instanceof ItemCollar itemCollar) { String message = CollarHelper.getServiceSentence(collar);
String message = itemCollar.getServiceSentence(collar);
if (message != null && !message.isEmpty()) { if (message != null && !message.isEmpty()) {
return message; return message;
} }
} }
}
return DEFAULT_MESSAGE; return DEFAULT_MESSAGE;
} }
@@ -119,9 +113,9 @@ public class BondageServiceHandler {
*/ */
private void capturePlayer(Player player) { private void capturePlayer(Player player) {
ItemStack collar = npc.getEquipment(BodyRegionV2.NECK); ItemStack collar = npc.getEquipment(BodyRegionV2.NECK);
if (!(collar.getItem() instanceof ItemCollar itemCollar)) return; if (!CollarHelper.isCollar(collar)) return;
java.util.UUID cellId = itemCollar.getCellId(collar); java.util.UUID cellId = CollarHelper.getCellId(collar);
if (cellId == null) return; if (cellId == null) return;
// Get cell position from registry // Get cell position from registry
@@ -141,7 +135,7 @@ public class BondageServiceHandler {
); );
// Warn masters if configured // Warn masters if configured
warnOwners(player, itemCollar, collar); warnOwners(player, collar);
// Get player's kidnapped state // Get player's kidnapped state
PlayerBindState state = PlayerBindState.getInstance(player); PlayerBindState state = PlayerBindState.getInstance(player);
@@ -149,18 +143,18 @@ public class BondageServiceHandler {
// Apply bondage // Apply bondage
state.equip( state.equip(
BodyRegionV2.ARMS, BodyRegionV2.ARMS,
new ItemStack(ModItems.getBind(BindVariant.ROPES)) DataDrivenBondageItem.createStack(new ResourceLocation("tiedup", "ropes"))
); );
state.equip( state.equip(
BodyRegionV2.MOUTH, BodyRegionV2.MOUTH,
new ItemStack(ModItems.getGag(GagVariant.BALL_GAG)) DataDrivenBondageItem.createStack(new ResourceLocation("tiedup", "ball_gag"))
); );
// Teleport to cell // Teleport to cell
state.teleportToPosition(cellPosition); state.teleportToPosition(cellPosition);
// Tie to pole if configured on collar // Tie to pole if configured on collar
if (itemCollar.shouldTieToPole(collar)) { if (CollarHelper.shouldTieToPole(collar)) {
state.tieToClosestPole(3); state.tieToClosestPole(3);
} }
} }
@@ -178,10 +172,9 @@ public class BondageServiceHandler {
*/ */
private void warnOwners( private void warnOwners(
Player capturedPlayer, Player capturedPlayer,
ItemCollar itemCollar,
ItemStack collarStack ItemStack collarStack
) { ) {
if (!itemCollar.shouldWarnMasters(collarStack)) { if (!CollarHelper.shouldWarnMasters(collarStack)) {
return; return;
} }
@@ -191,7 +184,7 @@ public class BondageServiceHandler {
capturedPlayer.getName().getString() + capturedPlayer.getName().getString() +
" via bondage service!"; " via bondage service!";
for (UUID ownerUUID : itemCollar.getOwners(collarStack)) { for (UUID ownerUUID : CollarHelper.getOwners(collarStack)) {
Player owner = npc.level().getPlayerByUUID(ownerUUID); Player owner = npc.level().getPlayerByUUID(ownerUUID);
if (owner != null) { if (owner != null) {
SystemMessageManager.sendChatToPlayer( SystemMessageManager.sendChatToPlayer(

View File

@@ -5,7 +5,7 @@ import com.tiedup.remake.core.TiedUpMod;
import com.tiedup.remake.entities.damsel.components.*; import com.tiedup.remake.entities.damsel.components.*;
import com.tiedup.remake.entities.skins.DamselSkinManager; import com.tiedup.remake.entities.skins.DamselSkinManager;
import com.tiedup.remake.entities.skins.Gender; import com.tiedup.remake.entities.skins.Gender;
import com.tiedup.remake.items.base.ItemCollar; import com.tiedup.remake.v2.bondage.CollarHelper;
import com.tiedup.remake.state.ICaptor; import com.tiedup.remake.state.ICaptor;
import com.tiedup.remake.v2.BodyRegionV2; import com.tiedup.remake.v2.BodyRegionV2;
import java.util.UUID; import java.util.UUID;
@@ -527,8 +527,8 @@ public class EntityDamsel
if (!this.hasCollar()) return false; if (!this.hasCollar()) return false;
ItemStack collar = this.getEquipment(BodyRegionV2.NECK); ItemStack collar = this.getEquipment(BodyRegionV2.NECK);
if (!(collar.getItem() instanceof ItemCollar collarItem)) return false; if (!CollarHelper.isCollar(collar)) return false;
if (!collarItem.getOwners(collar).contains(commander.getUUID())) { if (!CollarHelper.isOwner(collar, commander.getUUID())) {
if (!this.isGagged()) { if (!this.isGagged()) {
com.tiedup.remake.dialogue.EntityDialogueManager.talkByDialogueId( com.tiedup.remake.dialogue.EntityDialogueManager.talkByDialogueId(
this, this,
@@ -653,8 +653,8 @@ public class EntityDamsel
return net.minecraft.world.InteractionResult.FAIL; return net.minecraft.world.InteractionResult.FAIL;
} }
ItemStack collar = this.getEquipment(BodyRegionV2.NECK); ItemStack collar = this.getEquipment(BodyRegionV2.NECK);
if (collar.getItem() instanceof ItemCollar collarItem) { if (CollarHelper.isCollar(collar)) {
if (!collarItem.isOwner(collar, player)) { if (!CollarHelper.isOwner(collar, player)) {
if ( if (
player instanceof player instanceof
net.minecraft.server.level.ServerPlayer sp net.minecraft.server.level.ServerPlayer sp
@@ -693,9 +693,9 @@ public class EntityDamsel
this.hasCollar() this.hasCollar()
) { ) {
ItemStack collar = this.getEquipment(BodyRegionV2.NECK); ItemStack collar = this.getEquipment(BodyRegionV2.NECK);
if (collar.getItem() instanceof ItemCollar collarItem) { if (CollarHelper.isCollar(collar)) {
if ( if (
collarItem.isOwner(collar, player) && CollarHelper.isOwner(collar, player) &&
player instanceof player instanceof
net.minecraft.server.level.ServerPlayer serverPlayer net.minecraft.server.level.ServerPlayer serverPlayer
) { ) {
@@ -822,8 +822,8 @@ public class EntityDamsel
public String getTargetRelation(Player player) { public String getTargetRelation(Player player) {
if (hasCollar()) { if (hasCollar()) {
ItemStack collar = getEquipment(BodyRegionV2.NECK); ItemStack collar = getEquipment(BodyRegionV2.NECK);
if (collar.getItem() instanceof ItemCollar collarItem) { if (CollarHelper.isCollar(collar)) {
if (collarItem.isOwner(collar, player)) { if (CollarHelper.isOwner(collar, player)) {
return "master"; return "master";
} }
} }

View File

@@ -12,7 +12,7 @@ import com.tiedup.remake.entities.kidnapper.components.KidnapperAggressionSystem
import com.tiedup.remake.entities.skins.Gender; import com.tiedup.remake.entities.skins.Gender;
import com.tiedup.remake.entities.skins.KidnapperSkinManager; import com.tiedup.remake.entities.skins.KidnapperSkinManager;
import com.tiedup.remake.items.ModItems; import com.tiedup.remake.items.ModItems;
import com.tiedup.remake.items.base.ItemCollar; import com.tiedup.remake.v2.bondage.CollarHelper;
import com.tiedup.remake.personality.PersonalityType; import com.tiedup.remake.personality.PersonalityType;
import com.tiedup.remake.state.IBondageState; import com.tiedup.remake.state.IBondageState;
import com.tiedup.remake.state.ICaptor; import com.tiedup.remake.state.ICaptor;
@@ -1367,10 +1367,7 @@ public class EntityKidnapper
if (!this.hasCollar()) return false; if (!this.hasCollar()) return false;
ItemStack collar = this.getEquipment(BodyRegionV2.NECK); ItemStack collar = this.getEquipment(BodyRegionV2.NECK);
if (collar.getItem() instanceof ItemCollar collarItem) { return CollarHelper.isOwner(collar, player);
return collarItem.isOwner(collar, player);
}
return false;
} }
/** Damage reduction multiplier against monsters (50% damage taken) */ /** Damage reduction multiplier against monsters (50% damage taken) */

View File

@@ -18,6 +18,7 @@ import com.tiedup.remake.state.IBondageState;
import com.tiedup.remake.state.ICaptor; import com.tiedup.remake.state.ICaptor;
import com.tiedup.remake.util.MessageDispatcher; import com.tiedup.remake.util.MessageDispatcher;
import com.tiedup.remake.v2.BodyRegionV2; import com.tiedup.remake.v2.BodyRegionV2;
import com.tiedup.remake.v2.bondage.datadriven.DataDrivenBondageItem;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.HashSet; import java.util.HashSet;
@@ -615,78 +616,82 @@ public class EntityKidnapperMerchant extends EntityKidnapperElite {
private List<ItemStack> collectAllModItems() { private List<ItemStack> collectAllModItems() {
List<ItemStack> items = new ArrayList<>(); List<ItemStack> items = new ArrayList<>();
// All binds (15) // All binds — iterate V1 variants, create V2 stacks
// Items with colors get multiple variants (one per color)
for (BindVariant variant : BindVariant.values()) { for (BindVariant variant : BindVariant.values()) {
if (variant.supportsColor()) { if (variant.supportsColor()) {
// Add one item per color (16 standard colors)
for (ItemColor color : ItemColor.values()) { for (ItemColor color : ItemColor.values()) {
if ( if (
color != ItemColor.CAUTION && color != ItemColor.CLEAR color != ItemColor.CAUTION && color != ItemColor.CLEAR
) { ) {
ItemStack stack = new ItemStack( ItemStack stack = DataDrivenBondageItem.createStack(
ModItems.getBind(variant) new net.minecraft.resources.ResourceLocation("tiedup", variant.getRegistryName())
); );
KidnapperItemSelector.applyColor(stack, color); KidnapperItemSelector.applyColor(stack, color);
items.add(stack); items.add(stack);
} }
} }
} else { } else {
// No color variants items.add(DataDrivenBondageItem.createStack(
items.add(new ItemStack(ModItems.getBind(variant))); new net.minecraft.resources.ResourceLocation("tiedup", variant.getRegistryName())
));
} }
} }
// All gags (19) // All gags
for (GagVariant variant : GagVariant.values()) { for (GagVariant variant : GagVariant.values()) {
if (variant.supportsColor()) { if (variant.supportsColor()) {
// Add one item per color
for (ItemColor color : ItemColor.values()) { for (ItemColor color : ItemColor.values()) {
// TAPE_GAG can use caution/clear, others only standard colors
if ( if (
variant == GagVariant.TAPE_GAG || variant == GagVariant.TAPE_GAG ||
(color != ItemColor.CAUTION && color != ItemColor.CLEAR) (color != ItemColor.CAUTION && color != ItemColor.CLEAR)
) { ) {
ItemStack stack = new ItemStack( ItemStack stack = DataDrivenBondageItem.createStack(
ModItems.getGag(variant) new net.minecraft.resources.ResourceLocation("tiedup", variant.getRegistryName())
); );
KidnapperItemSelector.applyColor(stack, color); KidnapperItemSelector.applyColor(stack, color);
items.add(stack); items.add(stack);
} }
} }
} else { } else {
items.add(new ItemStack(ModItems.getGag(variant))); items.add(DataDrivenBondageItem.createStack(
new net.minecraft.resources.ResourceLocation("tiedup", variant.getRegistryName())
));
} }
} }
// All blindfolds (2) - BOTH support colors // All blindfolds
for (BlindfoldVariant variant : BlindfoldVariant.values()) { for (BlindfoldVariant variant : BlindfoldVariant.values()) {
if (variant.supportsColor()) { if (variant.supportsColor()) {
// Add one item per color (16 standard colors)
for (ItemColor color : ItemColor.values()) { for (ItemColor color : ItemColor.values()) {
if ( if (
color != ItemColor.CAUTION && color != ItemColor.CLEAR color != ItemColor.CAUTION && color != ItemColor.CLEAR
) { ) {
ItemStack stack = new ItemStack( ItemStack stack = DataDrivenBondageItem.createStack(
ModItems.getBlindfold(variant) new net.minecraft.resources.ResourceLocation("tiedup", variant.getRegistryName())
); );
KidnapperItemSelector.applyColor(stack, color); KidnapperItemSelector.applyColor(stack, color);
items.add(stack); items.add(stack);
} }
} }
} else { } else {
items.add(new ItemStack(ModItems.getBlindfold(variant))); items.add(DataDrivenBondageItem.createStack(
new net.minecraft.resources.ResourceLocation("tiedup", variant.getRegistryName())
));
} }
} }
// Earplugs - no color support // Earplugs - no color support
for (EarplugsVariant variant : EarplugsVariant.values()) { for (EarplugsVariant variant : EarplugsVariant.values()) {
items.add(new ItemStack(ModItems.getEarplugs(variant))); items.add(DataDrivenBondageItem.createStack(
new net.minecraft.resources.ResourceLocation("tiedup", variant.getRegistryName())
));
} }
// Mittens - no color support // Mittens - no color support
for (MittensVariant variant : MittensVariant.values()) { for (MittensVariant variant : MittensVariant.values()) {
items.add(new ItemStack(ModItems.getMittens(variant))); items.add(DataDrivenBondageItem.createStack(
new net.minecraft.resources.ResourceLocation("tiedup", variant.getRegistryName())
));
} }
// Knives - no color support // Knives - no color support

View File

@@ -94,10 +94,8 @@ public class EntityRopeArrow extends AbstractArrow {
int roll = this.random.nextInt(100) + 1; int roll = this.random.nextInt(100) + 1;
if (roll <= bindChance) { if (roll <= bindChance) {
// Success! Bind the target // Success! Bind the target
ItemStack ropeItem = new ItemStack( ItemStack ropeItem = com.tiedup.remake.v2.bondage.datadriven.DataDrivenBondageItem.createStack(
ModItems.getBind( new net.minecraft.resources.ResourceLocation("tiedup", "ropes")
com.tiedup.remake.items.base.BindVariant.ROPES
)
); );
targetState.equip(BodyRegionV2.ARMS, ropeItem); targetState.equip(BodyRegionV2.ARMS, ropeItem);

View File

@@ -1,7 +1,8 @@
package com.tiedup.remake.entities; package com.tiedup.remake.entities;
import com.tiedup.remake.items.ModItems; import com.tiedup.remake.items.ModItems;
import com.tiedup.remake.items.base.BindVariant; import com.tiedup.remake.v2.bondage.datadriven.DataDrivenBondageItem;
import net.minecraft.resources.ResourceLocation;
import com.tiedup.remake.v2.bondage.IV2BondageItem; import com.tiedup.remake.v2.bondage.IV2BondageItem;
import net.minecraft.world.entity.EquipmentSlot; import net.minecraft.world.entity.EquipmentSlot;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
@@ -46,7 +47,7 @@ public class KidnapperCaptureEquipment {
) { ) {
return mainHand; return mainHand;
} }
return new ItemStack(ModItems.getBind(BindVariant.ROPES)); return DataDrivenBondageItem.createStack(new ResourceLocation("tiedup", "ropes"));
} }
/** /**

View File

@@ -1,11 +1,9 @@
package com.tiedup.remake.entities; package com.tiedup.remake.entities;
import com.tiedup.remake.items.base.ItemCollar;
import com.tiedup.remake.util.teleport.Position;
import com.tiedup.remake.v2.BodyRegionV2; import com.tiedup.remake.v2.BodyRegionV2;
import com.tiedup.remake.v2.bondage.CollarHelper;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
@@ -31,21 +29,7 @@ public class KidnapperCollarConfig {
this.kidnapper = kidnapper; this.kidnapper = kidnapper;
} }
// COLLAR ITEM ACCESS // COLLAR STACK ACCESS
/**
* Get the collar item if equipped.
* @return ItemCollar or null if no collar or not an ItemCollar
*/
@Nullable
public ItemCollar getCollarItem() {
ItemStack collar = kidnapper.getEquipment(BodyRegionV2.NECK);
if (collar.isEmpty()) return null;
if (collar.getItem() instanceof ItemCollar itemCollar) {
return itemCollar;
}
return null;
}
/** /**
* Get the collar ItemStack. * Get the collar ItemStack.
@@ -55,30 +39,29 @@ public class KidnapperCollarConfig {
return kidnapper.getEquipment(BodyRegionV2.NECK); return kidnapper.getEquipment(BodyRegionV2.NECK);
} }
/**
* Check if the kidnapper has a valid collar.
*/
private boolean hasValidCollar() {
return kidnapper.hasCollar() && CollarHelper.isCollar(getCollarStack());
}
// KIDNAPPING MODE // KIDNAPPING MODE
/** /**
* Check if kidnapping mode is enabled via collar. * Check if kidnapping mode is enabled via collar.
*/ */
public boolean isKidnappingModeEnabled() { public boolean isKidnappingModeEnabled() {
if (!kidnapper.hasCollar()) return false; if (!hasValidCollar()) return false;
return CollarHelper.isKidnappingModeEnabled(getCollarStack());
ItemCollar itemCollar = getCollarItem();
if (itemCollar == null) return false;
return itemCollar.isKidnappingModeEnabled(getCollarStack());
} }
/** /**
* Check if kidnapping mode is fully ready (enabled + prison set). * Check if kidnapping mode is fully ready (enabled + prison set).
*/ */
public boolean isKidnappingModeReady() { public boolean isKidnappingModeReady() {
if (!kidnapper.hasCollar()) return false; if (!hasValidCollar()) return false;
return CollarHelper.isKidnappingModeReady(getCollarStack());
ItemCollar itemCollar = getCollarItem();
if (itemCollar == null) return false;
return itemCollar.isKidnappingModeReady(getCollarStack());
} }
// POSITION GETTERS // POSITION GETTERS
@@ -88,20 +71,16 @@ public class KidnapperCollarConfig {
*/ */
@Nullable @Nullable
public java.util.UUID getCellId() { public java.util.UUID getCellId() {
ItemCollar itemCollar = getCollarItem(); if (!hasValidCollar()) return null;
if (itemCollar == null) return null; return CollarHelper.getCellId(getCollarStack());
return itemCollar.getCellId(getCollarStack());
} }
/** /**
* Check if collar has a cell assigned. * Check if collar has a cell assigned.
*/ */
public boolean hasCellAssigned() { public boolean hasCellAssigned() {
ItemCollar itemCollar = getCollarItem(); if (!hasValidCollar()) return false;
if (itemCollar == null) return false; return CollarHelper.hasCellAssigned(getCollarStack());
return itemCollar.hasCellAssigned(getCollarStack());
} }
// BEHAVIOR FLAGS // BEHAVIOR FLAGS
@@ -110,20 +89,16 @@ public class KidnapperCollarConfig {
* Check if should warn masters after capturing slave. * Check if should warn masters after capturing slave.
*/ */
public boolean shouldWarnMasters() { public boolean shouldWarnMasters() {
ItemCollar itemCollar = getCollarItem(); if (!hasValidCollar()) return false;
if (itemCollar == null) return false; return CollarHelper.shouldWarnMasters(getCollarStack());
return itemCollar.shouldWarnMasters(getCollarStack());
} }
/** /**
* Check if should tie slave to pole in prison. * Check if should tie slave to pole in prison.
*/ */
public boolean shouldTieToPole() { public boolean shouldTieToPole() {
ItemCollar itemCollar = getCollarItem(); if (!hasValidCollar()) return false;
if (itemCollar == null) return false; return CollarHelper.shouldTieToPole(getCollarStack());
return itemCollar.shouldTieToPole(getCollarStack());
} }
// BLACKLIST/WHITELIST // BLACKLIST/WHITELIST
@@ -139,19 +114,18 @@ public class KidnapperCollarConfig {
* </ul> * </ul>
*/ */
public boolean isValidKidnappingTarget(Player player) { public boolean isValidKidnappingTarget(Player player) {
ItemCollar itemCollar = getCollarItem(); if (!hasValidCollar()) return true; // No collar config = everyone is valid
if (itemCollar == null) return true; // No collar config = everyone is valid
ItemStack collarStack = getCollarStack(); ItemStack collarStack = getCollarStack();
UUID playerUUID = player.getUUID(); UUID playerUUID = player.getUUID();
// If whitelist exists and is not empty, player MUST be on it // If whitelist exists and is not empty, player MUST be on it
List<UUID> whitelist = itemCollar.getWhitelist(collarStack); List<UUID> whitelist = CollarHelper.getWhitelist(collarStack);
if (!whitelist.isEmpty()) { if (!whitelist.isEmpty()) {
return whitelist.contains(playerUUID); return whitelist.contains(playerUUID);
} }
// Otherwise, check blacklist (blacklisted = not a valid target) // Otherwise, check blacklist (blacklisted = not a valid target)
return !itemCollar.isBlacklisted(collarStack, playerUUID); return !CollarHelper.isBlacklisted(collarStack, playerUUID);
} }
} }

View File

@@ -1,8 +1,9 @@
package com.tiedup.remake.entities; package com.tiedup.remake.entities;
import com.tiedup.remake.items.ModItems;
import com.tiedup.remake.items.base.*; import com.tiedup.remake.items.base.*;
import com.tiedup.remake.v2.bondage.datadriven.DataDrivenBondageItem;
import java.util.Random; import java.util.Random;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
@@ -242,7 +243,9 @@ public class KidnapperItemSelector {
BindVariant variant, BindVariant variant,
@Nullable ItemColor color @Nullable ItemColor color
) { ) {
ItemStack stack = new ItemStack(ModItems.getBind(variant)); ItemStack stack = DataDrivenBondageItem.createStack(
new ResourceLocation("tiedup", variant.getRegistryName())
);
if (color != null && variant.supportsColor()) { if (color != null && variant.supportsColor()) {
applyColor(stack, color); applyColor(stack, color);
} }
@@ -257,7 +260,9 @@ public class KidnapperItemSelector {
GagVariant variant, GagVariant variant,
@Nullable ItemColor color @Nullable ItemColor color
) { ) {
ItemStack stack = new ItemStack(ModItems.getGag(variant)); ItemStack stack = DataDrivenBondageItem.createStack(
new ResourceLocation("tiedup", variant.getRegistryName())
);
if ( if (
color != null && color != null &&
variant.supportsColor() && variant.supportsColor() &&
@@ -276,7 +281,9 @@ public class KidnapperItemSelector {
BlindfoldVariant variant, BlindfoldVariant variant,
@Nullable ItemColor color @Nullable ItemColor color
) { ) {
ItemStack stack = new ItemStack(ModItems.getBlindfold(variant)); ItemStack stack = DataDrivenBondageItem.createStack(
new ResourceLocation("tiedup", variant.getRegistryName())
);
if ( if (
color != null && color != null &&
variant.supportsColor() && variant.supportsColor() &&
@@ -292,7 +299,9 @@ public class KidnapperItemSelector {
* Mittens don't have color variants. * Mittens don't have color variants.
*/ */
public static ItemStack createMittens() { public static ItemStack createMittens() {
return new ItemStack(ModItems.getMittens(MittensVariant.LEATHER)); return DataDrivenBondageItem.createStack(
new ResourceLocation("tiedup", "leather_mittens")
);
} }
/** /**
@@ -300,7 +309,9 @@ public class KidnapperItemSelector {
* Earplugs don't have color variants. * Earplugs don't have color variants.
*/ */
public static ItemStack createEarplugs() { public static ItemStack createEarplugs() {
return new ItemStack(ModItems.getEarplugs(EarplugsVariant.CLASSIC)); return DataDrivenBondageItem.createStack(
new ResourceLocation("tiedup", "classic_earplugs")
);
} }
// COLOR METHODS // COLOR METHODS

View File

@@ -2,7 +2,7 @@ package com.tiedup.remake.entities;
import com.tiedup.remake.core.TiedUpMod; import com.tiedup.remake.core.TiedUpMod;
import com.tiedup.remake.items.ModItems; import com.tiedup.remake.items.ModItems;
import com.tiedup.remake.items.base.ItemCollar; import com.tiedup.remake.v2.bondage.CollarHelper;
import com.tiedup.remake.state.CollarRegistry; import com.tiedup.remake.state.CollarRegistry;
import com.tiedup.remake.state.IBondageState; import com.tiedup.remake.state.IBondageState;
import com.tiedup.remake.util.tasks.ItemTask; import com.tiedup.remake.util.tasks.ItemTask;
@@ -162,15 +162,15 @@ public class KidnapperJobManager {
// Put a shock collar on the worker AFTER untie/free // Put a shock collar on the worker AFTER untie/free
ItemStack shockCollar = new ItemStack(ModItems.SHOCK_COLLAR_AUTO.get()); ItemStack shockCollar = new ItemStack(ModItems.SHOCK_COLLAR_AUTO.get());
if (shockCollar.getItem() instanceof ItemCollar collarItem) {
// Add kidnapper as owner so the collar is linked // Add kidnapper as owner so the collar is linked
collarItem.addOwner( CollarHelper.addOwner(
shockCollar, shockCollar,
kidnapper.getUUID(), kidnapper.getUUID(),
kidnapper.getNpcName() kidnapper.getNpcName()
); );
// Lock the collar so they can't remove it // Lock the collar so they can't remove it
shockCollar = collarItem.setLocked(shockCollar, true); if (shockCollar.getItem() instanceof com.tiedup.remake.items.base.ILockable lockable) {
shockCollar = lockable.setLocked(shockCollar, true);
} }
captive.equip(BodyRegionV2.NECK, shockCollar); captive.equip(BodyRegionV2.NECK, shockCollar);

View File

@@ -1,7 +1,6 @@
package com.tiedup.remake.entities; package com.tiedup.remake.entities;
import com.tiedup.remake.items.ModItems; import com.tiedup.remake.v2.bondage.PoseTypeHelper;
import com.tiedup.remake.items.base.BindVariant;
import com.tiedup.remake.state.IBondageState; import com.tiedup.remake.state.IBondageState;
import com.tiedup.remake.util.KidnappedHelper; import com.tiedup.remake.util.KidnappedHelper;
import com.tiedup.remake.v2.BodyRegionV2; import com.tiedup.remake.v2.BodyRegionV2;
@@ -108,7 +107,7 @@ public final class LeashProxyEntity extends Turtle {
ItemStack bind = state.getEquipment(BodyRegionV2.ARMS); ItemStack bind = state.getEquipment(BodyRegionV2.ARMS);
if ( if (
!bind.isEmpty() && !bind.isEmpty() &&
bind.getItem() == ModItems.getBind(BindVariant.DOGBINDER) PoseTypeHelper.getPoseType(bind) == com.tiedup.remake.items.base.PoseType.DOG
) { ) {
yOffset = 0.35D; // Lower for 4-legged dogwalk pose (back/hip level) yOffset = 0.35D; // Lower for 4-legged dogwalk pose (back/hip level)
} }

View File

@@ -11,7 +11,7 @@ import com.tiedup.remake.entities.EntityKidnapper;
import com.tiedup.remake.entities.EntityKidnapper.CaptivePriority; import com.tiedup.remake.entities.EntityKidnapper.CaptivePriority;
import com.tiedup.remake.entities.ai.StuckDetector; import com.tiedup.remake.entities.ai.StuckDetector;
import com.tiedup.remake.entities.ai.WaypointNavigator; import com.tiedup.remake.entities.ai.WaypointNavigator;
import com.tiedup.remake.items.base.ItemCollar; import com.tiedup.remake.v2.bondage.CollarHelper;
import com.tiedup.remake.prison.PrisonerManager; import com.tiedup.remake.prison.PrisonerManager;
import com.tiedup.remake.prison.PrisonerRecord; import com.tiedup.remake.prison.PrisonerRecord;
import com.tiedup.remake.prison.PrisonerState; import com.tiedup.remake.prison.PrisonerState;
@@ -260,7 +260,7 @@ public class KidnapperBringToCellGoal extends Goal {
); );
IRestrainable captive = this.kidnapper.getCaptive(); IRestrainable captive = this.kidnapper.getCaptive();
if (captive != null) { if (captive != null) {
ItemCollar.runWithSuppressedAlert(() -> CollarHelper.runWithSuppressedAlert(() ->
captive.free(false) captive.free(false)
); );
this.kidnapper.removeCaptive(captive, false); this.kidnapper.removeCaptive(captive, false);
@@ -1079,9 +1079,9 @@ public class KidnapperBringToCellGoal extends Goal {
ItemStack collar = captive.getEquipment(BodyRegionV2.NECK); ItemStack collar = captive.getEquipment(BodyRegionV2.NECK);
if ( if (
!collar.isEmpty() && !collar.isEmpty() &&
collar.getItem() instanceof ItemCollar collarItem CollarHelper.isCollar(collar)
) { ) {
collarItem.setCellId(collar, this.targetCell.getId()); CollarHelper.setCellId(collar, this.targetCell.getId());
} }
TiedUpMod.LOGGER.info( TiedUpMod.LOGGER.info(

View File

@@ -8,7 +8,7 @@ import com.tiedup.remake.entities.EntityKidnapper;
import com.tiedup.remake.entities.ai.StuckDetector; import com.tiedup.remake.entities.ai.StuckDetector;
import com.tiedup.remake.items.ItemKey; import com.tiedup.remake.items.ItemKey;
import com.tiedup.remake.items.ModItems; import com.tiedup.remake.items.ModItems;
import com.tiedup.remake.items.base.ItemCollar; import com.tiedup.remake.v2.bondage.CollarHelper;
import com.tiedup.remake.network.ModNetwork; import com.tiedup.remake.network.ModNetwork;
import com.tiedup.remake.network.action.PacketTying; import com.tiedup.remake.network.action.PacketTying;
import com.tiedup.remake.prison.PrisonerManager; import com.tiedup.remake.prison.PrisonerManager;
@@ -849,11 +849,8 @@ public class KidnapperCaptureGoal extends Goal {
// If already has collar, check ownership // If already has collar, check ownership
if (state.hasCollar()) { if (state.hasCollar()) {
ItemStack existingCollar = state.getEquipment(BodyRegionV2.NECK); ItemStack existingCollar = state.getEquipment(BodyRegionV2.NECK);
if ( if (CollarHelper.isCollar(existingCollar)) {
existingCollar.getItem() instanceof java.util.List<java.util.UUID> owners = CollarHelper.getOwners(
com.tiedup.remake.items.base.ItemCollar collarItem
) {
java.util.List<java.util.UUID> owners = collarItem.getOwners(
existingCollar existingCollar
); );
if (!owners.contains(this.kidnapper.getUUID())) { if (!owners.contains(this.kidnapper.getUUID())) {
@@ -885,9 +882,9 @@ public class KidnapperCaptureGoal extends Goal {
for (java.util.UUID oldOwner : new java.util.ArrayList<>( for (java.util.UUID oldOwner : new java.util.ArrayList<>(
owners owners
)) { )) {
collarItem.removeOwner(existingCollar, oldOwner); CollarHelper.removeOwner(existingCollar, oldOwner);
} }
collarItem.addOwner( CollarHelper.addOwner(
existingCollar, existingCollar,
this.kidnapper.getUUID(), this.kidnapper.getUUID(),
this.kidnapper.getNpcName() this.kidnapper.getNpcName()
@@ -929,9 +926,9 @@ public class KidnapperCaptureGoal extends Goal {
if (this.captureProgress >= COLLAR_APPLY_TIME) { if (this.captureProgress >= COLLAR_APPLY_TIME) {
// Create a copy of the collar and configure it // Create a copy of the collar and configure it
ItemStack collarCopy = collar.copy(); ItemStack collarCopy = collar.copy();
if (collarCopy.getItem() instanceof ItemCollar collarItem) { if (CollarHelper.isCollar(collarCopy)) {
// Add kidnapper as owner // Add kidnapper as owner
collarItem.addOwner( CollarHelper.addOwner(
collarCopy, collarCopy,
this.kidnapper.getUUID(), this.kidnapper.getUUID(),
this.kidnapper.getNpcName() this.kidnapper.getNpcName()
@@ -941,12 +938,17 @@ public class KidnapperCaptureGoal extends Goal {
ItemStack keyStack = new ItemStack(ModItems.COLLAR_KEY.get()); ItemStack keyStack = new ItemStack(ModItems.COLLAR_KEY.get());
if (keyStack.getItem() instanceof ItemKey keyItem) { if (keyStack.getItem() instanceof ItemKey keyItem) {
UUID keyUUID = keyItem.getKeyUUID(keyStack); UUID keyUUID = keyItem.getKeyUUID(keyStack);
collarItem.setLockedByKeyUUID(collarCopy, keyUUID); // Lock via ILockable interface (collar must implement it)
if (collarCopy.getItem() instanceof com.tiedup.remake.items.base.ILockable lockable) {
lockable.setLockedByKeyUUID(collarCopy, keyUUID);
}
// Store the key on the kidnapper for potential drop on death // Store the key on the kidnapper for potential drop on death
this.kidnapper.addCollarKey(keyStack); this.kidnapper.addCollarKey(keyStack);
} else { } else {
// Fallback: just lock without a key // Fallback: just lock without a key
collarItem.setLocked(collarCopy, true); if (collarCopy.getItem() instanceof com.tiedup.remake.items.base.ILockable lockable) {
lockable.setLocked(collarCopy, true);
}
} }
} }

View File

@@ -8,8 +8,8 @@ import com.tiedup.remake.entities.AbstractTiedUpNpc;
import com.tiedup.remake.entities.EntityKidnapper; import com.tiedup.remake.entities.EntityKidnapper;
import com.tiedup.remake.entities.ai.StuckDetector; import com.tiedup.remake.entities.ai.StuckDetector;
import com.tiedup.remake.entities.ai.WaypointNavigator; import com.tiedup.remake.entities.ai.WaypointNavigator;
import com.tiedup.remake.items.ModItems; import com.tiedup.remake.v2.bondage.datadriven.DataDrivenBondageItem;
import com.tiedup.remake.items.base.BindVariant; import net.minecraft.resources.ResourceLocation;
import com.tiedup.remake.state.IBondageState; import com.tiedup.remake.state.IBondageState;
import com.tiedup.remake.util.KidnappedHelper; import com.tiedup.remake.util.KidnappedHelper;
import com.tiedup.remake.util.KidnapperAIHelper; import com.tiedup.remake.util.KidnapperAIHelper;
@@ -547,9 +547,7 @@ public class KidnapperWalkPrisonerGoal extends Goal {
); );
// 3. Change bind to DOGBINDER // 3. Change bind to DOGBINDER
ItemStack dogBinder = new ItemStack( ItemStack dogBinder = DataDrivenBondageItem.createStack(new ResourceLocation("tiedup", "dogbinder"));
ModItems.getBind(BindVariant.DOGBINDER)
);
this.walkedPrisoner.equip(BodyRegionV2.ARMS, dogBinder); this.walkedPrisoner.equip(BodyRegionV2.ARMS, dogBinder);
TiedUpMod.LOGGER.debug( TiedUpMod.LOGGER.debug(
@@ -738,7 +736,7 @@ public class KidnapperWalkPrisonerGoal extends Goal {
if (currentBind.isEmpty() || !prisoner.isTiedUp()) { if (currentBind.isEmpty() || !prisoner.isTiedUp()) {
// They freed themselves - put dogbinder back on // They freed themselves - put dogbinder back on
ItemStack dogBinder = new ItemStack( ItemStack dogBinder = new ItemStack(
ModItems.getBind(BindVariant.DOGBINDER) DataDrivenBondageItem.createStack(new ResourceLocation("tiedup", "dogbinder")).getItem()
); );
prisoner.equip(BodyRegionV2.ARMS, dogBinder); prisoner.equip(BodyRegionV2.ARMS, dogBinder);
} }

View File

@@ -338,10 +338,8 @@ public class MaidReturnGoal extends Goal {
// Fallback: use basic rope if no snapshot // Fallback: use basic rope if no snapshot
cap.equip( cap.equip(
BodyRegionV2.ARMS, BodyRegionV2.ARMS,
new ItemStack( com.tiedup.remake.v2.bondage.datadriven.DataDrivenBondageItem.createStack(
com.tiedup.remake.items.ModItems.getBind( new net.minecraft.resources.ResourceLocation("tiedup", "ropes")
com.tiedup.remake.items.base.BindVariant.ROPES
)
) )
); );
} }

View File

@@ -3,8 +3,8 @@ package com.tiedup.remake.entities.ai.master;
import com.tiedup.remake.core.TiedUpMod; import com.tiedup.remake.core.TiedUpMod;
import com.tiedup.remake.dialogue.DialogueBridge; import com.tiedup.remake.dialogue.DialogueBridge;
import com.tiedup.remake.entities.EntityMaster; import com.tiedup.remake.entities.EntityMaster;
import com.tiedup.remake.items.ModItems; import com.tiedup.remake.v2.bondage.datadriven.DataDrivenBondageItem;
import com.tiedup.remake.items.base.BindVariant; import net.minecraft.resources.ResourceLocation;
import com.tiedup.remake.state.HumanChairHelper; import com.tiedup.remake.state.HumanChairHelper;
import com.tiedup.remake.state.PlayerBindState; import com.tiedup.remake.state.PlayerBindState;
import com.tiedup.remake.v2.BodyRegionV2; import com.tiedup.remake.v2.BodyRegionV2;
@@ -394,8 +394,8 @@ public class MasterHumanChairGoal extends Goal {
// Apply invisible dogbind for the pose animation // Apply invisible dogbind for the pose animation
if (!bindState.isTiedUp()) { if (!bindState.isTiedUp()) {
ItemStack dogbind = new ItemStack( ItemStack dogbind = DataDrivenBondageItem.createStack(
ModItems.getBind(BindVariant.DOGBINDER) new ResourceLocation("tiedup", "dogbinder")
); );
CompoundTag tag = dogbind.getOrCreateTag(); CompoundTag tag = dogbind.getOrCreateTag();
tag.putBoolean(NBT_HUMAN_CHAIR_BIND, true); tag.putBoolean(NBT_HUMAN_CHAIR_BIND, true);

View File

@@ -3,12 +3,9 @@ package com.tiedup.remake.entities.ai.master;
import com.tiedup.remake.core.TiedUpMod; import com.tiedup.remake.core.TiedUpMod;
import com.tiedup.remake.dialogue.DialogueBridge; import com.tiedup.remake.dialogue.DialogueBridge;
import com.tiedup.remake.entities.EntityMaster; import com.tiedup.remake.entities.EntityMaster;
import com.tiedup.remake.items.ItemChokeCollar; import com.tiedup.remake.v2.bondage.CollarHelper;
import com.tiedup.remake.items.ModItems; import com.tiedup.remake.v2.bondage.datadriven.DataDrivenBondageItem;
import com.tiedup.remake.items.base.BindVariant; import net.minecraft.resources.ResourceLocation;
import com.tiedup.remake.items.base.BlindfoldVariant;
import com.tiedup.remake.items.base.GagVariant;
import com.tiedup.remake.items.base.MittensVariant;
import com.tiedup.remake.state.PlayerBindState; import com.tiedup.remake.state.PlayerBindState;
import com.tiedup.remake.v2.BodyRegionV2; import com.tiedup.remake.v2.BodyRegionV2;
import com.tiedup.remake.v2.bondage.IV2BondageEquipment; import com.tiedup.remake.v2.bondage.IV2BondageEquipment;
@@ -261,7 +258,7 @@ public class MasterPunishGoal extends Goal {
// CHOKE: only if pet has choke collar // CHOKE: only if pet has choke collar
if (bindState != null && bindState.hasCollar()) { if (bindState != null && bindState.hasCollar()) {
ItemStack collar = bindState.getEquipment(BodyRegionV2.NECK); ItemStack collar = bindState.getEquipment(BodyRegionV2.NECK);
if (collar.getItem() instanceof ItemChokeCollar) { if (CollarHelper.isChokeCollar(collar)) {
available.add(PunishmentType.CHOKE_COLLAR); available.add(PunishmentType.CHOKE_COLLAR);
} }
} }
@@ -393,8 +390,8 @@ public class MasterPunishGoal extends Goal {
PlayerBindState bindState = PlayerBindState.getInstance(pet); PlayerBindState bindState = PlayerBindState.getInstance(pet);
if (bindState != null && bindState.hasCollar()) { if (bindState != null && bindState.hasCollar()) {
ItemStack collar = bindState.getEquipment(BodyRegionV2.NECK); ItemStack collar = bindState.getEquipment(BodyRegionV2.NECK);
if (collar.getItem() instanceof ItemChokeCollar chokeCollar) { if (CollarHelper.isChokeCollar(collar)) {
chokeCollar.setChoking(collar, true); CollarHelper.setChoking(collar, true);
this.activeChokeCollar = collar; this.activeChokeCollar = collar;
this.chokeActiveTimer = 1; this.chokeActiveTimer = 1;
@@ -457,12 +454,14 @@ public class MasterPunishGoal extends Goal {
*/ */
private ItemStack createAccessory(BodyRegionV2 region) { private ItemStack createAccessory(BodyRegionV2 region) {
return switch (region) { return switch (region) {
case EYES -> new ItemStack( case EYES -> DataDrivenBondageItem.createStack(
ModItems.getBlindfold(BlindfoldVariant.CLASSIC) new ResourceLocation("tiedup", "classic_blindfold")
); );
case MOUTH -> new ItemStack(ModItems.getGag(GagVariant.BALL_GAG)); case MOUTH -> DataDrivenBondageItem.createStack(
case HANDS -> new ItemStack( new ResourceLocation("tiedup", "ball_gag")
ModItems.getMittens(MittensVariant.LEATHER) );
case HANDS -> DataDrivenBondageItem.createStack(
new ResourceLocation("tiedup", "leather_mittens")
); );
default -> ItemStack.EMPTY; default -> ItemStack.EMPTY;
}; };
@@ -472,8 +471,8 @@ public class MasterPunishGoal extends Goal {
* Apply armbinder as punishment. * Apply armbinder as punishment.
*/ */
private void applyTighten(ServerPlayer pet) { private void applyTighten(ServerPlayer pet) {
ItemStack armbinder = new ItemStack( ItemStack armbinder = DataDrivenBondageItem.createStack(
ModItems.getBind(BindVariant.ARMBINDER) new ResourceLocation("tiedup", "armbinder")
); );
// Mark as temporary // Mark as temporary
@@ -545,9 +544,9 @@ public class MasterPunishGoal extends Goal {
private void deactivateChoke() { private void deactivateChoke() {
if ( if (
!activeChokeCollar.isEmpty() && !activeChokeCollar.isEmpty() &&
activeChokeCollar.getItem() instanceof ItemChokeCollar chokeCollar CollarHelper.isChokeCollar(activeChokeCollar)
) { ) {
chokeCollar.setChoking(activeChokeCollar, false); CollarHelper.setChoking(activeChokeCollar, false);
} }
this.activeChokeCollar = ItemStack.EMPTY; this.activeChokeCollar = ItemStack.EMPTY;
this.chokeActiveTimer = 0; this.chokeActiveTimer = 0;

View File

@@ -3,11 +3,8 @@ package com.tiedup.remake.entities.ai.master;
import com.tiedup.remake.core.TiedUpMod; import com.tiedup.remake.core.TiedUpMod;
import com.tiedup.remake.dialogue.DialogueBridge; import com.tiedup.remake.dialogue.DialogueBridge;
import com.tiedup.remake.entities.EntityMaster; import com.tiedup.remake.entities.EntityMaster;
import com.tiedup.remake.items.ModItems; import com.tiedup.remake.v2.bondage.datadriven.DataDrivenBondageItem;
import com.tiedup.remake.items.base.BindVariant; import net.minecraft.resources.ResourceLocation;
import com.tiedup.remake.items.base.BlindfoldVariant;
import com.tiedup.remake.items.base.GagVariant;
import com.tiedup.remake.items.base.MittensVariant;
import com.tiedup.remake.state.PlayerBindState; import com.tiedup.remake.state.PlayerBindState;
import com.tiedup.remake.v2.BodyRegionV2; import com.tiedup.remake.v2.BodyRegionV2;
import com.tiedup.remake.v2.bondage.IV2BondageEquipment; import com.tiedup.remake.v2.bondage.IV2BondageEquipment;
@@ -17,7 +14,6 @@ import java.util.List;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.entity.ai.goal.Goal; import net.minecraft.world.entity.ai.goal.Goal;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
/** /**
@@ -249,15 +245,18 @@ public class MasterRandomEventGoal extends Goal {
* Create a random accessory item for the given body region. * Create a random accessory item for the given body region.
*/ */
private ItemStack createRandomAccessory(BodyRegionV2 region) { private ItemStack createRandomAccessory(BodyRegionV2 region) {
Item item = switch (region) { return switch (region) {
case EYES -> ModItems.getBlindfold(BlindfoldVariant.CLASSIC); case EYES -> DataDrivenBondageItem.createStack(
case MOUTH -> ModItems.getGag(GagVariant.BALL_GAG); new ResourceLocation("tiedup", "classic_blindfold")
case HANDS -> ModItems.getMittens(MittensVariant.LEATHER); );
default -> null; case MOUTH -> DataDrivenBondageItem.createStack(
new ResourceLocation("tiedup", "ball_gag")
);
case HANDS -> DataDrivenBondageItem.createStack(
new ResourceLocation("tiedup", "leather_mittens")
);
default -> ItemStack.EMPTY;
}; };
if (item == null) return ItemStack.EMPTY;
return new ItemStack(item);
} }
/** /**
@@ -304,8 +303,8 @@ public class MasterRandomEventGoal extends Goal {
// Put pet in dogbind if not already tied // Put pet in dogbind if not already tied
PlayerBindState bindState = PlayerBindState.getInstance(pet); PlayerBindState bindState = PlayerBindState.getInstance(pet);
if (bindState != null && !bindState.isTiedUp()) { if (bindState != null && !bindState.isTiedUp()) {
ItemStack dogbind = new ItemStack( ItemStack dogbind = DataDrivenBondageItem.createStack(
ModItems.getBind(BindVariant.DOGBINDER) new ResourceLocation("tiedup", "dogbinder")
); );
bindState.equip(BodyRegionV2.ARMS, dogbind); bindState.equip(BodyRegionV2.ARMS, dogbind);
} }

View File

@@ -3,7 +3,7 @@ package com.tiedup.remake.entities.ai.master;
import com.tiedup.remake.core.TiedUpMod; import com.tiedup.remake.core.TiedUpMod;
import com.tiedup.remake.dialogue.DialogueBridge; import com.tiedup.remake.dialogue.DialogueBridge;
import com.tiedup.remake.entities.EntityMaster; import com.tiedup.remake.entities.EntityMaster;
import com.tiedup.remake.items.ItemChokeCollar; import com.tiedup.remake.v2.bondage.CollarHelper;
import com.tiedup.remake.state.PlayerBindState; import com.tiedup.remake.state.PlayerBindState;
import com.tiedup.remake.util.MessageDispatcher; import com.tiedup.remake.util.MessageDispatcher;
import com.tiedup.remake.v2.BodyRegionV2; import com.tiedup.remake.v2.BodyRegionV2;
@@ -441,8 +441,8 @@ public class MasterTaskWatchGoal extends Goal {
if (bindState != null && bindState.hasCollar()) { if (bindState != null && bindState.hasCollar()) {
ItemStack collar = bindState.getEquipment(BodyRegionV2.NECK); ItemStack collar = bindState.getEquipment(BodyRegionV2.NECK);
if (collar.getItem() instanceof ItemChokeCollar chokeCollar) { if (CollarHelper.isChokeCollar(collar)) {
chokeCollar.setChoking(collar, true); CollarHelper.setChoking(collar, true);
this.activeChokeCollar = collar; this.activeChokeCollar = collar;
this.chokeTimer = CHOKE_DURATION; this.chokeTimer = CHOKE_DURATION;
@@ -475,9 +475,9 @@ public class MasterTaskWatchGoal extends Goal {
private void deactivateChoke() { private void deactivateChoke() {
if ( if (
!activeChokeCollar.isEmpty() && !activeChokeCollar.isEmpty() &&
activeChokeCollar.getItem() instanceof ItemChokeCollar chokeCollar CollarHelper.isChokeCollar(activeChokeCollar)
) { ) {
chokeCollar.setChoking(activeChokeCollar, false); CollarHelper.setChoking(activeChokeCollar, false);
TiedUpMod.LOGGER.debug( TiedUpMod.LOGGER.debug(
"[MasterTaskWatchGoal] {} deactivated choke", "[MasterTaskWatchGoal] {} deactivated choke",
master.getNpcName() master.getNpcName()

View File

@@ -1,7 +1,7 @@
package com.tiedup.remake.entities.ai.personality; package com.tiedup.remake.entities.ai.personality;
import com.tiedup.remake.entities.EntityDamsel; import com.tiedup.remake.entities.EntityDamsel;
import com.tiedup.remake.items.base.ItemBind; import com.tiedup.remake.v2.bondage.BindModeHelper;
import com.tiedup.remake.personality.NpcCommand; import com.tiedup.remake.personality.NpcCommand;
import com.tiedup.remake.personality.ToolMode; import com.tiedup.remake.personality.ToolMode;
import com.tiedup.remake.v2.BodyRegionV2; import com.tiedup.remake.v2.BodyRegionV2;
@@ -506,7 +506,7 @@ public class NpcFollowCommandGoal extends Goal {
if (dist <= ATTACK_RANGE) { if (dist <= ATTACK_RANGE) {
// Try to capture using bind item // Try to capture using bind item
ItemStack bindItem = npc.getMainHandItem(); ItemStack bindItem = npc.getMainHandItem();
if (bindItem.getItem() instanceof ItemBind) { if (BindModeHelper.isBindItem(bindItem)) {
// Apply bind to target // Apply bind to target
captureTarget.equip(BodyRegionV2.ARMS, bindItem.copy()); captureTarget.equip(BodyRegionV2.ARMS, bindItem.copy());

View File

@@ -1,8 +1,8 @@
package com.tiedup.remake.entities.ai.personality; package com.tiedup.remake.entities.ai.personality;
import com.tiedup.remake.entities.EntityDamsel; import com.tiedup.remake.entities.EntityDamsel;
import com.tiedup.remake.items.base.ItemBind; import com.tiedup.remake.v2.bondage.BindModeHelper;
import com.tiedup.remake.items.base.ItemCollar; import com.tiedup.remake.v2.bondage.CollarHelper;
import com.tiedup.remake.personality.NpcCommand; import com.tiedup.remake.personality.NpcCommand;
import com.tiedup.remake.personality.PersonalityState; import com.tiedup.remake.personality.PersonalityState;
import com.tiedup.remake.v2.BodyRegionV2; import com.tiedup.remake.v2.BodyRegionV2;
@@ -426,7 +426,7 @@ public class NpcGuardCommandGoal extends Goal {
NonNullList<ItemStack> inventory = npc.getNpcInventory(); NonNullList<ItemStack> inventory = npc.getNpcInventory();
for (int i = 0; i < inventory.size(); i++) { for (int i = 0; i < inventory.size(); i++) {
ItemStack stack = inventory.get(i); ItemStack stack = inventory.get(i);
if (stack.getItem() instanceof ItemBind) { if (BindModeHelper.isBindItem(stack)) {
// Apply bind to slave // Apply bind to slave
slave.equip(BodyRegionV2.ARMS, stack.copy()); slave.equip(BodyRegionV2.ARMS, stack.copy());
stack.shrink(1); stack.shrink(1);
@@ -486,8 +486,8 @@ public class NpcGuardCommandGoal extends Goal {
private UUID getCollarOwnerUUID(EntityDamsel slave) { private UUID getCollarOwnerUUID(EntityDamsel slave) {
if (!slave.hasCollar()) return null; if (!slave.hasCollar()) return null;
ItemStack collar = slave.getEquipment(BodyRegionV2.NECK); ItemStack collar = slave.getEquipment(BodyRegionV2.NECK);
if (collar.getItem() instanceof ItemCollar collarItem) { if (CollarHelper.isCollar(collar)) {
java.util.List<UUID> owners = collarItem.getOwners(collar); java.util.List<UUID> owners = CollarHelper.getOwners(collar);
if (!owners.isEmpty()) { if (!owners.isEmpty()) {
return owners.get(0); return owners.get(0);
} }

View File

@@ -3,7 +3,7 @@ package com.tiedup.remake.entities.damsel.components;
import com.tiedup.remake.core.TiedUpMod; import com.tiedup.remake.core.TiedUpMod;
import com.tiedup.remake.entities.AbstractTiedUpNpc; import com.tiedup.remake.entities.AbstractTiedUpNpc;
import com.tiedup.remake.entities.BondageServiceHandler; import com.tiedup.remake.entities.BondageServiceHandler;
import com.tiedup.remake.items.base.ItemCollar; import com.tiedup.remake.v2.bondage.CollarHelper;
import com.tiedup.remake.state.ICaptor; import com.tiedup.remake.state.ICaptor;
import com.tiedup.remake.state.IRestrainable; import com.tiedup.remake.state.IRestrainable;
import com.tiedup.remake.state.IRestrainableEntity; import com.tiedup.remake.state.IRestrainableEntity;
@@ -565,9 +565,9 @@ public class DamselBondageManager implements IRestrainable {
ItemStack collar = getEquipment(BodyRegionV2.NECK); ItemStack collar = getEquipment(BodyRegionV2.NECK);
if (collar.isEmpty()) return false; if (collar.isEmpty()) return false;
if (!(collar.getItem() instanceof ItemCollar itemCollar)) return false; if (!CollarHelper.isCollar(collar)) return false;
UUID cellId = itemCollar.getCellId(collar); UUID cellId = CollarHelper.getCellId(collar);
if (cellId == null) return false; if (cellId == null) return false;
// Get cell position from registry // Get cell position from registry

View File

@@ -2,7 +2,7 @@ package com.tiedup.remake.entities.damsel.components;
import com.tiedup.remake.core.TiedUpMod; import com.tiedup.remake.core.TiedUpMod;
import com.tiedup.remake.dialogue.EntityDialogueManager; import com.tiedup.remake.dialogue.EntityDialogueManager;
import com.tiedup.remake.items.base.ItemCollar; import com.tiedup.remake.v2.bondage.CollarHelper;
import com.tiedup.remake.personality.*; import com.tiedup.remake.personality.*;
import com.tiedup.remake.v2.BodyRegionV2; import com.tiedup.remake.v2.BodyRegionV2;
import java.util.*; import java.util.*;
@@ -180,8 +180,8 @@ public class DamselPersonalitySystem {
UUID masterUUID = null; UUID masterUUID = null;
if (context.hasCollar()) { if (context.hasCollar()) {
ItemStack collar = context.getEquipment(BodyRegionV2.NECK); ItemStack collar = context.getEquipment(BodyRegionV2.NECK);
if (collar.getItem() instanceof ItemCollar collarItem) { if (CollarHelper.isCollar(collar)) {
List<UUID> owners = collarItem.getOwners(collar); List<UUID> owners = CollarHelper.getOwners(collar);
if (!owners.isEmpty()) { if (!owners.isEmpty()) {
masterUUID = owners.get(0); masterUUID = owners.get(0);
} }

View File

@@ -4,7 +4,11 @@ import com.tiedup.remake.core.ModConfig;
import com.tiedup.remake.core.TiedUpMod; import com.tiedup.remake.core.TiedUpMod;
import com.tiedup.remake.entities.AbstractTiedUpNpc; import com.tiedup.remake.entities.AbstractTiedUpNpc;
import com.tiedup.remake.items.base.ILockable; import com.tiedup.remake.items.base.ILockable;
import com.tiedup.remake.items.base.ItemCollar; import com.tiedup.remake.v2.bondage.CollarHelper;
import com.tiedup.remake.v2.bondage.datadriven.DataDrivenBondageItem;
import com.tiedup.remake.v2.bondage.component.ComponentType;
import com.tiedup.remake.v2.bondage.component.GaggingComponent;
import com.tiedup.remake.v2.bondage.component.BlindingComponent;
import com.tiedup.remake.state.IRestrainableEntity; import com.tiedup.remake.state.IRestrainableEntity;
import com.tiedup.remake.util.RestraintEffectUtils; import com.tiedup.remake.util.RestraintEffectUtils;
import com.tiedup.remake.util.TiedUpSounds; import com.tiedup.remake.util.TiedUpSounds;
@@ -112,19 +116,15 @@ public class NpcEquipmentManager {
public boolean hasGaggingEffect() { public boolean hasGaggingEffect() {
ItemStack gag = getCurrentGag(); ItemStack gag = getCurrentGag();
if (gag.isEmpty()) return false; if (gag.isEmpty()) return false;
return ( if (DataDrivenBondageItem.getComponent(gag, ComponentType.GAGGING, GaggingComponent.class) != null) return true;
gag.getItem() instanceof return gag.getItem() instanceof com.tiedup.remake.items.base.IHasGaggingEffect;
com.tiedup.remake.items.base.IHasGaggingEffect
);
} }
public boolean hasBlindingEffect() { public boolean hasBlindingEffect() {
ItemStack blindfold = getCurrentBlindfold(); ItemStack blindfold = getCurrentBlindfold();
if (blindfold.isEmpty()) return false; if (blindfold.isEmpty()) return false;
return ( if (DataDrivenBondageItem.getComponent(blindfold, ComponentType.BLINDING, BlindingComponent.class) != null) return true;
blindfold.getItem() instanceof return blindfold.getItem() instanceof com.tiedup.remake.items.base.IHasBlindingEffect;
com.tiedup.remake.items.base.IHasBlindingEffect
);
} }
public boolean hasKnives() { public boolean hasKnives() {
@@ -768,8 +768,8 @@ public class NpcEquipmentManager {
public boolean isCollarOwner(Player player) { public boolean isCollarOwner(Player player) {
if (!hasCollar()) return true; if (!hasCollar()) return true;
ItemStack collar = getCurrentCollar(); ItemStack collar = getCurrentCollar();
if (!(collar.getItem() instanceof ItemCollar collarItem)) return true; if (!CollarHelper.isCollar(collar)) return true;
return collarItem.isOwner(collar, player); return CollarHelper.isOwner(collar, player);
} }
// COERCION // COERCION

View File

@@ -6,7 +6,7 @@ import com.tiedup.remake.core.TiedUpMod;
import com.tiedup.remake.dialogue.EntityDialogueManager; import com.tiedup.remake.dialogue.EntityDialogueManager;
import com.tiedup.remake.entities.EntityKidnapper; import com.tiedup.remake.entities.EntityKidnapper;
import com.tiedup.remake.entities.ai.kidnapper.KidnapperState; import com.tiedup.remake.entities.ai.kidnapper.KidnapperState;
import com.tiedup.remake.items.base.ItemCollar; import com.tiedup.remake.v2.bondage.CollarHelper;
import com.tiedup.remake.prison.PrisonerManager; import com.tiedup.remake.prison.PrisonerManager;
import com.tiedup.remake.prison.PrisonerRecord; import com.tiedup.remake.prison.PrisonerRecord;
import com.tiedup.remake.prison.PrisonerState; import com.tiedup.remake.prison.PrisonerState;
@@ -189,9 +189,9 @@ public class KidnapperCaptiveManager {
// If target has collar, verify we own it // If target has collar, verify we own it
if (target.hasCollar()) { if (target.hasCollar()) {
ItemStack collar = target.getEquipment(BodyRegionV2.NECK); ItemStack collar = target.getEquipment(BodyRegionV2.NECK);
if (collar.getItem() instanceof ItemCollar collarItem) { if (CollarHelper.isCollar(collar)) {
// Check if THIS kidnapper is owner // Check if THIS kidnapper is owner
if (!collarItem.getOwners(collar).contains(host.getUUID())) { if (!CollarHelper.getOwners(collar).contains(host.getUUID())) {
TiedUpMod.LOGGER.debug( TiedUpMod.LOGGER.debug(
"[KidnapperCaptiveManager] {} can't capture {} - collar owned by someone else", "[KidnapperCaptiveManager] {} can't capture {} - collar owned by someone else",
host.getNpcName(), host.getNpcName(),

View File

@@ -7,7 +7,7 @@ import com.tiedup.remake.entities.EntityKidnapper;
import com.tiedup.remake.entities.EntityKidnapperElite; import com.tiedup.remake.entities.EntityKidnapperElite;
import com.tiedup.remake.entities.ai.kidnapper.KidnapperState; import com.tiedup.remake.entities.ai.kidnapper.KidnapperState;
import com.tiedup.remake.items.ModItems; import com.tiedup.remake.items.ModItems;
import com.tiedup.remake.items.base.ItemCollar; import com.tiedup.remake.v2.bondage.CollarHelper;
import com.tiedup.remake.prison.PrisonerManager; import com.tiedup.remake.prison.PrisonerManager;
import com.tiedup.remake.prison.PrisonerRecord; import com.tiedup.remake.prison.PrisonerRecord;
import com.tiedup.remake.state.IBondageState; import com.tiedup.remake.state.IBondageState;
@@ -206,8 +206,8 @@ public class KidnapperTargetSelector {
// Self-collared entities (exploit) are treated as uncolllared — kidnappers ignore self-collars // Self-collared entities (exploit) are treated as uncolllared — kidnappers ignore self-collars
if (state.hasCollar()) { if (state.hasCollar()) {
ItemStack collar = state.getEquipment(BodyRegionV2.NECK); ItemStack collar = state.getEquipment(BodyRegionV2.NECK);
if (collar.getItem() instanceof ItemCollar collarItem) { if (CollarHelper.isCollar(collar)) {
java.util.List<UUID> owners = collarItem.getOwners(collar); java.util.List<UUID> owners = CollarHelper.getOwners(collar);
// Filter out self-collar (owner == wearer = exploit) // Filter out self-collar (owner == wearer = exploit)
java.util.List<UUID> realOwners = owners java.util.List<UUID> realOwners = owners
.stream() .stream()
@@ -312,8 +312,8 @@ public class KidnapperTargetSelector {
// Other kidnappers' collars are fair game — kidnapper can steal from kidnapper // Other kidnappers' collars are fair game — kidnapper can steal from kidnapper
if (state != null && state.hasCollar()) { if (state != null && state.hasCollar()) {
ItemStack collar = state.getEquipment(BodyRegionV2.NECK); ItemStack collar = state.getEquipment(BodyRegionV2.NECK);
if (collar.getItem() instanceof ItemCollar collarItem) { if (CollarHelper.isCollar(collar)) {
java.util.List<UUID> owners = collarItem.getOwners(collar); java.util.List<UUID> owners = CollarHelper.getOwners(collar);
if (!owners.isEmpty() && !owners.contains(host.getUUID())) { if (!owners.isEmpty() && !owners.contains(host.getUUID())) {
// Check if any owner is a DIFFERENT player (not self-collared, not a kidnapper) // Check if any owner is a DIFFERENT player (not self-collared, not a kidnapper)
if (host.level() instanceof ServerLevel sl) { if (host.level() instanceof ServerLevel sl) {

View File

@@ -4,7 +4,7 @@ import com.tiedup.remake.core.TiedUpMod;
import com.tiedup.remake.entities.EntityMaster; import com.tiedup.remake.entities.EntityMaster;
import com.tiedup.remake.entities.ai.master.MasterRandomEventGoal; import com.tiedup.remake.entities.ai.master.MasterRandomEventGoal;
import com.tiedup.remake.entities.ai.master.MasterState; import com.tiedup.remake.entities.ai.master.MasterState;
import com.tiedup.remake.items.base.ItemCollar; import com.tiedup.remake.v2.bondage.CollarHelper;
import com.tiedup.remake.minigame.StruggleSessionManager; import com.tiedup.remake.minigame.StruggleSessionManager;
import com.tiedup.remake.state.IBondageState; import com.tiedup.remake.state.IBondageState;
import com.tiedup.remake.util.KidnappedHelper; import com.tiedup.remake.util.KidnappedHelper;
@@ -126,22 +126,27 @@ public class MasterPetManager {
// Configure for pet play BEFORE equipping // Configure for pet play BEFORE equipping
if ( if (
chokeCollar.getItem() instanceof chokeCollar.getItem() instanceof
com.tiedup.remake.items.ItemChokeCollar collar com.tiedup.remake.items.base.IHasResistance resistable
) { ) {
collar.setCurrentResistance(chokeCollar, PET_COLLAR_RESISTANCE); resistable.setCurrentResistance(chokeCollar, PET_COLLAR_RESISTANCE);
collar.setLocked(chokeCollar, true); resistable.setCanBeStruggledOut(chokeCollar, true); // Can struggle, but very hard
collar.setLockable(chokeCollar, false); // Cannot be lockpicked }
collar.setCanBeStruggledOut(chokeCollar, true); // Can struggle, but very hard if (
chokeCollar.getItem() instanceof
com.tiedup.remake.items.base.ILockable lockable
) {
lockable.setLocked(chokeCollar, true);
lockable.setLockable(chokeCollar, false); // Cannot be lockpicked
}
// Add this Master as owner // Add this Master as owner
collar.addOwner(chokeCollar, master.getUUID(), master.getNpcName()); CollarHelper.addOwner(chokeCollar, master.getUUID(), master.getNpcName());
// Set NBT flag for pet play mode // Set NBT flag for pet play mode
chokeCollar.getOrCreateTag().putBoolean("petPlayMode", true); CollarHelper.setPetPlayMode(chokeCollar, true);
chokeCollar chokeCollar
.getOrCreateTag() .getOrCreateTag()
.putUUID("masterUUID", master.getUUID()); .putUUID("masterUUID", master.getUUID());
}
// Replace any existing collar (force removal) with the choke collar // Replace any existing collar (force removal) with the choke collar
state.replaceEquipment(BodyRegionV2.NECK, chokeCollar, true); state.replaceEquipment(BodyRegionV2.NECK, chokeCollar, true);
@@ -186,9 +191,9 @@ public class MasterPetManager {
} }
// Unlock the collar // Unlock the collar
if (collarStack.getItem() instanceof ItemCollar collar) { if (collarStack.getItem() instanceof com.tiedup.remake.items.base.ILockable lockable) {
collar.setLocked(collarStack, false); lockable.setLocked(collarStack, false);
collar.setLockable(collarStack, true); lockable.setLockable(collarStack, true);
} }
} }
@@ -242,8 +247,8 @@ public class MasterPetManager {
); );
if (collarStack.isEmpty()) return; if (collarStack.isEmpty()) return;
if (collarStack.getItem() instanceof ItemCollar collar) { if (collarStack.getItem() instanceof com.tiedup.remake.items.base.IHasResistance resistable) {
collar.setCurrentResistance(collarStack, PET_COLLAR_RESISTANCE); resistable.setCurrentResistance(collarStack, PET_COLLAR_RESISTANCE);
TiedUpMod.LOGGER.debug( TiedUpMod.LOGGER.debug(
"[MasterPetManager] Reset collar resistance for {}", "[MasterPetManager] Reset collar resistance for {}",
pet.getName().getString() pet.getName().getString()

View File

@@ -4,7 +4,7 @@ import com.tiedup.remake.cells.CampLifecycleManager;
import com.tiedup.remake.core.TiedUpMod; import com.tiedup.remake.core.TiedUpMod;
import com.tiedup.remake.entities.EntityMaid; import com.tiedup.remake.entities.EntityMaid;
import com.tiedup.remake.entities.EntitySlaveTrader; import com.tiedup.remake.entities.EntitySlaveTrader;
import com.tiedup.remake.items.base.ItemBind; import com.tiedup.remake.v2.bondage.BindModeHelper;
import java.util.UUID; import java.util.UUID;
import net.minecraft.ChatFormatting; import net.minecraft.ChatFormatting;
import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Component;
@@ -40,7 +40,7 @@ public class CampNpcProtectionHandler {
// Check if player is holding restraint item // Check if player is holding restraint item
ItemStack heldItem = player.getItemInHand(event.getHand()); ItemStack heldItem = player.getItemInHand(event.getHand());
if (!(heldItem.getItem() instanceof ItemBind)) return; if (!BindModeHelper.isBindItem(heldItem)) return;
// Check if target is trader or maid with active camp // Check if target is trader or maid with active camp
UUID campId = null; UUID campId = null;

View File

@@ -3,8 +3,8 @@ package com.tiedup.remake.events.captivity;
import com.tiedup.remake.core.SettingsAccessor; import com.tiedup.remake.core.SettingsAccessor;
import com.tiedup.remake.core.TiedUpMod; import com.tiedup.remake.core.TiedUpMod;
import com.tiedup.remake.entities.LeashProxyEntity; import com.tiedup.remake.entities.LeashProxyEntity;
import com.tiedup.remake.items.base.ItemCollar;
import com.tiedup.remake.state.IBondageState; import com.tiedup.remake.state.IBondageState;
import com.tiedup.remake.v2.bondage.CollarHelper;
import com.tiedup.remake.state.IPlayerLeashAccess; import com.tiedup.remake.state.IPlayerLeashAccess;
import com.tiedup.remake.state.PlayerBindState; import com.tiedup.remake.state.PlayerBindState;
import com.tiedup.remake.util.KidnappedHelper; import com.tiedup.remake.util.KidnappedHelper;
@@ -146,9 +146,9 @@ public class PlayerEnslavementHandler {
ItemStack collar = slaveKidnappedState.getEquipment( ItemStack collar = slaveKidnappedState.getEquipment(
BodyRegionV2.NECK BodyRegionV2.NECK
); );
if (collar.getItem() instanceof ItemCollar collarItem) { if (CollarHelper.isCollar(collar)) {
if ( if (
collarItem CollarHelper
.getOwners(collar) .getOwners(collar)
.contains(master.getUUID()) .contains(master.getUUID())
) { ) {

View File

@@ -4,8 +4,8 @@ import com.tiedup.remake.core.TiedUpMod;
import com.tiedup.remake.entities.EntityKidnapper; import com.tiedup.remake.entities.EntityKidnapper;
import com.tiedup.remake.entities.EntityMaid; import com.tiedup.remake.entities.EntityMaid;
import com.tiedup.remake.entities.EntitySlaveTrader; import com.tiedup.remake.entities.EntitySlaveTrader;
import com.tiedup.remake.items.base.ItemBind;
import com.tiedup.remake.prison.LaborRecord; import com.tiedup.remake.prison.LaborRecord;
import com.tiedup.remake.v2.bondage.BindModeHelper;
import com.tiedup.remake.prison.PrisonerManager; import com.tiedup.remake.prison.PrisonerManager;
import com.tiedup.remake.prison.PrisonerRecord; import com.tiedup.remake.prison.PrisonerRecord;
import com.tiedup.remake.prison.PrisonerState; import com.tiedup.remake.prison.PrisonerState;
@@ -145,7 +145,7 @@ public class LaborAttackPunishmentHandler {
// Check if player is holding a restraint item (rope, chain, etc.) // Check if player is holding a restraint item (rope, chain, etc.)
ItemStack heldItem = serverPlayer.getItemInHand(hand); ItemStack heldItem = serverPlayer.getItemInHand(hand);
if (!(heldItem.getItem() instanceof ItemBind)) { if (!BindModeHelper.isBindItem(heldItem)) {
return; // Not a restraint item return; // Not a restraint item
} }

View File

@@ -2,8 +2,8 @@ package com.tiedup.remake.events.restriction;
import com.tiedup.remake.core.TiedUpMod; import com.tiedup.remake.core.TiedUpMod;
import com.tiedup.remake.entities.EntityMaster; import com.tiedup.remake.entities.EntityMaster;
import com.tiedup.remake.items.ItemChokeCollar;
import com.tiedup.remake.state.PlayerBindState; import com.tiedup.remake.state.PlayerBindState;
import com.tiedup.remake.v2.bondage.CollarHelper;
import com.tiedup.remake.v2.BodyRegionV2; import com.tiedup.remake.v2.BodyRegionV2;
import com.tiedup.remake.v2.blocks.PetBedManager; import com.tiedup.remake.v2.blocks.PetBedManager;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
@@ -284,8 +284,8 @@ public class PetPlayRestrictionHandler {
if (bindState == null || !bindState.hasCollar()) return; if (bindState == null || !bindState.hasCollar()) return;
ItemStack collar = bindState.getEquipment(BodyRegionV2.NECK); ItemStack collar = bindState.getEquipment(BodyRegionV2.NECK);
if (collar.getItem() instanceof ItemChokeCollar chokeCollar) { if (CollarHelper.isChokeCollar(collar)) {
if (chokeCollar.isChoking(collar)) { if (CollarHelper.isChoking(collar)) {
// Apply ChokeEffect (short duration, re-applied each active tick) // Apply ChokeEffect (short duration, re-applied each active tick)
if ( if (
!player.hasEffect( !player.hasEffect(

View File

@@ -3,8 +3,8 @@ package com.tiedup.remake.events.restriction;
import com.tiedup.remake.core.SettingsAccessor; import com.tiedup.remake.core.SettingsAccessor;
import com.tiedup.remake.core.TiedUpMod; import com.tiedup.remake.core.TiedUpMod;
import com.tiedup.remake.entities.EntityKidnapper; import com.tiedup.remake.entities.EntityKidnapper;
import com.tiedup.remake.items.base.ItemCollar;
import com.tiedup.remake.minigame.StruggleSessionManager; import com.tiedup.remake.minigame.StruggleSessionManager;
import com.tiedup.remake.v2.bondage.CollarHelper;
import com.tiedup.remake.network.ModNetwork; import com.tiedup.remake.network.ModNetwork;
import com.tiedup.remake.network.personality.PacketSlaveBeingFreed; import com.tiedup.remake.network.personality.PacketSlaveBeingFreed;
import com.tiedup.remake.state.IBondageState; import com.tiedup.remake.state.IBondageState;
@@ -642,14 +642,11 @@ public class RestraintTaskTickHandler {
if (!(slave.level() instanceof ServerLevel serverLevel)) return; if (!(slave.level() instanceof ServerLevel serverLevel)) return;
ItemStack collar = slave.getEquipment(BodyRegionV2.NECK); ItemStack collar = slave.getEquipment(BodyRegionV2.NECK);
if ( if (collar.isEmpty() || !CollarHelper.isCollar(collar)) {
collar.isEmpty() ||
!(collar.getItem() instanceof ItemCollar collarItem)
) {
return; return;
} }
List<UUID> owners = collarItem.getOwners(collar); List<UUID> owners = CollarHelper.getOwners(collar);
if (owners.isEmpty()) return; if (owners.isEmpty()) return;
// Create alert packet // Create alert packet

View File

@@ -7,6 +7,9 @@ import com.tiedup.remake.dialogue.GagTalkManager;
import com.tiedup.remake.items.base.ItemGag; import com.tiedup.remake.items.base.ItemGag;
import com.tiedup.remake.state.IBondageState; import com.tiedup.remake.state.IBondageState;
import com.tiedup.remake.util.GagMaterial; import com.tiedup.remake.util.GagMaterial;
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.util.KidnappedHelper; import com.tiedup.remake.util.KidnappedHelper;
import com.tiedup.remake.util.TiedUpUtils; import com.tiedup.remake.util.TiedUpUtils;
import com.tiedup.remake.v2.BodyRegionV2; import com.tiedup.remake.v2.BodyRegionV2;
@@ -54,12 +57,22 @@ public class ChatEventHandler {
BodyRegionV2.MOUTH BodyRegionV2.MOUTH
); );
if ( // V2: check gagging component, V1 fallback: instanceof ItemGag
!gagStack.isEmpty() && GaggingComponent gaggingComp = DataDrivenBondageItem.getComponent(
gagStack.getItem() instanceof ItemGag gagItem gagStack, ComponentType.GAGGING, GaggingComponent.class);
) { boolean isGagItem = gaggingComp != null
|| gagStack.getItem() instanceof ItemGag;
if (!gagStack.isEmpty() && isGagItem) {
String originalMessage = event.getRawText(); String originalMessage = event.getRawText();
GagMaterial material = gagItem.getGagMaterial(); // V2: get material from component, V1 fallback: from ItemGag
GagMaterial material = null;
if (gaggingComp != null) {
material = gaggingComp.getMaterial();
}
if (material == null && gagStack.getItem() instanceof ItemGag gagItem) {
material = gagItem.getGagMaterial();
}
// 1. Process the message through our GagTalkManager V2 // 1. Process the message through our GagTalkManager V2
Component muffledMessage = GagTalkManager.processGagMessage( Component muffledMessage = GagTalkManager.processGagMessage(
@@ -83,7 +96,9 @@ public class ChatEventHandler {
.append("> ") .append("> ")
.append(muffledMessage); .append(muffledMessage);
double range = material.getTalkRange(); double range = material != null
? material.getTalkRange()
: (gaggingComp != null ? gaggingComp.getRange() : 10.0);
List<ServerPlayer> nearbyPlayers = List<ServerPlayer> nearbyPlayers =
TiedUpUtils.getPlayersAround( TiedUpUtils.getPlayersAround(

View File

@@ -1,9 +1,8 @@
package com.tiedup.remake.minigame; package com.tiedup.remake.minigame;
import com.tiedup.remake.core.TiedUpMod; import com.tiedup.remake.core.TiedUpMod;
import com.tiedup.remake.items.ItemShockCollar; import com.tiedup.remake.items.base.IHasResistance;
import com.tiedup.remake.items.base.ItemBind; import com.tiedup.remake.v2.bondage.CollarHelper;
import com.tiedup.remake.items.base.ItemCollar;
import com.tiedup.remake.minigame.ContinuousStruggleMiniGameState.TickResult; import com.tiedup.remake.minigame.ContinuousStruggleMiniGameState.TickResult;
import com.tiedup.remake.minigame.ContinuousStruggleMiniGameState.UpdateType; import com.tiedup.remake.minigame.ContinuousStruggleMiniGameState.UpdateType;
import com.tiedup.remake.network.ModNetwork; import com.tiedup.remake.network.ModNetwork;
@@ -544,11 +543,11 @@ public class StruggleSessionManager {
if (collar.isEmpty()) return false; if (collar.isEmpty()) return false;
// Only shock collars can trigger during struggle // Only shock collars can trigger during struggle
if (!(collar.getItem() instanceof ItemShockCollar)) return false; if (!CollarHelper.canShock(collar)) return false;
// Must be locked // Must be locked
if (collar.getItem() instanceof ItemCollar collarItem) { if (collar.getItem() instanceof com.tiedup.remake.items.base.ILockable lockable) {
return collarItem.isLocked(collar); return lockable.isLocked(collar);
} }
return false; return false;
} }
@@ -643,14 +642,13 @@ public class StruggleSessionManager {
player, player,
BodyRegionV2.ARMS BodyRegionV2.ARMS
); );
if ( if (bindStack.isEmpty()) {
bindStack.isEmpty() ||
!(bindStack.getItem() instanceof ItemBind bind)
) {
return; return;
} }
if (bindStack.getItem() instanceof IHasResistance resistanceItem) {
bind.setCurrentResistance(bindStack, session.getCurrentResistance()); resistanceItem.setCurrentResistance(bindStack, session.getCurrentResistance());
V2EquipmentHelper.sync(player);
}
} }
/** /**

View File

@@ -4,7 +4,7 @@ import com.tiedup.remake.compat.mca.MCACompat;
import com.tiedup.remake.core.TiedUpMod; import com.tiedup.remake.core.TiedUpMod;
import com.tiedup.remake.items.ItemKey; import com.tiedup.remake.items.ItemKey;
import com.tiedup.remake.items.ItemMasterKey; import com.tiedup.remake.items.ItemMasterKey;
import com.tiedup.remake.items.base.ItemCollar; import com.tiedup.remake.v2.bondage.CollarHelper;
import com.tiedup.remake.state.IBondageState; import com.tiedup.remake.state.IBondageState;
import com.tiedup.remake.v2.BodyRegionV2; import com.tiedup.remake.v2.BodyRegionV2;
import com.tiedup.remake.v2.bondage.IV2BondageItem; import com.tiedup.remake.v2.bondage.IV2BondageItem;
@@ -182,8 +182,8 @@ public abstract class MixinMCAVillagerInteraction {
// Can leash if player is a collar owner // Can leash if player is a collar owner
if (state.hasCollar()) { if (state.hasCollar()) {
ItemStack collar = state.getEquipment(BodyRegionV2.NECK); ItemStack collar = state.getEquipment(BodyRegionV2.NECK);
if (collar.getItem() instanceof ItemCollar collarItem) { if (CollarHelper.isCollar(collar)) {
return collarItem.getOwners(collar).contains(player.getUUID()); return CollarHelper.isOwner(collar, player);
} }
} }

View File

@@ -1,7 +1,7 @@
package com.tiedup.remake.mixin; package com.tiedup.remake.mixin;
import com.tiedup.remake.compat.mca.MCACompat; import com.tiedup.remake.compat.mca.MCACompat;
import com.tiedup.remake.items.base.ItemCollar; import com.tiedup.remake.v2.bondage.CollarHelper;
import com.tiedup.remake.state.IBondageState; import com.tiedup.remake.state.IBondageState;
import com.tiedup.remake.v2.BodyRegionV2; import com.tiedup.remake.v2.BodyRegionV2;
import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.LivingEntity;
@@ -71,8 +71,8 @@ public class MixinMCAVillagerLeash {
// Can be leashed if player is collar owner // Can be leashed if player is collar owner
if (state.hasCollar()) { if (state.hasCollar()) {
ItemStack collar = state.getEquipment(BodyRegionV2.NECK); ItemStack collar = state.getEquipment(BodyRegionV2.NECK);
if (collar.getItem() instanceof ItemCollar collarItem) { if (CollarHelper.isCollar(collar)) {
if (collarItem.getOwners(collar).contains(player.getUUID())) { if (CollarHelper.isOwner(collar, player)) {
cir.setReturnValue(true); cir.setReturnValue(true);
return; return;
} }

View File

@@ -1,7 +1,7 @@
package com.tiedup.remake.mixin.client; package com.tiedup.remake.mixin.client;
import com.tiedup.remake.items.base.ItemBind;
import com.tiedup.remake.items.base.PoseType; import com.tiedup.remake.items.base.PoseType;
import com.tiedup.remake.v2.bondage.PoseTypeHelper;
import com.tiedup.remake.state.HumanChairHelper; import com.tiedup.remake.state.HumanChairHelper;
import com.tiedup.remake.state.PlayerBindState; import com.tiedup.remake.state.PlayerBindState;
import com.tiedup.remake.v2.BodyRegionV2; import com.tiedup.remake.v2.BodyRegionV2;
@@ -57,11 +57,11 @@ public abstract class MixinCamera {
} }
ItemStack bind = state.getEquipment(BodyRegionV2.ARMS); ItemStack bind = state.getEquipment(BodyRegionV2.ARMS);
if (bind.isEmpty() || !(bind.getItem() instanceof ItemBind itemBind)) { if (bind.isEmpty()) {
return; return;
} }
if (itemBind.getPoseType() != PoseType.DOG) { if (PoseTypeHelper.getPoseType(bind) != PoseType.DOG) {
return; return;
} }

View File

@@ -2,8 +2,8 @@ package com.tiedup.remake.mixin.client;
import com.tiedup.remake.client.animation.render.DogPoseRenderHandler; import com.tiedup.remake.client.animation.render.DogPoseRenderHandler;
import com.tiedup.remake.client.animation.util.DogPoseHelper; import com.tiedup.remake.client.animation.util.DogPoseHelper;
import com.tiedup.remake.items.base.ItemBind;
import com.tiedup.remake.items.base.PoseType; import com.tiedup.remake.items.base.PoseType;
import com.tiedup.remake.v2.bondage.PoseTypeHelper;
import com.tiedup.remake.state.PlayerBindState; import com.tiedup.remake.state.PlayerBindState;
import com.tiedup.remake.v2.BodyRegionV2; import com.tiedup.remake.v2.BodyRegionV2;
import net.minecraft.client.model.PlayerModel; import net.minecraft.client.model.PlayerModel;
@@ -45,11 +45,11 @@ public class MixinPlayerModel {
} }
ItemStack bind = state.getEquipment(BodyRegionV2.ARMS); ItemStack bind = state.getEquipment(BodyRegionV2.ARMS);
if (bind.isEmpty() || !(bind.getItem() instanceof ItemBind itemBind)) { if (bind.isEmpty()) {
return; return;
} }
if (itemBind.getPoseType() != PoseType.DOG) { if (PoseTypeHelper.getPoseType(bind) != PoseType.DOG) {
return; return;
} }

View File

@@ -4,8 +4,9 @@ import com.tiedup.remake.client.animation.BondageAnimationManager;
import com.tiedup.remake.client.animation.StaticPoseApplier; import com.tiedup.remake.client.animation.StaticPoseApplier;
import com.tiedup.remake.client.animation.util.AnimationIdBuilder; import com.tiedup.remake.client.animation.util.AnimationIdBuilder;
import com.tiedup.remake.compat.mca.MCACompat; import com.tiedup.remake.compat.mca.MCACompat;
import com.tiedup.remake.items.base.ItemBind;
import com.tiedup.remake.items.base.PoseType; import com.tiedup.remake.items.base.PoseType;
import com.tiedup.remake.v2.bondage.BindModeHelper;
import com.tiedup.remake.v2.bondage.PoseTypeHelper;
import com.tiedup.remake.state.IBondageState; import com.tiedup.remake.state.IBondageState;
import com.tiedup.remake.v2.BodyRegionV2; import com.tiedup.remake.v2.BodyRegionV2;
import com.tiedup.remake.v2.bondage.capability.V2EquipmentHelper; import com.tiedup.remake.v2.bondage.capability.V2EquipmentHelper;
@@ -78,11 +79,7 @@ public class MixinVillagerEntityBaseModelMCA<T extends LivingEntity> {
// Get pose info from bind item // Get pose info from bind item
ItemStack bind = state.getEquipment(BodyRegionV2.ARMS); ItemStack bind = state.getEquipment(BodyRegionV2.ARMS);
PoseType poseType = PoseType.STANDARD; PoseType poseType = PoseTypeHelper.getPoseType(bind);
if (bind.getItem() instanceof ItemBind itemBind) {
poseType = itemBind.getPoseType();
}
// Derive bound state from V2 regions, fallback to V1 bind mode NBT // Derive bound state from V2 regions, fallback to V1 bind mode NBT
boolean armsBound = V2EquipmentHelper.isRegionOccupied( boolean armsBound = V2EquipmentHelper.isRegionOccupied(
@@ -94,9 +91,9 @@ public class MixinVillagerEntityBaseModelMCA<T extends LivingEntity> {
BodyRegionV2.LEGS BodyRegionV2.LEGS
); );
if (!armsBound && !legsBound && bind.getItem() instanceof ItemBind) { if (!armsBound && !legsBound && BindModeHelper.isBindItem(bind)) {
armsBound = ItemBind.hasArmsBound(bind); armsBound = BindModeHelper.hasArmsBound(bind);
legsBound = ItemBind.hasLegsBound(bind); legsBound = BindModeHelper.hasLegsBound(bind);
} }
// MCA doesn't track struggling state - use false for now // MCA doesn't track struggling state - use false for now

View File

@@ -5,8 +5,8 @@ import com.tiedup.remake.cells.CellRegistryV2;
import com.tiedup.remake.core.SystemMessageManager; import com.tiedup.remake.core.SystemMessageManager;
import com.tiedup.remake.core.TiedUpMod; import com.tiedup.remake.core.TiedUpMod;
import com.tiedup.remake.entities.EntityDamsel; import com.tiedup.remake.entities.EntityDamsel;
import com.tiedup.remake.items.base.ItemCollar;
import com.tiedup.remake.network.PacketRateLimiter; import com.tiedup.remake.network.PacketRateLimiter;
import com.tiedup.remake.v2.bondage.CollarHelper;
import com.tiedup.remake.network.sync.SyncManager; import com.tiedup.remake.network.sync.SyncManager;
import com.tiedup.remake.personality.PersonalityState; import com.tiedup.remake.personality.PersonalityState;
import com.tiedup.remake.state.IBondageState; import com.tiedup.remake.state.IBondageState;
@@ -14,9 +14,9 @@ import com.tiedup.remake.util.KidnappedHelper;
import com.tiedup.remake.v2.BodyRegionV2; import com.tiedup.remake.v2.BodyRegionV2;
import java.util.UUID; import java.util.UUID;
import java.util.function.Supplier; import java.util.function.Supplier;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
@@ -96,7 +96,7 @@ public class PacketAssignCellToCollar {
} }
ItemStack collarStack = state.getEquipment(BodyRegionV2.NECK); ItemStack collarStack = state.getEquipment(BodyRegionV2.NECK);
if (!(collarStack.getItem() instanceof ItemCollar collar)) { if (!CollarHelper.isCollar(collarStack)) {
TiedUpMod.LOGGER.debug( TiedUpMod.LOGGER.debug(
"[PacketAssignCellToCollar] Invalid collar item" "[PacketAssignCellToCollar] Invalid collar item"
); );
@@ -105,7 +105,7 @@ public class PacketAssignCellToCollar {
// Security: Verify sender owns the collar (or is admin) // Security: Verify sender owns the collar (or is admin)
if ( if (
!collar.isOwner(collarStack, sender) && !CollarHelper.isOwner(collarStack, sender) &&
!sender.hasPermissions(2) !sender.hasPermissions(2)
) { ) {
TiedUpMod.LOGGER.debug( TiedUpMod.LOGGER.debug(
@@ -139,7 +139,15 @@ public class PacketAssignCellToCollar {
} }
// Set the cell ID on the collar // Set the cell ID on the collar
collar.setCellId(collarStack, msg.cellId); if (msg.cellId != null) {
CollarHelper.setCellId(collarStack, msg.cellId);
} else {
// Clear cell assignment
CompoundTag collarTag = collarStack.getTag();
if (collarTag != null) {
collarTag.remove("cellId");
}
}
// Sync PersonalityState for damsels // Sync PersonalityState for damsels
if (target instanceof EntityDamsel damsel) { if (target instanceof EntityDamsel damsel) {

View File

@@ -7,8 +7,8 @@ import com.tiedup.remake.dialogue.EntityDialogueManager.DialogueCategory;
import com.tiedup.remake.entities.EntityDamsel; import com.tiedup.remake.entities.EntityDamsel;
import com.tiedup.remake.items.ItemCommandWand; import com.tiedup.remake.items.ItemCommandWand;
import com.tiedup.remake.items.ModItems; import com.tiedup.remake.items.ModItems;
import com.tiedup.remake.items.base.ItemCollar;
import com.tiedup.remake.network.ModNetwork; import com.tiedup.remake.network.ModNetwork;
import com.tiedup.remake.v2.bondage.CollarHelper;
import com.tiedup.remake.network.PacketRateLimiter; import com.tiedup.remake.network.PacketRateLimiter;
import com.tiedup.remake.personality.JobExperience; import com.tiedup.remake.personality.JobExperience;
import com.tiedup.remake.personality.NpcCommand; import com.tiedup.remake.personality.NpcCommand;
@@ -390,11 +390,11 @@ public class PacketNpcCommand {
} }
ItemStack collar = damsel.getEquipment(BodyRegionV2.NECK); ItemStack collar = damsel.getEquipment(BodyRegionV2.NECK);
if (!(collar.getItem() instanceof ItemCollar collarItem)) { if (!CollarHelper.isCollar(collar)) {
return false; return false;
} }
if (!collarItem.getOwners(collar).contains(sender.getUUID())) { if (!CollarHelper.isOwner(collar, sender)) {
SystemMessageManager.sendToPlayer( SystemMessageManager.sendToPlayer(
sender, sender,
SystemMessageManager.MessageCategory.ERROR, SystemMessageManager.MessageCategory.ERROR,

View File

@@ -1,7 +1,7 @@
package com.tiedup.remake.network.slave; package com.tiedup.remake.network.slave;
import com.tiedup.remake.items.base.ItemCollar;
import com.tiedup.remake.network.PacketRateLimiter; import com.tiedup.remake.network.PacketRateLimiter;
import com.tiedup.remake.v2.bondage.CollarHelper;
import com.tiedup.remake.state.IBondageState; import com.tiedup.remake.state.IBondageState;
import com.tiedup.remake.util.KidnappedHelper; import com.tiedup.remake.util.KidnappedHelper;
import com.tiedup.remake.v2.BodyRegionV2; import com.tiedup.remake.v2.BodyRegionV2;
@@ -75,9 +75,9 @@ public class PacketMasterEquip {
); );
if (targetState == null || !targetState.hasCollar()) return; if (targetState == null || !targetState.hasCollar()) return;
ItemStack collarStack = targetState.getEquipment(BodyRegionV2.NECK); ItemStack collarStack = targetState.getEquipment(BodyRegionV2.NECK);
if (collarStack.getItem() instanceof ItemCollar collar) { if (CollarHelper.isCollar(collarStack)) {
if ( if (
!collar.isOwner(collarStack, sender) && !CollarHelper.isOwner(collarStack, sender) &&
!sender.hasPermissions(2) !sender.hasPermissions(2)
) return; ) return;
} }

View File

@@ -2,10 +2,8 @@ package com.tiedup.remake.network.slave;
import com.tiedup.remake.core.SystemMessageManager; import com.tiedup.remake.core.SystemMessageManager;
import com.tiedup.remake.core.TiedUpMod; import com.tiedup.remake.core.TiedUpMod;
import com.tiedup.remake.items.ItemGpsCollar;
import com.tiedup.remake.items.ItemShockCollar;
import com.tiedup.remake.items.base.ItemCollar;
import com.tiedup.remake.state.IBondageState; import com.tiedup.remake.state.IBondageState;
import com.tiedup.remake.v2.bondage.CollarHelper;
import com.tiedup.remake.state.IRestrainable; import com.tiedup.remake.state.IRestrainable;
import com.tiedup.remake.state.PlayerBindState; import com.tiedup.remake.state.PlayerBindState;
import com.tiedup.remake.state.PlayerCaptorManager; import com.tiedup.remake.state.PlayerCaptorManager;
@@ -128,8 +126,8 @@ public class PacketSlaveAction {
ItemStack collarStack = kidnapped.getEquipment( ItemStack collarStack = kidnapped.getEquipment(
BodyRegionV2.NECK BodyRegionV2.NECK
); );
if (collarStack.getItem() instanceof ItemCollar collar) { if (CollarHelper.isCollar(collarStack)) {
if (collar.isOwner(collarStack, sender)) { if (CollarHelper.isOwner(collarStack, sender)) {
targetCaptive = kidnapped; targetCaptive = kidnapped;
break; break;
} }
@@ -219,10 +217,7 @@ public class PacketSlaveAction {
} }
ItemStack collarStack = target.getEquipment(BodyRegionV2.NECK); ItemStack collarStack = target.getEquipment(BodyRegionV2.NECK);
if ( if (!CollarHelper.canShock(collarStack)) {
!(collarStack.getItem() instanceof ItemCollar collar) ||
!collar.canShock()
) {
SystemMessageManager.sendToPlayer( SystemMessageManager.sendToPlayer(
sender, sender,
SystemMessageManager.MessageCategory.ERROR, SystemMessageManager.MessageCategory.ERROR,
@@ -232,14 +227,8 @@ public class PacketSlaveAction {
} }
// Check if sender is owner of the collar or collar is public // Check if sender is owner of the collar or collar is public
// FIX: Always check permissions for ANY collar that can shock, not just ItemShockCollar boolean isOwner = CollarHelper.isOwner(collarStack, sender);
boolean isOwner = collar.isOwner(collarStack, sender); boolean isPublic = CollarHelper.isPublicShock(collarStack);
boolean isPublic = false;
// ItemShockCollar has additional "public mode" that allows anyone to shock
if (collarStack.getItem() instanceof ItemShockCollar shockCollar) {
isPublic = shockCollar.isPublic(collarStack);
}
if (!isOwner && !isPublic) { if (!isOwner && !isPublic) {
SystemMessageManager.sendToPlayer( SystemMessageManager.sendToPlayer(
@@ -285,10 +274,7 @@ public class PacketSlaveAction {
} }
ItemStack collarStack = target.getEquipment(BodyRegionV2.NECK); ItemStack collarStack = target.getEquipment(BodyRegionV2.NECK);
if ( if (!CollarHelper.hasGPS(collarStack)) {
!(collarStack.getItem() instanceof ItemCollar collar) ||
!collar.hasGPS()
) {
SystemMessageManager.sendToPlayer( SystemMessageManager.sendToPlayer(
sender, sender,
SystemMessageManager.MessageCategory.ERROR, SystemMessageManager.MessageCategory.ERROR,
@@ -298,9 +284,8 @@ public class PacketSlaveAction {
} }
// Check permissions // Check permissions
if (collarStack.getItem() instanceof ItemGpsCollar gpsCollar) { boolean isOwner = CollarHelper.isOwner(collarStack, sender);
boolean isOwner = collar.isOwner(collarStack, sender); boolean isPublic = CollarHelper.hasPublicTracking(collarStack);
boolean isPublic = gpsCollar.hasPublicTracking(collarStack);
if (!isOwner && !isPublic) { if (!isOwner && !isPublic) {
SystemMessageManager.sendToPlayer( SystemMessageManager.sendToPlayer(
@@ -310,7 +295,6 @@ public class PacketSlaveAction {
); );
return; return;
} }
}
// Check same dimension // Check same dimension
if ( if (
@@ -367,8 +351,8 @@ public class PacketSlaveAction {
} else { } else {
// For collar-owned entities, just remove collar ownership // For collar-owned entities, just remove collar ownership
ItemStack collarStack = target.getEquipment(BodyRegionV2.NECK); ItemStack collarStack = target.getEquipment(BodyRegionV2.NECK);
if (collarStack.getItem() instanceof ItemCollar collar) { if (CollarHelper.isCollar(collarStack)) {
collar.removeOwner(collarStack, sender.getUUID()); CollarHelper.removeOwner(collarStack, sender.getUUID());
SystemMessageManager.sendToPlayer( SystemMessageManager.sendToPlayer(
sender, sender,
"Released collar control of " + name + "!", "Released collar control of " + name + "!",

View File

@@ -1,6 +1,6 @@
package com.tiedup.remake.personality; package com.tiedup.remake.personality;
import com.tiedup.remake.items.base.ItemBind; import com.tiedup.remake.v2.bondage.BindModeHelper;
import net.minecraft.world.item.AxeItem; import net.minecraft.world.item.AxeItem;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.PickaxeItem; import net.minecraft.world.item.PickaxeItem;
@@ -48,7 +48,7 @@ public enum ToolMode {
if (item instanceof AxeItem) { if (item instanceof AxeItem) {
return WOODCUTTING; return WOODCUTTING;
} }
if (item instanceof ItemBind) { if (BindModeHelper.isBindItem(mainHand)) {
return CAPTURE; return CAPTURE;
} }

View File

@@ -1,8 +1,8 @@
package com.tiedup.remake.state; package com.tiedup.remake.state;
import com.tiedup.remake.items.base.ILockable; import com.tiedup.remake.items.base.ILockable;
import com.tiedup.remake.items.base.ItemBind;
import com.tiedup.remake.v2.BodyRegionV2; import com.tiedup.remake.v2.BodyRegionV2;
import com.tiedup.remake.v2.bondage.BindModeHelper;
import java.util.function.Supplier; import java.util.function.Supplier;
import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
@@ -97,7 +97,7 @@ public interface IBondageState extends ICapturable {
if (!isTiedUp()) return false; if (!isTiedUp()) return false;
ItemStack bind = getEquipment(BodyRegionV2.ARMS); ItemStack bind = getEquipment(BodyRegionV2.ARMS);
if (bind.isEmpty()) return false; if (bind.isEmpty()) return false;
return ItemBind.hasArmsBound(bind); return BindModeHelper.hasArmsBound(bind);
} }
/** /**
@@ -111,7 +111,7 @@ public interface IBondageState extends ICapturable {
if (!isTiedUp()) return false; if (!isTiedUp()) return false;
ItemStack bind = getEquipment(BodyRegionV2.ARMS); ItemStack bind = getEquipment(BodyRegionV2.ARMS);
if (bind.isEmpty()) return false; if (bind.isEmpty()) return false;
return ItemBind.hasLegsBound(bind); return BindModeHelper.hasLegsBound(bind);
} }
/** /**
@@ -121,10 +121,10 @@ public interface IBondageState extends ICapturable {
* @return "full", "arms", or "legs" * @return "full", "arms", or "legs"
*/ */
default String getBindModeId() { default String getBindModeId() {
if (!isTiedUp()) return ItemBind.BIND_MODE_FULL; if (!isTiedUp()) return BindModeHelper.MODE_FULL;
ItemStack bind = getEquipment(BodyRegionV2.ARMS); ItemStack bind = getEquipment(BodyRegionV2.ARMS);
if (bind.isEmpty()) return ItemBind.BIND_MODE_FULL; if (bind.isEmpty()) return BindModeHelper.MODE_FULL;
return ItemBind.getBindModeId(bind); return BindModeHelper.getBindModeId(bind);
} }
/** /**

View File

@@ -3,8 +3,8 @@ package com.tiedup.remake.state;
import com.tiedup.remake.core.ModSounds; import com.tiedup.remake.core.ModSounds;
import com.tiedup.remake.core.TiedUpMod; import com.tiedup.remake.core.TiedUpMod;
import com.tiedup.remake.entities.LeashProxyEntity; import com.tiedup.remake.entities.LeashProxyEntity;
import com.tiedup.remake.items.base.ItemBind; import com.tiedup.remake.items.base.ILockable;
import com.tiedup.remake.items.base.ItemCollar; import com.tiedup.remake.v2.bondage.CollarHelper;
import com.tiedup.remake.network.sync.SyncManager; import com.tiedup.remake.network.sync.SyncManager;
import com.tiedup.remake.state.components.PlayerCaptivity; import com.tiedup.remake.state.components.PlayerCaptivity;
import com.tiedup.remake.state.components.PlayerClothesPermission; import com.tiedup.remake.state.components.PlayerClothesPermission;
@@ -737,8 +737,8 @@ public class PlayerBindState implements IRestrainable, IPlayerBindStateHost {
ItemStack collar = getCurrentCollar(); ItemStack collar = getCurrentCollar();
return ( return (
!collar.isEmpty() && !collar.isEmpty() &&
collar.getItem() instanceof ItemCollar collarItem && collar.getItem() instanceof ILockable lockable &&
collarItem.isLocked(collar) lockable.isLocked(collar)
); );
} }
@@ -1211,9 +1211,9 @@ public class PlayerBindState implements IRestrainable, IPlayerBindStateHost {
ItemStack collar = getEquipment(BodyRegionV2.NECK); ItemStack collar = getEquipment(BodyRegionV2.NECK);
if ( if (
!collar.isEmpty() && !collar.isEmpty() &&
collar.getItem() instanceof ItemCollar collarItem collar.getItem() instanceof ILockable lockable
) { ) {
collarItem.setLocked(collar, false); lockable.setLocked(collar, false);
} }
// Drop all items // Drop all items

View File

@@ -1,8 +1,8 @@
package com.tiedup.remake.state; package com.tiedup.remake.state;
import com.tiedup.remake.core.TiedUpMod; import com.tiedup.remake.core.TiedUpMod;
import com.tiedup.remake.items.base.ItemCollar;
import com.tiedup.remake.v2.BodyRegionV2; import com.tiedup.remake.v2.BodyRegionV2;
import com.tiedup.remake.v2.bondage.CollarHelper;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CopyOnWriteArrayList;
@@ -144,9 +144,9 @@ public class PlayerCaptorManager implements ICaptor {
// Check if target has collar with this captor as owner // Check if target has collar with this captor as owner
if (target.hasCollar()) { if (target.hasCollar()) {
ItemStack collar = target.getEquipment(BodyRegionV2.NECK); ItemStack collar = target.getEquipment(BodyRegionV2.NECK);
if (collar.getItem() instanceof ItemCollar collarItem) { if (CollarHelper.isCollar(collar)) {
if ( if (
collarItem.getOwners(collar).contains(this.captor.getUUID()) CollarHelper.getOwners(collar).contains(this.captor.getUUID())
) { ) {
return true; return true;
} }

View File

@@ -1,7 +1,7 @@
package com.tiedup.remake.state.components; package com.tiedup.remake.state.components;
import com.tiedup.remake.items.base.ItemCollar;
import com.tiedup.remake.state.hosts.IPlayerBindStateHost; import com.tiedup.remake.state.hosts.IPlayerBindStateHost;
import com.tiedup.remake.v2.bondage.CollarHelper;
import com.tiedup.remake.v2.BodyRegionV2; import com.tiedup.remake.v2.BodyRegionV2;
import com.tiedup.remake.v2.bondage.capability.V2EquipmentHelper; import com.tiedup.remake.v2.bondage.capability.V2EquipmentHelper;
import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.LivingEntity;
@@ -87,12 +87,9 @@ public class PlayerDataRetrieval {
Player player = host.getPlayer(); Player player = host.getPlayer();
ItemStack collar = getCurrentCollar(); ItemStack collar = getCurrentCollar();
if ( if (!collar.isEmpty() && CollarHelper.isCollar(collar)) {
!collar.isEmpty() &&
collar.getItem() instanceof ItemCollar collarItem
) {
// Try to get nickname from collar NBT // Try to get nickname from collar NBT
String nickname = collarItem.getNickname(collar); String nickname = CollarHelper.getNickname(collar);
if (nickname != null && !nickname.isEmpty()) { if (nickname != null && !nickname.isEmpty()) {
return nickname; return nickname;
} }
@@ -109,8 +106,8 @@ public class PlayerDataRetrieval {
ItemStack collar = getCurrentCollar(); ItemStack collar = getCurrentCollar();
if (collar.isEmpty()) return false; if (collar.isEmpty()) return false;
if (collar.getItem() instanceof ItemCollar collarItem) { if (CollarHelper.isCollar(collar)) {
String nickname = collarItem.getNickname(collar); String nickname = CollarHelper.getNickname(collar);
return nickname != null && !nickname.isEmpty(); return nickname != null && !nickname.isEmpty();
} }
return false; return false;

View File

@@ -1,8 +1,6 @@
package com.tiedup.remake.state.components; package com.tiedup.remake.state.components;
import com.tiedup.remake.items.base.ILockable; import com.tiedup.remake.items.base.ILockable;
import com.tiedup.remake.items.base.ItemBind;
import com.tiedup.remake.items.base.ItemCollar;
import com.tiedup.remake.state.hosts.IPlayerBindStateHost; import com.tiedup.remake.state.hosts.IPlayerBindStateHost;
import com.tiedup.remake.v2.BodyRegionV2; import com.tiedup.remake.v2.BodyRegionV2;
import com.tiedup.remake.v2.bondage.IV2BondageEquipment; import com.tiedup.remake.v2.bondage.IV2BondageEquipment;
@@ -154,9 +152,9 @@ public class PlayerEquipment {
); );
if (collar.isEmpty()) return ItemStack.EMPTY; if (collar.isEmpty()) return ItemStack.EMPTY;
if (collar.getItem() instanceof ItemCollar collarItem) { if (collar.getItem() instanceof ILockable lockable) {
if (!force && collarItem.isLocked(collar)) return ItemStack.EMPTY; if (!force && lockable.isLocked(collar)) return ItemStack.EMPTY;
collarItem.setLocked(collar, false); lockable.setLocked(collar, false);
} }
return V2EquipmentHelper.unequipFromRegion(player, BodyRegionV2.NECK); return V2EquipmentHelper.unequipFromRegion(player, BodyRegionV2.NECK);
} }

View File

@@ -3,8 +3,8 @@ package com.tiedup.remake.state.components;
import com.tiedup.remake.cells.CampOwnership; import com.tiedup.remake.cells.CampOwnership;
import com.tiedup.remake.cells.CellRegistryV2; import com.tiedup.remake.cells.CellRegistryV2;
import com.tiedup.remake.core.TiedUpMod; import com.tiedup.remake.core.TiedUpMod;
import com.tiedup.remake.items.base.ItemBind;
import com.tiedup.remake.state.hosts.IPlayerBindStateHost; import com.tiedup.remake.state.hosts.IPlayerBindStateHost;
import com.tiedup.remake.v2.bondage.BindModeHelper;
import com.tiedup.remake.v2.BodyRegionV2; import com.tiedup.remake.v2.BodyRegionV2;
import java.util.UUID; import java.util.UUID;
import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerLevel;
@@ -148,7 +148,7 @@ public class PlayerLifecycle {
*/ */
private boolean hasLegsBound(ItemStack bind) { private boolean hasLegsBound(ItemStack bind) {
if (bind.isEmpty()) return false; if (bind.isEmpty()) return false;
if (!(bind.getItem() instanceof ItemBind)) return false; if (!BindModeHelper.isBindItem(bind)) return false;
return ItemBind.hasLegsBound(bind); return BindModeHelper.hasLegsBound(bind);
} }
} }

View File

@@ -1,7 +1,19 @@
package com.tiedup.remake.util; package com.tiedup.remake.util;
import com.tiedup.remake.blocks.entity.IBondageItemHolder; import com.tiedup.remake.blocks.entity.IBondageItemHolder;
import com.tiedup.remake.items.base.*; import com.tiedup.remake.items.base.ItemBind;
import com.tiedup.remake.items.base.ItemBlindfold;
import com.tiedup.remake.items.base.ItemCollar;
import com.tiedup.remake.items.base.ItemEarplugs;
import com.tiedup.remake.items.base.ItemGag;
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.List; import java.util.List;
import net.minecraft.ChatFormatting; import net.minecraft.ChatFormatting;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
@@ -41,36 +53,32 @@ public final class BondageItemLoaderUtility {
ItemStack stack, ItemStack stack,
Player player Player player
) { ) {
if (stack.getItem() instanceof ItemBind && holder.getBind().isEmpty()) { if ((stack.getItem() instanceof ItemBind || BindModeHelper.isBindItem(stack)) && holder.getBind().isEmpty()) {
holder.setBind(stack.copyWithCount(1)); holder.setBind(stack.copyWithCount(1));
if (!player.isCreative()) stack.shrink(1); if (!player.isCreative()) stack.shrink(1);
return true; return true;
} }
if (stack.getItem() instanceof ItemGag && holder.getGag().isEmpty()) { if ((stack.getItem() instanceof ItemGag
|| DataDrivenBondageItem.getComponent(stack, ComponentType.GAGGING, GaggingComponent.class) != null)
&& holder.getGag().isEmpty()) {
holder.setGag(stack.copyWithCount(1)); holder.setGag(stack.copyWithCount(1));
if (!player.isCreative()) stack.shrink(1); if (!player.isCreative()) stack.shrink(1);
return true; return true;
} }
if ( if ((stack.getItem() instanceof ItemBlindfold || isDataDrivenForRegion(stack, BodyRegionV2.EYES))
stack.getItem() instanceof ItemBlindfold && && holder.getBlindfold().isEmpty()) {
holder.getBlindfold().isEmpty()
) {
holder.setBlindfold(stack.copyWithCount(1)); holder.setBlindfold(stack.copyWithCount(1));
if (!player.isCreative()) stack.shrink(1); if (!player.isCreative()) stack.shrink(1);
return true; return true;
} }
if ( if ((stack.getItem() instanceof ItemEarplugs || isDataDrivenForRegion(stack, BodyRegionV2.EARS))
stack.getItem() instanceof ItemEarplugs && && holder.getEarplugs().isEmpty()) {
holder.getEarplugs().isEmpty()
) {
holder.setEarplugs(stack.copyWithCount(1)); holder.setEarplugs(stack.copyWithCount(1));
if (!player.isCreative()) stack.shrink(1); if (!player.isCreative()) stack.shrink(1);
return true; return true;
} }
if ( if ((stack.getItem() instanceof ItemCollar || CollarHelper.isCollar(stack))
stack.getItem() instanceof ItemCollar && && holder.getCollar().isEmpty()) {
holder.getCollar().isEmpty()
) {
holder.setCollar(stack.copyWithCount(1)); holder.setCollar(stack.copyWithCount(1));
if (!player.isCreative()) stack.shrink(1); if (!player.isCreative()) stack.shrink(1);
return true; return true;
@@ -87,13 +95,28 @@ public final class BondageItemLoaderUtility {
* @return true if the item can be loaded into a bondage item holder * @return true if the item can be loaded into a bondage item holder
*/ */
public static boolean isLoadableBondageItem(ItemStack stack) { public static boolean isLoadableBondageItem(ItemStack stack) {
return ( if (stack.isEmpty()) return false;
(stack.getItem() instanceof ItemBind) || // V1 item types
(stack.getItem() instanceof ItemGag) || if (stack.getItem() instanceof ItemBind
(stack.getItem() instanceof ItemBlindfold) || || stack.getItem() instanceof ItemGag
(stack.getItem() instanceof ItemEarplugs) || || stack.getItem() instanceof ItemBlindfold
(stack.getItem() instanceof ItemCollar) || stack.getItem() instanceof ItemEarplugs
); || stack.getItem() instanceof ItemCollar) {
return true;
}
// V2 data-driven items: bind, gag, blindfold, earplugs, collar
if (BindModeHelper.isBindItem(stack)) return true;
if (DataDrivenBondageItem.getComponent(stack, ComponentType.GAGGING, GaggingComponent.class) != null) return true;
if (isDataDrivenForRegion(stack, BodyRegionV2.EYES)) return true;
if (isDataDrivenForRegion(stack, BodyRegionV2.EARS)) return true;
if (CollarHelper.isCollar(stack)) return true;
return false;
}
/** Check if a stack is a data-driven item occupying the given body region. */
private static boolean isDataDrivenForRegion(ItemStack stack, BodyRegionV2 region) {
DataDrivenItemDefinition def = DataDrivenItemRegistry.get(stack);
return def != null && def.occupiedRegions().contains(region);
} }
/** /**

View File

@@ -2,9 +2,8 @@ package com.tiedup.remake.util;
import com.tiedup.remake.core.TiedUpMod; import com.tiedup.remake.core.TiedUpMod;
import com.tiedup.remake.items.base.IHasResistance; import com.tiedup.remake.items.base.IHasResistance;
import com.tiedup.remake.items.base.ItemBind;
import com.tiedup.remake.items.base.ItemCollar;
import com.tiedup.remake.state.IBondageState; import com.tiedup.remake.state.IBondageState;
import com.tiedup.remake.v2.bondage.CollarHelper;
import com.tiedup.remake.v2.BodyRegionV2; import com.tiedup.remake.v2.BodyRegionV2;
import java.util.UUID; import java.util.UUID;
import net.minecraft.ChatFormatting; import net.minecraft.ChatFormatting;
@@ -60,7 +59,7 @@ public final class RestraintApplicator {
} }
// Tighten existing bind - reset resistance to max // Tighten existing bind - reset resistance to max
if (currentBind.getItem() instanceof ItemBind bindItem) { if (currentBind.getItem() instanceof IHasResistance bindItem) {
int maxResistance = bindItem.getBaseResistance(target); int maxResistance = bindItem.getBaseResistance(target);
state.setCurrentBindResistance(maxResistance); state.setCurrentBindResistance(maxResistance);
return true; return true;
@@ -286,11 +285,8 @@ public final class RestraintApplicator {
ItemStack collarCopy = collar.copy(); ItemStack collarCopy = collar.copy();
// Add owner if provided // Add owner if provided
if ( if (ownerUUID != null && CollarHelper.isCollar(collarCopy)) {
ownerUUID != null && CollarHelper.addOwner(
collarCopy.getItem() instanceof ItemCollar collarItem
) {
collarItem.addOwner(
collarCopy, collarCopy,
ownerUUID, ownerUUID,
ownerName != null ? ownerName : "Unknown" ownerName != null ? ownerName : "Unknown"

View File

@@ -1,7 +1,8 @@
package com.tiedup.remake.v2.bondage.movement; package com.tiedup.remake.v2.bondage.movement;
import com.tiedup.remake.items.base.ItemBind;
import com.tiedup.remake.items.base.PoseType; import com.tiedup.remake.items.base.PoseType;
import com.tiedup.remake.v2.bondage.BindModeHelper;
import com.tiedup.remake.v2.bondage.PoseTypeHelper;
import com.tiedup.remake.v2.BodyRegionV2; import com.tiedup.remake.v2.BodyRegionV2;
import com.tiedup.remake.v2.bondage.datadriven.DataDrivenItemDefinition; import com.tiedup.remake.v2.bondage.datadriven.DataDrivenItemDefinition;
import com.tiedup.remake.v2.bondage.datadriven.DataDrivenItemRegistry; import com.tiedup.remake.v2.bondage.datadriven.DataDrivenItemRegistry;
@@ -19,7 +20,7 @@ import org.jetbrains.annotations.Nullable;
* default speed/jump values. Modifiers from lower-severity items are ignored.</p> * default speed/jump values. Modifiers from lower-severity items are ignored.</p>
* *
* <h3>V1 Compatibility (H6 fix)</h3> * <h3>V1 Compatibility (H6 fix)</h3>
* <p>V1 items ({@link ItemBind}) stored in V2 capability * <p>V1 items (ItemBind) stored in V2 capability
* do not have data-driven definitions. This resolver provides a fallback that * do not have data-driven definitions. This resolver provides a fallback that
* maps V1 bind mode + pose type to a {@link MovementStyle} with speed values matching * maps V1 bind mode + pose type to a {@link MovementStyle} with speed values matching
* the original V1 behavior, preventing double stacking between the legacy * the original V1 behavior, preventing double stacking between the legacy
@@ -122,7 +123,7 @@ public final class MovementStyleResolver {
// ==================== V1 Fallback ==================== // ==================== V1 Fallback ====================
/** /**
* Attempt to derive a movement style from a V1 {@link ItemBind} item. * Attempt to derive a movement style from a V1 bind item.
* *
* <p>Only items with legs bound produce a movement style. The mapping preserves * <p>Only items with legs bound produce a movement style. The mapping preserves
* the original V1 speed values:</p> * the original V1 speed values:</p>
@@ -137,15 +138,15 @@ public final class MovementStyleResolver {
*/ */
@Nullable @Nullable
private static V1Fallback resolveV1Fallback(ItemStack stack) { private static V1Fallback resolveV1Fallback(ItemStack stack) {
if (!(stack.getItem() instanceof ItemBind bindItem)) { if (!BindModeHelper.isBindItem(stack)) {
return null; return null;
} }
if (!ItemBind.hasLegsBound(stack)) { if (!BindModeHelper.hasLegsBound(stack)) {
return null; return null;
} }
PoseType poseType = bindItem.getPoseType(); PoseType poseType = PoseTypeHelper.getPoseType(stack);
return switch (poseType) { return switch (poseType) {
case WRAP, LATEX_SACK -> new V1Fallback( case WRAP, LATEX_SACK -> new V1Fallback(

View File

@@ -1,8 +1,8 @@
package com.tiedup.remake.v2.furniture.network; package com.tiedup.remake.v2.furniture.network;
import com.tiedup.remake.core.TiedUpMod; import com.tiedup.remake.core.TiedUpMod;
import com.tiedup.remake.items.base.ItemCollar;
import com.tiedup.remake.network.PacketRateLimiter; import com.tiedup.remake.network.PacketRateLimiter;
import com.tiedup.remake.v2.bondage.CollarHelper;
import com.tiedup.remake.state.IBondageState; import com.tiedup.remake.state.IBondageState;
import com.tiedup.remake.util.KidnappedHelper; import com.tiedup.remake.util.KidnappedHelper;
import com.tiedup.remake.v2.BodyRegionV2; import com.tiedup.remake.v2.BodyRegionV2;
@@ -28,7 +28,7 @@ import net.minecraftforge.network.NetworkEvent;
* Client-to-server packet: master forces a captive onto a furniture seat. * Client-to-server packet: master forces a captive onto a furniture seat.
* *
* <p>The sender must own the captive's collar (verified via * <p>The sender must own the captive's collar (verified via
* {@link ItemCollar#isOwner(ItemStack, net.minecraft.world.entity.player.Player)}), * {@link CollarHelper#isOwner(ItemStack, net.minecraft.world.entity.player.Player)}),
* the captive must be alive and within 5 blocks of both sender and furniture, * the captive must be alive and within 5 blocks of both sender and furniture,
* and the furniture must have an available seat.</p> * and the furniture must have an available seat.</p>
* *
@@ -132,10 +132,7 @@ public class PacketFurnitureForcemount {
} }
ItemStack collarStack = captiveState.getEquipment(BodyRegionV2.NECK); ItemStack collarStack = captiveState.getEquipment(BodyRegionV2.NECK);
if ( if (!CollarHelper.isCollar(collarStack)) {
collarStack.isEmpty() ||
!(collarStack.getItem() instanceof ItemCollar collar)
) {
TiedUpMod.LOGGER.debug( TiedUpMod.LOGGER.debug(
"[PacketFurnitureForcemount] Invalid collar item on captive" "[PacketFurnitureForcemount] Invalid collar item on captive"
); );
@@ -143,7 +140,7 @@ public class PacketFurnitureForcemount {
} }
// Collar must be owned by sender (or sender has admin permission) // Collar must be owned by sender (or sender has admin permission)
if (!collar.isOwner(collarStack, sender) && !sender.hasPermissions(2)) { if (!CollarHelper.isOwner(collarStack, sender) && !sender.hasPermissions(2)) {
TiedUpMod.LOGGER.debug( TiedUpMod.LOGGER.debug(
"[PacketFurnitureForcemount] {} is not the collar owner of {}", "[PacketFurnitureForcemount] {} is not the collar owner of {}",
sender.getName().getString(), sender.getName().getString(),

View File

@@ -3,17 +3,20 @@ package com.tiedup.remake.worldgen;
import com.tiedup.remake.blocks.ModBlocks; import com.tiedup.remake.blocks.ModBlocks;
import com.tiedup.remake.blocks.entity.TrappedChestBlockEntity; import com.tiedup.remake.blocks.entity.TrappedChestBlockEntity;
import com.tiedup.remake.core.TiedUpMod; import com.tiedup.remake.core.TiedUpMod;
import com.tiedup.remake.items.ModItems;
import com.tiedup.remake.items.base.BindVariant;
import com.tiedup.remake.items.base.BlindfoldVariant;
import com.tiedup.remake.items.base.GagVariant;
import com.tiedup.remake.v2.V2Blocks; import com.tiedup.remake.v2.V2Blocks;
import com.tiedup.remake.v2.BodyRegionV2;
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 com.tiedup.remake.v2.blocks.PetCageBlock; import com.tiedup.remake.v2.blocks.PetCageBlock;
import com.tiedup.remake.v2.blocks.PetCagePartBlock; import com.tiedup.remake.v2.blocks.PetCagePartBlock;
import java.util.List;
import java.util.stream.Collectors;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction; import net.minecraft.core.Direction;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.nbt.DoubleTag; import net.minecraft.nbt.DoubleTag;
import net.minecraft.nbt.FloatTag; import net.minecraft.nbt.FloatTag;
import net.minecraft.nbt.ListTag; import net.minecraft.nbt.ListTag;
@@ -540,38 +543,46 @@ public class HangingCagePiece extends StructurePiece {
BlockEntity be = level.getBlockEntity(chestPos); BlockEntity be = level.getBlockEntity(chestPos);
if (be instanceof TrappedChestBlockEntity trappedChest) { if (be instanceof TrappedChestBlockEntity trappedChest) {
// Random bind // Random bind from data-driven ARMS items
BindVariant[] bindVariants = BindVariant.values(); trappedChest.setBind(randomItemForRegion(random, BodyRegionV2.ARMS, FALLBACK_BINDS));
BindVariant chosenBind = bindVariants[random.nextInt(
bindVariants.length
)];
ItemStack bindStack = new ItemStack(ModItems.getBind(chosenBind));
trappedChest.setBind(bindStack);
// Random gag (50% chance) // Random gag (50% chance)
if (random.nextFloat() < 0.50f) { if (random.nextFloat() < 0.50f) {
GagVariant[] gagVariants = GagVariant.values(); trappedChest.setGag(randomItemForRegion(random, BodyRegionV2.MOUTH, FALLBACK_GAGS));
GagVariant chosenGag = gagVariants[random.nextInt(
gagVariants.length
)];
ItemStack gagStack = new ItemStack(ModItems.getGag(chosenGag));
trappedChest.setGag(gagStack);
} }
// Random blindfold (30% chance) // Random blindfold (30% chance)
if (random.nextFloat() < 0.30f) { if (random.nextFloat() < 0.30f) {
BlindfoldVariant[] bfVariants = BlindfoldVariant.values(); trappedChest.setBlindfold(randomItemForRegion(random, BodyRegionV2.EYES, FALLBACK_BLINDFOLDS));
BlindfoldVariant chosenBf = bfVariants[random.nextInt(
bfVariants.length
)];
ItemStack bfStack = new ItemStack(
ModItems.getBlindfold(chosenBf)
);
trappedChest.setBlindfold(bfStack);
} }
} }
} }
// Fallback item IDs for worldgen when DataDrivenItemRegistry is empty (race with reload)
private static final ResourceLocation[] FALLBACK_BINDS = {
new ResourceLocation("tiedup", "ropes"),
new ResourceLocation("tiedup", "chain"),
new ResourceLocation("tiedup", "armbinder")
};
private static final ResourceLocation[] FALLBACK_GAGS = {
new ResourceLocation("tiedup", "cloth_gag"),
new ResourceLocation("tiedup", "ball_gag")
};
private static final ResourceLocation[] FALLBACK_BLINDFOLDS = {
new ResourceLocation("tiedup", "classic_blindfold")
};
private static ItemStack randomItemForRegion(RandomSource random, BodyRegionV2 region, ResourceLocation[] fallbacks) {
List<DataDrivenItemDefinition> defs = DataDrivenItemRegistry.getAll().stream()
.filter(d -> d.occupiedRegions().contains(region))
.collect(Collectors.toList());
if (!defs.isEmpty()) {
return DataDrivenBondageItem.createStack(defs.get(random.nextInt(defs.size())).id());
}
// Fallback for worldgen race condition (registry not loaded yet)
return DataDrivenBondageItem.createStack(fallbacks[random.nextInt(fallbacks.length)]);
}
static void safeSetBlock( static void safeSetBlock(
WorldGenLevel level, WorldGenLevel level,
BlockPos pos, BlockPos pos,
@@ -629,9 +640,7 @@ public class HangingCagePiece extends StructurePiece {
entityTag.putUUID("UUID", java.util.UUID.randomUUID()); entityTag.putUUID("UUID", java.util.UUID.randomUUID());
// Random bind item — the damsel spawns already restrained // Random bind item — the damsel spawns already restrained
BindVariant[] variants = BindVariant.values(); ItemStack bindStack = randomItemForRegion(random, BodyRegionV2.ARMS, FALLBACK_BINDS);
BindVariant chosenBind = variants[random.nextInt(variants.length)];
ItemStack bindStack = new ItemStack(ModItems.getBind(chosenBind));
bindStack.getOrCreateTag().putString("bindMode", "full"); bindStack.getOrCreateTag().putString("bindMode", "full");
entityTag.put("Bind", bindStack.save(new CompoundTag())); entityTag.put("Bind", bindStack.save(new CompoundTag()));
@@ -640,9 +649,8 @@ public class HangingCagePiece extends StructurePiece {
if (chunk instanceof ProtoChunk protoChunk) { if (chunk instanceof ProtoChunk protoChunk) {
protoChunk.addEntity(entityTag); protoChunk.addEntity(entityTag);
TiedUpMod.LOGGER.info( TiedUpMod.LOGGER.info(
"[HangingCage] Scheduled {} damsel with {} at {}", "[HangingCage] Scheduled {} damsel at {}",
shiny ? "shiny" : "regular", shiny ? "shiny" : "regular",
chosenBind.getRegistryName(),
masterPos.toShortString() masterPos.toShortString()
); );
} }