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 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 foundServers = new(); private void Start() { if (networkDiscovery == null) networkDiscovery = FindObjectOfType(); _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(); if (xr != null) { Debug.Log("Found my XR Origin player."); TutorialController tutorial = xr.GetComponent(); 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(); if (label != null) label.text = endPoint.Address.ToString(); Button btn = item.GetComponent