Files
Nitrox/NitroxServer/GameLogic/EscapePodManager.cs
2025-07-06 00:23:46 +02:00

156 lines
4.8 KiB
C#

using System;
using System.Collections.Generic;
using NitroxModel.DataStructures;
using NitroxModel.DataStructures.GameLogic;
using NitroxModel.DataStructures.GameLogic.Entities;
using NitroxModel.DataStructures.GameLogic.Entities.Metadata;
using NitroxModel.DataStructures.Unity;
using NitroxModel.DataStructures.Util;
using NitroxServer.GameLogic.Entities;
namespace NitroxServer.GameLogic;
public class EscapePodManager
{
private const int PLAYERS_PER_ESCAPEPOD = 50;
private readonly EntityRegistry entityRegistry;
private readonly ThreadSafeDictionary<ushort, EscapePodWorldEntity> escapePodsByPlayerId = new();
private EscapePodWorldEntity podForNextPlayer;
private readonly string seed;
private readonly RandomStartGenerator randomStart;
public EscapePodManager(EntityRegistry entityRegistry, RandomStartGenerator randomStart, string seed)
{
this.seed = seed;
this.randomStart = randomStart;
this.entityRegistry = entityRegistry;
List<EscapePodWorldEntity> escapePods = entityRegistry.GetEntities<EscapePodWorldEntity>();
InitializePodForNextPlayer(escapePods);
InitializeEscapePodsByPlayerId(escapePods);
}
public NitroxId AssignPlayerToEscapePod(ushort playerId, out Optional<EscapePodWorldEntity> newlyCreatedPod)
{
newlyCreatedPod = Optional.Empty;
if (escapePodsByPlayerId.TryGetValue(playerId, out EscapePodWorldEntity podEntity))
{
return podEntity.Id;
}
if (IsPodFull(podForNextPlayer))
{
newlyCreatedPod = Optional.Of(CreateNewEscapePod());
podForNextPlayer = newlyCreatedPod.Value;
}
podForNextPlayer.Players.Add(playerId);
escapePodsByPlayerId[playerId] = podForNextPlayer;
return podForNextPlayer.Id;
}
private EscapePodWorldEntity CreateNewEscapePod()
{
EscapePodWorldEntity escapePod = new(GetStartPosition(), new NitroxId(), new EscapePodMetadata(false, false));
escapePod.ChildEntities.Add(new PrefabChildEntity(new NitroxId(), "5c06baec-0539-4f26-817d-78443548cc52", new NitroxTechType("Radio"), 0, null, escapePod.Id));
escapePod.ChildEntities.Add(new PrefabChildEntity(new NitroxId(), "c0175cf7-0b6a-4a1d-938f-dad0dbb6fa06", new NitroxTechType("MedicalCabinet"), 0, null, escapePod.Id));
escapePod.ChildEntities.Add(new PrefabChildEntity(new NitroxId(), "9f16d82b-11f4-4eeb-aedf-f2fa2bfca8e3", new NitroxTechType("Fabricator"), 0, null, escapePod.Id));
escapePod.ChildEntities.Add(new InventoryEntity(0, new NitroxId(), new NitroxTechType("SmallStorage"), null, escapePod.Id, []));
entityRegistry.AddOrUpdate(escapePod);
return escapePod;
}
private NitroxVector3 GetStartPosition()
{
List<EscapePodWorldEntity> escapePods = entityRegistry.GetEntities<EscapePodWorldEntity>();
Random rnd = new(seed.GetHashCode());
NitroxVector3 position = randomStart.GenerateRandomStartPosition(rnd);
if (escapePods.Count == 0)
{
return position;
}
foreach (EscapePodWorldEntity escapePodModel in escapePods)
{
if (position == NitroxVector3.Zero)
{
break;
}
if (escapePodModel.Transform.Position != position)
{
return position;
}
}
float xNormed = (float)rnd.NextDouble();
float zNormed = (float)rnd.NextDouble();
if (xNormed < 0.3f)
{
xNormed = 0.3f;
}
else if (xNormed > 0.7f)
{
xNormed = 0.7f;
}
if (zNormed < 0.3f)
{
zNormed = 0.3f;
}
else if (zNormed > 0.7f)
{
zNormed = 0.7f;
}
NitroxVector3 lastEscapePodPosition = escapePods[escapePods.Count - 1].Transform.Position;
float x = xNormed * 100 - 50;
float z = zNormed * 100 - 50;
return new NitroxVector3(lastEscapePodPosition.X + x, 0, lastEscapePodPosition.Z + z);
}
private void InitializePodForNextPlayer(List<EscapePodWorldEntity> escapePods)
{
foreach (EscapePodWorldEntity pod in escapePods)
{
if (!IsPodFull(pod))
{
podForNextPlayer = pod;
return;
}
}
podForNextPlayer = CreateNewEscapePod();
}
private void InitializeEscapePodsByPlayerId(List<EscapePodWorldEntity> escapePods)
{
escapePodsByPlayerId.Clear();
foreach (EscapePodWorldEntity pod in escapePods)
{
foreach (ushort playerId in pod.Players)
{
escapePodsByPlayerId[playerId] = pod;
}
}
}
private static bool IsPodFull(EscapePodWorldEntity pod)
{
return pod.Players.Count >= PLAYERS_PER_ESCAPEPOD;
}
}