feat(D-01/A): self-bondage region routing (A11)
- handleV2SelfBondage: split into region-based routing - NECK → blocked (cannot self-collar) - ARMS → handleV2SelfBind (tying task with progress bar) - Other → handleV2SelfAccessory (instant equip) - handleV2SelfAccessory: arms-bound check via BindModeHelper, locked check for swap, V2EquipmentHelper for conflict resolution
This commit is contained in:
@@ -14,8 +14,10 @@ import com.tiedup.remake.tasks.TyingTask;
|
|||||||
import com.tiedup.remake.tasks.V2TyingPlayerTask;
|
import com.tiedup.remake.tasks.V2TyingPlayerTask;
|
||||||
import com.tiedup.remake.util.KidnappedHelper;
|
import com.tiedup.remake.util.KidnappedHelper;
|
||||||
import com.tiedup.remake.v2.BodyRegionV2;
|
import com.tiedup.remake.v2.BodyRegionV2;
|
||||||
|
import com.tiedup.remake.v2.bondage.BindModeHelper;
|
||||||
import com.tiedup.remake.v2.bondage.IV2BondageItem;
|
import com.tiedup.remake.v2.bondage.IV2BondageItem;
|
||||||
import com.tiedup.remake.v2.bondage.capability.V2EquipmentHelper;
|
import com.tiedup.remake.v2.bondage.capability.V2EquipmentHelper;
|
||||||
|
import com.tiedup.remake.v2.bondage.V2EquipResult;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
import net.minecraft.network.FriendlyByteBuf;
|
import net.minecraft.network.FriendlyByteBuf;
|
||||||
import net.minecraft.server.level.ServerPlayer;
|
import net.minecraft.server.level.ServerPlayer;
|
||||||
@@ -222,71 +224,112 @@ public class PacketSelfBondage {
|
|||||||
IV2BondageItem v2Item,
|
IV2BondageItem v2Item,
|
||||||
IBondageState state
|
IBondageState state
|
||||||
) {
|
) {
|
||||||
|
java.util.Set<BodyRegionV2> regions = v2Item.getOccupiedRegions(stack);
|
||||||
|
|
||||||
|
// Cannot self-collar
|
||||||
|
if (regions.contains(BodyRegionV2.NECK)) {
|
||||||
|
TiedUpMod.LOGGER.debug("[SelfBondage] {} tried to self-collar — blocked", player.getName().getString());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ARMS: tying task with progress bar
|
||||||
|
if (regions.contains(BodyRegionV2.ARMS)) {
|
||||||
|
handleV2SelfBind(player, stack, v2Item, state);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Accessories (MOUTH, EYES, EARS, HANDS): instant equip
|
||||||
|
handleV2SelfAccessory(player, stack, v2Item, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void handleV2SelfBind(
|
||||||
|
ServerPlayer player,
|
||||||
|
ItemStack stack,
|
||||||
|
IV2BondageItem v2Item,
|
||||||
|
IBondageState state
|
||||||
|
) {
|
||||||
|
// Can't self-tie if already tied
|
||||||
|
if (state.isTiedUp()) {
|
||||||
|
TiedUpMod.LOGGER.debug("[SelfBondage] {} tried V2 self-tie but already tied", player.getName().getString());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Check if all target regions are already occupied or blocked
|
// Check if all target regions are already occupied or blocked
|
||||||
boolean allBlocked = true;
|
boolean allBlocked = true;
|
||||||
for (BodyRegionV2 region : v2Item.getOccupiedRegions(stack)) {
|
for (BodyRegionV2 region : v2Item.getOccupiedRegions(stack)) {
|
||||||
if (
|
if (!V2EquipmentHelper.isRegionOccupied(player, region)
|
||||||
!V2EquipmentHelper.isRegionOccupied(player, region) &&
|
&& !V2EquipmentHelper.isRegionBlocked(player, region)) {
|
||||||
!V2EquipmentHelper.isRegionBlocked(player, region)
|
|
||||||
) {
|
|
||||||
allBlocked = false;
|
allBlocked = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (allBlocked) {
|
if (allBlocked) {
|
||||||
TiedUpMod.LOGGER.debug(
|
TiedUpMod.LOGGER.debug("[SelfBondage] {} tried V2 self-equip but all regions occupied", player.getName().getString());
|
||||||
"[SelfBondage] {} tried V2 self-equip but all regions occupied",
|
|
||||||
player.getName().getString()
|
|
||||||
);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
PlayerBindState playerState = PlayerBindState.getInstance(player);
|
PlayerBindState playerState = PlayerBindState.getInstance(player);
|
||||||
if (playerState == null) return;
|
if (playerState == null) return;
|
||||||
|
|
||||||
int tyingSeconds = SettingsAccessor.getTyingPlayerTime(
|
int tyingSeconds = SettingsAccessor.getTyingPlayerTime(player.level().getGameRules());
|
||||||
player.level().getGameRules()
|
|
||||||
);
|
|
||||||
|
|
||||||
// Create V2 tying task (uses V2EquipmentHelper on completion, NOT putBindOn)
|
|
||||||
V2TyingPlayerTask newTask = new V2TyingPlayerTask(
|
V2TyingPlayerTask newTask = new V2TyingPlayerTask(
|
||||||
stack.copy(), // copy for display/matching
|
stack.copy(), stack, state, player, tyingSeconds, player.level(), player
|
||||||
stack, // live reference for consumption
|
|
||||||
state,
|
|
||||||
player, // target is self
|
|
||||||
tyingSeconds,
|
|
||||||
player.level(),
|
|
||||||
player // kidnapper is also self
|
|
||||||
);
|
);
|
||||||
|
|
||||||
TyingTask currentTask = playerState.getCurrentTyingTask();
|
TyingTask currentTask = playerState.getCurrentTyingTask();
|
||||||
|
if (currentTask == null
|
||||||
if (
|
|| !currentTask.isSameTarget(player)
|
||||||
currentTask == null ||
|
|| currentTask.isOutdated()
|
||||||
!currentTask.isSameTarget(player) ||
|
|| !ItemStack.matches(currentTask.getBind(), stack)) {
|
||||||
currentTask.isOutdated() ||
|
|
||||||
!ItemStack.matches(currentTask.getBind(), stack)
|
|
||||||
) {
|
|
||||||
// Start new task
|
|
||||||
playerState.setCurrentTyingTask(newTask);
|
playerState.setCurrentTyingTask(newTask);
|
||||||
newTask.start();
|
newTask.start();
|
||||||
|
|
||||||
TiedUpMod.LOGGER.debug(
|
|
||||||
"[SelfBondage] {} started V2 self-tying ({} seconds)",
|
|
||||||
player.getName().getString(),
|
|
||||||
tyingSeconds
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
// Continue existing task — just mark active
|
|
||||||
currentTask.update();
|
currentTask.update();
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we started a new task, mark it active too
|
|
||||||
if (playerState.getCurrentTyingTask() == newTask) {
|
if (playerState.getCurrentTyingTask() == newTask) {
|
||||||
newTask.update();
|
newTask.update();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void handleV2SelfAccessory(
|
||||||
|
ServerPlayer player,
|
||||||
|
ItemStack stack,
|
||||||
|
IV2BondageItem v2Item,
|
||||||
|
IBondageState state
|
||||||
|
) {
|
||||||
|
// Can't equip accessories if arms are fully bound
|
||||||
|
ItemStack currentBind = V2EquipmentHelper.getInRegion(player, BodyRegionV2.ARMS);
|
||||||
|
if (!currentBind.isEmpty() && BindModeHelper.hasArmsBound(currentBind)) {
|
||||||
|
TiedUpMod.LOGGER.debug("[SelfBondage] {} can't self-accessory — arms bound", player.getName().getString());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if region is occupied — try to swap
|
||||||
|
for (BodyRegionV2 region : v2Item.getOccupiedRegions(stack)) {
|
||||||
|
if (V2EquipmentHelper.isRegionOccupied(player, region)) {
|
||||||
|
ItemStack existing = V2EquipmentHelper.getInRegion(player, region);
|
||||||
|
// Can't swap if locked
|
||||||
|
if (existing.getItem() instanceof ILockable lockable && lockable.isLocked(existing)) {
|
||||||
|
TiedUpMod.LOGGER.debug("[SelfBondage] {} can't swap — current is locked", player.getName().getString());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Equip via V2EquipmentHelper (handles conflict resolution, displaced items)
|
||||||
|
V2EquipResult result = V2EquipmentHelper.equipItem(player, stack.copy());
|
||||||
|
if (result.isSuccess()) {
|
||||||
|
for (ItemStack displaced : result.displaced()) {
|
||||||
|
player.spawnAtLocation(displaced);
|
||||||
|
}
|
||||||
|
stack.shrink(1);
|
||||||
|
SyncManager.syncInventory(player);
|
||||||
|
TiedUpMod.LOGGER.info("[SelfBondage] {} self-equipped V2 accessory", player.getName().getString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle self-equipping an accessory (gag, blindfold, mittens, earplugs).
|
* Handle self-equipping an accessory (gag, blindfold, mittens, earplugs).
|
||||||
* Can be used anytime (no need to be tied).
|
* Can be used anytime (no need to be tied).
|
||||||
|
|||||||
Reference in New Issue
Block a user