Clean repo for open source release
Remove build artifacts, dev tool configs, unused dependencies, and third-party source dumps. Add proper README, update .gitignore, clean up Makefile.
This commit is contained in:
@@ -0,0 +1,429 @@
|
||||
package com.tiedup.remake.state.components;
|
||||
|
||||
import com.tiedup.remake.v2.bondage.IV2BondageItem;
|
||||
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.v2.BodyRegionV2;
|
||||
import com.tiedup.remake.v2.bondage.IV2BondageEquipment;
|
||||
import com.tiedup.remake.v2.bondage.capability.V2EquipmentHelper;
|
||||
import java.util.function.Supplier;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
|
||||
/**
|
||||
* Component responsible for bondage equipment management.
|
||||
* Handles putting on, taking off, and replacing all bondage items.
|
||||
*
|
||||
* Single Responsibility: Equipment lifecycle management
|
||||
* Complexity: MEDIUM (V2 equipment coupling)
|
||||
* Risk: MEDIUM (core equipment system)
|
||||
*
|
||||
* Epic 5F: Uses V2EquipmentHelper.
|
||||
* Uses low-level setInRegion for equips because V1 items (IBondageItem) do not
|
||||
* implement IV2BondageItem, so V2EquipmentHelper.equipItem() would reject them.
|
||||
*/
|
||||
public class PlayerEquipment {
|
||||
|
||||
private final IPlayerBindStateHost host;
|
||||
|
||||
public PlayerEquipment(IPlayerBindStateHost host) {
|
||||
this.host = host;
|
||||
}
|
||||
|
||||
// ========== Put On Methods ==========
|
||||
|
||||
/** Equips a bind item and applies speed reduction. */
|
||||
public void putBindOn(ItemStack bind) {
|
||||
equipInRegion(BodyRegionV2.ARMS, bind);
|
||||
}
|
||||
|
||||
/** Equips a gag (enables gag talk if implemented). Issue #14 fix: now calls onEquipped. */
|
||||
public void putGagOn(ItemStack gag) {
|
||||
equipInRegion(BodyRegionV2.MOUTH, gag);
|
||||
}
|
||||
|
||||
/** Equips a blindfold (restricts vision). Issue #14 fix: now calls onEquipped. */
|
||||
public void putBlindfoldOn(ItemStack blindfold) {
|
||||
equipInRegion(BodyRegionV2.EYES, blindfold);
|
||||
}
|
||||
|
||||
/** Equips a collar (starts GPS/Shock monitoring). Issue #14 fix: now calls onEquipped. */
|
||||
public void putCollarOn(ItemStack collar) {
|
||||
equipInRegion(BodyRegionV2.NECK, collar);
|
||||
}
|
||||
|
||||
/** Issue #14 fix: now calls onEquipped. Syncs clothes config to all clients. */
|
||||
public void putClothesOn(ItemStack clothes) {
|
||||
equipInRegion(BodyRegionV2.TORSO, clothes);
|
||||
// Sync clothes config (dynamic textures, etc.) to all tracking clients
|
||||
host.syncClothesConfig();
|
||||
}
|
||||
|
||||
/** Equips mittens (blocks hand interactions). Phase 14.4: Mittens system. Issue #14 fix: now calls onEquipped. */
|
||||
public void putMittensOn(ItemStack mittens) {
|
||||
equipInRegion(BodyRegionV2.HANDS, mittens);
|
||||
checkMittensAfterApply();
|
||||
}
|
||||
|
||||
/** Equips earplugs (muffles sounds). Issue #14 fix: now calls onEquipped. */
|
||||
public void putEarplugsOn(ItemStack earplugs) {
|
||||
equipInRegion(BodyRegionV2.EARS, earplugs);
|
||||
checkEarplugsAfterApply();
|
||||
}
|
||||
|
||||
// ========== Take Off Methods ==========
|
||||
|
||||
/** Removes binds and restores speed. */
|
||||
public ItemStack takeBindOff() {
|
||||
return V2EquipmentHelper.unequipFromRegion(host.getPlayer(), BodyRegionV2.ARMS);
|
||||
}
|
||||
|
||||
public ItemStack takeGagOff() {
|
||||
return V2EquipmentHelper.unequipFromRegion(host.getPlayer(), BodyRegionV2.MOUTH);
|
||||
}
|
||||
|
||||
public ItemStack takeBlindfoldOff() {
|
||||
return V2EquipmentHelper.unequipFromRegion(host.getPlayer(), BodyRegionV2.EYES);
|
||||
}
|
||||
|
||||
public ItemStack takeCollarOff() {
|
||||
return V2EquipmentHelper.unequipFromRegion(host.getPlayer(), BodyRegionV2.NECK);
|
||||
}
|
||||
|
||||
/** Removes mittens. Phase 14.4: Mittens system */
|
||||
public ItemStack takeMittensOff() {
|
||||
ItemStack mittens = V2EquipmentHelper.getInRegion(host.getPlayer(), BodyRegionV2.HANDS);
|
||||
if (isLocked(mittens, false)) {
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
return V2EquipmentHelper.unequipFromRegion(host.getPlayer(), BodyRegionV2.HANDS);
|
||||
}
|
||||
|
||||
public ItemStack takeEarplugsOff() {
|
||||
ItemStack earplugs = V2EquipmentHelper.getInRegion(host.getPlayer(), BodyRegionV2.EARS);
|
||||
if (isLocked(earplugs, false)) {
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
return V2EquipmentHelper.unequipFromRegion(host.getPlayer(), BodyRegionV2.EARS);
|
||||
}
|
||||
|
||||
public ItemStack takeClothesOff() {
|
||||
ItemStack clothes = V2EquipmentHelper.unequipFromRegion(host.getPlayer(), BodyRegionV2.TORSO);
|
||||
// Sync clothes removal to all tracking clients
|
||||
host.syncClothesConfig();
|
||||
return clothes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to remove the collar. Fails if locked unless forced.
|
||||
*/
|
||||
public ItemStack takeCollarOff(boolean force) {
|
||||
Player player = host.getPlayer();
|
||||
ItemStack collar = V2EquipmentHelper.getInRegion(player, BodyRegionV2.NECK);
|
||||
if (collar.isEmpty()) return ItemStack.EMPTY;
|
||||
|
||||
if (collar.getItem() instanceof ItemCollar collarItem) {
|
||||
if (!force && collarItem.isLocked(collar)) return ItemStack.EMPTY;
|
||||
collarItem.setLocked(collar, false);
|
||||
}
|
||||
return V2EquipmentHelper.unequipFromRegion(player, BodyRegionV2.NECK);
|
||||
}
|
||||
|
||||
// ========== Replacement Methods ==========
|
||||
|
||||
/** Replaces the blindfold and returns the old one. Issue #14 fix: now calls lifecycle hooks. */
|
||||
public ItemStack replaceBlindfold(ItemStack newBlindfold) {
|
||||
ItemStack current = V2EquipmentHelper.getInRegion(host.getPlayer(), BodyRegionV2.EYES);
|
||||
if (current.isEmpty()) return ItemStack.EMPTY;
|
||||
return replaceInRegion(BodyRegionV2.EYES, newBlindfold);
|
||||
}
|
||||
|
||||
/** Replaces the gag and returns the old one. Issue #14 fix: now calls lifecycle hooks. */
|
||||
public ItemStack replaceGag(ItemStack newGag) {
|
||||
ItemStack current = V2EquipmentHelper.getInRegion(host.getPlayer(), BodyRegionV2.MOUTH);
|
||||
if (current.isEmpty()) return ItemStack.EMPTY;
|
||||
return replaceInRegion(BodyRegionV2.MOUTH, newGag);
|
||||
}
|
||||
|
||||
/** Replaces the collar and returns the old one. Issue #14 fix: now calls lifecycle hooks. */
|
||||
public ItemStack replaceCollar(ItemStack newCollar) {
|
||||
ItemStack current = V2EquipmentHelper.getInRegion(host.getPlayer(), BodyRegionV2.NECK);
|
||||
if (current.isEmpty()) return ItemStack.EMPTY;
|
||||
return replaceInRegion(BodyRegionV2.NECK, newCollar);
|
||||
}
|
||||
|
||||
/**
|
||||
* Thread Safety: Synchronized to prevent inventory tearing (gap between remove and add).
|
||||
*/
|
||||
public synchronized ItemStack replaceBind(ItemStack newBind) {
|
||||
ItemStack old = takeBindOff();
|
||||
if (!old.isEmpty()) {
|
||||
putBindOn(newBind);
|
||||
}
|
||||
return old;
|
||||
}
|
||||
|
||||
/**
|
||||
* Thread Safety: Synchronized to prevent inventory tearing (gap between remove and add).
|
||||
*/
|
||||
public synchronized ItemStack replaceBind(
|
||||
ItemStack newBind,
|
||||
boolean force
|
||||
) {
|
||||
// Safety: Don't remove current bind if newBind is empty
|
||||
if (newBind.isEmpty()) {
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
ItemStack current = V2EquipmentHelper.getInRegion(host.getPlayer(), BodyRegionV2.ARMS);
|
||||
if (isLocked(current, force)) {
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
ItemStack old = takeBindOff();
|
||||
if (!old.isEmpty()) {
|
||||
putBindOn(newBind);
|
||||
}
|
||||
return old;
|
||||
}
|
||||
|
||||
public ItemStack replaceGag(ItemStack newGag, boolean force) {
|
||||
ItemStack current = V2EquipmentHelper.getInRegion(host.getPlayer(), BodyRegionV2.MOUTH);
|
||||
if (isLocked(current, force)) {
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
ItemStack old = V2EquipmentHelper.unequipFromRegion(host.getPlayer(), BodyRegionV2.MOUTH);
|
||||
putGagOn(newGag);
|
||||
return old;
|
||||
}
|
||||
|
||||
public ItemStack replaceBlindfold(ItemStack newBlindfold, boolean force) {
|
||||
ItemStack current = V2EquipmentHelper.getInRegion(host.getPlayer(), BodyRegionV2.EYES);
|
||||
if (isLocked(current, force)) {
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
ItemStack old = V2EquipmentHelper.unequipFromRegion(host.getPlayer(), BodyRegionV2.EYES);
|
||||
putBlindfoldOn(newBlindfold);
|
||||
return old;
|
||||
}
|
||||
|
||||
public ItemStack replaceCollar(ItemStack newCollar, boolean force) {
|
||||
ItemStack current = V2EquipmentHelper.getInRegion(host.getPlayer(), BodyRegionV2.NECK);
|
||||
if (isLocked(current, force)) {
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
ItemStack old = takeCollarOff(force);
|
||||
putCollarOn(newCollar);
|
||||
return old;
|
||||
}
|
||||
|
||||
public ItemStack replaceEarplugs(ItemStack newEarplugs) {
|
||||
return replaceEarplugs(newEarplugs, false);
|
||||
}
|
||||
|
||||
public ItemStack replaceEarplugs(ItemStack newEarplugs, boolean force) {
|
||||
ItemStack current = V2EquipmentHelper.getInRegion(host.getPlayer(), BodyRegionV2.EARS);
|
||||
if (isLocked(current, force)) {
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
ItemStack old = takeEarplugsOff();
|
||||
putEarplugsOn(newEarplugs);
|
||||
return old;
|
||||
}
|
||||
|
||||
public ItemStack replaceMittens(ItemStack newMittens) {
|
||||
return replaceMittens(newMittens, false);
|
||||
}
|
||||
|
||||
public ItemStack replaceMittens(ItemStack newMittens, boolean force) {
|
||||
ItemStack current = V2EquipmentHelper.getInRegion(host.getPlayer(), BodyRegionV2.HANDS);
|
||||
if (isLocked(current, force)) {
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
ItemStack old = takeMittensOff();
|
||||
if (!old.isEmpty() || !hasMittens()) {
|
||||
putMittensOn(newMittens);
|
||||
}
|
||||
return old;
|
||||
}
|
||||
|
||||
// ========== Resistance Methods ==========
|
||||
|
||||
/**
|
||||
* Phase 14.1.7: Now part of IRestrainable interface
|
||||
*/
|
||||
public synchronized int getCurrentBindResistance() {
|
||||
Player player = host.getPlayer();
|
||||
ItemStack stack = V2EquipmentHelper.getInRegion(player, BodyRegionV2.ARMS);
|
||||
if (
|
||||
stack.isEmpty() || !(stack.getItem() instanceof ItemBind bind)
|
||||
) return 0;
|
||||
return bind.getCurrentResistance(stack, player);
|
||||
}
|
||||
|
||||
/**
|
||||
* Phase 14.1.7: Now part of IRestrainable interface
|
||||
*/
|
||||
public synchronized void setCurrentBindResistance(int resistance) {
|
||||
Player player = host.getPlayer();
|
||||
ItemStack stack = V2EquipmentHelper.getInRegion(player, BodyRegionV2.ARMS);
|
||||
if (
|
||||
stack.isEmpty() || !(stack.getItem() instanceof ItemBind bind)
|
||||
) return;
|
||||
bind.setCurrentResistance(stack, resistance);
|
||||
}
|
||||
|
||||
/**
|
||||
* Phase 14.1.7: Added for IRestrainable interface
|
||||
*/
|
||||
public synchronized int getCurrentCollarResistance() {
|
||||
Player player = host.getPlayer();
|
||||
ItemStack stack = V2EquipmentHelper.getInRegion(player, BodyRegionV2.NECK);
|
||||
if (
|
||||
stack.isEmpty() || !(stack.getItem() instanceof ItemCollar collar)
|
||||
) return 0;
|
||||
return collar.getCurrentResistance(stack, player);
|
||||
}
|
||||
|
||||
/**
|
||||
* Phase 14.1.7: Added for IRestrainable interface
|
||||
*/
|
||||
public synchronized void setCurrentCollarResistance(int resistance) {
|
||||
Player player = host.getPlayer();
|
||||
ItemStack stack = V2EquipmentHelper.getInRegion(player, BodyRegionV2.NECK);
|
||||
if (
|
||||
stack.isEmpty() || !(stack.getItem() instanceof ItemCollar collar)
|
||||
) return;
|
||||
collar.setCurrentResistance(stack, resistance);
|
||||
}
|
||||
|
||||
// ========== Helper Methods ==========
|
||||
|
||||
/** Helper to drop an item at the kidnapped player's feet. */
|
||||
public void kidnappedDropItem(ItemStack stack) {
|
||||
if (stack.isEmpty() || host.getPlayer() == null) return;
|
||||
host.getPlayer().drop(stack, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to take a bondage item if it's unlocked, and drop it.
|
||||
*/
|
||||
public void takeBondageItemIfUnlocked(
|
||||
ItemStack item,
|
||||
Supplier<ItemStack> takeOffMethod
|
||||
) {
|
||||
if (isLocked(item, false)) {
|
||||
return; // Item is locked, cannot remove
|
||||
}
|
||||
ItemStack removed = takeOffMethod.get();
|
||||
if (!removed.isEmpty()) {
|
||||
kidnappedDropItem(removed);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if an item is locked.
|
||||
* @param stack The item to check
|
||||
* @param force If true, returns false (bypasses lock)
|
||||
* @return true if locked and not forced
|
||||
*/
|
||||
public boolean isLocked(ItemStack stack, boolean force) {
|
||||
if (force) return false;
|
||||
if (stack.isEmpty()) return false;
|
||||
|
||||
if (stack.getItem() instanceof ILockable lockable) {
|
||||
return lockable.isLocked(stack);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean hasMittens() {
|
||||
return V2EquipmentHelper.isRegionOccupied(host.getPlayer(), BodyRegionV2.HANDS);
|
||||
}
|
||||
|
||||
// ========== Low-level V2 equipment operations ==========
|
||||
|
||||
/**
|
||||
* Low-level equip: writes to V2 capability, calls IBondageItem lifecycle hooks, syncs.
|
||||
* Uses setInRegion directly because V1 items do not implement IV2BondageItem.
|
||||
*/
|
||||
private void equipInRegion(BodyRegionV2 region, ItemStack stack) {
|
||||
Player player = host.getPlayer();
|
||||
if (player == null || player.level().isClientSide) return;
|
||||
if (stack.isEmpty()) return;
|
||||
|
||||
IV2BondageEquipment equip = V2EquipmentHelper.getEquipment(player);
|
||||
if (equip == null) return;
|
||||
|
||||
// Check if already occupied
|
||||
if (equip.isRegionOccupied(region)) return;
|
||||
|
||||
// Check canEquip via V1 IBondageItem interface
|
||||
if (stack.getItem() instanceof IV2BondageItem bondageItem) {
|
||||
if (!bondageItem.canEquip(stack, player)) return;
|
||||
}
|
||||
|
||||
equip.setInRegion(region, stack.copy());
|
||||
|
||||
// Fire lifecycle hook
|
||||
if (stack.getItem() instanceof IV2BondageItem bondageItem) {
|
||||
bondageItem.onEquipped(stack, player);
|
||||
}
|
||||
|
||||
V2EquipmentHelper.sync(player);
|
||||
}
|
||||
|
||||
/**
|
||||
* Low-level replace: unequips old item with lifecycle hooks, equips new item.
|
||||
* Unequips old item (with onUnequipped hook), sets new item, fires onEquipped.
|
||||
*/
|
||||
private ItemStack replaceInRegion(BodyRegionV2 region, ItemStack newStack) {
|
||||
Player player = host.getPlayer();
|
||||
if (player == null || player.level().isClientSide) return ItemStack.EMPTY;
|
||||
|
||||
IV2BondageEquipment equip = V2EquipmentHelper.getEquipment(player);
|
||||
if (equip == null) return ItemStack.EMPTY;
|
||||
|
||||
ItemStack oldStack = equip.getInRegion(region);
|
||||
|
||||
// Call onUnequipped for the old item
|
||||
if (!oldStack.isEmpty() && oldStack.getItem() instanceof IV2BondageItem oldItem) {
|
||||
oldItem.onUnequipped(oldStack, player);
|
||||
}
|
||||
|
||||
// Set the new item
|
||||
equip.setInRegion(region, newStack.copy());
|
||||
|
||||
// Call onEquipped for the new item
|
||||
if (!newStack.isEmpty() && newStack.getItem() instanceof IV2BondageItem newItem) {
|
||||
newItem.onEquipped(newStack, player);
|
||||
}
|
||||
|
||||
V2EquipmentHelper.sync(player);
|
||||
return oldStack;
|
||||
}
|
||||
|
||||
// ========== Callbacks ==========
|
||||
|
||||
public void checkGagAfterApply() {
|
||||
// Gag talk handled via ChatEventHandler + GagTalkManager (event-based)
|
||||
// No initialization needed here - effects apply automatically on chat
|
||||
}
|
||||
|
||||
public void checkBlindfoldAfterApply() {
|
||||
// Effects applied client-side via rendering
|
||||
}
|
||||
|
||||
public void checkEarplugsAfterApply() {
|
||||
// Effects applied client-side via sound system
|
||||
}
|
||||
|
||||
public void checkCollarAfterApply() {
|
||||
// Collar timers/GPS handled elsewhere
|
||||
}
|
||||
|
||||
public void checkMittensAfterApply() {
|
||||
// Mittens effects handled elsewhere
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user