File size: 3,033 Bytes
811126d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
import { useEffect, useRef } from "react";
import { io, Socket } from "socket.io-client";

export function useGameSocket(gameId: string) {
  const socketRef = useRef<Socket | null>(null);
  const peerConnectionRef = useRef<RTCPeerConnection | null>(null);

  useEffect(() => {
    // Connexion au serveur de jeu
    socketRef.current = io("http://localhost:5001", {
      path: "/",
      query: { gameId },
    });

    // Configuration WebRTC
    const configuration = {
      iceServers: [{ urls: "stun:stun.l.google.com:19302" }],
    };
    peerConnectionRef.current = new RTCPeerConnection(configuration);

    // Gestion des événements Socket.IO
    socketRef.current.on("offer", async (offer: RTCSessionDescriptionInit) => {
      if (!peerConnectionRef.current) return;
      await peerConnectionRef.current.setRemoteDescription(
        new RTCSessionDescription(offer)
      );
      const answer = await peerConnectionRef.current.createAnswer();
      await peerConnectionRef.current.setLocalDescription(answer);
      socketRef.current?.emit("answer", answer);
    });

    socketRef.current.on(
      "answer",
      async (answer: RTCSessionDescriptionInit) => {
        if (!peerConnectionRef.current) return;
        await peerConnectionRef.current.setRemoteDescription(
          new RTCSessionDescription(answer)
        );
      }
    );

    socketRef.current.on(
      "candidate",
      async (candidate: RTCIceCandidateInit) => {
        if (!peerConnectionRef.current) return;
        await peerConnectionRef.current.addIceCandidate(
          new RTCIceCandidate(candidate)
        );
      }
    );

    // Gestion des candidats ICE
    peerConnectionRef.current.onicecandidate = (event) => {
      if (event.candidate) {
        socketRef.current?.emit("candidate", event.candidate);
      }
    };

    // Nettoyage à la déconnexion
    return () => {
      if (socketRef.current) {
        socketRef.current.disconnect();
      }
      if (peerConnectionRef.current) {
        peerConnectionRef.current.close();
      }
    };
  }, [gameId]);

  // Fonction pour démarrer un appel
  const startCall = async (stream: MediaStream) => {
    if (!peerConnectionRef.current || !socketRef.current) return;

    // Ajout du flux audio local
    stream.getTracks().forEach((track) => {
      if (!peerConnectionRef.current) return;
      peerConnectionRef.current.addTrack(track, stream);
    });

    // Création et envoi de l'offre
    const offer = await peerConnectionRef.current.createOffer();
    await peerConnectionRef.current.setLocalDescription(offer);
    socketRef.current.emit("offer", offer);
  };

  // Fonction pour recevoir l'audio
  const handleIncomingAudio = (onTrack: (stream: MediaStream) => void) => {
    if (!peerConnectionRef.current) return;

    peerConnectionRef.current.ontrack = (event) => {
      onTrack(event.streams[0]);
    };
  };

  return {
    startCall,
    handleIncomingAudio,
    socket: socketRef.current,
    peerConnection: peerConnectionRef.current,
  };
}