better fluid spreading (#14529)

This commit is contained in:
Slava0135
2023-03-24 17:09:52 +03:00
committed by GitHub
parent 473a02120d
commit 81159b0ff5
2 changed files with 46 additions and 39 deletions

View File

@@ -3,13 +3,13 @@ using System.Linq;
using Content.Server.Fluids.Components;
using Content.Shared;
using Content.Shared.Directions;
using Content.Shared.Maps;
using Content.Shared.Physics;
using JetBrains.Annotations;
using Robust.Shared.Map;
using Robust.Shared.Map.Components;
using Robust.Shared.Physics;
using Robust.Shared.Utility;
using Robust.Shared.Physics.Components;
using Robust.Shared.Physics.Systems;
using Robust.Shared.Timing;
namespace Content.Server.Fluids.EntitySystems;
@@ -23,6 +23,8 @@ public sealed class FluidSpreaderSystem : EntitySystem
[Dependency] private readonly IGameTiming _gameTiming = default!;
[Dependency] private readonly IMapManager _mapManager = default!;
[Dependency] private readonly PuddleSystem _puddleSystem = default!;
[Dependency] private readonly SharedTransformSystem _transform = default!;
[Dependency] private readonly SharedPhysicsSystem _physics = default!;
/// <summary>
/// Adds an overflow component to the map data component tracking overflowing puddles
@@ -72,20 +74,19 @@ public sealed class FluidSpreaderSystem : EntitySystem
puddles.Clear();
var pos = transform.Coordinates;
var totalVolume = _puddleSystem.CurrentVolume(puddle.Owner, puddle);
var totalVolume = _puddleSystem.CurrentVolume(puddleUid, puddle);
exploreDirections.Shuffle();
foreach (var direction in exploreDirections)
{
var newPos = pos.Offset(direction);
if (CheckTile(puddle.Owner, puddle, newPos, mapGrid,
out var puddleComponent))
if (CheckTile(puddleUid, puddle, newPos, mapGrid, puddleQuery, out var uid, out var component))
{
puddles.Add(puddleComponent);
totalVolume += _puddleSystem.CurrentVolume(puddleComponent.Owner, puddleComponent);
puddles.Add(component);
totalVolume += _puddleSystem.CurrentVolume(uid.Value, component);
}
}
_puddleSystem.EqualizePuddles(puddle.Owner, puddles, totalVolume, newIteration, puddle);
_puddleSystem.EqualizePuddles(puddleUid, puddles, totalVolume, newIteration, puddle);
}
fluidMapData.Puddles.Clear();
@@ -100,49 +101,57 @@ public sealed class FluidSpreaderSystem : EntitySystem
/// </summary>
/// <param name="srcUid">Entity Uid of original puddle</param>
/// <param name="srcPuddle">PuddleComponent attached to srcUid</param>
/// <param name="pos">at which to check tile</param>
/// <param name="dstPos">at which to check tile</param>
/// <param name="mapGrid">helper param needed to extract entities</param>
/// <param name="puddle">either found or newly created PuddleComponent.</param>
/// <param name="newPuddleUid">either found or newly created PuddleComponent.</param>
/// <returns>true if tile is empty or occupied by a non-overflowing puddle (or a puddle close to being overflowing)</returns>
private bool CheckTile(EntityUid srcUid, PuddleComponent srcPuddle, EntityCoordinates pos, MapGridComponent mapGrid,
[NotNullWhen(true)] out PuddleComponent? puddle)
private bool CheckTile(EntityUid srcUid, PuddleComponent srcPuddle, EntityCoordinates dstPos,
MapGridComponent mapGrid, EntityQuery<PuddleComponent> puddleQuery,
[NotNullWhen(true)] out EntityUid? newPuddleUid, [NotNullWhen(true)] out PuddleComponent? newPuddleComp)
{
if (!mapGrid.TryGetTileRef(pos, out var tileRef)
if (!mapGrid.TryGetTileRef(dstPos, out var tileRef)
|| tileRef.Tile.IsEmpty)
{
puddle = null;
newPuddleUid = null;
newPuddleComp = null;
return false;
}
// check if puddle can spread there at all
var dstMap = dstPos.ToMap(EntityManager, _transform);
var dst = dstMap.Position;
var src = Transform(srcUid).MapPosition.Position;
var dir = src - dst;
var ray = new CollisionRay(dst, dir.Normalized, (int) (CollisionGroup.Impassable | CollisionGroup.HighImpassable));
var mapId = dstMap.MapId;
var results = _physics.IntersectRay(mapId, ray, dir.Length, returnOnFirstHit: true);
if (results.Any())
{
newPuddleUid = null;
newPuddleComp = null;
return false;
}
var puddleCurrentVolume = _puddleSystem.CurrentVolume(srcUid, srcPuddle);
foreach (var entity in mapGrid.GetAnchoredEntities(pos))
foreach (var entity in dstPos.GetEntitiesInTile())
{
// If this is valid puddle check if we spread to it.
if (TryComp(entity, out PuddleComponent? existingPuddle))
if (puddleQuery.TryGetComponent(entity, out var existingPuddle))
{
// If current puddle has more volume than current we skip that field
if (_puddleSystem.CurrentVolume(existingPuddle.Owner, existingPuddle) >= puddleCurrentVolume)
if (_puddleSystem.CurrentVolume(entity, existingPuddle) >= puddleCurrentVolume)
{
puddle = null;
newPuddleUid = null;
newPuddleComp = null;
return false;
}
puddle = existingPuddle;
newPuddleUid = entity;
newPuddleComp = existingPuddle;
return true;
}
// if not puddle is this tile blocked by an object like wall or door
if (TryComp(entity, out PhysicsComponent? physComponent)
&& physComponent.CanCollide
&& (physComponent.CollisionLayer & (int) CollisionGroup.MobMask) != 0)
{
puddle = null;
return false;
}
}
puddle = _puddleSystem.SpawnPuddle(srcUid, pos, srcPuddle);
_puddleSystem.SpawnPuddle(srcUid, dstPos, srcPuddle, out var uid, out var comp);
newPuddleUid = uid;
newPuddleComp = comp;
return true;
}
}

View File

@@ -266,17 +266,15 @@ namespace Content.Server.Fluids.EntitySystems
return CurrentVolume(uid, puddle) > puddle.OverflowVolume;
}
public PuddleComponent SpawnPuddle(EntityUid srcUid, EntityCoordinates pos, PuddleComponent? srcPuddleComponent = null)
public void SpawnPuddle(EntityUid srcUid, EntityCoordinates pos, PuddleComponent srcPuddleComponent, out EntityUid uid, out PuddleComponent component)
{
MetaDataComponent? metadata = null;
Resolve(srcUid, ref srcPuddleComponent, ref metadata);
Resolve(srcUid, ref metadata);
var prototype = metadata?.EntityPrototype?.ID ?? "PuddleSmear"; // TODO Spawn a entity based on another entity
var destUid = EntityManager.SpawnEntity(prototype, pos);
var destPuddle = EntityManager.EnsureComponent<PuddleComponent>(destUid);
return destPuddle;
uid = EntityManager.SpawnEntity(prototype, pos);
component = EntityManager.EnsureComponent<PuddleComponent>(uid);
}
}
}