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:
447
src/main/java/com/tiedup/remake/util/RestraintEffectUtils.java
Normal file
447
src/main/java/com/tiedup/remake/util/RestraintEffectUtils.java
Normal file
@@ -0,0 +1,447 @@
|
||||
package com.tiedup.remake.util;
|
||||
|
||||
import com.tiedup.remake.core.TiedUpMod;
|
||||
import com.tiedup.remake.state.IPlayerLeashAccess;
|
||||
import java.util.UUID;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.world.effect.MobEffectInstance;
|
||||
import net.minecraft.world.effect.MobEffects;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.entity.Mob;
|
||||
import net.minecraft.world.entity.ai.attributes.AttributeInstance;
|
||||
import net.minecraft.world.entity.ai.attributes.AttributeModifier;
|
||||
import net.minecraft.world.entity.ai.attributes.Attributes;
|
||||
import net.minecraft.world.entity.decoration.LeashFenceKnotEntity;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.FenceBlock;
|
||||
import net.minecraft.world.level.block.WallBlock;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
|
||||
/**
|
||||
* Phase 5: Utility class for applying/removing restraint effects
|
||||
*
|
||||
* Manages attribute modifiers for movement speed reduction and other effects.
|
||||
* Phase 14.1: Refactored to support LivingEntity (Player + NPCs)
|
||||
*/
|
||||
public class RestraintEffectUtils {
|
||||
|
||||
// UUID for the movement speed modifier (must be consistent)
|
||||
private static final UUID BIND_SPEED_MODIFIER_UUID = UUID.fromString(
|
||||
"7f3c7c8e-9d4e-4c7a-8e5f-1a2b3c4d5e6f"
|
||||
);
|
||||
private static final String BIND_SPEED_MODIFIER_NAME = "tiedup.bind_speed";
|
||||
|
||||
// Speed reduction: -0.09 (90% reduction) when tied up
|
||||
// Player base speed is 0.10, so this reduces them to 0.01 (10% speed)
|
||||
private static final double BIND_SPEED_REDUCTION = -0.09;
|
||||
|
||||
// Full immobilization: -0.10 (100% reduction) for WRAP/LATEX_SACK
|
||||
// Player can only move by jumping
|
||||
private static final double FULL_IMMOBILIZATION_REDUCTION = -0.10;
|
||||
|
||||
private static final boolean DEBUG = false;
|
||||
|
||||
/**
|
||||
* Apply movement speed reduction to a tied entity.
|
||||
*
|
||||
* @param entity The living entity to apply the effect to
|
||||
* @deprecated For players, use {@link com.tiedup.remake.v2.bondage.movement.MovementStyleManager}
|
||||
* which handles speed via tick-based resolution. This method remains for NPC entities
|
||||
* (Damsel, MCA villagers) that are not managed by MovementStyleManager.
|
||||
* Scheduled for removal once NPC movement is migrated to V2.
|
||||
*/
|
||||
@Deprecated(forRemoval = true)
|
||||
public static void applyBindSpeedReduction(LivingEntity entity) {
|
||||
applyBindSpeedReduction(entity, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply movement speed reduction to a tied entity.
|
||||
*
|
||||
* @param entity The living entity to apply the effect to
|
||||
* @param fullImmobilization If true, applies 100% speed reduction (for WRAP/LATEX_SACK)
|
||||
* @deprecated For players, use {@link com.tiedup.remake.v2.bondage.movement.MovementStyleManager}
|
||||
* which handles speed via tick-based resolution. This method remains for NPC entities
|
||||
* (Damsel, MCA villagers) that are not managed by MovementStyleManager.
|
||||
* Scheduled for removal once NPC movement is migrated to V2.
|
||||
*/
|
||||
@Deprecated(forRemoval = true)
|
||||
public static void applyBindSpeedReduction(
|
||||
LivingEntity entity,
|
||||
boolean fullImmobilization
|
||||
) {
|
||||
if (entity == null) {
|
||||
TiedUpMod.LOGGER.warn(
|
||||
"[RESTRAINT-UTIL] Cannot apply speed reduction - entity is null"
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
AttributeInstance movementSpeed = entity.getAttribute(
|
||||
Attributes.MOVEMENT_SPEED
|
||||
);
|
||||
if (movementSpeed == null) {
|
||||
TiedUpMod.LOGGER.error(
|
||||
"[RESTRAINT-UTIL] Entity {} has no MOVEMENT_SPEED attribute!",
|
||||
entity.getName().getString()
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// Remove existing modifier if present (to avoid duplicates)
|
||||
removeBindSpeedReduction(entity);
|
||||
|
||||
// Choose reduction amount based on immobilization type
|
||||
double reduction = fullImmobilization
|
||||
? FULL_IMMOBILIZATION_REDUCTION
|
||||
: BIND_SPEED_REDUCTION;
|
||||
|
||||
// Create and apply new modifier
|
||||
AttributeModifier modifier = new AttributeModifier(
|
||||
BIND_SPEED_MODIFIER_UUID,
|
||||
BIND_SPEED_MODIFIER_NAME,
|
||||
reduction,
|
||||
AttributeModifier.Operation.ADDITION
|
||||
);
|
||||
|
||||
movementSpeed.addPermanentModifier(modifier);
|
||||
|
||||
if (DEBUG) {
|
||||
TiedUpMod.LOGGER.info(
|
||||
"[RESTRAINT-UTIL] Applied speed reduction to {} (base: {}, modified: {}, full: {})",
|
||||
entity.getName().getString(),
|
||||
movementSpeed.getBaseValue(),
|
||||
movementSpeed.getValue(),
|
||||
fullImmobilization
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove movement speed reduction from an entity.
|
||||
*
|
||||
* @param entity The living entity to remove the effect from
|
||||
* @deprecated For players, use {@link com.tiedup.remake.v2.bondage.movement.MovementStyleManager}
|
||||
* which handles speed cleanup via tick-based resolution. This method remains for
|
||||
* NPC entities (Damsel, MCA villagers) that are not managed by MovementStyleManager.
|
||||
* Scheduled for removal once NPC movement is migrated to V2.
|
||||
*/
|
||||
@Deprecated(forRemoval = true)
|
||||
public static void removeBindSpeedReduction(LivingEntity entity) {
|
||||
if (entity == null) {
|
||||
TiedUpMod.LOGGER.warn(
|
||||
"[RESTRAINT-UTIL] Cannot remove speed reduction - entity is null"
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
AttributeInstance movementSpeed = entity.getAttribute(
|
||||
Attributes.MOVEMENT_SPEED
|
||||
);
|
||||
if (movementSpeed == null) {
|
||||
TiedUpMod.LOGGER.error(
|
||||
"[RESTRAINT-UTIL] Entity {} has no MOVEMENT_SPEED attribute!",
|
||||
entity.getName().getString()
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// Remove modifier if present
|
||||
if (movementSpeed.getModifier(BIND_SPEED_MODIFIER_UUID) != null) {
|
||||
movementSpeed.removeModifier(BIND_SPEED_MODIFIER_UUID);
|
||||
|
||||
if (DEBUG) {
|
||||
TiedUpMod.LOGGER.info(
|
||||
"[RESTRAINT-UTIL] Removed speed reduction from {} (restored speed: {})",
|
||||
entity.getName().getString(),
|
||||
movementSpeed.getValue()
|
||||
);
|
||||
}
|
||||
} else {
|
||||
if (DEBUG) {
|
||||
TiedUpMod.LOGGER.debug(
|
||||
"[RESTRAINT-UTIL] No speed modifier found on {} (already removed or never applied)",
|
||||
entity.getName().getString()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if an entity currently has the bind speed reduction applied.
|
||||
*
|
||||
* @param entity The living entity to check
|
||||
* @return true if the modifier is active
|
||||
* @deprecated For players, movement style is tracked by {@link com.tiedup.remake.v2.bondage.movement.MovementStyleManager}.
|
||||
* Scheduled for removal once NPC movement is migrated to V2.
|
||||
*/
|
||||
@Deprecated(forRemoval = true)
|
||||
public static boolean hasBindSpeedReduction(LivingEntity entity) {
|
||||
if (entity == null) return false;
|
||||
|
||||
AttributeInstance movementSpeed = entity.getAttribute(
|
||||
Attributes.MOVEMENT_SPEED
|
||||
);
|
||||
if (movementSpeed == null) return false;
|
||||
|
||||
return movementSpeed.getModifier(BIND_SPEED_MODIFIER_UUID) != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-apply speed reduction if needed (called on login/respawn).
|
||||
*
|
||||
* @param entity The living entity
|
||||
* @param shouldBeSlowed Whether the entity should have reduced speed
|
||||
* @deprecated For players, use {@link com.tiedup.remake.v2.bondage.movement.MovementStyleManager}
|
||||
* which re-resolves on every tick. Scheduled for removal once NPC movement is migrated to V2.
|
||||
*/
|
||||
@Deprecated(forRemoval = true)
|
||||
public static void updateBindSpeedReduction(
|
||||
LivingEntity entity,
|
||||
boolean shouldBeSlowed
|
||||
) {
|
||||
updateBindSpeedReduction(entity, shouldBeSlowed, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-apply speed reduction if needed (called on login/respawn).
|
||||
*
|
||||
* @param entity The living entity
|
||||
* @param shouldBeSlowed Whether the entity should have reduced speed
|
||||
* @param fullImmobilization If true, applies 100% speed reduction (for WRAP/LATEX_SACK)
|
||||
* @deprecated For players, use {@link com.tiedup.remake.v2.bondage.movement.MovementStyleManager}
|
||||
* which re-resolves on every tick. Scheduled for removal once NPC movement is migrated to V2.
|
||||
*/
|
||||
@Deprecated(forRemoval = true)
|
||||
public static void updateBindSpeedReduction(
|
||||
LivingEntity entity,
|
||||
boolean shouldBeSlowed,
|
||||
boolean fullImmobilization
|
||||
) {
|
||||
boolean currentlySlowed = hasBindSpeedReduction(entity);
|
||||
|
||||
if (shouldBeSlowed && !currentlySlowed) {
|
||||
// Need to apply
|
||||
applyBindSpeedReduction(entity, fullImmobilization);
|
||||
if (DEBUG) {
|
||||
TiedUpMod.LOGGER.info(
|
||||
"[RESTRAINT-UTIL] Re-applied speed reduction to {} on login/respawn (full={})",
|
||||
entity.getName().getString(),
|
||||
fullImmobilization
|
||||
);
|
||||
}
|
||||
} else if (shouldBeSlowed && currentlySlowed) {
|
||||
// Already slowed - but might need to change immobilization level
|
||||
// Re-apply with correct level
|
||||
applyBindSpeedReduction(entity, fullImmobilization);
|
||||
} else if (!shouldBeSlowed && currentlySlowed) {
|
||||
// Need to remove
|
||||
removeBindSpeedReduction(entity);
|
||||
if (DEBUG) {
|
||||
TiedUpMod.LOGGER.info(
|
||||
"[RESTRAINT-UTIL] Removed speed reduction from {} on login/respawn",
|
||||
entity.getName().getString()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ========================================
|
||||
// POLE BINDING UTILITIES
|
||||
// ========================================
|
||||
|
||||
/**
|
||||
* Find the closest fence or wall block within a radius.
|
||||
*
|
||||
* @param level The level to search in
|
||||
* @param center The center position to search from
|
||||
* @param radius The search radius in blocks
|
||||
* @return The position of the closest fence/wall, or null if none found
|
||||
*/
|
||||
@Nullable
|
||||
public static BlockPos findClosestFence(
|
||||
Level level,
|
||||
BlockPos center,
|
||||
int radius
|
||||
) {
|
||||
if (level == null || center == null) return null;
|
||||
|
||||
BlockPos closestFence = null;
|
||||
double closestDistance = Double.MAX_VALUE;
|
||||
|
||||
for (int x = -radius; x <= radius; x++) {
|
||||
for (int y = -radius; y <= radius; y++) {
|
||||
for (int z = -radius; z <= radius; z++) {
|
||||
BlockPos checkPos = center.offset(x, y, z);
|
||||
BlockState state = level.getBlockState(checkPos);
|
||||
|
||||
if (
|
||||
state.getBlock() instanceof FenceBlock ||
|
||||
state.getBlock() instanceof WallBlock
|
||||
) {
|
||||
double dist = center.distSqr(checkPos);
|
||||
if (dist < closestDistance) {
|
||||
closestDistance = dist;
|
||||
closestFence = checkPos;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return closestFence;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tie an entity to the closest fence or wall block.
|
||||
* Works for both Players (via LeashProxy) and NPCs (via vanilla leash).
|
||||
*
|
||||
* @param entity The entity to tie
|
||||
* @param searchRadius The search radius for fence blocks
|
||||
* @return true if successfully tied, false otherwise
|
||||
*/
|
||||
public static boolean tieToClosestPole(
|
||||
LivingEntity entity,
|
||||
int searchRadius
|
||||
) {
|
||||
if (entity == null || entity.level().isClientSide) return false;
|
||||
if (!(entity.level() instanceof ServerLevel serverLevel)) return false;
|
||||
|
||||
BlockPos entityPos = entity.blockPosition();
|
||||
BlockPos closestFence = findClosestFence(
|
||||
serverLevel,
|
||||
entityPos,
|
||||
searchRadius
|
||||
);
|
||||
|
||||
if (closestFence == null) {
|
||||
if (DEBUG) {
|
||||
TiedUpMod.LOGGER.debug(
|
||||
"[RESTRAINT-UTIL] No fence found within {} blocks of {}",
|
||||
searchRadius,
|
||||
entity.getName().getString()
|
||||
);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get or create a LeashFenceKnotEntity at the fence position
|
||||
LeashFenceKnotEntity fenceKnot = LeashFenceKnotEntity.getOrCreateKnot(
|
||||
serverLevel,
|
||||
closestFence
|
||||
);
|
||||
|
||||
if (fenceKnot == null) {
|
||||
TiedUpMod.LOGGER.warn(
|
||||
"[RESTRAINT-UTIL] Failed to create fence knot at {}",
|
||||
closestFence
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Handle differently based on entity type
|
||||
if (entity instanceof Player player) {
|
||||
// Player: use LeashProxy system
|
||||
if (player instanceof IPlayerLeashAccess access) {
|
||||
access.tiedup$attachLeash(fenceKnot);
|
||||
TiedUpMod.LOGGER.debug(
|
||||
"[RESTRAINT-UTIL] Tied player {} to pole at {}",
|
||||
player.getName().getString(),
|
||||
closestFence
|
||||
);
|
||||
return true;
|
||||
} else {
|
||||
TiedUpMod.LOGGER.error(
|
||||
"[RESTRAINT-UTIL] Player {} does not implement IPlayerLeashAccess!",
|
||||
player.getName().getString()
|
||||
);
|
||||
return false;
|
||||
}
|
||||
} else if (entity instanceof Mob mob) {
|
||||
// NPC (Mob): use vanilla leash mechanics
|
||||
mob.setLeashedTo(fenceKnot, true);
|
||||
TiedUpMod.LOGGER.debug(
|
||||
"[RESTRAINT-UTIL] Tied mob {} to pole at {}",
|
||||
mob.getName().getString(),
|
||||
closestFence
|
||||
);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// ========================================
|
||||
// CHLOROFORM UTILITIES
|
||||
// ========================================
|
||||
|
||||
/**
|
||||
* Apply chloroform effects to an entity.
|
||||
* Effects: Slowness, Mining Fatigue, Blindness, Jump Boost (all at max amplifier).
|
||||
*
|
||||
* @param entity The entity to affect
|
||||
* @param durationSeconds Duration in seconds
|
||||
*/
|
||||
public static void applyChloroformEffects(
|
||||
LivingEntity entity,
|
||||
int durationSeconds
|
||||
) {
|
||||
if (entity == null || entity.level().isClientSide) return;
|
||||
|
||||
int tickDuration = durationSeconds * GameConstants.TICKS_PER_SECOND;
|
||||
|
||||
entity.addEffect(
|
||||
new MobEffectInstance(
|
||||
MobEffects.MOVEMENT_SLOWDOWN,
|
||||
tickDuration,
|
||||
GameConstants.CHLOROFORM_SLOWDOWN_AMPLIFIER,
|
||||
false,
|
||||
false
|
||||
)
|
||||
);
|
||||
entity.addEffect(
|
||||
new MobEffectInstance(
|
||||
MobEffects.DIG_SLOWDOWN,
|
||||
tickDuration,
|
||||
GameConstants.CHLOROFORM_DIG_SLOWDOWN_AMPLIFIER,
|
||||
false,
|
||||
false
|
||||
)
|
||||
);
|
||||
entity.addEffect(
|
||||
new MobEffectInstance(
|
||||
MobEffects.BLINDNESS,
|
||||
tickDuration,
|
||||
GameConstants.CHLOROFORM_BLINDNESS_AMPLIFIER,
|
||||
false,
|
||||
false
|
||||
)
|
||||
);
|
||||
entity.addEffect(
|
||||
new MobEffectInstance(
|
||||
MobEffects.JUMP,
|
||||
tickDuration,
|
||||
GameConstants.CHLOROFORM_JUMP_AMPLIFIER,
|
||||
false,
|
||||
false
|
||||
)
|
||||
);
|
||||
|
||||
// Stop navigation for mobs
|
||||
if (entity instanceof Mob mob) {
|
||||
mob.getNavigation().stop();
|
||||
}
|
||||
|
||||
if (DEBUG) {
|
||||
TiedUpMod.LOGGER.debug(
|
||||
"[RESTRAINT-UTIL] Applied chloroform to {} for {} seconds",
|
||||
entity.getName().getString(),
|
||||
durationSeconds
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user