Strip all Phase references, TODO/FUTURE roadmap notes, and internal planning comments from the codebase. Run Prettier for consistent formatting across all Java files.
289 lines
8.4 KiB
Java
289 lines
8.4 KiB
Java
package com.tiedup.remake.items;
|
|
|
|
import com.tiedup.remake.core.ModConfig;
|
|
import com.tiedup.remake.core.SettingsAccessor;
|
|
import com.tiedup.remake.core.SystemMessageManager;
|
|
import com.tiedup.remake.core.TiedUpMod;
|
|
import com.tiedup.remake.state.IRestrainable;
|
|
import com.tiedup.remake.state.PlayerBindState;
|
|
import com.tiedup.remake.util.KidnappedHelper;
|
|
import java.util.List;
|
|
import net.minecraft.ChatFormatting;
|
|
import net.minecraft.nbt.CompoundTag;
|
|
import net.minecraft.network.chat.Component;
|
|
import net.minecraft.world.InteractionHand;
|
|
import net.minecraft.world.InteractionResult;
|
|
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.player.Player;
|
|
import net.minecraft.world.item.Item;
|
|
import net.minecraft.world.item.ItemStack;
|
|
import net.minecraft.world.item.TooltipFlag;
|
|
import net.minecraft.world.level.Level;
|
|
import org.jetbrains.annotations.Nullable;
|
|
|
|
/**
|
|
* Rag - Can be soaked in chloroform to knock out targets
|
|
* Has wet/dry state managed via NBT.
|
|
*
|
|
*
|
|
* Usage:
|
|
* 1. Hold chloroform bottle, rag in offhand, right-click → rag becomes wet
|
|
* 2. Hold wet rag, right-click target → apply chloroform effect
|
|
* 3. Wet rag evaporates over time (configurable)
|
|
*
|
|
* Effects on target:
|
|
* - Slowness 127 (cannot move)
|
|
* - Blindness
|
|
* - Nausea
|
|
* - UNCONSCIOUS pose
|
|
*/
|
|
public class ItemRag extends Item {
|
|
|
|
private static final String NBT_WET = "wet";
|
|
private static final String NBT_WET_TIME = "wetTime"; // Ticks remaining
|
|
|
|
public ItemRag() {
|
|
super(new Item.Properties().stacksTo(16));
|
|
}
|
|
|
|
@Override
|
|
public void appendHoverText(
|
|
ItemStack stack,
|
|
@Nullable Level level,
|
|
List<Component> tooltip,
|
|
TooltipFlag flag
|
|
) {
|
|
if (isWet(stack)) {
|
|
int ticksRemaining = getWetTime(stack);
|
|
int secondsRemaining = ticksRemaining / 20;
|
|
tooltip.add(
|
|
Component.literal("Soaked with chloroform").withStyle(
|
|
ChatFormatting.GREEN
|
|
)
|
|
);
|
|
tooltip.add(
|
|
Component.literal(
|
|
"Evaporates in: " + secondsRemaining + "s"
|
|
).withStyle(ChatFormatting.GRAY)
|
|
);
|
|
} else {
|
|
tooltip.add(
|
|
Component.literal("Dry - needs chloroform").withStyle(
|
|
ChatFormatting.GRAY
|
|
)
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Called when player right-clicks another entity with the rag.
|
|
* If wet, applies chloroform effect to the target.
|
|
*/
|
|
@Override
|
|
public InteractionResult interactLivingEntity(
|
|
ItemStack stack,
|
|
Player player,
|
|
LivingEntity target,
|
|
InteractionHand hand
|
|
) {
|
|
// Only run on server side
|
|
if (player.level().isClientSide) {
|
|
return InteractionResult.SUCCESS;
|
|
}
|
|
|
|
// Must be wet to apply chloroform
|
|
if (!isWet(stack)) {
|
|
SystemMessageManager.sendToPlayer(
|
|
player,
|
|
SystemMessageManager.MessageCategory.RAG_DRY
|
|
);
|
|
return InteractionResult.PASS;
|
|
}
|
|
|
|
// Apply chloroform to target
|
|
applyChloroformToTarget(target, player);
|
|
|
|
// The rag stays wet (can be used multiple times until it evaporates)
|
|
|
|
TiedUpMod.LOGGER.info(
|
|
"[ItemRag] {} applied chloroform to {}",
|
|
player.getName().getString(),
|
|
target.getName().getString()
|
|
);
|
|
|
|
return InteractionResult.SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* Tick the rag to handle evaporation of wet state.
|
|
*/
|
|
@Override
|
|
public void inventoryTick(
|
|
ItemStack stack,
|
|
Level level,
|
|
Entity entity,
|
|
int slot,
|
|
boolean selected
|
|
) {
|
|
if (level.isClientSide) return;
|
|
|
|
if (isWet(stack)) {
|
|
int wetTime = getWetTime(stack);
|
|
if (wetTime > 0) {
|
|
setWetTime(stack, wetTime - 1);
|
|
} else {
|
|
// Evaporated
|
|
setWet(stack, false);
|
|
if (entity instanceof Player player) {
|
|
SystemMessageManager.sendToPlayer(
|
|
player,
|
|
SystemMessageManager.MessageCategory.RAG_EVAPORATED
|
|
);
|
|
}
|
|
TiedUpMod.LOGGER.debug("[ItemRag] Chloroform evaporated");
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Apply chloroform effect to a target.
|
|
* Effects: Slowness 127, Blindness, Nausea for configured duration.
|
|
*
|
|
* @param target The target entity
|
|
* @param player The player applying chloroform
|
|
*/
|
|
private void applyChloroformToTarget(LivingEntity target, Player player) {
|
|
// Get duration from config via SettingsAccessor (single source of truth)
|
|
int duration = SettingsAccessor.getChloroformDuration();
|
|
|
|
// Apply effects
|
|
// Slowness 127 = cannot move at all
|
|
target.addEffect(
|
|
new MobEffectInstance(
|
|
MobEffects.MOVEMENT_SLOWDOWN,
|
|
duration,
|
|
127,
|
|
false,
|
|
false
|
|
)
|
|
);
|
|
// Blindness
|
|
target.addEffect(
|
|
new MobEffectInstance(
|
|
MobEffects.BLINDNESS,
|
|
duration,
|
|
0,
|
|
false,
|
|
false
|
|
)
|
|
);
|
|
// Nausea (confusion)
|
|
target.addEffect(
|
|
new MobEffectInstance(
|
|
MobEffects.CONFUSION,
|
|
duration,
|
|
0,
|
|
false,
|
|
false
|
|
)
|
|
);
|
|
// Weakness (cannot fight back)
|
|
target.addEffect(
|
|
new MobEffectInstance(
|
|
MobEffects.WEAKNESS,
|
|
duration,
|
|
127,
|
|
false,
|
|
false
|
|
)
|
|
);
|
|
|
|
// If target is IRestrainable, call applyChloroform to apply effects
|
|
IRestrainable kidnapped = KidnappedHelper.getKidnappedState(target);
|
|
if (kidnapped != null) {
|
|
kidnapped.applyChloroform(duration);
|
|
}
|
|
|
|
TiedUpMod.LOGGER.debug(
|
|
"[ItemRag] Applied chloroform to target for {} seconds",
|
|
duration
|
|
);
|
|
}
|
|
|
|
// ========== Wet/Dry State Management ==========
|
|
|
|
/**
|
|
* Check if this rag is soaked with chloroform.
|
|
* @param stack The item stack
|
|
* @return true if wet with chloroform
|
|
*/
|
|
public static boolean isWet(ItemStack stack) {
|
|
if (stack.isEmpty()) return false;
|
|
CompoundTag tag = stack.getTag();
|
|
return tag != null && tag.getBoolean(NBT_WET);
|
|
}
|
|
|
|
/**
|
|
* Set the wet state of this rag.
|
|
* @param stack The item stack
|
|
* @param wet true to make wet, false for dry
|
|
*/
|
|
public static void setWet(ItemStack stack, boolean wet) {
|
|
if (stack.isEmpty()) return;
|
|
stack.getOrCreateTag().putBoolean(NBT_WET, wet);
|
|
if (!wet) {
|
|
// Clear wet time when drying
|
|
stack.getOrCreateTag().remove(NBT_WET_TIME);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get the remaining wet time in ticks.
|
|
* @param stack The item stack
|
|
* @return Ticks remaining, or 0 if not wet
|
|
*/
|
|
public static int getWetTime(ItemStack stack) {
|
|
if (stack.isEmpty()) return 0;
|
|
CompoundTag tag = stack.getTag();
|
|
return tag != null ? tag.getInt(NBT_WET_TIME) : 0;
|
|
}
|
|
|
|
/**
|
|
* Set the remaining wet time in ticks.
|
|
* @param stack The item stack
|
|
* @param ticks Ticks remaining
|
|
*/
|
|
public static void setWetTime(ItemStack stack, int ticks) {
|
|
if (stack.isEmpty()) return;
|
|
stack.getOrCreateTag().putInt(NBT_WET_TIME, ticks);
|
|
}
|
|
|
|
/**
|
|
* Soak this rag with chloroform.
|
|
* Sets wet = true and initializes the evaporation timer.
|
|
*
|
|
* @param stack The item stack
|
|
* @param wetTime Time in ticks before evaporation
|
|
*/
|
|
public static void soak(ItemStack stack, int wetTime) {
|
|
if (stack.isEmpty()) return;
|
|
setWet(stack, true);
|
|
setWetTime(stack, wetTime);
|
|
TiedUpMod.LOGGER.debug(
|
|
"[ItemRag] Soaked with chloroform ({} ticks)",
|
|
wetTime
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Get the default wet time for soaking.
|
|
* @return Default wet time in ticks
|
|
*/
|
|
public static int getDefaultWetTime() {
|
|
return ModConfig.SERVER.ragWetTime.get();
|
|
}
|
|
}
|