import type { Location, PlayerState, CombatState, Profile, WorkbenchTab } from './types' import { useTranslation } from 'react-i18next' import { useAudio } from '../../contexts/AudioContext' import Workbench from './Workbench' import { GameTooltip } from '../common/GameTooltip' import { getAssetPath } from '../../utils/assetPath' import { getTranslatedText } from '../../utils/i18nUtils' interface LocationViewProps { location: Location playerState: PlayerState | null combatState: CombatState | null message: string locationMessages: Array<{ time: string; message: string }> expandedCorpse: string | null corpseDetails: any mobileMenuOpen: string showCraftingMenu: boolean showRepairMenu: boolean workbenchTab: WorkbenchTab craftableItems: any[] repairableItems: any[] uncraftableItems: any[] craftFilter: string repairFilter: string uncraftFilter: string craftCategoryFilter: string profile: Profile | null onSetMessage: (msg: string) => void onInitiateCombat: (npcId: number) => void onInitiatePvP: (playerId: number) => void onPickup: (itemId: number, quantity: number) => void onLootCorpse: (corpseId: string) => void onLootCorpseItem: (corpseId: string, itemIndex: number | null) => void onSetExpandedCorpse: (corpseId: string | null) => void onOpenCrafting?: () => void onOpenRepair?: () => void onCloseCrafting: () => void onSwitchWorkbenchTab: (tab: WorkbenchTab) => void onSetCraftFilter: (filter: string) => void onSetRepairFilter: (filter: string) => void onSetUncraftFilter: (filter: string) => void onSetCraftCategoryFilter: (category: string) => void onCraft: (itemId: number) => void onRepair: (uniqueItemId: string, inventoryId: number) => void onUncraft: (uniqueItemId: string, inventoryId: number) => void } function LocationView({ location, message, locationMessages, expandedCorpse, corpseDetails, mobileMenuOpen, showCraftingMenu, showRepairMenu, workbenchTab, craftableItems, repairableItems, uncraftableItems, craftFilter, repairFilter, uncraftFilter, craftCategoryFilter, profile, onSetMessage, onInitiateCombat, onInitiatePvP, onPickup, onLootCorpse, onLootCorpseItem, onSetExpandedCorpse, onOpenCrafting, onOpenRepair, onCloseCrafting, onSwitchWorkbenchTab, onSetCraftFilter, onSetRepairFilter, onSetUncraftFilter, onSetCraftCategoryFilter, onCraft, onRepair, onUncraft }: LocationViewProps) { const { t } = useTranslation() const { playSfx } = useAudio() return (

{getTranslatedText(location.name)} {location.danger_level !== undefined && location.danger_level === 0 && ( ✓ Safe )} {location.danger_level !== undefined && location.danger_level > 0 && ( ⚠️ {location.danger_level} )}

{location.tags && location.tags.length > 0 && (
{location.tags.map((tag: string, i: number) => { const isClickable = tag === 'workbench' || tag === 'repair_station' const handleClick = () => { if (tag === 'workbench' && onOpenCrafting) onOpenCrafting() else if (tag === 'repair_station' && onOpenRepair) onOpenRepair() } return ( {tag === 'workbench' && t('tags.workbench')} {tag === 'repair_station' && t('tags.repairStation')} {tag === 'safe_zone' && t('tags.safeZone')} {tag === 'shop' && t('tags.shop')} {tag === 'shelter' && t('tags.shelter')} {tag === 'medical' && t('tags.medical')} {tag === 'storage' && t('tags.storage')} {tag === 'water_source' && t('tags.water')} {tag === 'food_source' && t('tags.food')} {tag !== 'workbench' && tag !== 'repair_station' && tag !== 'safe_zone' && tag !== 'shop' && tag !== 'shelter' && tag !== 'medical' && tag !== 'storage' && tag !== 'water_source' && tag !== 'food_source' && `🏷️ ${tag}`} ) })}
)} {location.image_url && (
{getTranslatedText(location.name)} (e.currentTarget.style.display = 'none')} />
)}

{getTranslatedText(location.description)}

{message && (
onSetMessage('')}> {message}
)} {locationMessages.length > 0 && (

{t('location.recentActivity')}

{locationMessages.slice(-10).reverse().map((msg, idx) => (
{msg.time} {msg.message}
))}
)}
{/* Enemies */} {location.npcs.filter((npc: any) => npc.type === 'enemy').length > 0 && (

{t('location.enemies')}

{location.npcs.filter((npc: any) => npc.type === 'enemy').map((enemy: any, i: number) => (
{enemy.id && (
{getTranslatedText(enemy.name)} { e.currentTarget.style.display = 'none' }} />
)}
{getTranslatedText(enemy.name)}
{enemy.level &&
{t('location.level')} {enemy.level}
}
))}
)} {/* Corpses */} {location.corpses && location.corpses.length > 0 && (

{t('location.corpses')}

{location.corpses.map((corpse: any) => (
{corpse.emoji} {getTranslatedText(corpse.name)}
{corpse.loot_count} {t('location.items')}
{expandedCorpse === String(corpse.id) && corpseDetails && corpseDetails.loot_items && (

{t('location.lootableItems')}

{corpseDetails.loot_items.map((item: any) => (
{item.emoji} {getTranslatedText(item.item_name)}
{t('common.qty')}: {item.quantity_min}{item.quantity_min !== item.quantity_max ? `-${item.quantity_max}` : ''}
{item.required_tool && (
🔧 {getTranslatedText(item.required_tool_name)} {item.has_tool ? '✓' : '✗'}
)}
))}
)}
))}
)} {/* Friendly NPCs */} {location.npcs.filter((npc: any) => npc.type !== 'enemy').length > 0 && (

{t('location.npcs')}

{location.npcs.filter((npc: any) => npc.type !== 'enemy').map((npc: any, i: number) => (
🧑
{getTranslatedText(npc.name)}
{npc.level &&
{t('location.level')} {npc.level}
}
))}
)} {/* Items on Ground */} {location.items.length > 0 && (

{t('location.itemsOnGround')}

{location.items.map((item: any, i: number) => (
{item.image_path ? ( {getTranslatedText(item.name)} { (e.target as HTMLImageElement).style.display = 'none'; const icon = (e.target as HTMLImageElement).nextElementSibling; if (icon) icon.classList.remove('hidden'); }} /> ) : null} {item.emoji || '📦'}
{getTranslatedText(item.name) || 'Unknown Item'}
{item.quantity > 1 &&
×{item.quantity}
}
{item.description &&
{getTranslatedText(item.description)}
} {item.weight !== undefined && item.weight > 0 && (
⚖️ {t('stats.weight')}: {item.weight}kg {item.quantity > 1 && `(Total: ${(item.weight * item.quantity).toFixed(2)}kg)`}
)} {item.volume !== undefined && item.volume > 0 && (
📦 {t('stats.volume')}: {item.volume}L {item.quantity > 1 && `(Total: ${(item.volume * item.quantity).toFixed(2)}L)`}
)} {item.hp_restore && item.hp_restore > 0 && (
❤️ {t('stats.hpRestore')}: +{item.hp_restore}
)} {item.stamina_restore && item.stamina_restore > 0 && (
⚡ {t('stats.staminaRestore')}: +{item.stamina_restore}
)} {item.damage_min !== undefined && item.damage_max !== undefined && (item.damage_min > 0 || item.damage_max > 0) && (
⚔️ {t('stats.damage')}: {item.damage_min}-{item.damage_max}
)} {item.durability !== undefined && item.durability !== null && item.max_durability !== undefined && item.max_durability !== null && (
🔧 {t('stats.durability')}: {item.durability}/{item.max_durability}
)} {item.tier !== undefined && item.tier !== null && item.tier > 0 && (
⭐ {t('stats.tier')}: {item.tier}
)}
}>
{item.quantity === 1 ? ( ) : (
{item.quantity >= 5 && ( )} {item.quantity >= 10 && ( )}
)}
))}
)} {/* Other Players */} {location.other_players && location.other_players.length > 0 && (

👥 Other Players

{location.other_players.map((player: any, i: number) => (
🧍
{player.name || player.username}
Lv. {player.level}
{player.level_diff !== undefined && (
{player.level_diff > 0 ? `+${player.level_diff}` : player.level_diff} levels
)}
{player.can_pvp && ( )} {!player.can_pvp && player.level_diff !== undefined && Math.abs(player.level_diff) > 3 && (
{t('game.levelDifferenceTooHigh')}
)} {!player.can_pvp && location.danger_level !== undefined && location.danger_level < 3 && (
{t('game.areaTooSafeForPvP')}
)}
))}
)}
{(showCraftingMenu || showRepairMenu) && ( )} ) } export default LocationView