Files
TiedUp-/src/main/java/com/tiedup/remake/items/ItemGpsLocator.java
NotEvil fd60086322 feat(i18n): complete migration — items, entities, AI goals, GUI screens
119 new translation keys across 3 domains:
- Items/Blocks/Misc (46 keys): tooltips, action messages, trap states
- Entities/AI Goals (55 keys): NPC speech, maid/master/guard messages
- Client GUI (18 keys): widget labels, screen buttons, merchant display

Remaining 119 Component.literal() are all intentional:
- Debug/Admin/Command wands (47) — dev tools, not player-facing
- Entity display names (~25) — dynamic getNpcName() calls
- Empty string roots (~15) — .append() chain bases
- User-typed text (~10) — /me, /pm, /norp chat content
- Runtime data (~12) — StringBuilder, gag muffling, MCA compat
2026-04-16 12:33:13 +02:00

239 lines
8.5 KiB
Java

package com.tiedup.remake.items;
import com.tiedup.remake.core.SystemMessageManager;
import com.tiedup.remake.items.base.ItemOwnerTarget;
import com.tiedup.remake.v2.bondage.CollarHelper;
import com.tiedup.remake.state.IBondageState;
import com.tiedup.remake.util.KidnappedHelper;
import com.tiedup.remake.v2.BodyRegionV2;
import java.util.List;
import net.minecraft.ChatFormatting;
import net.minecraft.network.chat.Component;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.InteractionResultHolder;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.TooltipFlag;
import net.minecraft.world.level.Level;
import org.jetbrains.annotations.Nullable;
public class ItemGpsLocator extends ItemOwnerTarget {
public ItemGpsLocator() {
super(new net.minecraft.world.item.Item.Properties().stacksTo(1));
}
@Override
public void appendHoverText(
ItemStack stack,
@Nullable Level level,
List<Component> tooltip,
TooltipFlag flag
) {
super.appendHoverText(stack, level, tooltip, flag);
appendOwnerTooltip(stack, tooltip, "Right-click a player");
if (hasTarget(stack)) {
String displayName = resolveTargetDisplayName(stack, level);
tooltip.add(
Component.translatable("item.tiedup.gps_locator.target", displayName)
.withStyle(ChatFormatting.BLUE)
);
}
}
@Override
public InteractionResultHolder<ItemStack> use(
Level level,
Player player,
InteractionHand hand
) {
ItemStack stack = player.getItemInHand(hand);
if (level.isClientSide) return InteractionResultHolder.success(stack);
if (!hasOwner(stack)) {
SystemMessageManager.sendToPlayer(
player,
SystemMessageManager.MessageCategory.ERROR,
"You must claim this locator first! (Right-click a player)"
);
return InteractionResultHolder.fail(stack);
}
if (!isOwner(stack, player)) {
SystemMessageManager.sendToPlayer(
player,
SystemMessageManager.MessageCategory.LOCATOR_NOT_OWNER
);
return InteractionResultHolder.fail(stack);
}
if (hasTarget(stack)) {
// Use server player list for cross-dimension tracking
Player target = level
.getServer()
.getPlayerList()
.getPlayer(getTargetId(stack));
if (target != null) {
IBondageState targetState = KidnappedHelper.getKidnappedState(
target
);
if (targetState != null && targetState.hasCollar()) {
ItemStack collarStack = targetState.getEquipment(
BodyRegionV2.NECK
);
if (CollarHelper.hasGPS(collarStack)) {
if (
CollarHelper.isOwner(collarStack, player) ||
CollarHelper.hasPublicTracking(collarStack)
) {
// Check if same dimension
boolean sameDimension = player
.level()
.dimension()
.equals(target.level().dimension());
if (sameDimension) {
double distance = player.distanceTo(target);
String direction = getDirection(player, target);
SystemMessageManager.sendToPlayer(
player,
SystemMessageManager.MessageCategory.LOCATOR_DETECTED,
(int) distance + "m [" + direction + "]"
);
} else {
// Cross-dimension: show dimension name
String dimName = getDimensionDisplayName(
target
.level()
.dimension()
.location()
.getPath()
);
SystemMessageManager.sendToPlayer(
player,
SystemMessageManager.MessageCategory.LOCATOR_DETECTED,
"Target is in [" + dimName + "]"
);
}
playLocatorSound(player);
} else {
SystemMessageManager.sendToPlayer(
player,
SystemMessageManager.MessageCategory.ERROR,
"You are not allowed to access this GPS Collar!"
);
}
} else {
SystemMessageManager.sendToPlayer(
player,
SystemMessageManager.MessageCategory.ERROR,
"Target is not wearing a GPS Collar!"
);
}
}
} else {
SystemMessageManager.sendToPlayer(
player,
SystemMessageManager.MessageCategory.ERROR,
"Unable to locate target! (Offline)"
);
}
} else {
SystemMessageManager.sendToPlayer(
player,
SystemMessageManager.MessageCategory.ERROR,
"No target connected!"
);
}
return InteractionResultHolder.success(stack);
}
/**
*/
@Override
public InteractionResult interactLivingEntity(
ItemStack stack,
Player player,
LivingEntity target,
InteractionHand hand
) {
if (player.level().isClientSide) return InteractionResult.SUCCESS;
IBondageState playerState = KidnappedHelper.getKidnappedState(player);
if (
playerState != null && playerState.isTiedUp()
) return InteractionResult.FAIL;
if (!hasOwner(stack)) {
setOwner(stack, player);
SystemMessageManager.sendToPlayer(
player,
SystemMessageManager.MessageCategory.LOCATOR_CLAIMED
);
} else if (!isOwner(stack, player)) {
SystemMessageManager.sendToPlayer(
player,
SystemMessageManager.MessageCategory.LOCATOR_NOT_OWNER
);
return InteractionResult.FAIL;
}
IBondageState targetState = KidnappedHelper.getKidnappedState(target);
if (targetState != null) {
setTarget(stack, target);
player.setItemInHand(hand, stack); // Force sync
SystemMessageManager.sendChatToPlayer(
player,
"Connected to " + target.getName().getString(),
ChatFormatting.GREEN
);
return InteractionResult.SUCCESS;
}
return InteractionResult.PASS;
}
private String getDirection(Player source, Player target) {
double dx = target.getX() - source.getX();
double dz = target.getZ() - source.getZ();
if (Math.abs(dx) > Math.abs(dz)) {
return dx > 0 ? "EAST" : "WEST";
} else {
return dz > 0 ? "SOUTH" : "NORTH";
}
}
private void playLocatorSound(Player player) {
player
.level()
.playSound(
null,
player.blockPosition(),
com.tiedup.remake.core.ModSounds.SHOCKER_ACTIVATED.get(),
net.minecraft.sounds.SoundSource.PLAYERS,
0.5f,
1.0f
);
}
/**
* Get a user-friendly display name for a dimension.
*/
private String getDimensionDisplayName(String dimensionPath) {
return switch (dimensionPath) {
case "overworld" -> "Overworld";
case "the_nether" -> "The Nether";
case "the_end" -> "The End";
default -> dimensionPath.replace("_", " ");
};
}
}