Some mobs pvs-based systems (#321)

* outPVS despawn component

* Update CP14HelperPvsSystem.cs

* experimental constrained spawners
This commit is contained in:
Ed
2024-07-09 23:05:19 +03:00
committed by GitHub
parent 82f1ed1493
commit 1ac9ec85c5
7 changed files with 241 additions and 1 deletions

View File

@@ -208,7 +208,7 @@ namespace Content.Server.Explosion.EntitySystems
private void OnTriggerCollide(EntityUid uid, TriggerOnCollideComponent component, ref StartCollideEvent args)
{
if (args.OurFixtureId == component.FixtureID && (!component.IgnoreOtherNonHard || args.OtherFixture.Hard))
Trigger(uid);
Trigger(uid, args.OtherEntity); // CP14 Other Entity user
}
private void OnSpawnTriggered(EntityUid uid, TriggerOnSpawnComponent component, MapInitEvent args)

View File

@@ -0,0 +1,81 @@
using System.Numerics;
using Content.Server.Explosion.EntitySystems;
using Content.Server.GameTicking;
using Content.Shared.Ghost;
using Content.Shared.Mind;
using Content.Shared.Mind.Components;
using MyNamespace;
using Robust.Shared.Random;
namespace Content.Server._CP14.PVS;
public sealed class CP14ConstrainSpawnerSystem : EntitySystem
{
[Dependency] private readonly IRobustRandom _random = default!;
[Dependency] private readonly GameTicker _ticker = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<CP14ConstrainedSpawnerOnTriggerComponent, TriggerEvent>(OnSpawnTrigger);
}
private void OnSpawnTrigger(Entity<CP14ConstrainedSpawnerOnTriggerComponent> spawner, ref TriggerEvent args)
{
if (HasComp<GhostComponent>(args.User))//TODO replace with Whitelist system?
return;
if (!TryComp<MindContainerComponent>(args.User, out var mind))
return;
if (!mind.HasMind)
return;
TrySpawn(spawner);
}
private void UpdateSpawned(Entity<CP14ConstrainedSpawnerOnTriggerComponent> spawner)
{
foreach (var spawned in spawner.Comp.Spawned)
{
if (!EntityManager.EntityExists(spawned))
spawner.Comp.Spawned.Remove(spawned);
}
}
private bool CanSpawn(Entity<CP14ConstrainedSpawnerOnTriggerComponent> spawner)
{
UpdateSpawned(spawner);
return spawner.Comp.Spawned.Count < spawner.Comp.MaxCount;
}
private void TrySpawn(Entity<CP14ConstrainedSpawnerOnTriggerComponent> spawner)
{
if (CanSpawn(spawner))
Spawn(spawner);
}
private void Spawn(Entity<CP14ConstrainedSpawnerOnTriggerComponent> spawner)
{
if (!_random.Prob(spawner.Comp.Chance))
return;
if (spawner.Comp.Prototypes.Count == 0)
{
Log.Warning($"Prototype list in ConditionalSpawnComponent is empty! Entity: {ToPrettyString(spawner)}");
return;
}
if (Deleted(spawner))
return;
var offset = spawner.Comp.Offset;
var xOffset = _random.NextFloat(-offset, offset);
var yOffset = _random.NextFloat(-offset, offset);
var coordinates = Transform(spawner).Coordinates.Offset(new Vector2(xOffset, yOffset));
spawner.Comp.Spawned.Add(EntityManager.SpawnEntity(_random.Pick(spawner.Comp.Prototypes), coordinates));
}
}

View File

@@ -0,0 +1,25 @@
using Content.Server._CP14.PVS;
using Robust.Shared.Prototypes;
namespace MyNamespace;
/// <summary>
/// A spawner that clearly controls how many entities it can spawn.
/// </summary>
[RegisterComponent, Access(typeof(CP14ConstrainSpawnerSystem))]
public sealed partial class CP14ConstrainedSpawnerOnTriggerComponent : Component
{
[DataField]
public List<EntProtoId> Prototypes { get; set; } = new();
public HashSet<EntityUid> Spawned = new();
[DataField]
public float Chance { get; set; } = 1.0f;
[DataField]
public float Offset { get; set; } = 0.2f;
[DataField]
public int MaxCount = 1;
}

View File

@@ -0,0 +1,63 @@
using Content.Server.Administration.Logs;
using Content.Shared.Database;
using Content.Shared.Ghost;
using Content.Shared.Mind.Components;
using Robust.Shared;
using Robust.Shared.Timing;
namespace Content.Server._CP14.PVS;
public sealed partial class CP14HelperPvsSystem : EntitySystem
{
[Dependency] private readonly IGameTiming _timing = default!;
[Dependency] private readonly EntityLookupSystem _lookup = default!;
[Dependency] private readonly IAdminLogManager _adminLogger = default!;
private static readonly TimeSpan UpdateFrequency = TimeSpan.FromSeconds(5f);
public override void Update(float frameTime)
{
base.Update(frameTime);
var query = EntityQueryEnumerator<CP14OutPVSDespawnComponent>();
while (query.MoveNext(out var uid, out var pvs))
{
if (_timing.CurTime <= pvs.NextUpdate)
continue;
pvs.NextUpdate = _timing.CurTime + UpdateFrequency;
if (InPvs(uid))
{
pvs.DespawnAttempt = pvs.MaxDespawnAttempt;
}
else
{
pvs.DespawnAttempt--;
}
if (pvs.DespawnAttempt <= 0)
{
_adminLogger.Add(LogType.EntityDelete, LogImpact.Medium, $"{ToPrettyString(uid):entity} was out of the players' pvs for too long and was deleted");
QueueDel(uid);
}
}
}
public bool InPvs(EntityUid uid)
{
var nearMinds = _lookup.GetEntitiesInRange<MindContainerComponent>(Transform(uid).Coordinates, CVars.NetMaxUpdateRange.DefaultValue / 2);
foreach (var mind in nearMinds)
{
if (HasComp<GhostComponent>(mind))
continue;
if (!mind.Comp.HasMind)
continue;
return true;
}
return false;
}
}

View File

@@ -0,0 +1,17 @@
namespace Content.Server._CP14.PVS;
/// <summary>
/// Deletes an entity if it stays out of the players' pvs for too long
/// </summary>
[RegisterComponent, Access(typeof(CP14HelperPvsSystem)), AutoGenerateComponentPause]
public sealed partial class CP14OutPVSDespawnComponent : Component
{
[DataField]
public int MaxDespawnAttempt = 3;
[DataField]
public int DespawnAttempt = 3;
[DataField, AutoPausedField]
public TimeSpan NextUpdate = TimeSpan.Zero;
}

View File

@@ -0,0 +1,37 @@
- type: entity
id: CP14ConstrainedSpawnerBase
abstract: true
parent: MarkerBase
components:
- type: Sprite
layers:
- state: red
- type: Physics
bodyType: Static
fixedRotation: true
- type: Fixtures
fixtures:
spawn:
shape:
!type:PhysShapeCircle
radius: 15
hard: false
layer:
- AllMask
- type: TriggerOnCollide
fixtureID: spawn
- type: StepTrigger
requiredTriggeredSpeed: 0
stepOn: true
- type: entity
parent: CP14ConstrainedSpawnerBase
id: CP14ConstrainedSpawnerXeno
components:
- type: TriggerOnCollide
fixtureID: spawn
- type: CP14ConstrainedSpawnerOnTrigger
prototypes:
- CP14MobXeno
- CP14MobXenoPraetorian
- CP14MobXenoDrone

View File

@@ -0,0 +1,17 @@
- type: entity
id: CP14MobXeno
parent: MobXeno
components:
- type: CP14OutPVSDespawn
- type: entity
id: CP14MobXenoPraetorian
parent: MobXenoPraetorian
components:
- type: CP14OutPVSDespawn
- type: entity
id: CP14MobXenoDrone
parent: MobXenoDrone
components:
- type: CP14OutPVSDespawn