import { useQuery } from 'convex/react'; import { api } from '../../convex/_generated/api'; import { Id } from '../../convex/_generated/dataModel'; import closeImg from '../../assets/close.svg'; import { SelectElement } from './Player'; import { Messages } from './Messages'; import { toastOnError } from '../toasts'; import { useSendInput } from '../hooks/sendInput'; import { Player } from '../../convex/aiTown/player'; import { GameId } from '../../convex/aiTown/ids'; import { ServerGame } from '../hooks/serverGame'; export default function PlayerDetails({ worldId, engineId, game, playerId, setSelectedElement, scrollViewRef, }: { worldId: Id<'worlds'>; engineId: Id<'engines'>; game: ServerGame; playerId?: GameId<'players'>; setSelectedElement: SelectElement; scrollViewRef: React.RefObject; }) { const oauth = JSON.parse(localStorage.getItem('oauth')); const oauthToken = oauth ? oauth.userInfo.fullname : undefined; const humanTokenIdentifier = useQuery(api.world.userStatus, { worldId, oauthToken }); const players = [...game.world.players.values()]; const humanPlayer = players.find((p) => p.human === humanTokenIdentifier); const humanConversation = humanPlayer ? game.world.playerConversation(humanPlayer) : undefined; // Always select the other player if we're in a conversation with them. if (humanPlayer && humanConversation) { const otherPlayerIds = [...humanConversation.participants.keys()].filter( (p) => p !== humanPlayer.id, ); playerId = otherPlayerIds[0]; } const player = playerId && game.world.players.get(playerId); const playerConversation = player && game.world.playerConversation(player); const previousConversation = useQuery( api.world.previousConversation, playerId ? { worldId, playerId } : 'skip', ); const playerDescription = playerId && game.playerDescriptions.get(playerId); const startConversation = useSendInput(engineId, 'startConversation'); const acceptInvite = useSendInput(engineId, 'acceptInvite'); const rejectInvite = useSendInput(engineId, 'rejectInvite'); const leaveConversation = useSendInput(engineId, 'leaveConversation'); if (!playerId) { return (
Click on an agent on the map to see chat history.
); } if (!player) { return null; } const isMe = humanPlayer && player.id === humanPlayer.id; const canInvite = !isMe && !playerConversation && humanPlayer && !humanConversation; const sameConversation = !isMe && humanPlayer && humanConversation && playerConversation && humanConversation.id === playerConversation.id; const humanStatus = humanPlayer && humanConversation && humanConversation.participants.get(humanPlayer.id)?.status; const playerStatus = playerConversation && playerConversation.participants.get(playerId)?.status; const haveInvite = sameConversation && humanStatus?.kind === 'invited'; const waitingForAccept = sameConversation && playerConversation.participants.get(playerId)?.status.kind === 'invited'; const waitingForNearby = sameConversation && playerStatus?.kind === 'walkingOver' && humanStatus?.kind === 'walkingOver'; const inConversationWithMe = sameConversation && playerStatus?.kind === 'participating' && humanStatus?.kind === 'participating'; const onStartConversation = async () => { if (!humanPlayer || !playerId) { return; } console.log(`Starting conversation`); await toastOnError(startConversation({ playerId: humanPlayer.id, invitee: playerId })); }; const onAcceptInvite = async () => { if (!humanPlayer || !humanConversation || !playerId) { return; } await toastOnError( acceptInvite({ playerId: humanPlayer.id, conversationId: humanConversation.id, }), ); }; const onRejectInvite = async () => { if (!humanPlayer || !humanConversation) { return; } await toastOnError( rejectInvite({ playerId: humanPlayer.id, conversationId: humanConversation.id, }), ); }; const onLeaveConversation = async () => { if (!humanPlayer || !inConversationWithMe || !humanConversation) { return; } await toastOnError( leaveConversation({ playerId: humanPlayer.id, conversationId: humanConversation.id, }), ); }; // const pendingSuffix = (inputName: string) => // [...inflightInputs.values()].find((i) => i.name === inputName) ? ' opacity-50' : ''; const pendingSuffix = (s: string) => ''; return ( <>

{playerDescription?.name}

setSelectedElement(undefined)} >

{canInvite && (
Start conversation
)} {waitingForAccept && (
Waiting for accept...
)} {waitingForNearby && (
Walking over...
)} {inConversationWithMe && (
Leave conversation
)} {haveInvite && ( <>
Accept
Reject
)} {!playerConversation && player.activity && player.activity.until > Date.now() && (

{player.activity.description}

)}

{!isMe && playerDescription?.description} {isMe && This is you!} {!isMe && inConversationWithMe && ( <>

(Conversing with you!) )}

{!isMe && playerConversation && playerStatus?.kind === 'participating' && ( )} {!playerConversation && previousConversation && ( <>

Previous conversation

)} ); }