forked from cgvr/DeltaVR
		
	
		
			
				
	
	
		
			258 lines
		
	
	
		
			8.1 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			258 lines
		
	
	
		
			8.1 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
using _PROJECT.NewHandPresence;
 | 
						|
using FishNet;
 | 
						|
using FishNet.Discovery;
 | 
						|
using FishNet.Managing.Scened;
 | 
						|
using FishNet.Object;
 | 
						|
using System.Collections;
 | 
						|
using System.Collections.Concurrent;
 | 
						|
using System.Collections.Generic;
 | 
						|
using System.Net;
 | 
						|
using TMPro;
 | 
						|
using Unity.XR.CoreUtils;
 | 
						|
using UnityEngine;
 | 
						|
using UnityEngine.UI;
 | 
						|
 | 
						|
public class NetworkMenuUI : MonoBehaviour
 | 
						|
{
 | 
						|
 | 
						|
 | 
						|
    private ConcurrentQueue<System.Action> mainThreadQueue = new();
 | 
						|
    [Header("UI References")]
 | 
						|
    public Toggle VRToggle;
 | 
						|
   
 | 
						|
    public Button startPlayingButton;
 | 
						|
    public Button reloadButton;
 | 
						|
    public Button joinMultiplayerButton;
 | 
						|
    public Transform serverListContainer;
 | 
						|
    public GameObject serverListItemPrefab;
 | 
						|
    public TMP_Text statusText;
 | 
						|
    public Button quitButton;
 | 
						|
 | 
						|
    [Header("Networking")]
 | 
						|
    public NetworkDiscovery networkDiscovery;
 | 
						|
    public Camera uiCamera;
 | 
						|
    public AudioListener placeholderAudioListener;
 | 
						|
    private bool _useVR;
 | 
						|
    
 | 
						|
    //public Image coverImage;
 | 
						|
 | 
						|
    private readonly List<IPEndPoint> foundServers = new();
 | 
						|
 | 
						|
    private void Start()
 | 
						|
    {
 | 
						|
 | 
						|
        if (networkDiscovery == null)
 | 
						|
            networkDiscovery = FindObjectOfType<NetworkDiscovery>();
 | 
						|
 | 
						|
        _useVR = PlayerPrefs.GetInt("UseVR", 0) == 1;
 | 
						|
        VRToggle.isOn = _useVR;
 | 
						|
 | 
						|
        // React to UI toggle changes
 | 
						|
        VRToggle.onValueChanged.AddListener((isOn) =>
 | 
						|
        {
 | 
						|
            _useVR = isOn;
 | 
						|
            PlayerPrefs.SetInt("UseVR", _useVR ? 1 : 0);
 | 
						|
            PlayerPrefs.Save();
 | 
						|
            Debug.Log($"UseVR set to {_useVR}");
 | 
						|
        });
 | 
						|
 | 
						|
        startPlayingButton.onClick.AddListener(OnStartPlaying);
 | 
						|
        reloadButton.onClick.AddListener(OnReload);
 | 
						|
        joinMultiplayerButton.onClick.AddListener(OnJoinMultiplayer);
 | 
						|
        quitButton.onClick.AddListener(OnQuit);
 | 
						|
 | 
						|
        networkDiscovery.ServerFoundCallback += (endPoint) =>
 | 
						|
        {
 | 
						|
            Debug.Log("Found a server");
 | 
						|
            // Only queue the endpoint for main-thread processing
 | 
						|
            mainThreadQueue.Enqueue(() =>
 | 
						|
            {
 | 
						|
                StartCoroutine(ProcessServerFound(endPoint));
 | 
						|
            });
 | 
						|
        };
 | 
						|
    }
 | 
						|
    private void Update()
 | 
						|
    {
 | 
						|
        while (mainThreadQueue.TryDequeue(out var action))
 | 
						|
        {
 | 
						|
            action.Invoke(); // safely runs on main thread
 | 
						|
        }
 | 
						|
    }
 | 
						|
    private void OnStartPlaying()
 | 
						|
    {
 | 
						|
        statusText.text = "Starting host...";
 | 
						|
        StartCoroutine(HostAndSearchRoutine());
 | 
						|
    }
 | 
						|
 | 
						|
 | 
						|
    private void OnReload()
 | 
						|
    {
 | 
						|
        /*if (!InstanceFinder.IsClient)
 | 
						|
        {
 | 
						|
            Debug.LogWarning("Reload can only be called from a client!");
 | 
						|
            return;
 | 
						|
        }
 | 
						|
 | 
						|
        // Use the ClientManager.Objects dictionary
 | 
						|
        foreach (NetworkObject obj in InstanceFinder.ClientManager.Objects.)
 | 
						|
        {
 | 
						|
            if (obj.IsOwner) // This ensures it's YOUR local player
 | 
						|
            {
 | 
						|
                var xr = obj.GetComponentInChildren<XROrigin>();
 | 
						|
                if (xr != null)
 | 
						|
                {
 | 
						|
                    Debug.Log("Found my XR Origin player.");
 | 
						|
 | 
						|
                    TutorialController tutorial = xr.GetComponent<TutorialController>();
 | 
						|
                    if (tutorial != null)
 | 
						|
                    {
 | 
						|
                        tutorial._state = TutorialController.TutorialState.Initializing;
 | 
						|
                    }
 | 
						|
                }
 | 
						|
                else
 | 
						|
                {
 | 
						|
                    Debug.Log("My local player is not an XR Origin.");
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }*/
 | 
						|
    }
 | 
						|
 | 
						|
    private void OnJoinMultiplayer()
 | 
						|
    {
 | 
						|
        statusText.text = "Searching for servers...";
 | 
						|
        networkDiscovery.StopSearchingForServers();
 | 
						|
        ClearServerList();
 | 
						|
        //Debug.Log(foundServers.Count);
 | 
						|
        foundServers.Clear();
 | 
						|
        //Debug.Log(foundServers.Count);
 | 
						|
        networkDiscovery.StartSearchingForServers();
 | 
						|
    }
 | 
						|
 | 
						|
    private void OnQuit()
 | 
						|
    {
 | 
						|
        Debug.Log("Quitting application");
 | 
						|
        Application.Quit();
 | 
						|
    }
 | 
						|
 | 
						|
    private IEnumerator ProcessServerFound(IPEndPoint endPoint)
 | 
						|
    {
 | 
						|
        Debug.Log("server found");
 | 
						|
        //Debug.Log(endPoint.Address.ToString());
 | 
						|
        //Debug.Log(foundServers.Count);
 | 
						|
        if (foundServers.Contains(endPoint)) yield return null;
 | 
						|
        foundServers.Add(endPoint);
 | 
						|
 | 
						|
            Debug.Log($"Server found {endPoint}");
 | 
						|
            // Auto-join if started as host
 | 
						|
            if (InstanceFinder.IsServer)
 | 
						|
            {
 | 
						|
                Debug.Log("Server is local");
 | 
						|
                //networkDiscovery.StopAdvertisingServer();
 | 
						|
                networkDiscovery.StopSearchingForServers();
 | 
						|
 | 
						|
                uiCamera.enabled = false;
 | 
						|
                Debug.Log("Disabled placeholder audio source");
 | 
						|
                placeholderAudioListener.enabled = false;
 | 
						|
                //coverImage.gameObject.SetActive(false);
 | 
						|
 | 
						|
                InstanceFinder.ClientManager.StartConnection(endPoint.Address.ToString());
 | 
						|
                statusText.text = $"Joined server: {endPoint.Address}";
 | 
						|
                yield return null;
 | 
						|
            }
 | 
						|
            
 | 
						|
            Debug.Log("Server is foregin");
 | 
						|
            GameObject item = Instantiate(serverListItemPrefab, serverListContainer);
 | 
						|
 | 
						|
            
 | 
						|
 | 
						|
            TMP_Text label = item.GetComponentInChildren<TMP_Text>();
 | 
						|
            if (label != null)
 | 
						|
                label.text = endPoint.Address.ToString();
 | 
						|
 | 
						|
            Button btn = item.GetComponent<Button>();
 | 
						|
            btn.onClick.RemoveAllListeners(); // clear any old listener
 | 
						|
            btn.onClick.AddListener(() =>
 | 
						|
            {
 | 
						|
                networkDiscovery.StopSearchingForServers();
 | 
						|
                if (uiCamera != null) uiCamera.enabled = false;
 | 
						|
                if (placeholderAudioListener != null)
 | 
						|
                {
 | 
						|
                    Debug.Log("Disabled placeholder audio source");
 | 
						|
                    placeholderAudioListener.enabled = false;
 | 
						|
                }
 | 
						|
                //coverImage.gameObject.SetActive(false);
 | 
						|
                InstanceFinder.ClientManager.StartConnection(endPoint.Address.ToString());
 | 
						|
                statusText.text = $"Joined server: {endPoint.Address}";
 | 
						|
            });
 | 
						|
        
 | 
						|
    }
 | 
						|
    private Coroutine joinRoutine;
 | 
						|
 | 
						|
    private IEnumerator HostAndSearchRoutine()
 | 
						|
    {
 | 
						|
        // Step 1: Start hosting
 | 
						|
        InstanceFinder.ServerManager.StartConnection();
 | 
						|
 | 
						|
        // Step 2: Start advertising
 | 
						|
        yield return new WaitForSeconds(0.5f); // Let the server settle
 | 
						|
        networkDiscovery.StartAdvertisingServer();
 | 
						|
 | 
						|
        // Step 3: Begin searching
 | 
						|
        yield return new WaitForSeconds(0.5f); // Let advertisement initialize
 | 
						|
        networkDiscovery.StartSearchingForServers();
 | 
						|
 | 
						|
        // Step 4: Try to find and join a better server
 | 
						|
        yield return new WaitForSeconds(0.5f); // Give discovery a moment
 | 
						|
        StartJoinRoutine();
 | 
						|
    }
 | 
						|
 | 
						|
 | 
						|
    public void StartJoinRoutine()
 | 
						|
    {
 | 
						|
        if (joinRoutine != null) StopCoroutine(joinRoutine);
 | 
						|
        joinRoutine = StartCoroutine(TryJoinServerRepeatedly());
 | 
						|
    }
 | 
						|
 | 
						|
    private IEnumerator TryJoinServerRepeatedly()
 | 
						|
    {
 | 
						|
        float timeout = 10f;
 | 
						|
        float timer = 0f;
 | 
						|
 | 
						|
        while (timer < timeout)
 | 
						|
        {
 | 
						|
            if (foundServers.Count > 0)
 | 
						|
            {
 | 
						|
                var firstServer = foundServers[0];
 | 
						|
                //networkDiscovery.StopAdvertisingServer();
 | 
						|
                if (uiCamera != null) uiCamera.enabled = false;
 | 
						|
                if (placeholderAudioListener != null)
 | 
						|
                {
 | 
						|
                    Debug.Log("Disabled placeholder audio source");
 | 
						|
                    placeholderAudioListener.enabled = false;
 | 
						|
                }
 | 
						|
                networkDiscovery.StopSearchingForServers();
 | 
						|
                InstanceFinder.ClientManager.StartConnection(firstServer.Address.ToString());
 | 
						|
                statusText.text = $"Joined server: {firstServer.Address}";
 | 
						|
                //coverImage.gameObject.SetActive(false);
 | 
						|
                yield break;
 | 
						|
            }
 | 
						|
 | 
						|
            statusText.text = $"Searching for servers... ({Mathf.FloorToInt(timer)}s)";
 | 
						|
            yield return new WaitForSeconds(1f);
 | 
						|
            timer += 1f;
 | 
						|
        }
 | 
						|
 | 
						|
 | 
						|
        statusText.text = "No servers found. Acting as host.";
 | 
						|
        // You can optionally start your own server here
 | 
						|
    }
 | 
						|
 | 
						|
    private void ClearServerList()
 | 
						|
    {
 | 
						|
        foreach (Transform child in serverListContainer)
 | 
						|
        {
 | 
						|
            Destroy(child.gameObject);
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 |