DeltaVR/Assets/Fish-Networking-Discovery-main/NetworkDiscoveryCanvasUI.cs

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);
}
}
}