feat(D-01/E): quickwins — debug toggle, HumanChairHelper move, collar equip

Q1: Remove F9 debug toggle from GltfAnimationApplier + delete dead
    GltfRenderLayer + remove keybind registration

Q2: Move HumanChairHelper from state/ to util/ — pure utility with
    no state dependency. 7 import updates.

Q3: Wire NECK collar equip flow in DataDrivenBondageItem:
    - Target must be tied up (V1 rule preserved)
    - Distance + line-of-sight validation
    - Owner added to NBT before equip via CollarHelper.addOwner()
    - V2EquipmentHelper handles conflict resolution
    - ModSounds.COLLAR_PUT played on success
    - OwnershipComponent.onEquipped registers in CollarRegistry
This commit is contained in:
NotEvil
2026-04-15 10:48:21 +02:00
committed by NotEvil
parent cc0ce89de5
commit f945e9449b
13 changed files with 50 additions and 215 deletions

View File

@@ -46,9 +46,7 @@ import org.joml.Matrix4f;
* pushPose/popPose pair. Joint matrices are computed per-GLB-model
* because different GLB models have different skeletons.
*
* <p>Unlike {@link com.tiedup.remake.client.gltf.GltfRenderLayer},
* this layer is always active (no F9 toggle guard) and renders on
* ALL entities (no local-player-only guard).
* <p>This layer is always active and renders on ALL entities.
*/
@OnlyIn(Dist.CLIENT)
public class V2BondageRenderLayer<

View File

@@ -1,7 +1,12 @@
package com.tiedup.remake.v2.bondage.datadriven;
import com.tiedup.remake.core.ModSounds;
import com.tiedup.remake.core.TiedUpMod;
import com.tiedup.remake.state.IRestrainable;
import com.tiedup.remake.util.KidnappedHelper;
import com.tiedup.remake.v2.BodyRegionV2;
import com.tiedup.remake.v2.bondage.CollarHelper;
import com.tiedup.remake.v2.bondage.V2EquipResult;
import com.tiedup.remake.v2.bondage.BindModeHelper;
import com.tiedup.remake.v2.bondage.IV2BondageEquipment;
import com.tiedup.remake.v2.bondage.TyingInteractionHelper;
@@ -168,11 +173,39 @@ public class DataDrivenBondageItem extends AbstractV2BondageItem {
return TyingInteractionHelper.handleTying(serverPlayer, target, stack, hand);
}
// NECK: blocked — collar equip requires owner setup (add owner to NBT,
// register in CollarRegistry, play sound, sync) which is not yet wired
// through interactLivingEntity. TODO: implement collar equip flow.
if (regions.contains(BodyRegionV2.NECK)) {
TiedUpMod.LOGGER.debug("[DataDrivenBondageItem] NECK equip via right-click not yet implemented");
// NECK: collar equip flow
if (regions.contains(BodyRegionV2.NECK) && player instanceof ServerPlayer serverPlayer) {
// Target must be tied up to collar (V1 rule preserved)
IRestrainable targetState = KidnappedHelper.getKidnappedState(target);
if (targetState == null || !targetState.isTiedUp()) {
return InteractionResult.PASS;
}
// Distance + line-of-sight
if (player.distanceTo(target) > 4.0 || !player.hasLineOfSight(target)) {
return InteractionResult.PASS;
}
// Add player as owner in NBT before equip
ItemStack collarCopy = stack.copy();
CollarHelper.addOwner(collarCopy, player);
// Equip via V2 system (handles conflict resolution, displaced items)
V2EquipResult result = V2EquipmentHelper.equipItem(target, collarCopy);
if (result.isSuccess()) {
for (ItemStack displaced : result.displaced()) {
target.spawnAtLocation(displaced);
}
stack.shrink(1);
// Play collar equip sound
target.level().playSound(null, target.getX(), target.getY(), target.getZ(),
ModSounds.COLLAR_PUT.get(),
net.minecraft.sounds.SoundSource.PLAYERS, 0.5f, 1.0f);
V2EquipmentHelper.sync(target);
TiedUpMod.LOGGER.info("[DataDrivenBondageItem] {} collared {} (owner added)",
player.getName().getString(), target.getName().getString());
return InteractionResult.SUCCESS;
}
return InteractionResult.PASS;
}