using System.Numerics; using System.Threading.Tasks; using Content.Server.NPC.Pathfinding; using Content.Shared.Procedural; using Content.Shared.Procedural.PostGeneration; using Robust.Shared.Map; using Robust.Shared.Random; namespace Content.Server.Procedural.DungeonJob; public sealed partial class DungeonJob { /// /// /// private async Task PostGen( SplineDungeonConnectorDunGen gen, List dungeons, HashSet reservedTiles, Random random) { // NOOP if (dungeons.Count <= 1) return Dungeon.Empty; var nodes = new List(); foreach (var dungeon in dungeons) { foreach (var room in dungeon.Rooms) { if (room.Entrances.Count == 0) continue; nodes.Add(room.Entrances[0]); break; } } var tree = _dungeon.MinimumSpanningTree(nodes, random); await SuspendDungeon(); if (!ValidateResume()) return Dungeon.Empty; var tiles = new List<(Vector2i Index, Tile Tile)>(); var pathfinding = _entManager.System(); var allTiles = new HashSet(); var pathTile = new Tile(_prototype.Index(gen.Tile).TileId); var widen = _prototype.Index(gen.WidenTile ?? gen.Tile); foreach (var pair in tree) { var path = pathfinding.GetSplinePath(new PathfindingSystem.SplinePathArgs() { Distance = gen.DivisionDistance, MaxRatio = gen.VarianceMax, Args = new PathfindingSystem.SimplePathArgs() { Start = pair.Start, End = pair.End, TileCost = node => { // We want these to get prioritised internally and into space if it's a space dungeon. if (_maps.TryGetTile(_grid, node, out var tile) && !tile.IsEmpty) return 1f; return 5f; } }, }, random); // Welp if (path.Path.Count == 0) { _sawmill.Error($"Unable to connect spline dungeon path for {_entManager.ToPrettyString(_gridUid)} between {pair.Start} and {pair.End}"); continue; } await SuspendDungeon(); if (!ValidateResume()) return Dungeon.Empty; var wide = pathfinding.GetWiden(new PathfindingSystem.WidenArgs() { Path = path.Path, }, random); tiles.Clear(); allTiles.EnsureCapacity(allTiles.Count + wide.Count); foreach (var node in wide) { if (reservedTiles.Contains(node)) continue; allTiles.Add(node); Tile tile; if (random.Prob(0.9f)) { tile = new Tile(widen.TileId); } else { tile = _tileDefManager.GetVariantTile(widen, random); } tiles.Add((node, tile)); } _maps.SetTiles(_gridUid, _grid, tiles); tiles.Clear(); allTiles.EnsureCapacity(allTiles.Count + path.Path.Count); foreach (var node in path.Path) { if (reservedTiles.Contains(node)) continue; allTiles.Add(node); tiles.Add((node, pathTile)); } _maps.SetTiles(_gridUid, _grid, tiles); } var dungy = new Dungeon(); var dungyRoom = new DungeonRoom(allTiles, Vector2.Zero, Box2i.Empty, new HashSet()); dungy.AddRoom(dungyRoom); return dungy; } }