Files
tbd-station-14/Content.Server/Procedural/DungeonJob/DungeonJob.Junction.cs
metalgearsloth fe7b96147c Biome rework (#37735)
* DungeonData rework

Back to fields, serializes better, just make new layers dumby.

* wawawewa

* Fix this

* Fixes

* Port the work over

* wawawewa

* zoom

* Kinda workin

* Adjust wawa

* Unloading work

* Ore + entitytable fixes

Iterate every dungeon not just last.

* Big shot

* wawawewa

* Fixes

* true

* Fixes

# Conflicts:
#	Content.Server/Procedural/DungeonJob/DungeonJob.cs

* wawawewa

* Fixes

* Fix

* Lot of work

* wawawewa

* Fixing

* eh?

* a

* Fix a heap of stuff

* Better ignored check

* Reserve tile changes

* biome

* changes

* wawawewa

* Fixes & snow

* Shadow fixes

* wawawewa

* smol

* Add layer API

* More work

* wawawewa

* Preloads and running again

* wawawewa

* Modified

* Replacements and command

* Runtime support

* werk

* Fix expeds + dungeon alltiles

* reh

---------

Co-authored-by: Nemanja <98561806+EmoGarbage404@users.noreply.github.com>
2025-07-03 00:36:06 -04:00

145 lines
5.2 KiB
C#

using System.Threading.Tasks;
using Content.Shared.Maps;
using Content.Shared.Procedural;
using Content.Shared.Procedural.PostGeneration;
using Content.Shared.Storage;
using Robust.Shared.Map.Components;
namespace Content.Server.Procedural.DungeonJob;
public sealed partial class DungeonJob
{
/// <summary>
/// <see cref="JunctionDunGen"/>
/// </summary>
private async Task PostGen(JunctionDunGen gen, Dungeon dungeon, HashSet<Vector2i> reservedTiles, Random random)
{
var tileDef = _tileDefManager[gen.Tile];
var contents = _prototype.Index(gen.Contents);
// N-wide junctions
foreach (var tile in dungeon.CorridorTiles)
{
if (!_anchorable.TileFree((_gridUid, _grid), tile, DungeonSystem.CollisionLayer, DungeonSystem.CollisionMask))
continue;
// Check each direction:
// - Check if immediate neighbors are free
// - Check if the neighbors beyond that are not free
// - Then check either side if they're slightly more free
var exteriorWidth = (int) Math.Floor(gen.Width / 2f);
var width = (int) Math.Ceiling(gen.Width / 2f);
for (var i = 0; i < 2; i++)
{
var isValid = true;
var neighborDir = (Direction) (i * 2);
var neighborVec = neighborDir.ToIntVec();
for (var j = -width; j <= width; j++)
{
if (j == 0)
continue;
var neighbor = tile + neighborVec * j;
// If it's an end tile then check it's occupied.
if (j == -width ||
j == width)
{
if (!HasWall(neighbor))
{
isValid = false;
break;
}
continue;
}
// If we're not at the end tile then check it + perpendicular are free.
if (!_anchorable.TileFree((_gridUid, _grid), neighbor, DungeonSystem.CollisionLayer, DungeonSystem.CollisionMask))
{
isValid = false;
break;
}
var perp1 = tile + neighborVec * j + ((Direction) ((i * 2 + 2) % 8)).ToIntVec();
var perp2 = tile + neighborVec * j + ((Direction) ((i * 2 + 6) % 8)).ToIntVec();
if (!_anchorable.TileFree((_gridUid, _grid), perp1, DungeonSystem.CollisionLayer, DungeonSystem.CollisionMask))
{
isValid = false;
break;
}
if (!_anchorable.TileFree((_gridUid, _grid), perp2, DungeonSystem.CollisionLayer, DungeonSystem.CollisionMask))
{
isValid = false;
break;
}
}
if (!isValid)
continue;
// Check corners to see if either side opens up (if it's just a 1x wide corridor do nothing, needs to be a funnel.
foreach (var j in new [] {-exteriorWidth, exteriorWidth})
{
var freeCount = 0;
// Need at least 3 of 4 free
for (var k = 0; k < 4; k++)
{
var cornerDir = (Direction) (k * 2 + 1);
var cornerVec = cornerDir.ToIntVec();
var cornerNeighbor = tile + neighborVec * j + cornerVec;
if (_anchorable.TileFree((_gridUid, _grid), cornerNeighbor, DungeonSystem.CollisionLayer, DungeonSystem.CollisionMask))
{
freeCount++;
}
}
if (freeCount < gen.Width)
continue;
// Valid!
isValid = true;
for (var x = -width + 1; x < width; x++)
{
var weh = tile + neighborDir.ToIntVec() * x;
if (reservedTiles.Contains(weh))
continue;
var tileVariant = _tile.GetVariantTile((ContentTileDefinition)tileDef, random);
_maps.SetTile(_gridUid, _grid, weh, tileVariant);
AddLoadedTile(weh, tileVariant);
var coords = _maps.GridTileToLocal(_gridUid, _grid, weh);
var uids = _entManager.SpawnEntitiesAttachedTo(coords, _entTable.GetSpawns(contents, random));
foreach (var uid in uids)
{
AddLoadedEntity(weh, uid);
}
}
break;
}
if (isValid)
{
await SuspendDungeon();
if (!ValidateResume())
return;
}
break;
}
}
}
}