using System.Collections; using System.Collections.Generic; using FishNet.Broadcast; using FishNet.Managing; using FishNet.Transporting; using SoapCustomVariable; using UnityEngine; public class MultiplayerFishManager : MonoBehaviour { private struct FishSyncData { public int ID; public float weight; public Vector3 position; } private struct FishZoneSyncData : IBroadcast { public int childIndex; public List fishSyncDatas; } [SerializeField] private FishDatabase fishDatabase; [SerializeField] [Tooltip("Delay in seconds between sending fish synchronization packets to slave clients")] [Range(0f, 1f)] private float fishSyncDelay = 0.2f; private FishSystemManager fishSystemManager; private NetworkManager NetworkManager => NetworkManager.Instances[0]; private void OnFishZoneSync(FishZoneSyncData fishZoneSyncData, Channel channel) { if (!NetworkManager.IsClientStarted || NetworkManager.IsServerStarted) { return; } if ((object)fishSystemManager == null) { fishSystemManager = Object.FindFirstObjectByType(); } if (fishSystemManager == null) { return; } int childCount = fishSystemManager.transform.childCount; if (fishZoneSyncData.childIndex < 0 || fishZoneSyncData.childIndex >= childCount) { return; } Transform child = fishSystemManager.transform.GetChild(fishZoneSyncData.childIndex); if (child == null || !child.gameObject.activeSelf || !child.TryGetComponent(out var component)) { return; } for (int i = 0; i < component.FishControllers.Count; i++) { FishController fishController = component.FishControllers[i]; if (!(fishController == null) && !IsFishInInteractionWithLocalPlayer(fishController) && fishZoneSyncData.fishSyncDatas.Count > i) { FishSyncData fishSyncData = fishZoneSyncData.fishSyncDatas[i]; if (fishController.FishData.ID != fishSyncData.ID || fishController.Mass != fishSyncData.weight) { fishController.Reinitialize(fishDatabase.GetNewInstanceByID(fishSyncData.ID), fishSyncData.weight); } if (fishSyncData.position.x == float.PositiveInfinity) { fishController.followPosition = null; } else { fishController.followPosition = fishSyncData.position; } } } } private void OnEnable() { NetworkManager.ClientManager.RegisterBroadcast(OnFishZoneSync); } private void OnDisable() { NetworkManager.ClientManager.UnregisterBroadcast(OnFishZoneSync); } private void Start() { StartCoroutine(FishSyncCoroutine()); } private bool IsFishInInteractionWithLocalPlayer(FishController fish) { if (fish.fishState.Value != FishState.idle) { return fish.fishState.Value != FishState.patrol; } return false; } private IEnumerator FishSyncCoroutine() { int index = 0; while (true) { yield return new WaitForSeconds(fishSyncDelay); if (!NetworkManager.IsServerStarted) { continue; } if ((object)fishSystemManager == null) { fishSystemManager = Object.FindFirstObjectByType(); } if (fishSystemManager == null || fishSystemManager.transform.childCount == 0) { continue; } if (index >= fishSystemManager.transform.childCount) { index = 0; } Transform child = fishSystemManager.transform.GetChild(index); int num = index + 1; index = num; while (!child.gameObject.activeSelf && index < fishSystemManager.transform.childCount) { child = fishSystemManager.transform.GetChild(index); num = index + 1; index = num; } if (!child.gameObject.activeSelf || !child.TryGetComponent(out var component)) { continue; } List list = new List(); foreach (FishController fishController in component.FishControllers) { if (!(fishController == null)) { fishController.followPosition = null; Vector3 position = fishController.transform.position; if (IsFishInInteractionWithLocalPlayer(fishController)) { position = Vector3.positiveInfinity; } list.Add(new FishSyncData { ID = fishController.FishData.ID, weight = fishController.Mass, position = position }); } } FishZoneSyncData message = new FishZoneSyncData { childIndex = child.GetSiblingIndex(), fishSyncDatas = list }; NetworkManager.ServerManager.Broadcast(message); } } }