Files
jelito/Assets/jelycho/Code/Beacons/BaseManagerActor.cs
2025-10-24 13:54:27 +02:00

135 lines
5.0 KiB
C#

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<Beacon> m_Beacons = new List<Beacon>();
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);
}
}
}
}