mirror of
https://github.com/space-wizards/RobustToolbox.git
synced 2026-02-15 03:30:53 +01:00
189 lines
6.6 KiB
C#
189 lines
6.6 KiB
C#
using System;
|
|
using System.Diagnostics.CodeAnalysis;
|
|
using Robust.Shared.GameStates;
|
|
using Robust.Shared.Map;
|
|
using Robust.Shared.Map.Components;
|
|
using Robust.Shared.Physics.Dynamics;
|
|
using Robust.Shared.Utility;
|
|
|
|
namespace Robust.Shared.GameObjects;
|
|
|
|
public abstract partial class SharedMapSystem
|
|
{
|
|
protected int LastMapId;
|
|
|
|
private void InitializeMap()
|
|
{
|
|
SubscribeLocalEvent<MapComponent, ComponentAdd>(OnComponentAdd);
|
|
SubscribeLocalEvent<MapComponent, ComponentInit>(OnCompInit);
|
|
SubscribeLocalEvent<MapComponent, ComponentStartup>(OnCompStartup);
|
|
SubscribeLocalEvent<MapComponent, MapInitEvent>(OnMapInit);
|
|
SubscribeLocalEvent<MapComponent, ComponentShutdown>(OnMapRemoved);
|
|
SubscribeLocalEvent<MapComponent, ComponentHandleState>(OnMapHandleState);
|
|
SubscribeLocalEvent<MapComponent, ComponentGetState>(OnMapGetState);
|
|
}
|
|
|
|
public bool MapExists([NotNullWhen(true)] MapId? mapId)
|
|
{
|
|
return mapId != null && Maps.ContainsKey(mapId.Value);
|
|
}
|
|
|
|
public EntityUid GetMap(MapId mapId)
|
|
{
|
|
return Maps[mapId];
|
|
}
|
|
|
|
public bool TryGetMap([NotNullWhen(true)] MapId? mapId, [NotNullWhen(true)] out EntityUid? uid)
|
|
{
|
|
if (mapId == null || !Maps.TryGetValue(mapId.Value, out var map))
|
|
{
|
|
uid = null;
|
|
return false;
|
|
}
|
|
|
|
uid = map;
|
|
return true;
|
|
}
|
|
|
|
private void OnMapHandleState(EntityUid uid, MapComponent component, ref ComponentHandleState args)
|
|
{
|
|
if (args.Current is not MapComponentState state)
|
|
return;
|
|
|
|
if (component.MapId == MapId.Nullspace)
|
|
{
|
|
if (state.MapId == MapId.Nullspace)
|
|
throw new Exception($"Received invalid map state? {ToPrettyString(uid)}");
|
|
|
|
component.MapId = state.MapId;
|
|
Maps.Add(component.MapId, uid);
|
|
RecursiveMapIdUpdate(uid, uid, component.MapId);
|
|
}
|
|
|
|
DebugTools.AssertEqual(component.MapId, state.MapId);
|
|
component.LightingEnabled = state.LightingEnabled;
|
|
component.MapInitialized = state.Initialized;
|
|
|
|
if (LifeStage(uid) >= EntityLifeStage.Initialized)
|
|
SetPaused(uid, state.MapPaused);
|
|
else
|
|
component.MapPaused = state.MapPaused;
|
|
}
|
|
|
|
private void RecursiveMapIdUpdate(EntityUid uid, EntityUid mapUid, MapId mapId)
|
|
{
|
|
// This is required only in the event where an entity becomes a map AFTER children have already been attached to it.
|
|
// AFAIK, this currently only happens when the client applies entity states out of order (i.e., ignoring transform hierarchy),
|
|
// which itself only happens if PVS is disabled.
|
|
// TODO MAPS remove this
|
|
|
|
var xform = Transform(uid);
|
|
xform.MapUid = mapUid;
|
|
xform.MapID = mapId;
|
|
xform._mapIdInitialized = true;
|
|
foreach (var child in xform._children)
|
|
{
|
|
RecursiveMapIdUpdate(child, mapUid, mapId);
|
|
}
|
|
}
|
|
|
|
private void OnMapGetState(EntityUid uid, MapComponent component, ref ComponentGetState args)
|
|
{
|
|
args.State = new MapComponentState(component.MapId, component.LightingEnabled, component.MapPaused, component.MapInitialized);
|
|
}
|
|
|
|
protected abstract MapId GetNextMapId();
|
|
|
|
private void OnComponentAdd(EntityUid uid, MapComponent component, ComponentAdd args)
|
|
{
|
|
// ordered startups when
|
|
EnsureComp<PhysicsMapComponent>(uid);
|
|
EnsureComp<GridTreeComponent>(uid);
|
|
EnsureComp<MovedGridsComponent>(uid);
|
|
}
|
|
|
|
private void OnCompInit(EntityUid uid, MapComponent component, ComponentInit args)
|
|
{
|
|
if (component.MapId == MapId.Nullspace)
|
|
component.MapId = GetNextMapId();
|
|
|
|
DebugTools.AssertEqual(component.MapId.IsClientSide, IsClientSide(uid));
|
|
if (!Maps.TryAdd(component.MapId, uid))
|
|
{
|
|
if (Maps[component.MapId] != uid)
|
|
throw new Exception($"Attempted to initialize a map {ToPrettyString(uid)} with a duplicate map id {component.MapId}");
|
|
}
|
|
|
|
var msg = new MapChangedEvent(uid, component.MapId, true);
|
|
RaiseLocalEvent(uid, msg, true);
|
|
}
|
|
|
|
private void OnCompStartup(EntityUid uid, MapComponent component, ComponentStartup args)
|
|
{
|
|
if (component.MapPaused)
|
|
RecursiveSetPaused(uid, true);
|
|
}
|
|
|
|
private void OnMapRemoved(EntityUid uid, MapComponent component, ComponentShutdown args)
|
|
{
|
|
DebugTools.Assert(component.MapId != MapId.Nullspace);
|
|
Maps.Remove(component.MapId);
|
|
|
|
var msg = new MapChangedEvent(uid, component.MapId, false);
|
|
RaiseLocalEvent(uid, msg, true);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Creates a new map, automatically assigning a map id.
|
|
/// </summary>
|
|
public EntityUid CreateMap(out MapId mapId, bool runMapInit = true)
|
|
{
|
|
mapId = GetNextMapId();
|
|
var uid = CreateMap(mapId, runMapInit);
|
|
return uid;
|
|
}
|
|
|
|
/// <inheritdoc cref="CreateMap(out Robust.Shared.Map.MapId,bool)"/>
|
|
public EntityUid CreateMap(bool runMapInit = true) => CreateMap(out _, runMapInit);
|
|
|
|
/// <summary>
|
|
/// Creates a new map with the specified map id.
|
|
/// </summary>
|
|
/// <exception cref="ArgumentException">Throws if an invalid or already existing map id is provided.</exception>
|
|
public EntityUid CreateMap(MapId mapId, bool runMapInit = true)
|
|
{
|
|
if (Maps.ContainsKey(mapId))
|
|
throw new ArgumentException($"Map with id {mapId} already exists");
|
|
|
|
if (mapId == MapId.Nullspace)
|
|
throw new ArgumentException($"Cannot create a null-space map");
|
|
|
|
if (_netManager.IsServer && mapId.IsClientSide)
|
|
throw new ArgumentException($"Attempted to create a client-side map on the server?");
|
|
|
|
if (_netManager.IsClient && _netManager.IsConnected && !mapId.IsClientSide)
|
|
throw new ArgumentException($"Attempted to create a client-side map entity with a non client-side map ID?");
|
|
|
|
var uid = EntityManager.CreateEntityUninitialized(null);
|
|
var map = _factory.GetComponent<MapComponent>();
|
|
map.MapId = mapId;
|
|
AddComp(uid, map);
|
|
|
|
// Give the entity a name, mainly for debugging. Content can always override this with a localized name.
|
|
var meta = MetaData(uid);
|
|
_meta.SetEntityName(uid, $"Map Entity", meta);
|
|
|
|
// Initialize components. this should add the map id to the collections.
|
|
EntityManager.InitializeComponents(uid, meta);
|
|
EntityManager.StartComponents(uid);
|
|
DebugTools.Assert(Maps[mapId] == uid);
|
|
|
|
if (runMapInit)
|
|
InitializeMap((uid, map));
|
|
else
|
|
SetPaused((uid, map), true);
|
|
|
|
return uid;
|
|
}
|
|
}
|