XRoom_Unity/Assets/Photon/FusionAddons/ConnectionManager/Scripts/ConnectionManager.cs

460 lines
18 KiB
C#

using BNG;
using Fusion.Sockets;
using Fusion.XR.Host.Rig;
using Photon.Realtime;
using System;
using System.Collections.Generic;
using System.Security.Policy;
using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
using static Unity.Collections.Unicode;
namespace Fusion.Addons.ConnectionManagerAddon
{
/**
*
* Handles:
* - connection launch (either with room name or matchmaking session properties)
* - user representation spawn on connection
**/
public class ConnectionManager : MonoBehaviour, INetworkRunnerCallbacks
{
public GameObject[] chairs;
public bool presentation;
public GameObject Loading;
[System.Flags]
public enum ConnectionCriterias
{
RoomName = 1,
SessionProperties = 2
}
public Transform itemPos;
[System.Serializable]
public struct StringSessionProperty
{
public string propertyName;
public string value;
}
public void Update()
{
if (Application.loadedLevelName.Equals("Lobby"))
Destroy(gameObject);
if (Input.GetKeyDown(KeyCode.I))
{
FusionRig.instance.transform.position = usersPlace[0].transform.position;
}
if (runner.IsConnectedToServer&&presentation&&!PlayerTeleport.instance.chair&&runner.LocalPlayer.PlayerId>1)
{
chairs[runner.LocalPlayer.PlayerId].GetComponent<Chair>().SetSit();
}
Loading.gameObject.SetActive(!runner||! runner.IsConnectedToServer);
}
[Header("Room configuration")]
public GameMode gameMode = GameMode.Shared;
public string roomName = "SampleFusion";
public bool connectOnStart = true;
[Tooltip("Set it to 0 to use the DefaultPlayers value, from the Global NetworkProjectConfig (simulation section)")]
public int playerCount = 0;
public static ConnectionManager instance;
[Header("Room selection criteria")]
public ConnectionCriterias connectionCriterias = ConnectionCriterias.RoomName;
[Tooltip("If connectionCriterias include SessionProperties, additionalSessionProperties (editable in the inspector) will be added to sessionProperties")]
public List<StringSessionProperty> additionalSessionProperties = new List<StringSessionProperty>();
public Dictionary<string, SessionProperty> sessionProperties;
[Header("Fusion settings")]
[Tooltip("Fusion runner. Automatically created if not set")]
public NetworkRunner runner;
public INetworkSceneManager sceneManager;
//[Header("Local user spawner")]
// public NetworkObject userPrefab;
public NetworkObject whiteboardPrefab;
[Header("Event")]
public UnityEvent onWillConnect = new UnityEvent();
[Header("Info")]
public List<StringSessionProperty> actualSessionProperties = new List<StringSessionProperty>();
// Dictionary of spawned user prefabs, to store them on the server for host topology, and destroy them on disconnection (for shared topology, use Network Objects's "Destroy When State Authority Leaves" option)
private Dictionary<PlayerRef, NetworkObject> _spawnedUsers = new Dictionary<PlayerRef, NetworkObject>();
bool ShouldConnectWithRoomName => (connectionCriterias & ConnectionManager.ConnectionCriterias.RoomName) != 0;
bool ShouldConnectWithSessionProperties => (connectionCriterias & ConnectionManager.ConnectionCriterias.SessionProperties) != 0;
private void Awake()
{
if (!EN.instance)
{
//Application.LoadLevel(0);
Destroy(gameObject);
return;
}
// Check if a runner exist on the same game object
if (runner == null) runner = GetComponent<NetworkRunner>();
instance = this;
// Create the Fusion runner and let it know that we will be providing user input
if (runner == null) runner = gameObject.AddComponent<NetworkRunner>();
runner.ProvideInput = true;
}
public void createChairs()
{
for (int i = 0; i < chairs.Length; i++)
{
chairs[i].GetComponent<Chair>().enabled = true;
chairs[i].GetComponentInChildren<VRCanvas>().enabled = true;
}
}
private async void Start()
{
chairs = GameObject.FindGameObjectsWithTag("chair");
//Invoke("createChairs", 5);
PlaySound("intro");
// Launch the connection at start
if (connectOnStart) await Connect();
}
Dictionary<string, SessionProperty> AllConnectionSessionProperties
{
get
{
var propDict = new Dictionary<string, SessionProperty>();
actualSessionProperties = new List<StringSessionProperty>();
if (sessionProperties != null)
{
foreach (var prop in sessionProperties)
{
propDict.Add(prop.Key, prop.Value);
actualSessionProperties.Add(new StringSessionProperty { propertyName = prop.Key, value = prop.Value });
}
}
if (additionalSessionProperties != null)
{
foreach (var additionalProperty in additionalSessionProperties)
{
propDict[additionalProperty.propertyName] = additionalProperty.value;
actualSessionProperties.Add(additionalProperty);
}
}
return propDict;
}
}
public Transform pos;
public virtual NetworkSceneInfo CurrentSceneInfo()
{
var activeScene = SceneManager.GetActiveScene();
SceneRef sceneRef = default;
if (activeScene.buildIndex < 0 || activeScene.buildIndex >= SceneManager.sceneCountInBuildSettings)
{
Debug.LogError("Current scene is not part of the build settings");
}
else
{
sceneRef = SceneRef.FromIndex(activeScene.buildIndex);
}
var sceneInfo = new NetworkSceneInfo();
if (sceneRef.IsValid)
{
sceneInfo.AddSceneRef(sceneRef, LoadSceneMode.Single);
}
return sceneInfo;
}
public async Task Connect()
{
// Create the scene manager if it does not exist
if (sceneManager == null) sceneManager = gameObject.AddComponent<NetworkSceneManagerDefault>();
if (onWillConnect != null) onWillConnect.Invoke();
// Start or join (depends on gamemode) a session with a specific name
var args = new StartGameArgs()
{
GameMode = gameMode,
Scene = CurrentSceneInfo(),
SceneManager = sceneManager
};
// Connection criteria
if (ShouldConnectWithRoomName)
{
args.SessionName = roomName;
}
if (ShouldConnectWithSessionProperties)
{
args.SessionProperties = AllConnectionSessionProperties;
}
// Room details
if (playerCount > 0)
{
args.PlayerCount = playerCount;
}
await runner.StartGame(args);
string prop = "";
if (runner.SessionInfo.Properties != null && runner.SessionInfo.Properties.Count > 0)
{
prop = "SessionProperties: ";
foreach (var p in runner.SessionInfo.Properties) prop += $" ({p.Key}={p.Value.PropertyValue}) ";
}
Debug.Log($"Session info: Room name {runner.SessionInfo.Name}. Region: {runner.SessionInfo.Region}. {prop}");
if ((connectionCriterias & ConnectionManager.ConnectionCriterias.RoomName) == 0)
{
roomName = runner.SessionInfo.Name;
}
}
#region Player spawn
public void OnPlayerJoinedSharedMode(NetworkRunner runner, PlayerRef player)
{
if (player == runner.LocalPlayer)
{
// Spawn the user prefab for the local user
// pos.transform.position = usersPlace[runner.SessionInfo.PlayerCount - 1].transform.position;
// NetworkObject networkPlayerObject = runner.Spawn(EN.instance.SelectedUser.character, position: pos.transform.position, rotation: transform.rotation, player, (runner, obj) => {
// });
}
}
NetworkObject laser,marker, tablet;
public NetworkObject Marker;
public NetworkObject Tablet;
public NetworkObject Laser;
public NetworkObject spark;
internal void CreateTablet(Transform trans)
{
if (tablet)
runner.Despawn(tablet);
// if (marker)
// runner.Despawn(marker);
//if (marker)
// runner.Despawn(marker);
//if (laser)
// runner.Despawn(laser);
tablet = runner.Spawn(Tablet, position: itemPos.position, rotation: itemPos.rotation, inputAuthority: runner.LocalPlayer, (runner, obj) => {
// obj.GetComponent<MarkerNetwork>().DrawColor = color;
});
}
internal void CreateLaser(Transform trans)
{
//if (ereaser)
// runner.Despawn(ereaser);
//if (marker)
// runner.Despawn(marker);
if (laser)
runner.Despawn(laser);
laser = runner.Spawn(Laser, position: (trans.transform.position + new Vector3(0, 0, .0f)), rotation: trans.rotation, inputAuthority: runner.LocalPlayer, (runner, obj) => {
// obj.GetComponent<MarkerNetwork>().DrawColor = color;
});
} internal void CreateSpark(NetworkObject item,Transform trans)
{
//if (ereaser)
// runner.Despawn(ereaser);
//if (marker)
// runner.Despawn(marker);
if (spark)
runner.Despawn(spark);
spark = runner.Spawn(item, position: (trans.transform.position + new Vector3(0, 0, .0f)), rotation: trans.rotation, inputAuthority: runner.LocalPlayer, (runner, obj) => {
// obj.GetComponent<MarkerNetwork>().DrawColor = color;
});
}
internal void CreateImage(Transform trans, NetworkObject obj,string url)
{
runner.Spawn(obj, position: (trans.transform.position + new Vector3(0, 0, .0f)), rotation: trans.rotation, inputAuthority: runner.LocalPlayer, (runner, obj) => {
obj.GetComponent<ImagePlayer>().Show(url);
});
}
internal void CreateVideo(Transform trans, NetworkObject obj,string url)
{
runner.Spawn(obj, position: (trans.transform.position + new Vector3(0, 0, .0f)), rotation: trans.rotation, inputAuthority: runner.LocalPlayer, (runner, obj) => {
obj.GetComponent<VideoPlayerManager>().Show(url);
});
}
internal void CreateMarker(Transform trans, Color color)
{
if (marker)
runner.Despawn(marker);
marker = runner.Spawn(Marker, position: (trans.transform.position + new Vector3(0, 0, .0f)), rotation: trans.rotation, inputAuthority: runner.LocalPlayer, (runner, obj) => {
obj.GetComponent<MarkerNetwork>().DrawColor = color;
});
}
public NetworkObject networkPlayerObject;
public void OnPlayerJoinedHostMode(NetworkRunner runner, PlayerRef player)
{
if (player != runner.LocalPlayer)
return;
// The user's prefab has to be spawned by the host
pos.transform.position = usersPlace[runner.SessionInfo.PlayerCount - 1].transform.position;
// We make sure to give the input authority to the connecting player for their user's object
if ( EN.instance.SelectedUser.character != null)
{
Debug.Log($"OnPlayerJoined. PlayerId: {player.PlayerId}" + usersPlace[runner.SessionInfo.PlayerCount - 1].transform.position.ToString());
networkPlayerObject = runner.Spawn(EN.instance.Me.character, position: pos.position, rotation: transform.rotation, inputAuthority: player, (runner, obj) => {
obj.GetComponent<playerManager>().player = player;
// obj.GetComponent<playerManager>().RPC_RequestCharacterSpawn(player);
});
// Keep track of the player avatars so we can remove it when they disconnect
_spawnedUsers.Add(player, networkPlayerObject);
}
if (player.PlayerId == runner.LocalPlayer.PlayerId)
FusionRig.instance.transform.position = pos.position;
}
// Despawn the user object upon disconnection
public void OnPlayerLeftHostMode(NetworkRunner runner, PlayerRef player)
{
// Find and remove the players avatar (only the host would have stored the spawned game object)
if (_spawnedUsers.TryGetValue(player, out NetworkObject networkObject))
{
runner.Despawn(networkObject);
_spawnedUsers.Remove(player);
}
}
// public GameObject[] users;
#endregion
#region INetworkRunnerCallbacks
public void OnPlayerJoined(NetworkRunner runner, PlayerRef player)
{
print(player.PlayerId + "==" + runner.LocalPlayer.PlayerId + "," + runner.SessionInfo.PlayerCount);
// if ((runner.SessionInfo.PlayerCount == 1) && player.PlayerId == runner.LocalPlayer.PlayerId)
// whiteboard = runner.Spawn(whiteboardPrefab, position: wbPostion.position,
// rotation: wbPostion.rotation);
// if (runner.Topology == Topologies.ClientServer)
{
OnPlayerJoinedHostMode(runner, player);
}
// else
{
// OnPlayerJoinedSharedMode(runner, player);
}
}
public void OnPlayerLeft(NetworkRunner runner, PlayerRef player)
{
if (runner.Topology == Topologies.ClientServer)
{
OnPlayerLeftHostMode(runner, player);
}
}
NetworkObject whiteboard;
public Transform wbPostion;
public Transform[] usersPlace;
#endregion
#region INetworkRunnerCallbacks (debug log only)
public void OnConnectedToServer(NetworkRunner runner)
{
Debug.Log("OnConnectedToServer:" + runner.IsServer);
}
public void OnShutdown(NetworkRunner runner, ShutdownReason shutdownReason)
{
Debug.Log("Shutdown: " + shutdownReason);
//Application.LoadLevel(0);
}
public void OnDisconnectedFromServer(NetworkRunner runner, NetDisconnectReason reason)
{
Debug.Log("OnDisconnectedFromServer: " + reason);
Application.LoadLevel(0);
}
public void OnConnectFailed(NetworkRunner runner, NetAddress remoteAddress, NetConnectFailedReason reason)
{
Debug.Log("OnConnectFailed: " + reason);
Application.LoadLevel(0);
}
#endregion
#region Unused INetworkRunnerCallbacks
public void OnInput(NetworkRunner runner, NetworkInput input) { }
public void OnInputMissing(NetworkRunner runner, PlayerRef player, NetworkInput input) { }
public void OnConnectRequest(NetworkRunner runner, NetworkRunnerCallbackArgs.ConnectRequest request, byte[] token) { }
public void OnUserSimulationMessage(NetworkRunner runner, SimulationMessagePtr message) { }
public void OnSessionListUpdated(NetworkRunner runner, List<SessionInfo> sessionList) { }
public void OnCustomAuthenticationResponse(NetworkRunner runner, Dictionary<string, object> data) { }
public void OnHostMigration(NetworkRunner runner, HostMigrationToken hostMigrationToken) { }
public void OnReliableDataReceived(NetworkRunner runner, PlayerRef player, ArraySegment<byte> data) { }
public void OnSceneLoadDone(NetworkRunner runner) { }
public void OnSceneLoadStart(NetworkRunner runner) { }
public void OnObjectExitAOI(NetworkRunner runner, NetworkObject obj, PlayerRef player) { }
public void OnObjectEnterAOI(NetworkRunner runner, NetworkObject obj, PlayerRef player) { }
public void OnReliableDataReceived(NetworkRunner runner, PlayerRef player, ReliableKey key, ArraySegment<byte> data) { }
public void OnReliableDataProgress(NetworkRunner runner, PlayerRef player, ReliableKey key, float progress) { }
#endregion
public void PlaySound(string soundName,float volume=1f)
{
// بارگذاری صدا از پوشه Resources
AudioClip clip = Resources.Load<AudioClip>("sounds/" + soundName);
if (clip != null)
{
// ایجاد یک GameObject جدید برای پخش صدا
GameObject audioObject = new GameObject("AudioSource_" + soundName);
AudioSource audioSource = audioObject.AddComponent<AudioSource>();
audioSource.volume = volume;
audioSource.spatialBlend = 1;
// تنظیم clip و پخش صدا
audioSource.clip = clip;
audioSource.Play();
// حذف GameObject بعد از پایان صدا
Destroy(audioObject, clip.length);
}
else
{
Debug.LogError("Sound not found: " + soundName);
}
}
internal void CreateImage(Transform trans, NetworkObject obj, RawImage rawImage)
{
runner.Spawn(obj, position: (trans.transform.position + new Vector3(0, 0, .0f)), rotation: trans.rotation, inputAuthority: runner.LocalPlayer, (runner, obj) => {
obj.GetComponent<ImagePlayer>().Show(rawImage);
});
}
}
}