Files
wwdpublic/Content.Server/Procedural/DungeonSystem.cs
sleepyyapril 885ee5a831 Wizmerge for Station AI (#1351)
<!--
This is a semi-strict format, you can add/remove sections as needed but
the order/format should be kept the same
Remove these comments before submitting
-->

# Description

the adding AI is now up to y'all because i'm not touching loadout code
for name datasets, but it shouldn't be too bad from here

---------

Signed-off-by: sleepyyapril <123355664+sleepyyapril@users.noreply.github.com>
Signed-off-by: SolStar <44028047+ewokswagger@users.noreply.github.com>
Signed-off-by: deltanedas <39013340+deltanedas@users.noreply.github.com>
Co-authored-by: themias <89101928+themias@users.noreply.github.com>
Co-authored-by: Verm <32827189+Vermidia@users.noreply.github.com>
Co-authored-by: DrSmugleaf <10968691+DrSmugleaf@users.noreply.github.com>
Co-authored-by: Sphiral <145869023+SphiraI@users.noreply.github.com>
Co-authored-by: Ed <96445749+TheShuEd@users.noreply.github.com>
Co-authored-by: Mr. 27 <45323883+Dutch-VanDerLinde@users.noreply.github.com>
Co-authored-by: metalgearsloth <comedian_vs_clown@hotmail.com>
Co-authored-by: Alzore <140123969+Blackern5000@users.noreply.github.com>
Co-authored-by: ravage <142820619+ravage123321@users.noreply.github.com>
Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com>
Co-authored-by: Intoxicating-Innocence <188202277+Intoxicating-Innocence@users.noreply.github.com>
Co-authored-by: Saphire <lattice@saphi.re>
Co-authored-by: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com>
Co-authored-by: Errant <35878406+Errant-4@users.noreply.github.com>
Co-authored-by: Tayrtahn <tayrtahn@gmail.com>
Co-authored-by: CaasGit <87243814+CaasGit@users.noreply.github.com>
Co-authored-by: BramvanZijp <56019239+BramvanZijp@users.noreply.github.com>
Co-authored-by: Boaz1111 <149967078+Boaz1111@users.noreply.github.com>
Co-authored-by: NakataRin <45946146+NakataRin@users.noreply.github.com>
Co-authored-by: Kara <lunarautomaton6@gmail.com>
Co-authored-by: Plykiya <58439124+Plykiya@users.noreply.github.com>
Co-authored-by: SlamBamActionman <slambamactionman@gmail.com>
Co-authored-by: Doomsdrayk <robotdoughnut@comcast.net>
Co-authored-by: Brandon Hu <103440971+Brandon-Huu@users.noreply.github.com>
Co-authored-by: SlamBamActionman <83650252+SlamBamActionman@users.noreply.github.com>
Co-authored-by: ElectroJr <leonsfriedrich@gmail.com>
Co-authored-by: Pieter-Jan Briers <pieterjan.briers+git@gmail.com>
Co-authored-by: DrSmugleaf <DrSmugleaf@users.noreply.github.com>
Co-authored-by: Julian Giebel <juliangiebel@live.de>
Co-authored-by: nikthechampiongr <32041239+nikthechampiongr@users.noreply.github.com>
Co-authored-by: Repo <47093363+Titian3@users.noreply.github.com>
Co-authored-by: Chief-Engineer <119664036+Chief-Engineer@users.noreply.github.com>
Co-authored-by: icekot8 <93311212+icekot8@users.noreply.github.com>
Co-authored-by: AJCM-git <60196617+AJCM-git@users.noreply.github.com>
Co-authored-by: Leon Friedrich <60421075+ElectroJr@users.noreply.github.com>
Co-authored-by: no <165581243+pissdemon@users.noreply.github.com>
Co-authored-by: Tornado Tech <54727692+Tornado-Technology@users.noreply.github.com>
Co-authored-by: osjarw <62134478+osjarw@users.noreply.github.com>
Co-authored-by: Simon <63975668+Simyon264@users.noreply.github.com>
Co-authored-by: TGRCDev <tgrc@tgrc.dev>
Co-authored-by: Milon <milonpl.git@proton.me>
Co-authored-by: deltanedas <39013340+deltanedas@users.noreply.github.com>
Co-authored-by: ShadowCommander <10494922+ShadowCommander@users.noreply.github.com>
Co-authored-by: Fildrance <fildrance@gmail.com>
Co-authored-by: pa.pecherskij <pa.pecherskij@interfax.ru>
Co-authored-by: chavonadelal <156101927+chavonadelal@users.noreply.github.com>
Co-authored-by: SolStar <44028047+ewokswagger@users.noreply.github.com>
Co-authored-by: K-Dynamic <20566341+K-Dynamic@users.noreply.github.com>
Co-authored-by: lzk <124214523+lzk228@users.noreply.github.com>
Co-authored-by: ArchRBX <5040911+ArchRBX@users.noreply.github.com>
Co-authored-by: archrbx <punk.gear5260@fastmail.com>
Co-authored-by: Radezolid <snappednexus@gmail.com>
Co-authored-by: Nemanja <98561806+EmoGarbage404@users.noreply.github.com>
Co-authored-by: EmoGarbage404 <retron404@gmail.com>
Co-authored-by: MilenVolf <63782763+MilenVolf@users.noreply.github.com>
Co-authored-by: Velcroboy <107660393+IamVelcroboy@users.noreply.github.com>
Co-authored-by: Velcroboy <velcroboy333@hotmail.com>
Co-authored-by: neuPanda <chriseparton@gmail.com>
Co-authored-by: neuPanda <spainman0@yahoo.com>
Co-authored-by: Dvir <39403717+dvir001@users.noreply.github.com>
Co-authored-by: Whatstone <whatston3@gmail.com>
Co-authored-by: VideoKompany <135313844+VlaDOS1408@users.noreply.github.com>

(cherry picked from commit 93ed70acfeda357133a701f637d3faeec02749bb)
2025-01-14 00:13:42 +03:00

266 lines
8.1 KiB
C#

using System.Threading;
using System.Threading.Tasks;
using Content.Server.Construction;
using Robust.Shared.CPUJob.JobQueues.Queues;
using Content.Server.Decals;
using Content.Server.GameTicking.Events;
using Content.Shared.CCVar;
using Content.Shared.Construction.EntitySystems;
using Content.Shared.GameTicking;
using Content.Shared.Maps;
using Content.Shared.Physics;
using Content.Shared.Procedural;
using Content.Shared.Tag;
using Robust.Server.GameObjects;
using Robust.Shared.Configuration;
using Robust.Shared.Console;
using Robust.Shared.Map;
using Robust.Shared.Map.Components;
using Robust.Shared.Prototypes;
using Robust.Shared.Random;
namespace Content.Server.Procedural;
public sealed partial class DungeonSystem : SharedDungeonSystem
{
[Dependency] private readonly IConfigurationManager _configManager = default!;
[Dependency] private readonly IConsoleHost _console = default!;
[Dependency] private readonly IMapManager _mapManager = default!;
[Dependency] private readonly IPrototypeManager _prototype = default!;
[Dependency] private readonly IRobustRandom _random = default!;
[Dependency] private readonly ITileDefinitionManager _tileDefManager = default!;
[Dependency] private readonly AnchorableSystem _anchorable = default!;
[Dependency] private readonly DecalSystem _decals = default!;
[Dependency] private readonly EntityLookupSystem _lookup = default!;
[Dependency] private readonly TagSystem _tag = default!;
[Dependency] private readonly TileSystem _tile = default!;
[Dependency] private readonly MapLoaderSystem _loader = default!;
[Dependency] private readonly SharedMapSystem _maps = default!;
[Dependency] private readonly SharedTransformSystem _transform = default!;
private readonly List<(Vector2i, Tile)> _tiles = new();
private EntityQuery<MetaDataComponent> _metaQuery;
private EntityQuery<TransformComponent> _xformQuery;
private const double DungeonJobTime = 0.005;
public const int CollisionMask = (int) CollisionGroup.Impassable;
public const int CollisionLayer = (int) CollisionGroup.Impassable;
private readonly JobQueue _dungeonJobQueue = new(DungeonJobTime);
private readonly Dictionary<DungeonJob, CancellationTokenSource> _dungeonJobs = new();
[ValidatePrototypeId<ContentTileDefinition>]
public const string FallbackTileId = "FloorSteel";
public override void Initialize()
{
base.Initialize();
_metaQuery = GetEntityQuery<MetaDataComponent>();
_xformQuery = GetEntityQuery<TransformComponent>();
_console.RegisterCommand("dungen", Loc.GetString("cmd-dungen-desc"), Loc.GetString("cmd-dungen-help"), GenerateDungeon, CompletionCallback);
_console.RegisterCommand("dungen_preset_vis", Loc.GetString("cmd-dungen_preset_vis-desc"), Loc.GetString("cmd-dungen_preset_vis-help"), DungeonPresetVis, PresetCallback);
_console.RegisterCommand("dungen_pack_vis", Loc.GetString("cmd-dungen_pack_vis-desc"), Loc.GetString("cmd-dungen_pack_vis-help"), DungeonPackVis, PackCallback);
SubscribeLocalEvent<PrototypesReloadedEventArgs>(PrototypeReload);
SubscribeLocalEvent<RoundRestartCleanupEvent>(OnRoundCleanup);
SubscribeLocalEvent<RoundStartingEvent>(OnRoundStart);
}
public override void Update(float frameTime)
{
base.Update(frameTime);
_dungeonJobQueue.Process();
}
private void OnRoundCleanup(RoundRestartCleanupEvent ev)
{
foreach (var token in _dungeonJobs.Values)
{
token.Cancel();
}
_dungeonJobs.Clear();
}
private void OnRoundStart(RoundStartingEvent ev)
{
var query = AllEntityQuery<DungeonAtlasTemplateComponent>();
while (query.MoveNext(out var uid, out _))
{
QueueDel(uid);
}
if (!_configManager.GetCVar(CCVars.ProcgenPreload))
return;
// Force all templates to be setup.
foreach (var room in _prototype.EnumeratePrototypes<DungeonRoomPrototype>())
{
GetOrCreateTemplate(room);
}
}
public override void Shutdown()
{
base.Shutdown();
foreach (var token in _dungeonJobs.Values)
{
token.Cancel();
}
_dungeonJobs.Clear();
}
private void PrototypeReload(PrototypesReloadedEventArgs obj)
{
if (!obj.ByType.TryGetValue(typeof(DungeonRoomPrototype), out var rooms))
{
return;
}
foreach (var proto in rooms.Modified.Values)
{
var roomProto = (DungeonRoomPrototype) proto;
var query = AllEntityQuery<DungeonAtlasTemplateComponent>();
while (query.MoveNext(out var uid, out var comp))
{
if (!roomProto.AtlasPath.Equals(comp.Path))
continue;
QueueDel(uid);
break;
}
}
if (!_configManager.GetCVar(CCVars.ProcgenPreload))
return;
foreach (var proto in rooms.Modified.Values)
{
var roomProto = (DungeonRoomPrototype) proto;
var query = AllEntityQuery<DungeonAtlasTemplateComponent>();
var found = false;
while (query.MoveNext(out var comp))
{
if (!roomProto.AtlasPath.Equals(comp.Path))
continue;
found = true;
break;
}
if (!found)
{
GetOrCreateTemplate(roomProto);
}
}
}
public MapId GetOrCreateTemplate(DungeonRoomPrototype proto)
{
var query = AllEntityQuery<DungeonAtlasTemplateComponent>();
DungeonAtlasTemplateComponent? comp;
while (query.MoveNext(out var uid, out comp))
{
// Exists
if (comp.Path.Equals(proto.AtlasPath))
return Transform(uid).MapID;
}
var mapId = _mapManager.CreateMap();
_mapManager.AddUninitializedMap(mapId);
_loader.Load(mapId, proto.AtlasPath.ToString());
var mapUid = _mapManager.GetMapEntityId(mapId);
_mapManager.SetMapPaused(mapId, true);
comp = AddComp<DungeonAtlasTemplateComponent>(mapUid);
comp.Path = proto.AtlasPath;
return mapId;
}
public void GenerateDungeon(DungeonConfigPrototype gen,
EntityUid gridUid,
MapGridComponent grid,
Vector2i position,
int seed)
{
var cancelToken = new CancellationTokenSource();
var job = new DungeonJob(
Log,
DungeonJobTime,
EntityManager,
_mapManager,
_prototype,
_tileDefManager,
_anchorable,
_decals,
this,
_lookup,
_tag,
_tile,
_transform,
gen,
grid,
gridUid,
seed,
position,
cancelToken.Token);
_dungeonJobs.Add(job, cancelToken);
_dungeonJobQueue.EnqueueJob(job);
}
public async Task<Dungeon> GenerateDungeonAsync(
DungeonConfigPrototype gen,
EntityUid gridUid,
MapGridComponent grid,
Vector2i position,
int seed)
{
var cancelToken = new CancellationTokenSource();
var job = new DungeonJob(
Log,
DungeonJobTime,
EntityManager,
_mapManager,
_prototype,
_tileDefManager,
_anchorable,
_decals,
this,
_lookup,
_tag,
_tile,
_transform,
gen,
grid,
gridUid,
seed,
position,
cancelToken.Token);
_dungeonJobs.Add(job, cancelToken);
_dungeonJobQueue.EnqueueJob(job);
await job.AsTask;
if (job.Exception != null)
{
throw job.Exception;
}
return job.Result!;
}
public Angle GetDungeonRotation(int seed)
{
// Mask 0 | 1 for rotation seed
var dungeonRotationSeed = 3 & seed;
return Math.PI / 2 * dungeonRotationSeed;
}
}