using System; using System.Collections.Generic; using RebootKit.Engine.Main; using RebootKit.Engine.Network; using RebootKit.Engine.Simulation; using RebootReality.jelycho.InfectedArea; using RebootReality.jelycho.Main; using Unity.Mathematics; using UnityEngine; using UnityEngine.AddressableAssets; using Logger = RebootKit.Engine.Foundation.Logger; namespace RebootReality.jelycho.Beacons { public class BaseManagerActorData : IActorData { public void Serialize(NetworkBufferWriter writer) { } public void Deserialize(NetworkBufferReader reader) { } public int GetMaxBytes() { return 0; } } public enum BaseManagerActorCommands : byte { None = 0x00, SpawnBeacon = 0x01, } public struct SpawnBeaconCommandData : ISerializableEntity { public Vector3 Position; public void Serialize(NetworkBufferWriter writer) { writer.Write(Position); } public void Deserialize(NetworkBufferReader reader) { reader.Read(out Position); } public int GetMaxBytes() { return sizeof(float) * 3; } } public class BaseManagerActor : Actor { static readonly Logger s_Logger = new Logger(nameof(BaseManagerActor)); [field: SerializeField] public MotherActor Mother { get; private set; } [SerializeField] AssetReferenceGameObject m_BeaconPrefab; [SerializeField] float m_ConnectionRopeLength = 10.0f; [SerializeField] float m_BeaconSpawnRadius = 15.0f; [SerializeField] float m_BeaconSpawnShakeIntensity = 1.0f; [SerializeField] float m_BeaconSpawnShakeRadius = 20.0f; [SerializeField] float m_BeaconSpawnShakeDuration = 1.0f; readonly List m_Beacons = new List(); void Start() { if (RR.World.Context is WorldContext worldContext) { worldContext.InfectedAreaManager.Add(Mother.transform.position, m_BeaconSpawnRadius); } } protected override IActorData CreateActorData() { return new BaseManagerActorData(); } protected override void OnActorCommandServer(ulong senderID, ActorCommand actorCommand) { if (actorCommand.CommandID == (byte) BaseManagerActorCommands.SpawnBeacon) { SpawnBeaconCommandData commandData = new SpawnBeaconCommandData(); DataSerializationUtils.Deserialize(actorCommand.Data, ref commandData); Transform closestGutConnector = FindClosestGutConnector(commandData.Position); if (closestGutConnector == null) { return; } Actor beaconActor = RR.SpawnActor(m_BeaconPrefab, commandData.Position, Quaternion.identity); if (beaconActor is not Beacon beacon) { s_Logger.Info($"Cannot spawn beacon at position: {commandData.Position}"); return; } m_Beacons.Add(beacon); ConnectGut(beacon.GutConnector, closestGutConnector); if (RR.World.Context is WorldContext worldContext) { worldContext.FeedbacksManager.ShakeCamera(commandData.Position, m_BeaconSpawnRadius, m_BeaconSpawnShakeIntensity, m_BeaconSpawnShakeDuration); worldContext.InfectedAreaManager.Add(commandData.Position, m_BeaconSpawnRadius); } } } public void TrySpawnBeacon(Vector3 position) { SpawnBeaconCommandData commandData = new SpawnBeaconCommandData { Position = position }; SendActorCommand((byte) BaseManagerActorCommands.SpawnBeacon, ref commandData); } Transform FindClosestGutConnector(float3 position) { float spawnRadiusSq = m_BeaconSpawnRadius * m_BeaconSpawnRadius; float closestDistanceSq = math.distancesq(position, Mother.transform.position); Transform connector = null; if (closestDistanceSq < spawnRadiusSq) { connector = Mother.GutConnector; } foreach (Beacon beacon in m_Beacons) { float beaconDistSq = math.distancesq(position, beacon.transform.position); if (beaconDistSq < closestDistanceSq) { closestDistanceSq = beaconDistSq; connector = beacon.GutConnector; } } return connector; } void ConnectGut(Transform connectorA, Transform connectorB) { if (RR.World.Context is WorldContext worldContext) { worldContext.RopesManager.SpawnRope(connectorA.position, connectorB.position, true, true); } } } }