import type { GameEvents } from "./events.js"; export interface PresenceInfo { online: boolean; serverId?: string; zoneId?: string; instanceId?: string; } export interface EmoteEntityLookup { get(id: string): { position: readonly [number, number, number]; role: string; } | null; } export interface EmoteSpatialLookup { inRadius(center: readonly [number, number, number], radius: number, filter?: (id: string) => boolean): readonly string[]; } export interface EmotesDeps { entities: EmoteEntityLookup; spatial: EmoteSpatialLookup; } export interface SocialDeps { events: GameEvents; presence?: (userId: string) => PresenceInfo; now?: () => number; emotes?: EmotesDeps; worldInviteTtlMs?: number; } export interface FriendEntry { userId: string; online: boolean; } export interface FriendsSnapshot { friends: string[]; blocked: string[]; } export interface FriendRequestEntry { requestId: string; fromUserId: string; } export interface Friends { canRequest(fromUserId: string, toUserId: string): { reason: string; } | null; request(fromUserId: string, toUserId: string): { requestId: string; } | { reason: string; }; accept(userId: string, requestId: string): { reason: string; } | null; decline(userId: string, requestId: string): void; remove(userId: string, friendUserId: string): void; block(userId: string, targetUserId: string): void; list(userId: string): FriendEntry[]; requestsFor(userId: string): FriendRequestEntry[]; snapshot(userId: string): FriendsSnapshot; hydrate(userId: string, data: FriendsSnapshot): void; } export type PartyRole = "leader" | "member"; export interface PartyMemberEntry { userId: string; role: PartyRole; } export interface PartyConfig { maxMembers: number; inviteTtlMs?: number; } export interface PartyInviteEntry { inviteId: string; fromUserId: string; createdAt: number; } export interface Party { register(config: PartyConfig): void; canInvite(fromUserId: string, toUserId: string): { reason: string; } | null; invite(fromUserId: string, toUserId: string): { inviteId: string; } | { reason: string; }; accept(userId: string, inviteId: string): { reason: string; } | null; decline(userId: string, inviteId: string): void; kick(leaderUserId: string, memberUserId: string): { reason: string; } | null; leave(userId: string): void; promote(leaderUserId: string, memberUserId: string): { reason: string; } | null; list(userId: string): PartyMemberEntry[]; membersOf(userId: string): string[]; invitesFor(userId: string): PartyInviteEntry[]; } export declare const DEFAULT_EMOTE_RADIUS = 20; export interface EmoteBroadcastResult { from: string; emoteId: string; at: readonly [number, number, number]; recipients: readonly string[]; } export interface Emotes { play(fromUserId: string, emoteId: string, radius?: number): EmoteBroadcastResult | { reason: string; }; } export interface WorldInviteTarget { serverId: string; joinCode?: string; } export interface WorldInvite extends WorldInviteTarget { id: string; fromUserId: string; toUserId: string; createdAt: number; } export interface WorldInvites { canInvite(fromUserId: string, toUserId: string): { reason: string; } | null; invite(fromUserId: string, toUserId: string, target: WorldInviteTarget): { inviteId: string; } | { reason: string; }; accept(userId: string, inviteId: string): { target: WorldInviteTarget; } | { reason: string; }; decline(userId: string, inviteId: string): void; listFor(userId: string): WorldInvite[]; } /** One party's replicated membership — id, current leader, and ordered member ids. */ export interface SocialPartySnapshot { id: string; leader: string; members: string[]; } /** * Full friends/party/world-invite state as one serializable baseline — the host→client replication * payload behind the `social` snapshot module. Presence and emotes are derived from live deps, not stored. */ export interface SocialSnapshot { friendships: Record; blocked: Record; friendRequests: Record; requestCounter: number; partyConfig: PartyConfig | null; parties: SocialPartySnapshot[]; partyInvites: Record; partyCounter: number; inviteCounter: number; worldInvites: WorldInvite[]; worldInviteCounter: number; } export interface Social { friends: Friends; party: Party; presence: { get(userId: string): PresenceInfo; }; emotes: Emotes; worldInvites: WorldInvites; snapshot(): SocialSnapshot; hydrate(data: SocialSnapshot): void; } /** * Emotes and lightweight social interactions between nearby players. * * @capability social-emotes emotes and social interactions between nearby players */ export declare function createSocial(deps: SocialDeps): Social;