Files
UltimateFishing2020/Assets/Scripts/Assembly-CSharp/MultiplayerFishSpawner.cs
2026-03-04 10:03:45 +08:00

467 lines
14 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using ExitGames.Client.Photon;
using Photon.Pun;
using Photon.Realtime;
using ShiningGames.UFS2;
using UFS2.Gameplay;
using UnityEngine;
public class MultiplayerFishSpawner : MonoBehaviour, IOnEventCallback
{
public class NetworkedFish
{
public string guid;
public int fishID;
public float fishWeight;
public FishEntity fishEntity;
public Vector3 position;
public int targetAreaID;
public int actorInControl;
public MultiplayerFishEntity multiplayerFishEntity;
public Guid Guid => new Guid(guid);
public NetworkedFish(string guid, int fishID, float fishWeight)
{
this.guid = guid;
this.fishID = fishID;
this.fishWeight = fishWeight;
fishEntity = null;
position = Vector3.zero;
targetAreaID = 0;
actorInControl = -1;
multiplayerFishEntity = null;
}
}
public static MultiplayerFishSpawner Instance;
[SerializeField]
[Tooltip("Delay in seconds between sending fish synchronization packets to slave clients")]
[Range(0f, 1f)]
private float fishSyncDelay = 0.2f;
[SerializeField]
[Tooltip("Number of fishes contained in one synchronization packet")]
[Range(1f, 30f)]
private int fishSyncCount = 3;
[SerializeField]
private MultiplayerFishEntity multiplayerFishEntity_prefab;
private List<NetworkedFish> networkedFishList;
private Coroutine fishSyncCoroutine;
public static bool IsOnline => GetIsOnline();
public static bool IsMaster => GetIsMaster();
public static bool IsSlave => GetIsSlave();
public static event Action<NetworkedFish> OnNetworkedFishSpawn;
public static event Action<NetworkedFish> OnNetworkedFishDelete;
public static event Action OnFishDeleteAfterInteraction;
public static bool GetIsOnline()
{
if (Instance != null)
{
return MultiplayerManager.InRoomLocationStatic;
}
return false;
}
public static bool GetIsMaster()
{
bool result = false;
if (GetIsOnline())
{
result = PhotonNetwork.IsMasterClient;
}
return result;
}
public static bool GetIsSlave()
{
bool result = false;
if (GetIsOnline())
{
result = !PhotonNetwork.IsMasterClient;
}
return result;
}
public static void CheckFishInteractionWithPlayer(FishEntity fishEntity, out bool withLocalPlayer, out bool withRemotePlayer)
{
withLocalPlayer = false;
withRemotePlayer = false;
NetworkedFish networkedFish = GetNetworkedFish(fishEntity);
if (networkedFish?.multiplayerFishEntity != null)
{
PhotonView photonView = networkedFish.multiplayerFishEntity.photonView;
withLocalPlayer = photonView.IsMine;
withRemotePlayer = !photonView.IsMine;
}
}
public static bool CheckFishInteractionWithPlayer(FishEntity fishEntity)
{
return GetNetworkedFish(fishEntity)?.multiplayerFishEntity != null;
}
public static NetworkedFish GetNetworkedFish(FishEntity fishEntity)
{
NetworkedFish result = null;
if (Instance != null && Instance.networkedFishList != null)
{
result = Instance.networkedFishList.FirstOrDefault((NetworkedFish fish) => fish.fishEntity == fishEntity);
}
return result;
}
public static NetworkedFish GetNetworkedFish(string guid)
{
NetworkedFish result = null;
if (Instance != null && Instance.networkedFishList != null)
{
result = Instance.networkedFishList.FirstOrDefault((NetworkedFish fish) => fish.guid == guid);
}
return result;
}
public static void FishControlRequest(FishEntity fishEntity)
{
NetworkedFish networkedFish = GetNetworkedFish(fishEntity);
PhotonNetwork.RaiseEvent(2, new object[1] { networkedFish.Guid.ToByteArray() }, new RaiseEventOptions
{
Receivers = ReceiverGroup.MasterClient
}, SendOptions.SendReliable);
}
public static void FishControlRequestCancel(FishEntity fishEntity)
{
NetworkedFish networkedFish = GetNetworkedFish(fishEntity);
PhotonNetwork.RaiseEvent(3, new object[1] { networkedFish.Guid.ToByteArray() }, new RaiseEventOptions
{
Receivers = ReceiverGroup.MasterClient
}, SendOptions.SendReliable);
}
public static MultiplayerFishEntity SpawnMultiplayerFishEntity(FishEntity fishEntity)
{
MultiplayerFishEntity multiplayerFishEntity = null;
NetworkedFish networkedFish = GetNetworkedFish(fishEntity);
if (!CheckFishInteractionWithPlayer(fishEntity) && networkedFish.actorInControl == PhotonNetwork.LocalPlayer.ActorNumber)
{
multiplayerFishEntity = PhotonNetwork.Instantiate(Instance.multiplayerFishEntity_prefab.name, fishEntity.transform.position, fishEntity.transform.rotation, 0).GetComponent<MultiplayerFishEntity>();
multiplayerFishEntity.Init(networkedFish);
}
return multiplayerFishEntity;
}
private void FishSpawner_OnDespawnFish(FishEntity fishEntity)
{
if (IsMaster)
{
NetworkedFish networkedFish = GetNetworkedFish(fishEntity);
if (networkedFish != null)
{
networkedFishList.Remove(networkedFish);
PhotonNetwork.RaiseEvent(1, new object[1] { networkedFish.Guid.ToByteArray() }, RaiseEventOptions.Default, SendOptions.SendReliable);
}
}
}
private void FishSpawner_OnSpawnFish(FishEntity fishEntity, int levelFishDataIndex)
{
if (IsMaster)
{
NetworkedFish networkedFish = new NetworkedFish(Guid.NewGuid().ToString(), levelFishDataIndex, fishEntity.Weight);
networkedFish.fishEntity = fishEntity;
networkedFish.position = fishEntity.transform.position;
networkedFish.targetAreaID = FishTargetBaker.Instance.Areas.IndexOf(fishEntity.CurrentArea);
networkedFish.actorInControl = -1;
networkedFishList.Add(networkedFish);
SendFishUpdateEvent(networkedFish);
}
}
private void SceneLoader_OnBeginSceneLoad(string sceneLoadName)
{
networkedFishList = new List<NetworkedFish>();
}
private void SceneLoader_OnSceneLoaded(string sceneLoadName)
{
ToggleFishSyncCoroutine(MultiplayerManager.InRoomLocationStatic);
}
private void Awake()
{
if (Instance != null && Instance != this)
{
UnityEngine.Object.Destroy(base.gameObject);
}
else
{
Instance = this;
}
}
private void OnEnable()
{
PhotonNetwork.AddCallbackTarget(this);
FishSpawner.OnSpawnFish += FishSpawner_OnSpawnFish;
FishSpawner.OnDespawnFish += FishSpawner_OnDespawnFish;
SceneLoader.OnBeginSceneLoad += SceneLoader_OnBeginSceneLoad;
SceneLoader.OnSceneLoaded += SceneLoader_OnSceneLoaded;
}
private void OnDisable()
{
PhotonNetwork.RemoveCallbackTarget(this);
FishSpawner.OnSpawnFish -= FishSpawner_OnSpawnFish;
FishSpawner.OnDespawnFish -= FishSpawner_OnDespawnFish;
SceneLoader.OnBeginSceneLoad -= SceneLoader_OnBeginSceneLoad;
SceneLoader.OnSceneLoaded -= SceneLoader_OnSceneLoaded;
}
private void Event_FishUpdate(string guid, int fishID, float fishWeight, Vector3 position, int targetAreaID, int actorInControl)
{
if (!IsSlave)
{
return;
}
NetworkedFish networkedFish = GetNetworkedFish(guid);
if (networkedFish != null)
{
networkedFish.position = position;
networkedFish.targetAreaID = targetAreaID;
networkedFish.fishEntity.CurrentArea = FishTargetBaker.Instance.Areas[targetAreaID];
networkedFish.actorInControl = actorInControl;
if (fishWeight != networkedFish.fishWeight)
{
networkedFish.fishWeight = fishWeight;
networkedFish.fishEntity.TryGrowFish(fishWeight);
}
}
else
{
NetworkedFish networkedFish2 = new NetworkedFish(guid, fishID, fishWeight);
networkedFish2.position = position;
networkedFish2.targetAreaID = targetAreaID;
networkedFish2.actorInControl = actorInControl;
networkedFishList.Add(networkedFish2);
MultiplayerFishSpawner.OnNetworkedFishSpawn?.Invoke(networkedFish2);
}
}
private void Event_FishDelete(string guid)
{
if (IsSlave)
{
NetworkedFish networkedFish = GetNetworkedFish(guid);
if (networkedFish != null)
{
networkedFishList.Remove(networkedFish);
MultiplayerFishSpawner.OnNetworkedFishDelete?.Invoke(networkedFish);
}
}
}
private void Event_FishControlRequest(string guid, int sender)
{
if (IsMaster)
{
NetworkedFish networkedFish = GetNetworkedFish(guid);
if (networkedFish != null && PhotonNetwork.CurrentRoom.Players.TryGetValue(sender, out var requestingPlayer) && !networkedFishList.Exists((NetworkedFish element) => element.actorInControl == requestingPlayer.ActorNumber) && !CheckFishInteractionWithPlayer(networkedFish.fishEntity) && networkedFish.actorInControl == -1)
{
networkedFish.actorInControl = requestingPlayer.ActorNumber;
SendFishUpdateEvent(networkedFish);
}
}
}
private void Event_FishControlRequestCancel(string guid, int sender)
{
if (IsMaster)
{
NetworkedFish networkedFish = GetNetworkedFish(guid);
if (networkedFish != null && PhotonNetwork.CurrentRoom.Players.TryGetValue(sender, out var value) && !CheckFishInteractionWithPlayer(networkedFish.fishEntity) && networkedFish.actorInControl == value.ActorNumber)
{
networkedFish.actorInControl = -1;
SendFishUpdateEvent(networkedFish);
}
}
}
private void Event_FishDeleteAfterInteraction(string guid)
{
if (IsMaster)
{
NetworkedFish networkedFish = GetNetworkedFish(guid);
if (networkedFish != null && networkedFish.fishEntity != null)
{
FishSpawner.Despawn(networkedFish.fishEntity);
UnityEngine.Object.Destroy(networkedFish.fishEntity.gameObject);
MultiplayerFishSpawner.OnFishDeleteAfterInteraction?.Invoke();
}
}
}
public void OnEvent(EventData photonEvent)
{
switch (photonEvent.Code)
{
case 0:
{
object[] obj = (object[])photonEvent.CustomData;
byte[][] array = (byte[][])obj[0];
byte[] array2 = (byte[])obj[1];
float[] array3 = (float[])obj[2];
Vector3[] array4 = (Vector3[])obj[3];
byte[] array5 = (byte[])obj[4];
byte[] array6 = (byte[])obj[5];
for (int i = 0; i < array.Length; i++)
{
if (!array[i].All((byte b) => b == 0))
{
string guid5 = new Guid(array[i]).ToString();
Event_FishUpdate(guid5, array2[i], array3[i], array4[i], array5[i], array6[i]);
}
}
break;
}
case 1:
{
string guid4 = new Guid((byte[])((object[])photonEvent.CustomData)[0]).ToString();
Event_FishDelete(guid4);
break;
}
case 2:
{
string guid3 = new Guid((byte[])((object[])photonEvent.CustomData)[0]).ToString();
Event_FishControlRequest(guid3, photonEvent.Sender);
break;
}
case 3:
{
string guid2 = new Guid((byte[])((object[])photonEvent.CustomData)[0]).ToString();
Event_FishControlRequestCancel(guid2, photonEvent.Sender);
break;
}
case 4:
{
string guid = new Guid((byte[])((object[])photonEvent.CustomData)[0]).ToString();
Event_FishDeleteAfterInteraction(guid);
break;
}
}
}
private void SendFishUpdateEvent(NetworkedFish networkedFish)
{
if (IsMaster)
{
networkedFish.position = networkedFish.fishEntity.transform.position;
networkedFish.targetAreaID = FishTargetBaker.Instance.Areas.IndexOf(networkedFish.fishEntity.CurrentArea);
byte[][] array = new byte[1][] { networkedFish.Guid.ToByteArray() };
byte[] array2 = new byte[1] { (byte)networkedFish.fishID };
float[] array3 = new float[1] { networkedFish.fishWeight };
Vector3[] array4 = new Vector3[1] { networkedFish.position };
byte[] array5 = new byte[1] { (byte)networkedFish.targetAreaID };
byte[] array6 = new byte[1] { (byte)networkedFish.actorInControl };
PhotonNetwork.RaiseEvent(0, new object[6] { array, array2, array3, array4, array5, array6 }, RaiseEventOptions.Default, SendOptions.SendReliable);
}
}
private void ToggleFishSyncCoroutine(bool toggle = false)
{
if (fishSyncCoroutine != null)
{
StopCoroutine(fishSyncCoroutine);
fishSyncCoroutine = null;
}
if (toggle)
{
fishSyncCoroutine = StartCoroutine(FishSyncCoroutine());
}
}
private void ValidateFishes()
{
List<NetworkedFish> list = new List<NetworkedFish>();
foreach (NetworkedFish networkedFish in networkedFishList)
{
if (networkedFish.actorInControl != -1 && !PhotonNetwork.CurrentRoom.Players.ContainsKey(networkedFish.actorInControl))
{
networkedFish.actorInControl = -1;
}
if (networkedFish.fishEntity == null)
{
list.Add(networkedFish);
}
}
list.ForEach(delegate(NetworkedFish element)
{
networkedFishList.Remove(element);
});
}
private IEnumerator FishSyncCoroutine()
{
int index = 0;
while (true)
{
yield return new WaitForSeconds(fishSyncDelay);
if (!IsMaster || MultiplayerManager.Instance.CurrentState != MultiplayerManager.State.InRoomLocation || networkedFishList.Count <= 0)
{
continue;
}
byte[][] array = Enumerable.Repeat(Enumerable.Repeat((byte)0, 16).ToArray(), fishSyncCount).ToArray();
byte[] array2 = new byte[fishSyncCount];
float[] array3 = new float[fishSyncCount];
Vector3[] array4 = new Vector3[fishSyncCount];
byte[] array5 = new byte[fishSyncCount];
byte[] array6 = new byte[fishSyncCount];
for (int i = 0; i < fishSyncCount; i++)
{
if (index >= networkedFishList.Count)
{
index = 0;
}
NetworkedFish networkedFish = networkedFishList[index];
if (!CheckFishInteractionWithPlayer(networkedFish.fishEntity))
{
networkedFish.fishWeight = networkedFish.fishEntity.Weight;
networkedFish.position = networkedFish.fishEntity.transform.position;
networkedFish.targetAreaID = FishTargetBaker.Instance.Areas.IndexOf(networkedFish.fishEntity.CurrentArea);
array[i] = networkedFish.Guid.ToByteArray();
array2[i] = (byte)networkedFish.fishID;
array3[i] = networkedFish.fishWeight;
array4[i] = networkedFish.position;
array5[i] = (byte)networkedFish.targetAreaID;
array6[i] = (byte)networkedFish.actorInControl;
}
int num = index + 1;
index = num;
}
PhotonNetwork.RaiseEvent(0, new object[6] { array, array2, array3, array4, array5, array6 }, RaiseEventOptions.Default, SendOptions.SendReliable);
ValidateFishes();
}
}
}