feat(D-01/D): V1 cleanup — delete 28 files, ~5400 lines removed
D1: ThreadLocal alert suppression moved from ItemCollar to CollarHelper.
onCollarRemoved() logic (kidnapper alert) moved to CollarHelper.
D2+D3: Deleted 17 V1 item classes + 4 V1-only interfaces:
ItemBind, ItemGag, ItemBlindfold, ItemCollar, ItemEarplugs, ItemMittens,
ItemColor, ItemClassicCollar, ItemShockCollar, ItemShockCollarAuto,
ItemGpsCollar, ItemChokeCollar, ItemHood, ItemMedicalGag,
IBondageItem, IHasGaggingEffect, IHasBlindingEffect, IAdjustable
D4: KidnapperTheme/KidnapperItemSelector/DispenserBehaviors migrated
from variant enums to string-based DataDrivenItemRegistry IDs.
D5: Deleted 11 variant enums + Generic* factories + ItemBallGag3D:
BindVariant, GagVariant, BlindfoldVariant, EarplugsVariant, MittensVariant,
GenericBind, GenericGag, GenericBlindfold, GenericEarplugs, GenericMittens
D6: ModItems cleaned — all V1 bondage registrations removed.
D7: ModCreativeTabs rewritten — iterates DataDrivenItemRegistry.
D8+D9: All V2 helpers cleaned (V1 fallbacks removed), orphan imports removed.
Zero V1 bondage code references remain (only Javadoc comments).
All bondage items are now data-driven via 47 JSON definitions.
This commit is contained in:
@@ -796,16 +796,14 @@ public abstract class AbstractTiedUpNpc
|
||||
public boolean hasGaggingEffect() {
|
||||
ItemStack gag = this.getEquipment(BodyRegionV2.MOUTH);
|
||||
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;
|
||||
return DataDrivenBondageItem.getComponent(gag, ComponentType.GAGGING, GaggingComponent.class) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasBlindingEffect() {
|
||||
ItemStack blindfold = this.getEquipment(BodyRegionV2.EYES);
|
||||
if (blindfold.isEmpty()) return false;
|
||||
if (DataDrivenBondageItem.getComponent(blindfold, ComponentType.BLINDING, BlindingComponent.class) != null) return true;
|
||||
return blindfold.getItem() instanceof com.tiedup.remake.items.base.IHasBlindingEffect;
|
||||
return DataDrivenBondageItem.getComponent(blindfold, ComponentType.BLINDING, BlindingComponent.class) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1087,9 +1085,7 @@ public abstract class AbstractTiedUpNpc
|
||||
public boolean hasShockCollar() {
|
||||
ItemStack collar = this.getEquipment(BodyRegionV2.NECK);
|
||||
if (collar.isEmpty()) return false;
|
||||
return (
|
||||
collar.getItem() instanceof com.tiedup.remake.items.ItemShockCollar
|
||||
);
|
||||
return com.tiedup.remake.v2.bondage.CollarHelper.canShock(collar);
|
||||
}
|
||||
|
||||
// BONDAGE SERVICE (delegated to BondageManager)
|
||||
|
||||
@@ -616,82 +616,10 @@ public class EntityKidnapperMerchant extends EntityKidnapperElite {
|
||||
private List<ItemStack> collectAllModItems() {
|
||||
List<ItemStack> items = new ArrayList<>();
|
||||
|
||||
// All binds — iterate V1 variants, create V2 stacks
|
||||
for (BindVariant variant : BindVariant.values()) {
|
||||
if (variant.supportsColor()) {
|
||||
for (ItemColor color : ItemColor.values()) {
|
||||
if (
|
||||
color != ItemColor.CAUTION && color != ItemColor.CLEAR
|
||||
) {
|
||||
ItemStack stack = DataDrivenBondageItem.createStack(
|
||||
new net.minecraft.resources.ResourceLocation("tiedup", variant.getRegistryName())
|
||||
);
|
||||
KidnapperItemSelector.applyColor(stack, color);
|
||||
items.add(stack);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
items.add(DataDrivenBondageItem.createStack(
|
||||
new net.minecraft.resources.ResourceLocation("tiedup", variant.getRegistryName())
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
// All gags
|
||||
for (GagVariant variant : GagVariant.values()) {
|
||||
if (variant.supportsColor()) {
|
||||
for (ItemColor color : ItemColor.values()) {
|
||||
if (
|
||||
variant == GagVariant.TAPE_GAG ||
|
||||
(color != ItemColor.CAUTION && color != ItemColor.CLEAR)
|
||||
) {
|
||||
ItemStack stack = DataDrivenBondageItem.createStack(
|
||||
new net.minecraft.resources.ResourceLocation("tiedup", variant.getRegistryName())
|
||||
);
|
||||
KidnapperItemSelector.applyColor(stack, color);
|
||||
items.add(stack);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
items.add(DataDrivenBondageItem.createStack(
|
||||
new net.minecraft.resources.ResourceLocation("tiedup", variant.getRegistryName())
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
// All blindfolds
|
||||
for (BlindfoldVariant variant : BlindfoldVariant.values()) {
|
||||
if (variant.supportsColor()) {
|
||||
for (ItemColor color : ItemColor.values()) {
|
||||
if (
|
||||
color != ItemColor.CAUTION && color != ItemColor.CLEAR
|
||||
) {
|
||||
ItemStack stack = DataDrivenBondageItem.createStack(
|
||||
new net.minecraft.resources.ResourceLocation("tiedup", variant.getRegistryName())
|
||||
);
|
||||
KidnapperItemSelector.applyColor(stack, color);
|
||||
items.add(stack);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
items.add(DataDrivenBondageItem.createStack(
|
||||
new net.minecraft.resources.ResourceLocation("tiedup", variant.getRegistryName())
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
// Earplugs - no color support
|
||||
for (EarplugsVariant variant : EarplugsVariant.values()) {
|
||||
items.add(DataDrivenBondageItem.createStack(
|
||||
new net.minecraft.resources.ResourceLocation("tiedup", variant.getRegistryName())
|
||||
));
|
||||
}
|
||||
|
||||
// Mittens - no color support
|
||||
for (MittensVariant variant : MittensVariant.values()) {
|
||||
items.add(DataDrivenBondageItem.createStack(
|
||||
new net.minecraft.resources.ResourceLocation("tiedup", variant.getRegistryName())
|
||||
));
|
||||
// All data-driven bondage items (binds, gags, blindfolds, earplugs, mittens, collars, etc.)
|
||||
for (com.tiedup.remake.v2.bondage.datadriven.DataDrivenItemDefinition def :
|
||||
com.tiedup.remake.v2.bondage.datadriven.DataDrivenItemRegistry.getAll()) {
|
||||
items.add(DataDrivenBondageItem.createStack(def.id()));
|
||||
}
|
||||
|
||||
// Knives - no color support
|
||||
@@ -699,16 +627,11 @@ public class EntityKidnapperMerchant extends EntityKidnapperElite {
|
||||
items.add(new ItemStack(ModItems.getKnife(variant)));
|
||||
}
|
||||
|
||||
// Complex items
|
||||
items.add(new ItemStack(ModItems.CLASSIC_COLLAR.get()));
|
||||
items.add(new ItemStack(ModItems.SHOCK_COLLAR.get()));
|
||||
items.add(new ItemStack(ModItems.GPS_COLLAR.get()));
|
||||
// Tools
|
||||
items.add(new ItemStack(ModItems.WHIP.get()));
|
||||
// BLACKLIST: TASER (too powerful)
|
||||
// BLACKLIST: LOCKPICK (now in guaranteed utilities)
|
||||
// BLACKLIST: MASTER_KEY (too OP - unlocks everything)
|
||||
items.add(new ItemStack(ModItems.MEDICAL_GAG.get()));
|
||||
items.add(new ItemStack(ModItems.HOOD.get()));
|
||||
items.add(new ItemStack(ModItems.CLOTHES.get()));
|
||||
|
||||
return items;
|
||||
@@ -754,13 +677,13 @@ public class EntityKidnapperMerchant extends EntityKidnapperElite {
|
||||
Item i = item.getItem();
|
||||
|
||||
// Tier 4: GPS collar
|
||||
if (i == ModItems.GPS_COLLAR.get()) {
|
||||
if (com.tiedup.remake.v2.bondage.CollarHelper.hasGPS(item)) {
|
||||
return 4;
|
||||
}
|
||||
|
||||
// Tier 3: Shock collar, taser, master key
|
||||
if (
|
||||
i == ModItems.SHOCK_COLLAR.get() ||
|
||||
com.tiedup.remake.v2.bondage.CollarHelper.canShock(item) ||
|
||||
i == ModItems.TASER.get() ||
|
||||
i == ModItems.MASTER_KEY.get()
|
||||
) {
|
||||
@@ -769,11 +692,9 @@ public class EntityKidnapperMerchant extends EntityKidnapperElite {
|
||||
|
||||
// Tier 2: Collars, whip, tools, complex items, clothes
|
||||
if (
|
||||
i == ModItems.CLASSIC_COLLAR.get() ||
|
||||
com.tiedup.remake.v2.bondage.CollarHelper.isCollar(item) ||
|
||||
i == ModItems.WHIP.get() ||
|
||||
i == ModItems.LOCKPICK.get() ||
|
||||
i == ModItems.MEDICAL_GAG.get() ||
|
||||
i == ModItems.HOOD.get() ||
|
||||
i instanceof GenericClothes
|
||||
) {
|
||||
return 2;
|
||||
|
||||
@@ -115,7 +115,8 @@ public class KidnapperCaptureEquipment {
|
||||
@Nullable
|
||||
public ItemStack getCollarItem() {
|
||||
// Kidnappers always have a shock collar to mark their captives
|
||||
return new ItemStack(ModItems.SHOCK_COLLAR.get());
|
||||
return com.tiedup.remake.v2.bondage.datadriven.DataDrivenBondageItem.createStack(
|
||||
new net.minecraft.resources.ResourceLocation("tiedup", "shock_collar"));
|
||||
}
|
||||
|
||||
// HELD ITEM MANAGEMENT
|
||||
|
||||
@@ -12,6 +12,8 @@ import org.jetbrains.annotations.Nullable;
|
||||
* Helper class for selecting themed items for kidnappers.
|
||||
* Handles probability-based item selection and color application.
|
||||
*
|
||||
* All bondage items are now created via DataDrivenBondageItem.createStack().
|
||||
*
|
||||
* Item selection order (most to least common):
|
||||
* 1. Bind (arms) - 100% (always)
|
||||
* 2. Gag - 50%
|
||||
@@ -79,33 +81,10 @@ public class KidnapperItemSelector {
|
||||
this.blindfold = blindfold;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if this selection has a gag.
|
||||
*/
|
||||
public boolean hasGag() {
|
||||
return !gag.isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if this selection has mittens.
|
||||
*/
|
||||
public boolean hasMittens() {
|
||||
return !mittens.isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if this selection has earplugs.
|
||||
*/
|
||||
public boolean hasEarplugs() {
|
||||
return !earplugs.isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if this selection has a blindfold.
|
||||
*/
|
||||
public boolean hasBlindfold() {
|
||||
return !blindfold.isEmpty();
|
||||
}
|
||||
public boolean hasGag() { return !gag.isEmpty(); }
|
||||
public boolean hasMittens() { return !mittens.isEmpty(); }
|
||||
public boolean hasEarplugs() { return !earplugs.isEmpty(); }
|
||||
public boolean hasBlindfold() { return !blindfold.isEmpty(); }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -129,16 +108,6 @@ public class KidnapperItemSelector {
|
||||
return selectItems(false, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate adjusted probability based on kidnapper type.
|
||||
*
|
||||
* @param baseProb Base probability for the item
|
||||
* @param eliteBonus Bonus probability for elite kidnappers
|
||||
* @param archerPenalty Penalty probability for archer kidnappers
|
||||
* @param isElite Whether the kidnapper is elite
|
||||
* @param isArcher Whether the kidnapper is an archer
|
||||
* @return Adjusted probability
|
||||
*/
|
||||
private static double getAdjustedProbability(
|
||||
double baseProb,
|
||||
double eliteBonus,
|
||||
@@ -152,9 +121,6 @@ public class KidnapperItemSelector {
|
||||
return prob;
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal item selection logic.
|
||||
*/
|
||||
private static SelectionResult selectItems(
|
||||
boolean isElite,
|
||||
boolean isArcher
|
||||
@@ -163,132 +129,64 @@ public class KidnapperItemSelector {
|
||||
KidnapperTheme theme = KidnapperTheme.getRandomWeighted();
|
||||
|
||||
// 2. Select color (if theme supports it)
|
||||
// Filter out colors that don't have textures for this theme's bind
|
||||
ItemColor color = theme.supportsColor()
|
||||
? getValidColorForBind(theme.getBind())
|
||||
? ItemColor.getRandomStandard()
|
||||
: null;
|
||||
|
||||
// 3. Create bind (always)
|
||||
ItemStack bind = createBind(theme.getBind(), color);
|
||||
ItemStack bind = createItemById(theme.getBindId(), color);
|
||||
|
||||
// 4. Roll for gag (randomly selected from theme's compatible gags)
|
||||
// 4. Roll for gag
|
||||
ItemStack gag = ItemStack.EMPTY;
|
||||
double gagProb = getAdjustedProbability(
|
||||
PROB_GAG,
|
||||
ELITE_GAG_BONUS,
|
||||
ARCHER_GAG_PENALTY,
|
||||
isElite,
|
||||
isArcher
|
||||
PROB_GAG, ELITE_GAG_BONUS, ARCHER_GAG_PENALTY, isElite, isArcher
|
||||
);
|
||||
if (RANDOM.nextDouble() < gagProb) {
|
||||
gag = createGag(theme.getRandomGag(), color);
|
||||
gag = createItemById(theme.getRandomGagId(), color);
|
||||
}
|
||||
|
||||
// 5. Roll for mittens (same for all themes)
|
||||
// 5. Roll for mittens
|
||||
ItemStack mittens = ItemStack.EMPTY;
|
||||
double mittensProb = getAdjustedProbability(
|
||||
PROB_MITTENS,
|
||||
ELITE_MITTENS_BONUS,
|
||||
ARCHER_MITTENS_PENALTY,
|
||||
isElite,
|
||||
isArcher
|
||||
PROB_MITTENS, ELITE_MITTENS_BONUS, ARCHER_MITTENS_PENALTY, isElite, isArcher
|
||||
);
|
||||
if (RANDOM.nextDouble() < mittensProb) {
|
||||
mittens = createMittens();
|
||||
}
|
||||
|
||||
// 6. Roll for earplugs (same for all themes)
|
||||
// 6. Roll for earplugs
|
||||
ItemStack earplugs = ItemStack.EMPTY;
|
||||
double earplugsProb = getAdjustedProbability(
|
||||
PROB_EARPLUGS,
|
||||
ELITE_EARPLUGS_BONUS,
|
||||
ARCHER_EARPLUGS_PENALTY,
|
||||
isElite,
|
||||
isArcher
|
||||
PROB_EARPLUGS, ELITE_EARPLUGS_BONUS, ARCHER_EARPLUGS_PENALTY, isElite, isArcher
|
||||
);
|
||||
if (RANDOM.nextDouble() < earplugsProb) {
|
||||
earplugs = createEarplugs();
|
||||
}
|
||||
|
||||
// 7. Roll for blindfold (last, most restrictive - randomly selected)
|
||||
// 7. Roll for blindfold
|
||||
ItemStack blindfold = ItemStack.EMPTY;
|
||||
double blindfoldProb = getAdjustedProbability(
|
||||
PROB_BLINDFOLD,
|
||||
ELITE_BLINDFOLD_BONUS,
|
||||
ARCHER_BLINDFOLD_PENALTY,
|
||||
isElite,
|
||||
isArcher
|
||||
PROB_BLINDFOLD, ELITE_BLINDFOLD_BONUS, ARCHER_BLINDFOLD_PENALTY, isElite, isArcher
|
||||
);
|
||||
if (theme.hasBlindfolds() && RANDOM.nextDouble() < blindfoldProb) {
|
||||
blindfold = createBlindfold(theme.getRandomBlindfold(), color);
|
||||
blindfold = createItemById(theme.getRandomBlindfoldId(), color);
|
||||
}
|
||||
|
||||
return new SelectionResult(
|
||||
theme,
|
||||
color,
|
||||
bind,
|
||||
gag,
|
||||
mittens,
|
||||
earplugs,
|
||||
blindfold
|
||||
theme, color, bind, gag, mittens, earplugs, blindfold
|
||||
);
|
||||
}
|
||||
|
||||
// ITEM CREATION METHODS
|
||||
|
||||
/**
|
||||
* Create a bind ItemStack with optional color.
|
||||
* Create a data-driven bondage item by registry name, with optional color.
|
||||
*/
|
||||
public static ItemStack createBind(
|
||||
BindVariant variant,
|
||||
@Nullable ItemColor color
|
||||
) {
|
||||
public static ItemStack createItemById(String id, @Nullable ItemColor color) {
|
||||
ItemStack stack = DataDrivenBondageItem.createStack(
|
||||
new ResourceLocation("tiedup", variant.getRegistryName())
|
||||
new ResourceLocation("tiedup", id)
|
||||
);
|
||||
if (color != null && variant.supportsColor()) {
|
||||
applyColor(stack, color);
|
||||
}
|
||||
return stack;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a gag ItemStack with optional color.
|
||||
* Validates that the color has a texture for this gag variant.
|
||||
*/
|
||||
public static ItemStack createGag(
|
||||
GagVariant variant,
|
||||
@Nullable ItemColor color
|
||||
) {
|
||||
ItemStack stack = DataDrivenBondageItem.createStack(
|
||||
new ResourceLocation("tiedup", variant.getRegistryName())
|
||||
);
|
||||
if (
|
||||
color != null &&
|
||||
variant.supportsColor() &&
|
||||
isColorValidForGag(color, variant)
|
||||
) {
|
||||
applyColor(stack, color);
|
||||
}
|
||||
return stack;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a blindfold ItemStack with optional color.
|
||||
* Validates that the color has a texture for this blindfold variant.
|
||||
*/
|
||||
public static ItemStack createBlindfold(
|
||||
BlindfoldVariant variant,
|
||||
@Nullable ItemColor color
|
||||
) {
|
||||
ItemStack stack = DataDrivenBondageItem.createStack(
|
||||
new ResourceLocation("tiedup", variant.getRegistryName())
|
||||
);
|
||||
if (
|
||||
color != null &&
|
||||
variant.supportsColor() &&
|
||||
isColorValidForBlindfold(color, variant)
|
||||
) {
|
||||
if (color != null) {
|
||||
applyColor(stack, color);
|
||||
}
|
||||
return stack;
|
||||
@@ -296,7 +194,6 @@ public class KidnapperItemSelector {
|
||||
|
||||
/**
|
||||
* Create mittens ItemStack.
|
||||
* Mittens don't have color variants.
|
||||
*/
|
||||
public static ItemStack createMittens() {
|
||||
return DataDrivenBondageItem.createStack(
|
||||
@@ -306,7 +203,6 @@ public class KidnapperItemSelector {
|
||||
|
||||
/**
|
||||
* Create earplugs ItemStack.
|
||||
* Earplugs don't have color variants.
|
||||
*/
|
||||
public static ItemStack createEarplugs() {
|
||||
return DataDrivenBondageItem.createStack(
|
||||
@@ -321,7 +217,6 @@ public class KidnapperItemSelector {
|
||||
|
||||
/**
|
||||
* Apply color NBT to an ItemStack.
|
||||
* Sets both the ItemColor name and CustomModelData for model selection.
|
||||
*/
|
||||
public static void applyColor(ItemStack stack, ItemColor color) {
|
||||
if (stack.isEmpty() || color == null) return;
|
||||
@@ -351,141 +246,9 @@ public class KidnapperItemSelector {
|
||||
|
||||
/**
|
||||
* Get the texture suffix for an item's color.
|
||||
* Example: "ropes" + "_red" = "ropes_red"
|
||||
* @return The color suffix (e.g., "_red"), or empty string if no color
|
||||
*/
|
||||
public static String getColorSuffix(ItemStack stack) {
|
||||
ItemColor color = getColor(stack);
|
||||
return color != null ? "_" + color.getName() : "";
|
||||
}
|
||||
|
||||
// COLOR VALIDATION
|
||||
|
||||
/**
|
||||
* Get a random color that has a texture for the given bind variant.
|
||||
* Excludes colors that don't have textures for specific variants.
|
||||
*/
|
||||
public static ItemColor getValidColorForBind(BindVariant variant) {
|
||||
ItemColor color;
|
||||
int attempts = 0;
|
||||
do {
|
||||
color = ItemColor.getRandomStandard();
|
||||
attempts++;
|
||||
// Prevent infinite loop
|
||||
if (attempts > 50) break;
|
||||
} while (!isColorValidForBind(color, variant));
|
||||
return color;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a color has a texture for the given bind variant.
|
||||
* Returns false for colors without textures.
|
||||
*/
|
||||
public static boolean isColorValidForBind(
|
||||
ItemColor color,
|
||||
BindVariant variant
|
||||
) {
|
||||
if (color == null || variant == null) return true;
|
||||
|
||||
// BROWN doesn't have textures for ROPES and SHIBARI
|
||||
if (
|
||||
color == ItemColor.BROWN &&
|
||||
(variant == BindVariant.ROPES || variant == BindVariant.SHIBARI)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// GRAY doesn't have texture for DUCT_TAPE
|
||||
if (color == ItemColor.GRAY && variant == BindVariant.DUCT_TAPE) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a color has a texture for the given gag variant.
|
||||
*/
|
||||
public static boolean isColorValidForGag(
|
||||
ItemColor color,
|
||||
GagVariant variant
|
||||
) {
|
||||
if (color == null || variant == null) return true;
|
||||
|
||||
// GRAY doesn't have texture for TAPE_GAG
|
||||
if (color == ItemColor.GRAY && variant == GagVariant.TAPE_GAG) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// WHITE doesn't have texture for CLOTH_GAG and CLEAVE_GAG
|
||||
if (
|
||||
color == ItemColor.WHITE &&
|
||||
(variant == GagVariant.CLOTH_GAG ||
|
||||
variant == GagVariant.CLEAVE_GAG)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// RED doesn't have texture for BALL_GAG and BALL_GAG_STRAP
|
||||
if (
|
||||
color == ItemColor.RED &&
|
||||
(variant == GagVariant.BALL_GAG ||
|
||||
variant == GagVariant.BALL_GAG_STRAP)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a color has a texture for the given blindfold variant.
|
||||
*/
|
||||
public static boolean isColorValidForBlindfold(
|
||||
ItemColor color,
|
||||
BlindfoldVariant variant
|
||||
) {
|
||||
if (color == null || variant == null) return true;
|
||||
|
||||
// BLACK doesn't have texture for CLASSIC or MASK blindfolds
|
||||
if (
|
||||
color == ItemColor.BLACK &&
|
||||
(variant == BlindfoldVariant.CLASSIC ||
|
||||
variant == BlindfoldVariant.MASK)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a random color that has a texture for the given gag variant.
|
||||
*/
|
||||
public static ItemColor getValidColorForGag(GagVariant variant) {
|
||||
ItemColor color;
|
||||
int attempts = 0;
|
||||
do {
|
||||
color = ItemColor.getRandomStandard();
|
||||
attempts++;
|
||||
if (attempts > 50) break;
|
||||
} while (!isColorValidForGag(color, variant));
|
||||
return color;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a random color that has a texture for the given blindfold variant.
|
||||
*/
|
||||
public static ItemColor getValidColorForBlindfold(
|
||||
BlindfoldVariant variant
|
||||
) {
|
||||
ItemColor color;
|
||||
int attempts = 0;
|
||||
do {
|
||||
color = ItemColor.getRandomStandard();
|
||||
attempts++;
|
||||
if (attempts > 50) break;
|
||||
} while (!isColorValidForBlindfold(color, variant));
|
||||
return color;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -161,7 +161,8 @@ public class KidnapperJobManager {
|
||||
);
|
||||
|
||||
// Put a shock collar on the worker AFTER untie/free
|
||||
ItemStack shockCollar = new ItemStack(ModItems.SHOCK_COLLAR_AUTO.get());
|
||||
ItemStack shockCollar = com.tiedup.remake.v2.bondage.datadriven.DataDrivenBondageItem.createStack(
|
||||
new net.minecraft.resources.ResourceLocation("tiedup", "shock_collar_auto"));
|
||||
// Add kidnapper as owner so the collar is linked
|
||||
CollarHelper.addOwner(
|
||||
shockCollar,
|
||||
|
||||
@@ -1,42 +1,33 @@
|
||||
package com.tiedup.remake.entities;
|
||||
|
||||
import com.tiedup.remake.items.base.BindVariant;
|
||||
import com.tiedup.remake.items.base.BlindfoldVariant;
|
||||
import com.tiedup.remake.items.base.GagVariant;
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* Defines themed item sets for kidnappers.
|
||||
* Each theme groups compatible binds, gags, and blindfolds.
|
||||
* Each theme groups compatible binds, gags, and blindfolds by registry name.
|
||||
*
|
||||
* Themes are selected randomly with weighted probabilities.
|
||||
* Higher weight = more common theme.
|
||||
*
|
||||
* Note: Natural themes (SLIME, VINE, WEB) are reserved for monsters.
|
||||
*
|
||||
* Registry names correspond to data-driven bondage item IDs in DataDrivenItemRegistry.
|
||||
*/
|
||||
public enum KidnapperTheme {
|
||||
// === ROPE THEMES (most common) ===
|
||||
|
||||
ROPE(
|
||||
BindVariant.ROPES,
|
||||
new GagVariant[] {
|
||||
GagVariant.ROPES_GAG,
|
||||
GagVariant.CLOTH_GAG,
|
||||
GagVariant.CLEAVE_GAG,
|
||||
},
|
||||
new BlindfoldVariant[] { BlindfoldVariant.CLASSIC },
|
||||
"ropes",
|
||||
new String[] { "ropes_gag", "cloth_gag", "cleave_gag" },
|
||||
new String[] { "classic_blindfold" },
|
||||
true, // supportsColor
|
||||
30 // weight (spawn probability)
|
||||
),
|
||||
|
||||
SHIBARI(
|
||||
BindVariant.SHIBARI,
|
||||
new GagVariant[] {
|
||||
GagVariant.ROPES_GAG,
|
||||
GagVariant.CLOTH_GAG,
|
||||
GagVariant.RIBBON_GAG,
|
||||
},
|
||||
new BlindfoldVariant[] { BlindfoldVariant.CLASSIC },
|
||||
"shibari",
|
||||
new String[] { "ropes_gag", "cloth_gag", "ribbon_gag" },
|
||||
new String[] { "classic_blindfold" },
|
||||
true,
|
||||
15
|
||||
),
|
||||
@@ -44,9 +35,9 @@ public enum KidnapperTheme {
|
||||
// === TAPE THEME ===
|
||||
|
||||
TAPE(
|
||||
BindVariant.DUCT_TAPE,
|
||||
new GagVariant[] { GagVariant.TAPE_GAG, GagVariant.WRAP_GAG },
|
||||
new BlindfoldVariant[] { BlindfoldVariant.MASK },
|
||||
"duct_tape",
|
||||
new String[] { "tape_gag", "wrap_gag" },
|
||||
new String[] { "mask_blindfold" },
|
||||
true,
|
||||
20
|
||||
),
|
||||
@@ -54,13 +45,9 @@ public enum KidnapperTheme {
|
||||
// === LEATHER/BDSM THEME ===
|
||||
|
||||
LEATHER(
|
||||
BindVariant.LEATHER_STRAPS,
|
||||
new GagVariant[] {
|
||||
GagVariant.BALL_GAG,
|
||||
GagVariant.BALL_GAG_STRAP,
|
||||
GagVariant.PANEL_GAG,
|
||||
},
|
||||
new BlindfoldVariant[] { BlindfoldVariant.MASK },
|
||||
"leather_straps",
|
||||
new String[] { "ball_gag", "ball_gag_strap", "panel_gag" },
|
||||
new String[] { "mask_blindfold" },
|
||||
false,
|
||||
15
|
||||
),
|
||||
@@ -68,12 +55,9 @@ public enum KidnapperTheme {
|
||||
// === CHAIN THEME ===
|
||||
|
||||
CHAIN(
|
||||
BindVariant.CHAIN,
|
||||
new GagVariant[] {
|
||||
GagVariant.CHAIN_PANEL_GAG,
|
||||
GagVariant.BALL_GAG_STRAP,
|
||||
},
|
||||
new BlindfoldVariant[] { BlindfoldVariant.MASK },
|
||||
"chain",
|
||||
new String[] { "chain_panel_gag", "ball_gag_strap" },
|
||||
new String[] { "mask_blindfold" },
|
||||
false,
|
||||
10
|
||||
),
|
||||
@@ -81,13 +65,9 @@ public enum KidnapperTheme {
|
||||
// === MEDICAL THEME ===
|
||||
|
||||
MEDICAL(
|
||||
BindVariant.MEDICAL_STRAPS,
|
||||
new GagVariant[] {
|
||||
GagVariant.TUBE_GAG,
|
||||
GagVariant.SPONGE_GAG,
|
||||
GagVariant.BALL_GAG,
|
||||
},
|
||||
new BlindfoldVariant[] { BlindfoldVariant.MASK },
|
||||
"medical_straps",
|
||||
new String[] { "tube_gag", "sponge_gag", "ball_gag" },
|
||||
new String[] { "mask_blindfold" },
|
||||
false,
|
||||
8
|
||||
),
|
||||
@@ -95,9 +75,9 @@ public enum KidnapperTheme {
|
||||
// === SCI-FI/BEAM THEME ===
|
||||
|
||||
BEAM(
|
||||
BindVariant.BEAM_CUFFS,
|
||||
new GagVariant[] { GagVariant.BEAM_PANEL_GAG, GagVariant.LATEX_GAG },
|
||||
new BlindfoldVariant[] { BlindfoldVariant.MASK },
|
||||
"beam_cuffs",
|
||||
new String[] { "beam_panel_gag", "latex_gag" },
|
||||
new String[] { "mask_blindfold" },
|
||||
false,
|
||||
5
|
||||
),
|
||||
@@ -105,9 +85,9 @@ public enum KidnapperTheme {
|
||||
// === LATEX THEME (rare) ===
|
||||
|
||||
LATEX(
|
||||
BindVariant.LATEX_SACK,
|
||||
new GagVariant[] { GagVariant.LATEX_GAG, GagVariant.TUBE_GAG },
|
||||
new BlindfoldVariant[] { BlindfoldVariant.MASK },
|
||||
"latex_sack",
|
||||
new String[] { "latex_gag", "tube_gag" },
|
||||
new String[] { "mask_blindfold" },
|
||||
false,
|
||||
3
|
||||
),
|
||||
@@ -115,13 +95,9 @@ public enum KidnapperTheme {
|
||||
// === ASYLUM THEME (rare) ===
|
||||
|
||||
ASYLUM(
|
||||
BindVariant.STRAITJACKET,
|
||||
new GagVariant[] {
|
||||
GagVariant.BITE_GAG,
|
||||
GagVariant.SPONGE_GAG,
|
||||
GagVariant.BALL_GAG,
|
||||
},
|
||||
new BlindfoldVariant[] { BlindfoldVariant.MASK },
|
||||
"straitjacket",
|
||||
new String[] { "bite_gag", "sponge_gag", "ball_gag" },
|
||||
new String[] { "mask_blindfold" },
|
||||
false,
|
||||
5
|
||||
),
|
||||
@@ -129,9 +105,9 @@ public enum KidnapperTheme {
|
||||
// === RIBBON THEME (cute/playful) ===
|
||||
|
||||
RIBBON(
|
||||
BindVariant.RIBBON,
|
||||
new GagVariant[] { GagVariant.RIBBON_GAG, GagVariant.CLOTH_GAG },
|
||||
new BlindfoldVariant[] { BlindfoldVariant.CLASSIC },
|
||||
"ribbon",
|
||||
new String[] { "ribbon_gag", "cloth_gag" },
|
||||
new String[] { "classic_blindfold" },
|
||||
false,
|
||||
8
|
||||
),
|
||||
@@ -139,54 +115,54 @@ public enum KidnapperTheme {
|
||||
// === WRAP THEME ===
|
||||
|
||||
WRAP(
|
||||
BindVariant.WRAP,
|
||||
new GagVariant[] { GagVariant.WRAP_GAG, GagVariant.TAPE_GAG },
|
||||
new BlindfoldVariant[] { BlindfoldVariant.MASK },
|
||||
"wrap",
|
||||
new String[] { "wrap_gag", "tape_gag" },
|
||||
new String[] { "mask_blindfold" },
|
||||
false,
|
||||
5
|
||||
);
|
||||
|
||||
private static final Random RANDOM = new Random();
|
||||
|
||||
private final BindVariant bind;
|
||||
private final GagVariant[] gags;
|
||||
private final BlindfoldVariant[] blindfolds;
|
||||
private final String bindId;
|
||||
private final String[] gagIds;
|
||||
private final String[] blindfoldIds;
|
||||
private final boolean supportsColor;
|
||||
private final int weight;
|
||||
|
||||
KidnapperTheme(
|
||||
BindVariant bind,
|
||||
GagVariant[] gags,
|
||||
BlindfoldVariant[] blindfolds,
|
||||
String bindId,
|
||||
String[] gagIds,
|
||||
String[] blindfoldIds,
|
||||
boolean supportsColor,
|
||||
int weight
|
||||
) {
|
||||
this.bind = bind;
|
||||
this.gags = gags;
|
||||
this.blindfolds = blindfolds;
|
||||
this.bindId = bindId;
|
||||
this.gagIds = gagIds;
|
||||
this.blindfoldIds = blindfoldIds;
|
||||
this.supportsColor = supportsColor;
|
||||
this.weight = weight;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the primary bind for this theme.
|
||||
* Get the primary bind registry name for this theme.
|
||||
*/
|
||||
public BindVariant getBind() {
|
||||
return bind;
|
||||
public String getBindId() {
|
||||
return bindId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get compatible gags for this theme (ordered by preference).
|
||||
* Get compatible gag IDs for this theme (ordered by preference).
|
||||
*/
|
||||
public GagVariant[] getGags() {
|
||||
return gags;
|
||||
public String[] getGagIds() {
|
||||
return gagIds;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get compatible blindfolds for this theme.
|
||||
* Get compatible blindfold IDs for this theme.
|
||||
*/
|
||||
public BlindfoldVariant[] getBlindfolds() {
|
||||
return blindfolds;
|
||||
public String[] getBlindfoldIds() {
|
||||
return blindfoldIds;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -206,41 +182,40 @@ public enum KidnapperTheme {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get primary gag (first in list).
|
||||
* Used when only one gag is selected.
|
||||
* Get primary gag ID (first in list).
|
||||
*/
|
||||
public GagVariant getPrimaryGag() {
|
||||
return gags.length > 0 ? gags[0] : GagVariant.BALL_GAG;
|
||||
public String getPrimaryGagId() {
|
||||
return gagIds.length > 0 ? gagIds[0] : "ball_gag";
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a random gag from this theme's compatible list.
|
||||
* Get a random gag ID from this theme's compatible list.
|
||||
*/
|
||||
public GagVariant getRandomGag() {
|
||||
if (gags.length == 0) return GagVariant.BALL_GAG;
|
||||
return gags[RANDOM.nextInt(gags.length)];
|
||||
public String getRandomGagId() {
|
||||
if (gagIds.length == 0) return "ball_gag";
|
||||
return gagIds[RANDOM.nextInt(gagIds.length)];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get primary blindfold (first in list).
|
||||
* Get primary blindfold ID (first in list).
|
||||
*/
|
||||
public BlindfoldVariant getPrimaryBlindfold() {
|
||||
return blindfolds.length > 0 ? blindfolds[0] : BlindfoldVariant.CLASSIC;
|
||||
public String getPrimaryBlindfoldId() {
|
||||
return blindfoldIds.length > 0 ? blindfoldIds[0] : "classic_blindfold";
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a random blindfold from this theme's compatible list.
|
||||
* Get a random blindfold ID from this theme's compatible list.
|
||||
*/
|
||||
public BlindfoldVariant getRandomBlindfold() {
|
||||
if (blindfolds.length == 0) return BlindfoldVariant.CLASSIC;
|
||||
return blindfolds[RANDOM.nextInt(blindfolds.length)];
|
||||
public String getRandomBlindfoldId() {
|
||||
if (blindfoldIds.length == 0) return "classic_blindfold";
|
||||
return blindfoldIds[RANDOM.nextInt(blindfoldIds.length)];
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if this theme has any blindfolds.
|
||||
*/
|
||||
public boolean hasBlindfolds() {
|
||||
return blindfolds.length > 0;
|
||||
return blindfoldIds.length > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -229,20 +229,21 @@ public class MaidDeliverCaptiveGoal extends Goal {
|
||||
kidnappedState.getEquipment(BodyRegionV2.NECK);
|
||||
if (
|
||||
!collar.isEmpty() &&
|
||||
collar.getItem() instanceof
|
||||
com.tiedup.remake.items.base.ItemCollar collarItem
|
||||
com.tiedup.remake.v2.bondage.CollarHelper.isCollar(collar)
|
||||
) {
|
||||
for (java.util.UUID ownerId : new java.util.ArrayList<>(
|
||||
collarItem.getOwners(collar)
|
||||
com.tiedup.remake.v2.bondage.CollarHelper.getOwners(collar)
|
||||
)) {
|
||||
collarItem.removeOwner(collar, ownerId);
|
||||
com.tiedup.remake.v2.bondage.CollarHelper.removeOwner(collar, ownerId);
|
||||
}
|
||||
collarItem.addOwner(
|
||||
com.tiedup.remake.v2.bondage.CollarHelper.addOwner(
|
||||
collar,
|
||||
buyerEntity.getUUID(),
|
||||
buyerEntity.getName().getString()
|
||||
);
|
||||
collarItem.setLocked(collar, false);
|
||||
if (collar.getItem() instanceof com.tiedup.remake.items.base.ILockable lockable) {
|
||||
lockable.setLocked(collar, false);
|
||||
}
|
||||
kidnappedState.equip(BodyRegionV2.NECK, collar);
|
||||
|
||||
if (
|
||||
|
||||
@@ -305,11 +305,8 @@ public class NpcStruggleGoal extends Goal {
|
||||
ItemStack collar = npc.getEquipment(BodyRegionV2.NECK);
|
||||
if (collar.isEmpty()) return false;
|
||||
|
||||
if (
|
||||
collar.getItem() instanceof
|
||||
com.tiedup.remake.items.base.ItemCollar collarItem
|
||||
) {
|
||||
List<UUID> ownerUUIDs = collarItem.getOwners(collar);
|
||||
if (com.tiedup.remake.v2.bondage.CollarHelper.isCollar(collar)) {
|
||||
List<UUID> ownerUUIDs = com.tiedup.remake.v2.bondage.CollarHelper.getOwners(collar);
|
||||
if (!ownerUUIDs.isEmpty()) {
|
||||
// Check if any owner is nearby
|
||||
List<Player> players = npc
|
||||
@@ -338,11 +335,8 @@ public class NpcStruggleGoal extends Goal {
|
||||
ItemStack collar = npc.getEquipment(BodyRegionV2.NECK);
|
||||
if (collar.isEmpty()) return null;
|
||||
|
||||
if (
|
||||
collar.getItem() instanceof
|
||||
com.tiedup.remake.items.base.ItemCollar collarItem
|
||||
) {
|
||||
List<UUID> ownerUUIDs = collarItem.getOwners(collar);
|
||||
if (com.tiedup.remake.v2.bondage.CollarHelper.isCollar(collar)) {
|
||||
List<UUID> ownerUUIDs = com.tiedup.remake.v2.bondage.CollarHelper.getOwners(collar);
|
||||
if (!ownerUUIDs.isEmpty()) {
|
||||
return ownerUUIDs.get(0);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.tiedup.remake.entities.armorstand;
|
||||
|
||||
import com.tiedup.remake.items.base.ItemBind;
|
||||
import com.tiedup.remake.items.base.PoseType;
|
||||
import com.tiedup.remake.v2.bondage.PoseTypeHelper;
|
||||
import com.tiedup.remake.v2.BodyRegionV2;
|
||||
import java.util.Map;
|
||||
import net.minecraft.core.Rotations;
|
||||
@@ -185,11 +185,8 @@ public class ArmorStandBondageHelper {
|
||||
// Save original pose if not already saved
|
||||
saveOriginalPose(stand);
|
||||
|
||||
// Get pose type from bind
|
||||
PoseType poseType = PoseType.STANDARD;
|
||||
if (bindStack.getItem() instanceof ItemBind bind) {
|
||||
poseType = bind.getPoseType();
|
||||
}
|
||||
// Get pose type from bind (V2 data-driven)
|
||||
PoseType poseType = PoseTypeHelper.getPoseType(bindStack);
|
||||
|
||||
// Apply pose
|
||||
applyBondagePose(stand, poseType);
|
||||
|
||||
@@ -116,15 +116,13 @@ public class NpcEquipmentManager {
|
||||
public boolean hasGaggingEffect() {
|
||||
ItemStack gag = getCurrentGag();
|
||||
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;
|
||||
return DataDrivenBondageItem.getComponent(gag, ComponentType.GAGGING, GaggingComponent.class) != null;
|
||||
}
|
||||
|
||||
public boolean hasBlindingEffect() {
|
||||
ItemStack blindfold = getCurrentBlindfold();
|
||||
if (blindfold.isEmpty()) return false;
|
||||
if (DataDrivenBondageItem.getComponent(blindfold, ComponentType.BLINDING, BlindingComponent.class) != null) return true;
|
||||
return blindfold.getItem() instanceof com.tiedup.remake.items.base.IHasBlindingEffect;
|
||||
return DataDrivenBondageItem.getComponent(blindfold, ComponentType.BLINDING, BlindingComponent.class) != null;
|
||||
}
|
||||
|
||||
public boolean hasKnives() {
|
||||
|
||||
@@ -361,19 +361,19 @@ public class KidnapperAppearance {
|
||||
this.itemSelection = new KidnapperItemSelector.SelectionResult(
|
||||
this.currentTheme,
|
||||
this.themeColor,
|
||||
KidnapperItemSelector.createBind(
|
||||
this.currentTheme.getBind(),
|
||||
KidnapperItemSelector.createItemById(
|
||||
this.currentTheme.getBindId(),
|
||||
this.themeColor
|
||||
),
|
||||
KidnapperItemSelector.createGag(
|
||||
this.currentTheme.getPrimaryGag(),
|
||||
KidnapperItemSelector.createItemById(
|
||||
this.currentTheme.getPrimaryGagId(),
|
||||
this.themeColor
|
||||
),
|
||||
KidnapperItemSelector.createMittens(),
|
||||
KidnapperItemSelector.createEarplugs(),
|
||||
this.currentTheme.hasBlindfolds()
|
||||
? KidnapperItemSelector.createBlindfold(
|
||||
this.currentTheme.getPrimaryBlindfold(),
|
||||
? KidnapperItemSelector.createItemById(
|
||||
this.currentTheme.getPrimaryBlindfoldId(),
|
||||
this.themeColor
|
||||
)
|
||||
: ItemStack.EMPTY
|
||||
|
||||
@@ -119,8 +119,8 @@ public class MasterPetManager {
|
||||
if (state == null) return;
|
||||
|
||||
// Create a choke collar for pet play
|
||||
ItemStack chokeCollar = new ItemStack(
|
||||
com.tiedup.remake.items.ModItems.CHOKE_COLLAR.get()
|
||||
ItemStack chokeCollar = com.tiedup.remake.v2.bondage.datadriven.DataDrivenBondageItem.createStack(
|
||||
new net.minecraft.resources.ResourceLocation("tiedup", "choke_collar")
|
||||
);
|
||||
|
||||
// Configure for pet play BEFORE equipping
|
||||
|
||||
Reference in New Issue
Block a user