Revert "Upstream sync (#1509)" (#1510)

This reverts commit a35c718734.
This commit is contained in:
Red
2025-07-08 11:59:51 +03:00
committed by GitHub
parent a35c718734
commit ae077c3971
935 changed files with 9384 additions and 19938 deletions

View File

@@ -82,7 +82,7 @@ namespace Content.Server.Abilities.Mime
// Get the tile in front of the mime
var offsetValue = xform.LocalRotation.ToWorldVec();
var coords = xform.Coordinates.Offset(offsetValue).SnapToGrid(EntityManager, _mapMan);
var tile = _turf.GetTileRef(coords);
var tile = coords.GetTileRef(EntityManager, _mapMan);
if (tile == null)
return;

View File

@@ -113,7 +113,7 @@ public sealed class AccessOverriderSystem : SharedAccessOverriderSystem
if (component.TargetAccessReaderId is { Valid: true } accessReader)
{
targetLabel = Loc.GetString("access-overrider-window-target-label") + " " + Comp<MetaDataComponent>(component.TargetAccessReaderId).EntityName;
targetLabel = Loc.GetString("access-overrider-window-target-label") + " " + EntityManager.GetComponent<MetaDataComponent>(component.TargetAccessReaderId).EntityName;
targetLabelColor = Color.White;
if (!_accessReader.GetMainAccessReader(accessReader, out var accessReaderEnt))
@@ -125,7 +125,7 @@ public sealed class AccessOverriderSystem : SharedAccessOverriderSystem
if (component.PrivilegedIdSlot.Item is { Valid: true } idCard)
{
privilegedIdName = Comp<MetaDataComponent>(idCard).EntityName;
privilegedIdName = EntityManager.GetComponent<MetaDataComponent>(idCard).EntityName;
if (component.TargetAccessReaderId is { Valid: true })
{

View File

@@ -73,7 +73,7 @@ public sealed class IdCardConsoleSystem : SharedIdCardConsoleSystem
List<ProtoId<AccessLevelPrototype>>? possibleAccess = null;
if (component.PrivilegedIdSlot.Item is { Valid: true } item)
{
privilegedIdName = Comp<MetaDataComponent>(item).EntityName;
privilegedIdName = EntityManager.GetComponent<MetaDataComponent>(item).EntityName;
possibleAccess = _accessReader.FindAccessTags(item).ToList();
}
@@ -95,8 +95,8 @@ public sealed class IdCardConsoleSystem : SharedIdCardConsoleSystem
}
else
{
var targetIdComponent = Comp<IdCardComponent>(targetId);
var targetAccessComponent = Comp<AccessComponent>(targetId);
var targetIdComponent = EntityManager.GetComponent<IdCardComponent>(targetId);
var targetAccessComponent = EntityManager.GetComponent<AccessComponent>(targetId);
var jobProto = targetIdComponent.JobPrototype ?? new ProtoId<AccessLevelPrototype>(string.Empty);
if (TryComp<StationRecordKeyStorageComponent>(targetId, out var keyStorage)

View File

@@ -47,12 +47,12 @@ public sealed class IdCardSystem : SharedIdCardSystem
{
_popupSystem.PopupCoordinates(Loc.GetString("id-card-component-microwave-burnt", ("id", uid)),
transformComponent.Coordinates, PopupType.Medium);
Spawn("FoodBadRecipe",
EntityManager.SpawnEntity("FoodBadRecipe",
transformComponent.Coordinates);
}
_adminLogger.Add(LogType.Action, LogImpact.Medium,
$"{ToPrettyString(args.Microwave)} burnt {ToPrettyString(uid):entity}");
QueueDel(uid);
EntityManager.QueueDeleteEntity(uid);
return;
}

View File

@@ -3,41 +3,52 @@ using Content.Shared.Administration;
using Content.Shared.Body.Part;
using Robust.Shared.Console;
namespace Content.Server.Administration.Commands;
[AdminCommand(AdminFlags.Admin)]
public sealed class AddBodyPartCommand : LocalizedEntityCommands
namespace Content.Server.Administration.Commands
{
[Dependency] private readonly BodySystem _bodySystem = default!;
public override string Command => "addbodypart";
public override void Execute(IConsoleShell shell, string argStr, string[] args)
[AdminCommand(AdminFlags.Admin)]
public sealed class AddBodyPartCommand : IConsoleCommand
{
if (args.Length != 4)
{
shell.WriteError(Loc.GetString("shell-wrong-arguments-number"));
return;
}
[Dependency] private readonly IEntityManager _entManager = default!;
if (!NetEntity.TryParse(args[0], out var childNetId) || !EntityManager.TryGetEntity(childNetId, out var childId))
{
shell.WriteError(Loc.GetString("shell-invalid-entity-uid", ("uid", args[0])));
return;
}
public string Command => "addbodypart";
public string Description => "Adds a given entity to a containing body.";
public string Help => "Usage: addbodypart <entity uid> <body uid> <part slot> <part type>";
if (!NetEntity.TryParse(args[1], out var parentNetId) || !EntityManager.TryGetEntity(parentNetId, out var parentId))
public void Execute(IConsoleShell shell, string argStr, string[] args)
{
shell.WriteError(Loc.GetString("shell-invalid-entity-uid", ("uid", args[1])));
return;
}
if (args.Length != 3)
{
shell.WriteError(Loc.GetString("shell-wrong-arguments-number"));
return;
}
if (Enum.TryParse<BodyPartType>(args[3], out var partType) &&
_bodySystem.TryCreatePartSlotAndAttach(parentId.Value, args[2], childId.Value, partType))
{
shell.WriteLine($@"Added {childId} to {parentId}.");
if (!NetEntity.TryParse(args[0], out var childNetId))
{
shell.WriteError(Loc.GetString("shell-entity-uid-must-be-number"));
return;
}
if (!NetEntity.TryParse(args[1], out var parentNetId))
{
shell.WriteError(Loc.GetString("shell-entity-uid-must-be-number"));
return;
}
var childId = _entManager.GetEntity(childNetId);
var parentId = _entManager.GetEntity(parentNetId);
var bodySystem = _entManager.System<BodySystem>();
if (Enum.TryParse<BodyPartType>(args[3], out var partType) &&
bodySystem.TryCreatePartSlotAndAttach(parentId, args[2], childId, partType))
{
shell.WriteLine($@"Added {childId} to {parentId}.");
}
else
{
shell.WriteError($@"Could not add {childId} to {parentId}.");
}
}
else
shell.WriteError($@"Could not add {childId} to {parentId}.");
}
}

View File

@@ -14,10 +14,9 @@ namespace Content.Server.Administration.Commands;
[AdminCommand(AdminFlags.Ban)]
public sealed class BanListCommand : LocalizedCommands
{
[Dependency] private readonly IPlayerLocator _locator = default!;
[Dependency] private readonly IPlayerManager _playerManager = default!;
[Dependency] private readonly IServerDbManager _dbManager = default!;
[Dependency] private readonly EuiManager _eui = default!;
[Dependency] private readonly IPlayerLocator _locator = default!;
public override string Command => "banlist";
@@ -67,7 +66,8 @@ public sealed class BanListCommand : LocalizedCommands
if (args.Length != 1)
return CompletionResult.Empty;
var options = _playerManager.Sessions.Select(c => c.Name).OrderBy(c => c).ToArray();
var playerMgr = IoCManager.Resolve<IPlayerManager>();
var options = playerMgr.Sessions.Select(c => c.Name).OrderBy(c => c).ToArray();
return CompletionResult.FromHintOptions(options, Loc.GetString("cmd-banlist-hint"));
}
}

View File

@@ -2,36 +2,39 @@ using Content.Server.Chat.Systems;
using Content.Shared.Administration;
using Robust.Shared.Console;
namespace Content.Server.Administration.Commands;
[AdminCommand(AdminFlags.Moderator)]
public sealed class DsayCommand : LocalizedEntityCommands
namespace Content.Server.Administration.Commands
{
[Dependency] private readonly ChatSystem _chatSystem = default!;
public override string Command => "dsay";
public override void Execute(IConsoleShell shell, string argStr, string[] args)
[AdminCommand(AdminFlags.Moderator)]
sealed class DSay : IConsoleCommand
{
if (shell.Player is not { } player)
[Dependency] private readonly IEntityManager _e = default!;
public string Command => "dsay";
public string Description => Loc.GetString("dsay-command-description");
public string Help => Loc.GetString("dsay-command-help-text", ("command", Command));
public void Execute(IConsoleShell shell, string argStr, string[] args)
{
shell.WriteError(Loc.GetString("shell-cannot-run-command-from-server"));
return;
if (shell.Player is not { } player)
{
shell.WriteError(Loc.GetString("shell-cannot-run-command-from-server"));
return;
}
if (player.AttachedEntity is not { Valid: true } entity)
return;
if (args.Length < 1)
return;
var message = string.Join(" ", args).Trim();
if (string.IsNullOrEmpty(message))
return;
var chat = _e.System<ChatSystem>();
chat.TrySendInGameOOCMessage(entity, message, InGameOOCChatType.Dead, false, shell, player);
}
if (player.AttachedEntity is not { Valid: true } entity)
{
shell.WriteError(Loc.GetString("shell-must-be-attached-to-entity"));
return;
}
if (args.Length < 1)
return;
var message = string.Join(" ", args).Trim();
if (string.IsNullOrEmpty(message))
return;
_chatSystem.TrySendInGameOOCMessage(entity, message, InGameOOCChatType.Dead, false, shell, player);
}
}

View File

@@ -4,18 +4,22 @@ using Robust.Shared.Console;
namespace Content.Server.Administration.Commands;
[AdminCommand(AdminFlags.Debug)]
public sealed class DirtyCommand : LocalizedEntityCommands
public sealed class DirtyCommand : IConsoleCommand
{
public override string Command => "dirty";
[Dependency] private readonly IEntityManager _entManager = default!;
public override async void Execute(IConsoleShell shell, string argStr, string[] args)
public string Command => "dirty";
public string Description => "Marks all components on an entity as dirty, if not specified, dirties everything";
public string Help => $"Usage: {Command} [entityUid]";
public async void Execute(IConsoleShell shell, string argStr, string[] args)
{
switch (args.Length)
{
case 0:
foreach (var entity in EntityManager.GetEntities())
foreach (var entity in _entManager.GetEntities())
{
DirtyAll(entity);
DirtyAll(_entManager, entity);
}
break;
case 1:
@@ -24,7 +28,7 @@ public sealed class DirtyCommand : LocalizedEntityCommands
shell.WriteError(Loc.GetString("shell-entity-uid-must-be-number"));
return;
}
DirtyAll(EntityManager.GetEntity(parsedTarget));
DirtyAll(_entManager, _entManager.GetEntity(parsedTarget));
break;
default:
shell.WriteLine(Loc.GetString("shell-wrong-arguments-number"));
@@ -32,11 +36,11 @@ public sealed class DirtyCommand : LocalizedEntityCommands
}
}
private void DirtyAll(EntityUid entityUid)
private static void DirtyAll(IEntityManager manager, EntityUid entityUid)
{
foreach (var component in EntityManager.GetNetComponents(entityUid))
foreach (var component in manager.GetNetComponents(entityUid))
{
EntityManager.Dirty(entityUid, component.component);
manager.Dirty(entityUid, component.component);
}
}
}

View File

@@ -6,13 +6,15 @@ using Robust.Shared.Enums;
namespace Content.Server.Administration.Commands;
[AdminCommand(AdminFlags.Admin)]
public sealed class FollowCommand : LocalizedEntityCommands
public sealed class FollowCommand : IConsoleCommand
{
[Dependency] private readonly FollowerSystem _followerSystem = default!;
[Dependency] private readonly IEntityManager _entManager = default!;
public override string Command => "follow";
public string Command => "follow";
public string Description => Loc.GetString("follow-command-description");
public string Help => Loc.GetString("follow-command-help");
public override void Execute(IConsoleShell shell, string argStr, string[] args)
public void Execute(IConsoleShell shell, string argStr, string[] args)
{
if (shell.Player is not { } player)
{
@@ -32,7 +34,10 @@ public sealed class FollowCommand : LocalizedEntityCommands
return;
}
if (NetEntity.TryParse(args[0], out var uidNet) && EntityManager.TryGetEntity(uidNet, out var uid))
_followerSystem.StartFollowingEntity(playerEntity, uid.Value);
var entity = args[0];
if (NetEntity.TryParse(entity, out var uidNet) && _entManager.TryGetEntity(uidNet, out var uid))
{
_entManager.System<FollowerSystem>().StartFollowingEntity(playerEntity, uid.Value);
}
}
}

View File

@@ -9,9 +9,6 @@ namespace Content.Server.Administration.Commands;
[AdminCommand(AdminFlags.ViewNotes)]
public sealed class OpenAdminNotesCommand : LocalizedCommands
{
[Dependency] private readonly IAdminNotesManager _adminNotes = default!;
[Dependency] private readonly IPlayerLocator _locator = default!;
public const string CommandName = "adminnotes";
public override string Command => CommandName;
@@ -31,7 +28,8 @@ public sealed class OpenAdminNotesCommand : LocalizedCommands
case 1 when Guid.TryParse(args[0], out notedPlayer):
break;
case 1:
var dbGuid = await _locator.LookupIdByNameAsync(args[0]);
var locator = IoCManager.Resolve<IPlayerLocator>();
var dbGuid = await locator.LookupIdByNameAsync(args[0]);
if (dbGuid == null)
{
@@ -46,7 +44,7 @@ public sealed class OpenAdminNotesCommand : LocalizedCommands
return;
}
await _adminNotes.OpenEui(player, notedPlayer);
await IoCManager.Resolve<IAdminNotesManager>().OpenEui(player, notedPlayer);
}
public override CompletionResult GetCompletion(IConsoleShell shell, string[] args)

View File

@@ -14,18 +14,18 @@ public sealed class PanicBunkerCommand : LocalizedCommands
public override void Execute(IConsoleShell shell, string argStr, string[] args)
{
var toggle = Toggle(CCVars.PanicBunkerEnabled, shell, args, _cfg, LocalizationManager);
var toggle = Toggle(CCVars.PanicBunkerEnabled, shell, args, _cfg);
if (toggle == null)
return;
shell.WriteLine(Loc.GetString(toggle.Value ? "panicbunker-command-enabled" : "panicbunker-command-disabled"));
}
public static bool? Toggle(CVarDef<bool> cvar, IConsoleShell shell, string[] args, IConfigurationManager config, ILocalizationManager loc)
public static bool? Toggle(CVarDef<bool> cvar, IConsoleShell shell, string[] args, IConfigurationManager config)
{
if (args.Length > 1)
{
shell.WriteError(loc.GetString("shell-need-between-arguments",("lower", 0), ("upper", 1)));
shell.WriteError(Loc.GetString("shell-need-between-arguments",("lower", 0), ("upper", 1)));
return null;
}
@@ -38,7 +38,7 @@ public sealed class PanicBunkerCommand : LocalizedCommands
if (args.Length == 1 && !bool.TryParse(args[0], out enabled))
{
shell.WriteError(loc.GetString("shell-argument-must-be-boolean"));
shell.WriteError(Loc.GetString("shell-argument-must-be-boolean"));
return null;
}
@@ -56,7 +56,7 @@ public sealed class PanicBunkerDisableWithAdminsCommand : LocalizedCommands
public override void Execute(IConsoleShell shell, string argStr, string[] args)
{
var toggle = PanicBunkerCommand.Toggle(CCVars.PanicBunkerDisableWithAdmins, shell, args, _cfg, LocalizationManager);
var toggle = PanicBunkerCommand.Toggle(CCVars.PanicBunkerDisableWithAdmins, shell, args, _cfg);
if (toggle == null)
return;
@@ -76,7 +76,7 @@ public sealed class PanicBunkerEnableWithoutAdminsCommand : LocalizedCommands
public override void Execute(IConsoleShell shell, string argStr, string[] args)
{
var toggle = PanicBunkerCommand.Toggle(CCVars.PanicBunkerEnableWithoutAdmins, shell, args, _cfg, LocalizationManager);
var toggle = PanicBunkerCommand.Toggle(CCVars.PanicBunkerEnableWithoutAdmins, shell, args, _cfg);
if (toggle == null)
return;
@@ -96,7 +96,7 @@ public sealed class PanicBunkerCountDeadminnedCommand : LocalizedCommands
public override void Execute(IConsoleShell shell, string argStr, string[] args)
{
var toggle = PanicBunkerCommand.Toggle(CCVars.PanicBunkerCountDeadminnedAdmins, shell, args, _cfg, LocalizationManager);
var toggle = PanicBunkerCommand.Toggle(CCVars.PanicBunkerCountDeadminnedAdmins, shell, args, _cfg);
if (toggle == null)
return;
@@ -116,7 +116,7 @@ public sealed class PanicBunkerShowReasonCommand : LocalizedCommands
public override void Execute(IConsoleShell shell, string argStr, string[] args)
{
var toggle = PanicBunkerCommand.Toggle(CCVars.PanicBunkerShowReason, shell, args, _cfg, LocalizationManager);
var toggle = PanicBunkerCommand.Toggle(CCVars.PanicBunkerShowReason, shell, args, _cfg);
if (toggle == null)
return;

View File

@@ -1,33 +1,39 @@
using Content.Server.Administration.Managers;
using Content.Shared.Administration;
using JetBrains.Annotations;
using Robust.Shared.Console;
using Robust.Shared.Utility;
namespace Content.Server.Administration.Commands;
[UsedImplicitly]
[AdminCommand(AdminFlags.Stealth)]
public sealed class StealthminCommand : LocalizedCommands
{
[Dependency] private readonly IAdminManager _adminManager = default!;
public override string Command => "stealthmin";
public override void Execute(IConsoleShell shell, string argStr, string[] args)
{
var player = shell.Player;
if (player == null)
{
shell.WriteLine(Loc.GetString("shell-cannot-run-command-from-server"));
return;
}
var player = shell.Player;
if (player == null)
{
shell.WriteLine(Loc.GetString("cmd-stealthmin-no-console"));
return;
}
var adminData = _adminManager.GetAdminData(player);
var mgr = IoCManager.Resolve<IAdminManager>();
DebugTools.AssertNotNull(adminData);
var adminData = mgr.GetAdminData(player);
if (!adminData!.Stealth)
_adminManager.Stealth(player);
else
_adminManager.UnStealth(player);
DebugTools.AssertNotNull(adminData);
if (!adminData!.Stealth)
{
mgr.Stealth(player);
}
else
{
mgr.UnStealth(player);
}
}
}

View File

@@ -42,12 +42,13 @@ public sealed class StripAllCommand : LocalizedEntityCommands
if (EntityManager.TryGetComponent<HandsComponent>(targetEntity, out var hands))
{
foreach (var hand in _handsSystem.EnumerateHands((targetEntity.Value, hands)))
foreach (var hand in _handsSystem.EnumerateHands(targetEntity.Value, hands))
{
_handsSystem.TryDrop((targetEntity.Value, hands),
_handsSystem.TryDrop(targetEntity.Value,
hand,
checkActionBlocker: false,
doDropInteraction: false);
doDropInteraction: false,
handsComp: hands);
}
}
}

View File

@@ -10,6 +10,7 @@ namespace Content.Server.Administration.Commands;
public sealed class VariantizeCommand : IConsoleCommand
{
[Dependency] private readonly IEntityManager _entManager = default!;
[Dependency] private readonly ITileDefinitionManager _tileDefManager = default!;
public string Command => "variantize";
@@ -39,11 +40,10 @@ public sealed class VariantizeCommand : IConsoleCommand
var mapsSystem = _entManager.System<SharedMapSystem>();
var tileSystem = _entManager.System<TileSystem>();
var turfSystem = _entManager.System<TurfSystem>();
foreach (var tile in mapsSystem.GetAllTiles(euid.Value, gridComp))
{
var def = turfSystem.GetContentTileDefinition(tile);
var def = tile.GetContentTileDefinition(_tileDefManager);
var newTile = new Tile(tile.Tile.TypeId, tile.Tile.Flags, tileSystem.PickVariant(def));
mapsSystem.SetTile(euid.Value, gridComp, tile.GridIndices, newTile);
}

View File

@@ -9,14 +9,12 @@ using Content.Shared.Administration.Logs;
using Content.Shared.CCVar;
using Content.Shared.Chat;
using Content.Shared.Database;
using Content.Shared.Mind;
using Content.Shared.Players.PlayTimeTracking;
using Prometheus;
using Robust.Shared;
using Robust.Shared.Configuration;
using Robust.Shared.Network;
using Robust.Shared.Player;
using Robust.Shared.Prototypes;
using Robust.Shared.Reflection;
using Robust.Shared.Timing;
@@ -35,7 +33,6 @@ public sealed partial class AdminLogManager : SharedAdminLogManager, IAdminLogMa
[Dependency] private readonly ISharedPlayerManager _player = default!;
[Dependency] private readonly ISharedPlaytimeManager _playtime = default!;
[Dependency] private readonly ISharedChatManager _chat = default!;
[Dependency] private readonly IPrototypeManager _proto = default!;
public const string SawmillId = "admin.logs";
@@ -333,8 +330,7 @@ public sealed partial class AdminLogManager : SharedAdminLogManager, IAdminLogMa
var cachedInfo = adminSys.GetCachedPlayerInfo(new NetUserId(id));
if (cachedInfo != null && cachedInfo.Antag)
{
var proto = cachedInfo.RoleProto == null ? null : _proto.Index(cachedInfo.RoleProto.Value);
var subtype = Loc.GetString(cachedInfo.Subtype ?? proto?.Name ?? RoleTypePrototype.FallbackName);
var subtype = Loc.GetString(cachedInfo.Subtype ?? cachedInfo.RoleProto.Name);
logMessage = Loc.GetString(
"admin-alert-antag-label",
("message", logMessage),

View File

@@ -224,14 +224,14 @@ public sealed class AdminSystem : EntitySystem
// Visible (identity) name can be different from real name
if (session?.AttachedEntity != null)
{
entityName = Comp<MetaDataComponent>(session.AttachedEntity.Value).EntityName;
entityName = EntityManager.GetComponent<MetaDataComponent>(session.AttachedEntity.Value).EntityName;
identityName = Identity.Name(session.AttachedEntity.Value, EntityManager);
}
var antag = false;
// Starting role, antagonist status and role type
RoleTypePrototype? roleType = null;
RoleTypePrototype roleType = new();
var startingRole = string.Empty;
LocId? subtype = null;
if (_minds.TryGetMind(session, out var mindId, out var mindComp) && mindComp is not null)
@@ -244,7 +244,7 @@ public sealed class AdminSystem : EntitySystem
subtype = mindComp.Subtype;
}
else
Log.Error($"{ToPrettyString(mindId)} has invalid Role Type '{mindComp.RoleType}'. Displaying '{Loc.GetString(RoleTypePrototype.FallbackName)}' instead");
Log.Error($"{ToPrettyString(mindId)} has invalid Role Type '{mindComp.RoleType}'. Displaying '{Loc.GetString(roleType.Name)}' instead");
antag = _role.MindIsAntagonist(mindId);
startingRole = _jobs.MindTryGetJobName(mindId);
@@ -270,7 +270,7 @@ public sealed class AdminSystem : EntitySystem
identityName,
startingRole,
antag,
roleType?.ID,
roleType,
subtype,
sortWeight,
GetNetEntity(session?.AttachedEntity),
@@ -433,9 +433,9 @@ public sealed class AdminSystem : EntitySystem
if (TryComp(entity, out HandsComponent? hands))
{
foreach (var hand in _hands.EnumerateHands((entity, hands)))
foreach (var hand in _hands.EnumerateHands(entity, hands))
{
_hands.TryDrop((entity, hands), hand, checkActionBlocker: false, doDropInteraction: false);
_hands.TryDrop(entity, hand, checkActionBlocker: false, doDropInteraction: false, handsComp: hands);
}
}

View File

@@ -79,11 +79,12 @@ public sealed partial class AdminVerbSystem
[Dependency] private readonly SharedTransformSystem _transformSystem = default!;
[Dependency] private readonly SuperBonkSystem _superBonkSystem = default!;
[Dependency] private readonly SlipperySystem _slipperySystem = default!;
[Dependency] private readonly OutfitSystem _outfitSystem = default!;
// All smite verbs have names so invokeverb works.
private void AddSmiteVerbs(GetVerbsEvent<Verb> args)
{
if (!TryComp(args.User, out ActorComponent? actor))
if (!EntityManager.TryGetComponent(args.User, out ActorComponent? actor))
return;
var player = actor.PlayerSession;
@@ -273,7 +274,7 @@ public sealed partial class AdminVerbSystem
Icon = new SpriteSpecifier.Rsi(new ("/Textures/Fluids/tomato_splat.rsi"), "puddle-1"),
Act = () =>
{
_bloodstreamSystem.SpillAllSolutions((args.Target, bloodstream));
_bloodstreamSystem.SpillAllSolutions(args.Target, bloodstream);
var xform = Transform(args.Target);
_popupSystem.PopupEntity(Loc.GetString("admin-smite-remove-blood-self"), args.Target,
args.Target, PopupType.LargeCaution);
@@ -586,7 +587,7 @@ public sealed partial class AdminVerbSystem
Icon = new SpriteSpecifier.Rsi(new ("/Textures/Clothing/Uniforms/Jumpskirt/janimaid.rsi"), "icon"),
Act = () =>
{
_outfit.SetOutfit(args.Target, "JanitorMaidGear", (_, clothing) =>
_outfitSystem.SetOutfit(args.Target, "JanitorMaidGear", (_, clothing) =>
{
if (HasComp<ClothingComponent>(clothing))
EnsureComp<UnremoveableComponent>(clothing);
@@ -622,7 +623,7 @@ public sealed partial class AdminVerbSystem
Icon = new SpriteSpecifier.Rsi(new ("/Textures/Objects/Materials/materials.rsi"), "ash"),
Act = () =>
{
QueueDel(args.Target);
EntityManager.QueueDeleteEntity(args.Target);
Spawn("Ash", Transform(args.Target).Coordinates);
_popupSystem.PopupEntity(Loc.GetString("admin-smite-turned-ash-other", ("name", args.Target)), args.Target, PopupType.LargeCaution);
},

View File

@@ -58,7 +58,7 @@ public sealed partial class AdminVerbSystem
private void AddTricksVerbs(GetVerbsEvent<Verb> args)
{
if (!TryComp(args.User, out ActorComponent? actor))
if (!EntityManager.TryGetComponent(args.User, out ActorComponent? actor))
return;
var player = actor.PlayerSession;
@@ -820,7 +820,7 @@ public sealed partial class AdminVerbSystem
}
else if (TryComp<HandsComponent>(target, out var hands))
{
foreach (var held in _handsSystem.EnumerateHeld((target, hands)))
foreach (var held in _handsSystem.EnumerateHeld(target, hands))
{
if (HasComp<AccessComponent>(held))
{

View File

@@ -88,7 +88,7 @@ namespace Content.Server.Administration.Systems
private void AddAdminVerbs(GetVerbsEvent<Verb> args)
{
if (!TryComp(args.User, out ActorComponent? actor))
if (!EntityManager.TryGetComponent(args.User, out ActorComponent? actor))
return;
var player = actor.PlayerSession;
@@ -395,7 +395,7 @@ namespace Content.Server.Administration.Systems
private void AddDebugVerbs(GetVerbsEvent<Verb> args)
{
if (!TryComp(args.User, out ActorComponent? actor))
if (!EntityManager.TryGetComponent(args.User, out ActorComponent? actor))
return;
var player = actor.PlayerSession;
@@ -408,7 +408,7 @@ namespace Content.Server.Administration.Systems
Text = Loc.GetString("delete-verb-get-data-text"),
Category = VerbCategory.Debug,
Icon = new SpriteSpecifier.Texture(new ("/Textures/Interface/VerbIcons/delete_transparent.svg.192dpi.png")),
Act = () => Del(args.Target),
Act = () => EntityManager.DeleteEntity(args.Target),
Impact = LogImpact.Medium,
ConfirmationPopup = true
};
@@ -451,7 +451,7 @@ namespace Content.Server.Administration.Systems
// Make Sentient verb
if (_groupController.CanCommand(player, "makesentient") &&
args.User != args.Target &&
!HasComp<MindContainerComponent>(args.Target))
!EntityManager.HasComponent<MindContainerComponent>(args.Target))
{
Verb verb = new()
{
@@ -517,7 +517,7 @@ namespace Content.Server.Administration.Systems
// Get Disposal tube direction verb
if (_groupController.CanCommand(player, "tubeconnections") &&
TryComp(args.Target, out DisposalTubeComponent? tube))
EntityManager.TryGetComponent(args.Target, out DisposalTubeComponent? tube))
{
Verb verb = new()
{
@@ -544,7 +544,7 @@ namespace Content.Server.Administration.Systems
}
if (_groupController.CanAdminMenu(player) &&
TryComp(args.Target, out ConfigurationComponent? config))
EntityManager.TryGetComponent(args.Target, out ConfigurationComponent? config))
{
Verb verb = new()
{
@@ -558,7 +558,7 @@ namespace Content.Server.Administration.Systems
// Add verb to open Solution Editor
if (_groupController.CanCommand(player, "addreagent") &&
HasComp<SolutionContainerManagerComponent>(args.Target))
EntityManager.HasComponent<SolutionContainerManagerComponent>(args.Target))
{
Verb verb = new()
{

View File

@@ -2,15 +2,16 @@
using Content.Server.Administration;
using Content.Server.Station.Systems;
using Content.Shared.Administration;
using JetBrains.Annotations;
using Robust.Shared.Console;
namespace Content.Server.AlertLevel.Commands
{
[UsedImplicitly]
[AdminCommand(AdminFlags.Fun)]
public sealed class SetAlertLevelCommand : LocalizedEntityCommands
public sealed class SetAlertLevelCommand : LocalizedCommands
{
[Dependency] private readonly AlertLevelSystem _alertLevelSystem = default!;
[Dependency] private readonly StationSystem _stationSystem = default!;
[Dependency] private readonly IEntitySystemManager _entitySystems = default!;
public override string Command => "setalertlevel";
@@ -20,9 +21,11 @@ namespace Content.Server.AlertLevel.Commands
var player = shell.Player;
if (player?.AttachedEntity != null)
{
var stationUid = _stationSystem.GetOwningStation(player.AttachedEntity.Value);
var stationUid = _entitySystems.GetEntitySystem<StationSystem>().GetOwningStation(player.AttachedEntity.Value);
if (stationUid != null)
{
levelNames = GetStationLevelNames(stationUid.Value);
}
}
return args.Length switch
@@ -57,7 +60,7 @@ namespace Content.Server.AlertLevel.Commands
return;
}
var stationUid = _stationSystem.GetOwningStation(player.AttachedEntity.Value);
var stationUid = _entitySystems.GetEntitySystem<StationSystem>().GetOwningStation(player.AttachedEntity.Value);
if (stationUid == null)
{
shell.WriteLine(LocalizationManager.GetString("cmd-setalertlevel-invalid-grid"));
@@ -72,12 +75,13 @@ namespace Content.Server.AlertLevel.Commands
return;
}
_alertLevelSystem.SetLevel(stationUid.Value, level, true, true, true, locked);
_entitySystems.GetEntitySystem<AlertLevelSystem>().SetLevel(stationUid.Value, level, true, true, true, locked);
}
private string[] GetStationLevelNames(EntityUid station)
{
if (!EntityManager.TryGetComponent<AlertLevelComponent>(station, out var alertLevelComp))
var entityManager = IoCManager.Resolve<IEntityManager>();
if (!entityManager.TryGetComponent<AlertLevelComponent>(station, out var alertLevelComp))
return new string[]{};
if (alertLevelComp.AlertLevels == null)

View File

@@ -246,7 +246,7 @@ public sealed class AmeControllerSystem : EntitySystem
return;
var humanReadableState = value ? "Inject" : "Not inject";
_adminLogger.Add(LogType.Action, LogImpact.Medium, $"{ToPrettyString(user.Value):player} has set the AME to {humanReadableState}");
_adminLogger.Add(LogType.Action, LogImpact.Medium, $"{EntityManager.ToPrettyString(user.Value):player} has set the AME to {humanReadableState}");
}
public void ToggleInjecting(EntityUid uid, EntityUid? user = null, AmeControllerComponent? controller = null)
@@ -281,7 +281,7 @@ public sealed class AmeControllerSystem : EntitySystem
var logImpact = (oldValue <= safeLimit && value > safeLimit) ? LogImpact.Extreme : LogImpact.Medium;
_adminLogger.Add(LogType.Action, logImpact, $"{ToPrettyString(user.Value):player} has set the AME to inject {controller.InjectionAmount} while set to {humanReadableState}");
_adminLogger.Add(LogType.Action, logImpact, $"{EntityManager.ToPrettyString(user.Value):player} has set the AME to inject {controller.InjectionAmount} while set to {humanReadableState}");
}
public void AdjustInjectionAmount(EntityUid uid, int delta, EntityUid? user = null, AmeControllerComponent? controller = null)

View File

@@ -29,7 +29,7 @@ public sealed class BlockGameArcadeSystem : EntitySystem
public override void Update(float frameTime)
{
var query = EntityQueryEnumerator<BlockGameArcadeComponent>();
var query = EntityManager.EntityQueryEnumerator<BlockGameArcadeComponent>();
while (query.MoveNext(out var _, out var blockGame))
{
blockGame.Game?.GameTick(frameTime);

View File

@@ -42,7 +42,7 @@ public sealed partial class SpaceVillainArcadeSystem : EntitySystem
if (arcade.RewardAmount <= 0)
return;
Spawn(_random.Pick(arcade.PossibleRewards), xform.Coordinates);
EntityManager.SpawnEntity(_random.Pick(arcade.PossibleRewards), xform.Coordinates);
arcade.RewardAmount--;
}

View File

@@ -497,7 +497,7 @@ public sealed class AtmosMonitoringConsoleSystem : SharedAtmosMonitoringConsoleS
if (component.NavMapBlip == null)
return;
var netEntity = GetNetEntity(uid);
var netEntity = EntityManager.GetNetEntity(uid);
var query = AllEntityQuery<AtmosMonitoringConsoleComponent, TransformComponent>();
while (query.MoveNext(out var ent, out var entConsole, out var entXform))
@@ -531,7 +531,7 @@ public sealed class AtmosMonitoringConsoleSystem : SharedAtmosMonitoringConsoleS
if (component.NavMapBlip == null)
return;
var netEntity = GetNetEntity(uid);
var netEntity = EntityManager.GetNetEntity(uid);
var query = AllEntityQuery<AtmosMonitoringConsoleComponent>();
while (query.MoveNext(out var ent, out var entConsole))

View File

@@ -122,7 +122,7 @@ namespace Content.Server.Atmos.EntitySystems
public void InvalidatePosition(Entity<MapGridComponent?> grid, Vector2i pos)
{
var query = GetEntityQuery<AirtightComponent>();
var query = EntityManager.GetEntityQuery<AirtightComponent>();
_explosionSystem.UpdateAirtightMap(grid, pos, grid, query);
_atmosphereSystem.InvalidateTile(grid.Owner, pos);
}

View File

@@ -252,128 +252,6 @@ namespace Content.Server.Atmos.EntitySystems
Merge(destination, buffer);
}
/// <summary>
/// Calculates the dimensionless fraction of gas required to equalize pressure between two gas mixtures.
/// </summary>
/// <param name="gasMixture1">The first gas mixture involved in the pressure equalization.
/// This mixture should be the one you always expect to be the highest pressure.</param>
/// <param name="gasMixture2">The second gas mixture involved in the pressure equalization.</param>
/// <returns>A float (from 0 to 1) representing the dimensionless fraction of gas that needs to be transferred from the
/// mixture of higher pressure to the mixture of lower pressure.</returns>
/// <remarks>
/// <para>
/// This properly takes into account the effect
/// of gas merging from inlet to outlet affecting the temperature
/// (and possibly increasing the pressure) in the outlet.
/// </para>
/// <para>
/// The gas is assumed to expand freely,
/// so the temperature of the gas with the greater pressure is not changing.
/// </para>
/// </remarks>
/// <example>
/// If you want to calculate the moles required to equalize pressure between an inlet and an outlet,
/// multiply the fraction returned by the source moles.
/// </example>
public float FractionToEqualizePressure(GasMixture gasMixture1, GasMixture gasMixture2)
{
/*
Problem: the gas being merged from the inlet to the outlet could affect the
temp. of the gas and cause a pressure rise.
We want the pressure to be equalized, so we have to account for this.
For clarity, let's assume that gasMixture1 is the inlet and gasMixture2 is the outlet.
We require mechanical equilibrium, so \( P_1' = P_2' \)
Before the transfer, we have:
\( P_1 = \frac{n_1 R T_1}{V_1} \)
\( P_2 = \frac{n_2 R T_2}{V_2} \)
After removing fraction \( x \) moles from the inlet, we have:
\( P_1' = \frac{(1 - x) n_1 R T_1}{V_1} \)
The outlet will gain the same \( x n_1 \) moles of gas.
So \( n_2' = n_2 + x n_1 \)
After mixing, the outlet temperature will be changed.
Denote the new mixture temperature as \( T_2' \).
Volume is constant.
So we have:
\( P_2' = \frac{(n_2 + x n_1) R T_2}{V_2} \)
The total energy of the incoming inlet to outlet gas at \( T_1 \) plus the existing energy of the outlet gas at \( T_2 \)
will be equal to the energy of the new outlet gas at \( T_2' \).
This leads to the following derivation:
\( x n_1 C_1 T_1 + n_2 C_2 T_2 = (x n_1 C_1 + n_2 C_2) T_2' \)
Where \( C_1 \) and \( C_2 \) are the heat capacities of the inlet and outlet gases, respectively.
Solving for \( T_2' \) gives us:
\( T_2' = \frac{x n_1 C_1 T_1 + n_2 C_2 T_2}{x n_1 C_1 + n_2 C_2} \)
Once again, we require mechanical equilibrium (\( P_1' = P_2' \)),
so we can substitute \( T_2' \) into the pressure equation:
\( \frac{(1 - x) n_1 R T_1}{V_1} =
\frac{(n_2 + x n_1) R}{V_2} \cdot
\frac{x n_1 C_1 T_1 + n_2 C_2 T_2}
{x n_1 C_1 + n_2 C_2} \)
Now it's a matter of solving for \( x \).
Not going to show the full derivation here, just steps.
1. Cancel common factor \( R \).
2. Multiply both sides by \( x n_1 C_1 + n_2 C_2 \), so that everything
becomes a polynomial in terms of \( x \).
3. Expand both sides.
4. Collect like powers of \( x \).
5. After collecting, you should end up with a polynomial of the form:
\( (-n_1 C_1 T_1 (1 + \frac{V_2}{V_1})) x^2 +
(n_1 T_1 \frac{V_2}{V_1} (C_1 - C_2) - n_2 C_1 T_1 - n_1 C_2 T_2) x +
(n_1 T_1 \frac{V_2}{V_1} C_2 - n_2 C_2 T_2) = 0 \)
Divide through by \( n_1 C_1 T_1 \) and replace each ratio with a symbol for clarity:
\( k_V = \frac{V_2}{V_1} \)
\( k_n = \frac{n_2}{n_1} \)
\( k_T = \frac{T_2}{T_1} \)
\( k_C = \frac{C_2}{C_1} \)
*/
// Ensure that P_1 > P_2 so the quadratic works out.
if (gasMixture1.Pressure < gasMixture2.Pressure)
{
(gasMixture1, gasMixture2) = (gasMixture2, gasMixture1);
}
// Establish the dimensionless ratios.
var volumeRatio = gasMixture2.Volume / gasMixture1.Volume;
var molesRatio = gasMixture2.TotalMoles / gasMixture1.TotalMoles;
var temperatureRatio = gasMixture2.Temperature / gasMixture1.Temperature;
var heatCapacityRatio = GetHeatCapacity(gasMixture2) / GetHeatCapacity(gasMixture1);
// The quadratic equation is solved for the transfer fraction.
var quadraticA = 1 + volumeRatio;
var quadraticB = molesRatio - volumeRatio + heatCapacityRatio * (temperatureRatio + volumeRatio);
var quadraticC = heatCapacityRatio * (molesRatio * temperatureRatio - volumeRatio);
return (-quadraticB + MathF.Sqrt(quadraticB * quadraticB - 4 * quadraticA * quadraticC)) / (2 * quadraticA);
}
/// <summary>
/// Determines the number of moles that need to be removed from a <see cref="GasMixture"/> to reach a target pressure threshold.
/// </summary>
/// <param name="gasMixture">The gas mixture whose moles and properties will be used in the calculation.</param>
/// <param name="targetPressure">The target pressure threshold to calculate against.</param>
/// <returns>The difference in moles required to reach the target pressure threshold.</returns>
/// <remarks>The temperature of the gas is assumed to be not changing due to a free expansion.</remarks>
public static float MolesToPressureThreshold(GasMixture gasMixture, float targetPressure)
{
// Kid named PV = nRT.
return gasMixture.TotalMoles -
targetPressure * gasMixture.Volume / (Atmospherics.R * gasMixture.Temperature);
}
/// <summary>
/// Checks whether a gas mixture is probably safe.
/// This only checks temperature and pressure, not gas composition.

View File

@@ -390,10 +390,10 @@ namespace Content.Server.Atmos.EntitySystems
// Note: This is still processed even if space wind is turned off since this handles playing the sounds.
var number = 0;
var bodies = GetEntityQuery<PhysicsComponent>();
var xforms = GetEntityQuery<TransformComponent>();
var metas = GetEntityQuery<MetaDataComponent>();
var pressureQuery = GetEntityQuery<MovedByPressureComponent>();
var bodies = EntityManager.GetEntityQuery<PhysicsComponent>();
var xforms = EntityManager.GetEntityQuery<TransformComponent>();
var metas = EntityManager.GetEntityQuery<MetaDataComponent>();
var pressureQuery = EntityManager.GetEntityQuery<MovedByPressureComponent>();
while (atmosphere.CurrentRunTiles.TryDequeue(out var tile))
{

View File

@@ -120,7 +120,7 @@ namespace Content.Server.Atmos.EntitySystems
var otherEnt = args.OtherEntity;
if (!TryComp(otherEnt, out FlammableComponent? flammable))
if (!EntityManager.TryGetComponent(otherEnt, out FlammableComponent? flammable))
return;
//Only ignite when the colliding fixture is projectile or ignition.

View File

@@ -82,7 +82,7 @@ public sealed class AtmosAlarmableSystem : EntitySystem
{
if (component.IgnoreAlarms) return;
if (!TryComp(uid, out DeviceNetworkComponent? netConn))
if (!EntityManager.TryGetComponent(uid, out DeviceNetworkComponent? netConn))
return;
if (!args.Data.TryGetValue(DeviceNetworkConstants.Command, out string? cmd)

View File

@@ -1,202 +0,0 @@
using Content.Server.Atmos.EntitySystems;
using Content.Server.Atmos.Piping.Components;
using Content.Server.NodeContainer.EntitySystems;
using Content.Server.NodeContainer.Nodes;
using Content.Shared.Atmos;
using Content.Shared.Atmos.EntitySystems;
using Content.Shared.Atmos.Piping;
using Content.Shared.Atmos.Piping.Binary.Components;
using Content.Shared.Audio;
using JetBrains.Annotations;
using Robust.Shared.Timing;
namespace Content.Server.Atmos.Piping.Binary.EntitySystems;
/// <summary>
/// Handles serverside logic for pressure regulators. Gas will only flow through the regulator
/// if the pressure on the inlet side is over a certain pressure threshold.
/// See https://en.wikipedia.org/wiki/Pressure_regulator
/// </summary>
[UsedImplicitly]
public sealed class GasPressureRegulatorSystem : SharedGasPressureRegulatorSystem
{
[Dependency] private readonly SharedAmbientSoundSystem _ambientSound = default!;
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
[Dependency] private readonly AtmosphereSystem _atmosphere = default!;
[Dependency] private readonly NodeContainerSystem _nodeContainer = default!;
[Dependency] private readonly IGameTiming _timing = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<GasPressureRegulatorComponent, ComponentInit>(OnInit);
SubscribeLocalEvent<GasPressureRegulatorComponent, AtmosDeviceUpdateEvent>(OnPressureRegulatorUpdated);
SubscribeLocalEvent<GasPressureRegulatorComponent, MapInitEvent>(OnMapInit);
}
private void OnMapInit(Entity<GasPressureRegulatorComponent> ent, ref MapInitEvent args)
{
ent.Comp.NextUiUpdate = _timing.CurTime + ent.Comp.UpdateInterval;
}
/// <summary>
/// Dirties the regulator every second or so, so that the UI can update.
/// The UI automatically updates after an AutoHandleStateEvent.
/// </summary>
/// <param name="frameTime"></param>
public override void Update(float frameTime)
{
base.Update(frameTime);
var query = EntityQueryEnumerator<GasPressureRegulatorComponent>();
while (query.MoveNext(out var uid, out var comp))
{
if (comp.NextUiUpdate > _timing.CurTime)
continue;
comp.NextUiUpdate += comp.UpdateInterval;
DirtyFields(uid,
comp,
null,
nameof(comp.InletPressure),
nameof(comp.OutletPressure),
nameof(comp.FlowRate));
}
}
private void OnInit(Entity<GasPressureRegulatorComponent> ent, ref ComponentInit args)
{
UpdateAppearance(ent);
}
/// <summary>
/// Handles the updating logic for the pressure regulator.
/// </summary>
/// <param name="ent"> the <see cref="Entity{T}" /> of the pressure regulator</param>
/// <param name="args"> Args provided to us via <see cref="AtmosDeviceUpdateEvent" /></param>
private void OnPressureRegulatorUpdated(Entity<GasPressureRegulatorComponent> ent,
ref AtmosDeviceUpdateEvent args)
{
if (!_nodeContainer.TryGetNodes(ent.Owner,
ent.Comp.InletName,
ent.Comp.OutletName,
out PipeNode? inletPipeNode,
out PipeNode? outletPipeNode))
{
ChangeStatus(false, ent, inletPipeNode, outletPipeNode, 0);
return;
}
/*
It's time for some math! :)
Gas is simply transferred from the inlet to the outlet, restricted by flow rate and pressure.
We want to transfer enough gas to bring the inlet pressure below the threshold,
and only as much as our max flow rate allows.
The equations:
PV = nRT
P1 = P2
Can be used to calculate the amount of gas we need to transfer.
*/
var p1 = inletPipeNode.Air.Pressure;
var p2 = outletPipeNode.Air.Pressure;
if (p1 <= ent.Comp.Threshold || p2 >= p1)
{
ChangeStatus(false, ent, inletPipeNode, outletPipeNode, 0);
return;
}
var t1 = inletPipeNode.Air.Temperature;
// First, calculate the amount of gas we need to transfer to bring us below the threshold.
var deltaMolesToPressureThreshold =
AtmosphereSystem.MolesToPressureThreshold(inletPipeNode.Air, ent.Comp.Threshold);
// Second, calculate the moles required to equalize the pressure.
// We round here to avoid the valve staying enabled for 0.00001 pressure differences.
var deltaMolesToEqualizePressure =
float.Round(_atmosphere.FractionToEqualizePressure(inletPipeNode.Air, outletPipeNode.Air) *
inletPipeNode.Air.TotalMoles,
1,
MidpointRounding.ToPositiveInfinity);
// Third, make sure we only transfer the minimum of the two.
// We do this so that we don't accidentally transfer so much gas to the point
// where the outlet pressure is higher than the inlet.
var deltaMolesToTransfer = Math.Min(deltaMolesToPressureThreshold, deltaMolesToEqualizePressure);
// Fourth, convert to the desired volume to transfer.
var desiredVolumeToTransfer = deltaMolesToTransfer * ((Atmospherics.R * t1) / p1);
// And finally, limit the transfer volume to the max flow rate of the valve.
var actualVolumeToTransfer = Math.Min(desiredVolumeToTransfer,
ent.Comp.MaxTransferRate * _atmosphere.PumpSpeedup() * args.dt);
// We remove the gas from the inlet and merge it into the outlet.
var removed = inletPipeNode.Air.RemoveVolume(actualVolumeToTransfer);
_atmosphere.Merge(outletPipeNode.Air, removed);
// Calculate the flow rate in L/s for the UI.
var sentFlowRate = MathF.Round(actualVolumeToTransfer / args.dt, 1);
ChangeStatus(true, ent, inletPipeNode, outletPipeNode, sentFlowRate);
}
/// <summary>
/// Updates the visual appearance of the pressure regulator based on its current state.
/// </summary>
/// <param name="ent">The <see cref="Entity{GasPressureRegulatorComponent, AppearanceComponent}"/>
/// representing the pressure regulator with respective components.</param>
private void UpdateAppearance(Entity<GasPressureRegulatorComponent> ent)
{
_appearance.SetData(ent,
PressureRegulatorVisuals.State,
ent.Comp.Enabled);
}
/// <summary>
/// Updates the pressure regulator's appearance and sound based on its current state, while
/// also preventing network spamming.
/// Also prepares data for dirtying.
/// </summary>
/// <param name="enabled">The new state to set</param>
/// <param name="ent">The pressure regulator to update</param>
/// <param name="inletNode">The inlet node of the pressure regulator</param>
/// <param name="outletNode">The outlet node of the pressure regulator</param>
/// <param name="flowRate">Current flow rate of the pressure regulator</param>
private void ChangeStatus(bool enabled,
Entity<GasPressureRegulatorComponent> ent,
PipeNode? inletNode,
PipeNode? outletNode,
float flowRate)
{
// First, set data on the component server-side.
ent.Comp.InletPressure = inletNode?.Air.Pressure ?? 0f;
ent.Comp.OutletPressure = outletNode?.Air.Pressure ?? 0f;
ent.Comp.FlowRate = flowRate;
// We need to prevent spamming the network with updates, so only check if we've
// switched states.
if (ent.Comp.Enabled == enabled)
return;
ent.Comp.Enabled = enabled;
_ambientSound.SetAmbience(ent, enabled);
UpdateAppearance(ent);
// The regulator has changed state, so we need to dirty all applicable fields *right now* so the UI updates
// at the same time as everything else.
DirtyFields(ent.AsNullable(),
null,
nameof(ent.Comp.InletPressure),
nameof(ent.Comp.OutletPressure),
nameof(ent.Comp.FlowRate));
}
}

View File

@@ -39,7 +39,7 @@ namespace Content.Server.Atmos.Piping.Binary.EntitySystems
private void OnExamined(Entity<GasRecyclerComponent> ent, ref ExaminedEvent args)
{
var comp = ent.Comp;
if (!Comp<TransformComponent>(ent).Anchored || !args.IsInDetailsRange) // Not anchored? Out of range? No status.
if (!EntityManager.GetComponent<TransformComponent>(ent).Anchored || !args.IsInDetailsRange) // Not anchored? Out of range? No status.
return;
if (!_nodeContainer.TryGetNode(ent.Owner, comp.InletName, out PipeNode? inlet))

View File

@@ -18,7 +18,7 @@ namespace Content.Server.Atmos.Piping.EntitySystems
private void OnStartup(EntityUid uid, AtmosPipeColorComponent component, ComponentStartup args)
{
if (!TryComp(uid, out AppearanceComponent? appearance))
if (!EntityManager.TryGetComponent(uid, out AppearanceComponent? appearance))
return;
_appearance.SetData(uid, PipeColorVisuals.Color, component.Color, appearance);
@@ -26,7 +26,7 @@ namespace Content.Server.Atmos.Piping.EntitySystems
private void OnShutdown(EntityUid uid, AtmosPipeColorComponent component, ComponentShutdown args)
{
if (!TryComp(uid, out AppearanceComponent? appearance))
if (!EntityManager.TryGetComponent(uid, out AppearanceComponent? appearance))
return;
_appearance.SetData(uid, PipeColorVisuals.Color, Color.White, appearance);
@@ -36,7 +36,7 @@ namespace Content.Server.Atmos.Piping.EntitySystems
{
component.Color = color;
if (!TryComp(uid, out AppearanceComponent? appearance))
if (!EntityManager.TryGetComponent(uid, out AppearanceComponent? appearance))
return;
_appearance.SetData(uid, PipeColorVisuals.Color, color, appearance);

View File

@@ -29,7 +29,7 @@ namespace Content.Server.Atmos.Piping.EntitySystems
private void OnUnanchorAttempt(EntityUid uid, AtmosUnsafeUnanchorComponent component, UnanchorAttemptEvent args)
{
if (!component.Enabled || !TryComp(uid, out NodeContainerComponent? nodes))
if (!component.Enabled || !EntityManager.TryGetComponent(uid, out NodeContainerComponent? nodes))
return;
if (_atmosphere.GetContainingMixture(uid, true) is not {} environment)
@@ -78,7 +78,7 @@ namespace Content.Server.Atmos.Piping.EntitySystems
/// </summary>
public void LeakGas(EntityUid uid, bool removeFromPipe = true)
{
if (!TryComp(uid, out NodeContainerComponent? nodes))
if (!EntityManager.TryGetComponent(uid, out NodeContainerComponent? nodes))
return;
if (_atmosphere.GetContainingMixture(uid, true, true) is not { } environment)

View File

@@ -103,10 +103,10 @@ namespace Content.Server.Atmos.Piping.Trinary.EntitySystems
if (args.Handled || !args.Complex)
return;
if (!TryComp(args.User, out ActorComponent? actor))
if (!EntityManager.TryGetComponent(args.User, out ActorComponent? actor))
return;
if (Comp<TransformComponent>(uid).Anchored)
if (EntityManager.GetComponent<TransformComponent>(uid).Anchored)
{
_userInterfaceSystem.OpenUi(uid, GasFilterUiKey.Key, actor.PlayerSession);
DirtyUI(uid, filter);

View File

@@ -143,7 +143,7 @@ namespace Content.Server.Atmos.Piping.Trinary.EntitySystems
if (args.Handled || !args.Complex)
return;
if (!TryComp(args.User, out ActorComponent? actor))
if (!EntityManager.TryGetComponent(args.User, out ActorComponent? actor))
return;
if (Transform(uid).Anchored)
@@ -165,7 +165,7 @@ namespace Content.Server.Atmos.Piping.Trinary.EntitySystems
return;
_userInterfaceSystem.SetUiState(uid, GasMixerUiKey.Key,
new GasMixerBoundUserInterfaceState(Comp<MetaDataComponent>(uid).EntityName, mixer.TargetPressure, mixer.Enabled, mixer.InletOneConcentration));
new GasMixerBoundUserInterfaceState(EntityManager.GetComponent<MetaDataComponent>(uid).EntityName, mixer.TargetPressure, mixer.Enabled, mixer.InletOneConcentration));
}
private void UpdateAppearance(EntityUid uid, GasMixerComponent? mixer = null, AppearanceComponent? appearance = null)
@@ -200,7 +200,7 @@ namespace Content.Server.Atmos.Piping.Trinary.EntitySystems
mixer.InletOneConcentration = nodeOne;
mixer.InletTwoConcentration = 1.0f - mixer.InletOneConcentration;
_adminLogger.Add(LogType.AtmosRatioChanged, LogImpact.Medium,
$"{ToPrettyString(args.Actor):player} set the ratio on {ToPrettyString(uid):device} to {mixer.InletOneConcentration}:{mixer.InletTwoConcentration}");
$"{EntityManager.ToPrettyString(args.Actor):player} set the ratio on {EntityManager.ToPrettyString(uid):device} to {mixer.InletOneConcentration}:{mixer.InletTwoConcentration}");
DirtyUI(uid, mixer);
}

View File

@@ -27,7 +27,7 @@ namespace Content.Server.Atmos.Piping.Unary.EntitySystems
private void OnPortableAnchorAttempt(EntityUid uid, GasPortableComponent component, AnchorAttemptEvent args)
{
if (!TryComp(uid, out TransformComponent? transform))
if (!EntityManager.TryGetComponent(uid, out TransformComponent? transform))
return;
// If we can't find any ports, cancel the anchoring.
@@ -52,7 +52,7 @@ namespace Content.Server.Atmos.Piping.Unary.EntitySystems
foreach (var entityUid in _mapSystem.GetLocal(gridId.Value, grid, coordinates))
{
if (TryComp(entityUid, out port))
if (EntityManager.TryGetComponent(entityUid, out port))
{
return true;
}

View File

@@ -218,7 +218,7 @@ namespace Content.Server.Atmos.Piping.Unary.EntitySystems
private void OnPacketRecv(EntityUid uid, GasVentPumpComponent component, DeviceNetworkPacketEvent args)
{
if (!TryComp(uid, out DeviceNetworkComponent? netConn)
if (!EntityManager.TryGetComponent(uid, out DeviceNetworkComponent? netConn)
|| !args.Data.TryGetValue(DeviceNetworkConstants.Command, out var cmd))
return;

View File

@@ -148,7 +148,7 @@ namespace Content.Server.Atmos.Piping.Unary.EntitySystems
private void OnPacketRecv(EntityUid uid, GasVentScrubberComponent component, DeviceNetworkPacketEvent args)
{
if (!TryComp(uid, out DeviceNetworkComponent? netConn)
if (!EntityManager.TryGetComponent(uid, out DeviceNetworkComponent? netConn)
|| !args.Data.TryGetValue(DeviceNetworkConstants.Command, out var cmd))
return;

View File

@@ -1,8 +1,8 @@
using Content.Server.Atmos.EntitySystems;
using Content.Server.Body.Components;
using Content.Server.Temperature.Components;
using Content.Shared.Atmos;
using Content.Shared.Atmos.Rotting;
using Content.Shared.Body.Events;
using Content.Shared.Damage;
using Robust.Server.Containers;
using Robust.Shared.Physics.Components;

View File

@@ -3,15 +3,12 @@ using Content.Server.GameTicking;
using Content.Server.GameTicking.Events;
using Content.Shared.Audio;
using Content.Shared.Audio.Events;
using Content.Shared.CCVar;
using Content.Shared.GameTicking;
using Robust.Server.Audio;
using Robust.Shared.Audio;
using Robust.Shared.Configuration;
using Robust.Shared.Prototypes;
using Robust.Shared.Random;
namespace Content.Server.Audio;
public sealed class ContentAudioSystem : SharedContentAudioSystem
@@ -22,36 +19,16 @@ public sealed class ContentAudioSystem : SharedContentAudioSystem
[Dependency] private readonly AudioSystem _serverAudio = default!;
[Dependency] private readonly IRobustRandom _robustRandom = default!;
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
[Dependency] private readonly IConfigurationManager _cfg = default!;
private SoundCollectionPrototype? _lobbyMusicCollection = default!;
private SoundCollectionPrototype _lobbyMusicCollection = default!;
private string[]? _lobbyPlaylist;
public override void Initialize()
{
base.Initialize();
//changes the music collection and reshuffles the playlist to update the lobby music
Subs.CVar(
_cfg,
CCVars.LobbyMusicCollection,
x =>
{
//Checks to see if the sound collection exists. If it does change it if not defaults to null
// as the new _lobbyMusicCollection meaning it wont play anything in the lobby.
if(_prototypeManager.TryIndex<SoundCollectionPrototype>(x, out var outputSoundCollection))
{
_lobbyMusicCollection = outputSoundCollection;
}
else
{
Log.Error($"Invalid Lobby Music sound collection specified: {x}");
_lobbyMusicCollection = null;
}
_lobbyPlaylist = ShuffleLobbyPlaylist();
},
true);
_lobbyMusicCollection = _prototypeManager.Index<SoundCollectionPrototype>(LobbyMusicCollection);
_lobbyPlaylist = ShuffleLobbyPlaylist();
SubscribeLocalEvent<RoundEndMessageEvent>(OnRoundEnd);
SubscribeLocalEvent<PlayerJoinedLobbyEvent>(OnPlayerJoinedLobby);
@@ -99,16 +76,11 @@ public sealed class ContentAudioSystem : SharedContentAudioSystem
private string[] ShuffleLobbyPlaylist()
{
if (_lobbyMusicCollection == null)
{
return [];
}
var playlist = _lobbyMusicCollection.PickFiles
.Select(x => x.ToString())
.ToArray();
_robustRandom.Shuffle(playlist);
_robustRandom.Shuffle(playlist);
return playlist;
return playlist;
}
}

View File

@@ -97,7 +97,8 @@ public sealed class CryostorageSystem : SharedCryostorageSystem
EntityUid? entity = null;
if (args.Type == CryostorageRemoveItemBuiMessage.RemovalType.Hand)
{
entity = _hands.GetHeldItem(cryoContained, args.Key);
if (_hands.TryGetHand(cryoContained, args.Key, out var hand))
entity = hand.HeldEntity;
}
else
{
@@ -319,10 +320,10 @@ public sealed class CryostorageSystem : SharedCryostorageSystem
foreach (var hand in _hands.EnumerateHands(uid))
{
if (!_hands.TryGetHeldItem(uid, hand, out var heldEntity))
if (hand.HeldEntity == null)
continue;
data.HeldItems.Add(hand, Name(heldEntity.Value));
data.HeldItems.Add(hand.Name, Name(hand.HeldEntity.Value));
}
return data;

View File

@@ -79,7 +79,7 @@ namespace Content.Server.Bible
// Clean up the old body
if (summonableComp.Summon != null)
{
Del(summonableComp.Summon.Value);
EntityManager.DeleteEntity(summonableComp.Summon.Value);
summonableComp.Summon = null;
}
summonableComp.AlreadySummoned = false;
@@ -235,7 +235,7 @@ namespace Content.Server.Bible
return;
// Make this familiar the component's summon
var familiar = Spawn(component.SpecialItemPrototype, position.Coordinates);
var familiar = EntityManager.SpawnEntity(component.SpecialItemPrototype, position.Coordinates);
component.Summon = familiar;
// If this is going to use a ghost role mob spawner, attach it to the bible.

View File

@@ -0,0 +1,7 @@
namespace Content.Server.Body.Components;
/// <summary>
/// Raised when a body gets gibbed, before it is deleted.
/// </summary>
[ByRefEvent]
public readonly record struct BeingGibbedEvent(HashSet<EntityUid> GibbedParts);

View File

@@ -0,0 +1,186 @@
using Content.Server.Body.Systems;
using Content.Server.Chemistry.EntitySystems;
using Content.Shared.Alert;
using Content.Shared.Chemistry.Components;
using Content.Shared.Chemistry.Reagent;
using Content.Shared.Damage;
using Content.Shared.Damage.Prototypes;
using Content.Shared.FixedPoint;
using Robust.Shared.Audio;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
namespace Content.Server.Body.Components
{
[RegisterComponent, Access(typeof(BloodstreamSystem), typeof(ReactionMixerSystem))]
public sealed partial class BloodstreamComponent : Component
{
public static string DefaultChemicalsSolutionName = "chemicals";
public static string DefaultBloodSolutionName = "bloodstream";
public static string DefaultBloodTemporarySolutionName = "bloodstreamTemporary";
/// <summary>
/// The next time that blood level will be updated and bloodloss damage dealt.
/// </summary>
[DataField(customTypeSerializer: typeof(TimeOffsetSerializer))]
public TimeSpan NextUpdate;
/// <summary>
/// The interval at which this component updates.
/// </summary>
[DataField]
public TimeSpan UpdateInterval = TimeSpan.FromSeconds(3);
/// <summary>
/// How much is this entity currently bleeding?
/// Higher numbers mean more blood lost every tick.
///
/// Goes down slowly over time, and items like bandages
/// or clotting reagents can lower bleeding.
/// </summary>
/// <remarks>
/// This generally corresponds to an amount of damage and can't go above 100.
/// </remarks>
[ViewVariables(VVAccess.ReadWrite)]
public float BleedAmount;
/// <summary>
/// How much should bleeding be reduced every update interval?
/// </summary>
[DataField]
public float BleedReductionAmount = 0.33f;
/// <summary>
/// How high can <see cref="BleedAmount"/> go?
/// </summary>
[DataField]
public float MaxBleedAmount = 10.0f;
/// <summary>
/// What percentage of current blood is necessary to avoid dealing blood loss damage?
/// </summary>
[DataField]
public float BloodlossThreshold = 0.9f;
/// <summary>
/// The base bloodloss damage to be incurred if below <see cref="BloodlossThreshold"/>
/// The default values are defined per mob/species in YML.
/// </summary>
[DataField(required: true)]
public DamageSpecifier BloodlossDamage = new();
/// <summary>
/// The base bloodloss damage to be healed if above <see cref="BloodlossThreshold"/>
/// The default values are defined per mob/species in YML.
/// </summary>
[DataField(required: true)]
public DamageSpecifier BloodlossHealDamage = new();
// TODO shouldn't be hardcoded, should just use some organ simulation like bone marrow or smth.
/// <summary>
/// How much reagent of blood should be restored each update interval?
/// </summary>
[DataField]
public FixedPoint2 BloodRefreshAmount = 1.0f;
/// <summary>
/// How much blood needs to be in the temporary solution in order to create a puddle?
/// </summary>
[DataField]
public FixedPoint2 BleedPuddleThreshold = 1.0f;
/// <summary>
/// A modifier set prototype ID corresponding to how damage should be modified
/// before taking it into account for bloodloss.
/// </summary>
/// <remarks>
/// For example, piercing damage is increased while poison damage is nullified entirely.
/// </remarks>
[DataField]
public ProtoId<DamageModifierSetPrototype> DamageBleedModifiers = "BloodlossHuman";
/// <summary>
/// The sound to be played when a weapon instantly deals blood loss damage.
/// </summary>
[DataField]
public SoundSpecifier InstantBloodSound = new SoundCollectionSpecifier("blood");
/// <summary>
/// The sound to be played when some damage actually heals bleeding rather than starting it.
/// </summary>
[DataField]
public SoundSpecifier BloodHealedSound = new SoundPathSpecifier("/Audio/Effects/lightburn.ogg");
/// <summary>
/// The minimum amount damage reduction needed to play the healing sound/popup.
/// This prevents tiny amounts of heat damage from spamming the sound, e.g. spacing.
/// </summary>
[DataField]
public float BloodHealedSoundThreshold = -0.1f;
// TODO probably damage bleed thresholds.
/// <summary>
/// Max volume of internal chemical solution storage
/// </summary>
[DataField]
public FixedPoint2 ChemicalMaxVolume = FixedPoint2.New(250);
/// <summary>
/// Max volume of internal blood storage,
/// and starting level of blood.
/// </summary>
[DataField]
public FixedPoint2 BloodMaxVolume = FixedPoint2.New(300);
/// <summary>
/// Which reagent is considered this entities 'blood'?
/// </summary>
/// <remarks>
/// Slime-people might use slime as their blood or something like that.
/// </remarks>
[DataField]
public ProtoId<ReagentPrototype> BloodReagent = "Blood";
/// <summary>Name/Key that <see cref="BloodSolution"/> is indexed by.</summary>
[DataField]
public string BloodSolutionName = DefaultBloodSolutionName;
/// <summary>Name/Key that <see cref="ChemicalSolution"/> is indexed by.</summary>
[DataField]
public string ChemicalSolutionName = DefaultChemicalsSolutionName;
/// <summary>Name/Key that <see cref="TemporarySolution"/> is indexed by.</summary>
[DataField]
public string BloodTemporarySolutionName = DefaultBloodTemporarySolutionName;
/// <summary>
/// Internal solution for blood storage
/// </summary>
[ViewVariables]
public Entity<SolutionComponent>? BloodSolution;
/// <summary>
/// Internal solution for reagent storage
/// </summary>
[ViewVariables]
public Entity<SolutionComponent>? ChemicalSolution;
/// <summary>
/// Temporary blood solution.
/// When blood is lost, it goes to this solution, and when this
/// solution hits a certain cap, the blood is actually spilled as a puddle.
/// </summary>
[ViewVariables]
public Entity<SolutionComponent>? TemporarySolution;
/// <summary>
/// Variable that stores the amount of status time added by having a low blood level.
/// </summary>
[ViewVariables(VVAccess.ReadWrite)]
public TimeSpan StatusTime;
[DataField]
public ProtoId<AlertPrototype> BleedingAlert = "Bleed";
}
}

View File

@@ -1,4 +1,3 @@
using Content.Shared.Body.Components;
using Content.Server.Body.Systems;
using Content.Shared.Body.Prototypes;
using Content.Shared.FixedPoint;

View File

@@ -1,6 +1,4 @@
using Content.Server.Body.Systems;
using Content.Shared.Alert;
using Content.Shared.Atmos;
using Content.Shared.Chat.Prototypes;
using Content.Shared.Damage;
using Robust.Shared.Prototypes;
@@ -11,28 +9,6 @@ namespace Content.Server.Body.Components
[RegisterComponent, Access(typeof(RespiratorSystem))]
public sealed partial class RespiratorComponent : Component
{
/// <summary>
/// Gas container for this entity
/// </summary>
[DataField]
public GasMixture Air = new()
{
Volume = 6, // 6 liters, the average lung capacity for a human according to Google
Temperature = Atmospherics.NormalBodyTemperature
};
/// <summary>
/// Volume of our breath in liters
/// </summary>
[DataField]
public float BreathVolume = Atmospherics.BreathVolume;
/// <summary>
/// How much of the gas we inhale is metabolized? Value range is (0, 1]
/// </summary>
[DataField]
public float Ratio = 1.0f;
/// <summary>
/// The next time that this body will inhale or exhale.
/// </summary>

View File

@@ -1,32 +1,189 @@
using Content.Shared.Body.Components;
using Content.Shared.Body.Systems;
using Content.Server.Body.Components;
using Content.Server.Fluids.EntitySystems;
using Content.Server.Popups;
using Content.Shared.Alert;
using Content.Shared.Body.Events;
using Content.Shared.Chemistry.Components;
using Content.Shared.Chemistry.EntitySystems;
using Content.Shared.Chemistry.Reaction;
using Content.Shared.Chemistry.Reagent;
using Content.Shared.Damage;
using Content.Shared.Damage.Prototypes;
using Content.Shared.Drunk;
using Content.Shared.EntityEffects.Effects;
using Content.Shared.FixedPoint;
using Content.Shared.Forensics;
using Content.Shared.Forensics.Components;
using Content.Shared.HealthExaminable;
using Content.Shared.Mobs.Systems;
using Content.Shared.Popups;
using Content.Shared.Rejuvenate;
using Content.Shared.Speech.EntitySystems;
using Robust.Server.Audio;
using Robust.Shared.Prototypes;
using Robust.Shared.Random;
using Robust.Shared.Timing;
namespace Content.Server.Body.Systems;
public sealed class BloodstreamSystem : SharedBloodstreamSystem
public sealed class BloodstreamSystem : EntitySystem
{
[Dependency] private readonly IGameTiming _gameTiming = default!;
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
[Dependency] private readonly IRobustRandom _robustRandom = default!;
[Dependency] private readonly AudioSystem _audio = default!;
[Dependency] private readonly DamageableSystem _damageableSystem = default!;
[Dependency] private readonly PopupSystem _popupSystem = default!;
[Dependency] private readonly PuddleSystem _puddleSystem = default!;
[Dependency] private readonly MobStateSystem _mobStateSystem = default!;
[Dependency] private readonly SharedDrunkSystem _drunkSystem = default!;
[Dependency] private readonly SharedSolutionContainerSystem _solutionContainerSystem = default!;
[Dependency] private readonly SharedStutteringSystem _stutteringSystem = default!;
[Dependency] private readonly AlertsSystem _alertsSystem = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<BloodstreamComponent, ComponentInit>(OnComponentInit);
SubscribeLocalEvent<BloodstreamComponent, MapInitEvent>(OnMapInit);
SubscribeLocalEvent<BloodstreamComponent, EntityUnpausedEvent>(OnUnpaused);
SubscribeLocalEvent<BloodstreamComponent, DamageChangedEvent>(OnDamageChanged);
SubscribeLocalEvent<BloodstreamComponent, HealthBeingExaminedEvent>(OnHealthBeingExamined);
SubscribeLocalEvent<BloodstreamComponent, BeingGibbedEvent>(OnBeingGibbed);
SubscribeLocalEvent<BloodstreamComponent, ApplyMetabolicMultiplierEvent>(OnApplyMetabolicMultiplier);
SubscribeLocalEvent<BloodstreamComponent, ReactionAttemptEvent>(OnReactionAttempt);
SubscribeLocalEvent<BloodstreamComponent, SolutionRelayEvent<ReactionAttemptEvent>>(OnReactionAttempt);
SubscribeLocalEvent<BloodstreamComponent, RejuvenateEvent>(OnRejuvenate);
SubscribeLocalEvent<BloodstreamComponent, GenerateDnaEvent>(OnDnaGenerated);
}
// not sure if we can move this to shared or not
// it would certainly help if SolutionContainer was documented
// but since we usually don't add the component dynamically to entities we can keep this unpredicted for now
private void OnMapInit(Entity<BloodstreamComponent> ent, ref MapInitEvent args)
{
ent.Comp.NextUpdate = _gameTiming.CurTime + ent.Comp.UpdateInterval;
}
private void OnUnpaused(Entity<BloodstreamComponent> ent, ref EntityUnpausedEvent args)
{
ent.Comp.NextUpdate += args.PausedTime;
}
private void OnReactionAttempt(Entity<BloodstreamComponent> entity, ref ReactionAttemptEvent args)
{
if (args.Cancelled)
return;
foreach (var effect in args.Reaction.Effects)
{
switch (effect)
{
case CreateEntityReactionEffect: // Prevent entities from spawning in the bloodstream
case AreaReactionEffect: // No spontaneous smoke or foam leaking out of blood vessels.
args.Cancelled = true;
return;
}
}
// The area-reaction effect canceling is part of avoiding smoke-fork-bombs (create two smoke bombs, that when
// ingested by mobs create more smoke). This also used to act as a rapid chemical-purge, because all the
// reagents would get carried away by the smoke/foam. This does still work for the stomach (I guess people vomit
// up the smoke or spawned entities?).
// TODO apply organ damage instead of just blocking the reaction?
// Having cheese-clots form in your veins can't be good for you.
}
private void OnReactionAttempt(Entity<BloodstreamComponent> entity, ref SolutionRelayEvent<ReactionAttemptEvent> args)
{
if (args.Name != entity.Comp.BloodSolutionName
&& args.Name != entity.Comp.ChemicalSolutionName
&& args.Name != entity.Comp.BloodTemporarySolutionName)
{
return;
}
OnReactionAttempt(entity, ref args.Event);
}
public override void Update(float frameTime)
{
base.Update(frameTime);
var query = EntityQueryEnumerator<BloodstreamComponent>();
while (query.MoveNext(out var uid, out var bloodstream))
{
if (_gameTiming.CurTime < bloodstream.NextUpdate)
continue;
bloodstream.NextUpdate += bloodstream.UpdateInterval;
if (!_solutionContainerSystem.ResolveSolution(uid, bloodstream.BloodSolutionName, ref bloodstream.BloodSolution, out var bloodSolution))
continue;
// Adds blood to their blood level if it is below the maximum; Blood regeneration. Must be alive.
if (bloodSolution.Volume < bloodSolution.MaxVolume && !_mobStateSystem.IsDead(uid))
{
TryModifyBloodLevel(uid, bloodstream.BloodRefreshAmount, bloodstream);
}
// Removes blood from the bloodstream based on bleed amount (bleed rate)
// as well as stop their bleeding to a certain extent.
if (bloodstream.BleedAmount > 0)
{
// Blood is removed from the bloodstream at a 1-1 rate with the bleed amount
TryModifyBloodLevel(uid, (-bloodstream.BleedAmount), bloodstream);
// Bleed rate is reduced by the bleed reduction amount in the bloodstream component.
TryModifyBleedAmount(uid, -bloodstream.BleedReductionAmount, bloodstream);
}
// deal bloodloss damage if their blood level is below a threshold.
var bloodPercentage = GetBloodLevelPercentage(uid, bloodstream);
if (bloodPercentage < bloodstream.BloodlossThreshold && !_mobStateSystem.IsDead(uid))
{
// bloodloss damage is based on the base value, and modified by how low your blood level is.
var amt = bloodstream.BloodlossDamage / (0.1f + bloodPercentage);
_damageableSystem.TryChangeDamage(uid, amt,
ignoreResistances: false, interruptsDoAfters: false);
// Apply dizziness as a symptom of bloodloss.
// The effect is applied in a way that it will never be cleared without being healthy.
// Multiplying by 2 is arbitrary but works for this case, it just prevents the time from running out
_drunkSystem.TryApplyDrunkenness(
uid,
(float) bloodstream.UpdateInterval.TotalSeconds * 2,
applySlur: false);
_stutteringSystem.DoStutter(uid, bloodstream.UpdateInterval * 2, refresh: false);
// storing the drunk and stutter time so we can remove it independently from other effects additions
bloodstream.StatusTime += bloodstream.UpdateInterval * 2;
}
else if (!_mobStateSystem.IsDead(uid))
{
// If they're healthy, we'll try and heal some bloodloss instead.
_damageableSystem.TryChangeDamage(
uid,
bloodstream.BloodlossHealDamage * bloodPercentage,
ignoreResistances: true, interruptsDoAfters: false);
// Remove the drunk effect when healthy. Should only remove the amount of drunk and stutter added by low blood level
_drunkSystem.TryRemoveDrunkenessTime(uid, bloodstream.StatusTime.TotalSeconds);
_stutteringSystem.DoRemoveStutterTime(uid, bloodstream.StatusTime.TotalSeconds);
// Reset the drunk and stutter time to zero
bloodstream.StatusTime = TimeSpan.Zero;
}
}
}
private void OnComponentInit(Entity<BloodstreamComponent> entity, ref ComponentInit args)
{
if (!SolutionContainer.EnsureSolution(entity.Owner,
if (!_solutionContainerSystem.EnsureSolution(entity.Owner,
entity.Comp.ChemicalSolutionName,
out var chemicalSolution) ||
!SolutionContainer.EnsureSolution(entity.Owner,
!_solutionContainerSystem.EnsureSolution(entity.Owner,
entity.Comp.BloodSolutionName,
out var bloodSolution) ||
!SolutionContainer.EnsureSolution(entity.Owner,
!_solutionContainerSystem.EnsureSolution(entity.Owner,
entity.Comp.BloodTemporarySolutionName,
out var tempSolution))
return;
@@ -40,10 +197,298 @@ public sealed class BloodstreamSystem : SharedBloodstreamSystem
bloodSolution.AddReagent(new ReagentId(entity.Comp.BloodReagent, GetEntityBloodData(entity.Owner)), entity.Comp.BloodMaxVolume - bloodSolution.Volume);
}
// forensics is not predicted yet
private void OnDamageChanged(Entity<BloodstreamComponent> ent, ref DamageChangedEvent args)
{
if (args.DamageDelta is null || !args.DamageIncreased)
{
return;
}
// TODO probably cache this or something. humans get hurt a lot
if (!_prototypeManager.TryIndex(ent.Comp.DamageBleedModifiers, out var modifiers))
return;
// some reagents may deal and heal different damage types in the same tick, which means DamageIncreased will be true
// but we only want to consider the dealt damage when causing bleeding
var damage = DamageSpecifier.GetPositive(args.DamageDelta);
var bloodloss = DamageSpecifier.ApplyModifierSet(damage, modifiers);
if (bloodloss.Empty)
return;
// Does the calculation of how much bleed rate should be added/removed, then applies it
var oldBleedAmount = ent.Comp.BleedAmount;
var total = bloodloss.GetTotal();
var totalFloat = total.Float();
TryModifyBleedAmount(ent, totalFloat, ent);
/// <summary>
/// Critical hit. Causes target to lose blood, using the bleed rate modifier of the weapon, currently divided by 5
/// The crit chance is currently the bleed rate modifier divided by 25.
/// Higher damage weapons have a higher chance to crit!
/// </summary>
var prob = Math.Clamp(totalFloat / 25, 0, 1);
if (totalFloat > 0 && _robustRandom.Prob(prob))
{
TryModifyBloodLevel(ent, -total / 5, ent);
_audio.PlayPvs(ent.Comp.InstantBloodSound, ent);
}
// Heat damage will cauterize, causing the bleed rate to be reduced.
else if (totalFloat <= ent.Comp.BloodHealedSoundThreshold && oldBleedAmount > 0)
{
// Magically, this damage has healed some bleeding, likely
// because it's burn damage that cauterized their wounds.
// We'll play a special sound and popup for feedback.
_audio.PlayPvs(ent.Comp.BloodHealedSound, ent);
_popupSystem.PopupEntity(Loc.GetString("bloodstream-component-wounds-cauterized"), ent,
ent, PopupType.Medium);
}
}
/// <summary>
/// Shows text on health examine, based on bleed rate and blood level.
/// </summary>
private void OnHealthBeingExamined(Entity<BloodstreamComponent> ent, ref HealthBeingExaminedEvent args)
{
// Shows massively bleeding at 0.75x the max bleed rate.
if (ent.Comp.BleedAmount > ent.Comp.MaxBleedAmount * 0.75f)
{
args.Message.PushNewline();
args.Message.AddMarkupOrThrow(Loc.GetString("bloodstream-component-massive-bleeding", ("target", ent.Owner)));
}
// Shows bleeding message when bleeding above half the max rate, but less than massively.
else if (ent.Comp.BleedAmount > ent.Comp.MaxBleedAmount * 0.5f)
{
args.Message.PushNewline();
args.Message.AddMarkupOrThrow(Loc.GetString("bloodstream-component-strong-bleeding", ("target", ent.Owner)));
}
// Shows bleeding message when bleeding above 0.25x the max rate, but less than half the max.
else if (ent.Comp.BleedAmount > ent.Comp.MaxBleedAmount * 0.25f)
{
args.Message.PushNewline();
args.Message.AddMarkupOrThrow(Loc.GetString("bloodstream-component-bleeding", ("target", ent.Owner)));
}
// Shows bleeding message when bleeding below 0.25x the max cap
else if (ent.Comp.BleedAmount > 0)
{
args.Message.PushNewline();
args.Message.AddMarkupOrThrow(Loc.GetString("bloodstream-component-slight-bleeding", ("target", ent.Owner)));
}
// If the mob's blood level is below the damage threshhold, the pale message is added.
if (GetBloodLevelPercentage(ent, ent) < ent.Comp.BloodlossThreshold)
{
args.Message.PushNewline();
args.Message.AddMarkupOrThrow(Loc.GetString("bloodstream-component-looks-pale", ("target", ent.Owner)));
}
}
private void OnBeingGibbed(Entity<BloodstreamComponent> ent, ref BeingGibbedEvent args)
{
SpillAllSolutions(ent, ent);
}
private void OnApplyMetabolicMultiplier(
Entity<BloodstreamComponent> ent,
ref ApplyMetabolicMultiplierEvent args)
{
// TODO REFACTOR THIS
// This will slowly drift over time due to floating point errors.
// Instead, raise an event with the base rates and allow modifiers to get applied to it.
if (args.Apply)
{
ent.Comp.UpdateInterval *= args.Multiplier;
return;
}
ent.Comp.UpdateInterval /= args.Multiplier;
}
private void OnRejuvenate(Entity<BloodstreamComponent> entity, ref RejuvenateEvent args)
{
TryModifyBleedAmount(entity.Owner, -entity.Comp.BleedAmount, entity.Comp);
if (_solutionContainerSystem.ResolveSolution(entity.Owner, entity.Comp.BloodSolutionName, ref entity.Comp.BloodSolution, out var bloodSolution))
TryModifyBloodLevel(entity.Owner, bloodSolution.AvailableVolume, entity.Comp);
if (_solutionContainerSystem.ResolveSolution(entity.Owner, entity.Comp.ChemicalSolutionName, ref entity.Comp.ChemicalSolution))
_solutionContainerSystem.RemoveAllSolution(entity.Comp.ChemicalSolution.Value);
}
/// <summary>
/// Attempt to transfer provided solution to internal solution.
/// </summary>
public bool TryAddToChemicals(EntityUid uid, Solution solution, BloodstreamComponent? component = null)
{
return Resolve(uid, ref component, logMissing: false)
&& _solutionContainerSystem.ResolveSolution(uid, component.ChemicalSolutionName, ref component.ChemicalSolution)
&& _solutionContainerSystem.TryAddSolution(component.ChemicalSolution.Value, solution);
}
public bool FlushChemicals(EntityUid uid, string excludedReagentID, FixedPoint2 quantity, BloodstreamComponent? component = null)
{
if (!Resolve(uid, ref component, logMissing: false)
|| !_solutionContainerSystem.ResolveSolution(uid, component.ChemicalSolutionName, ref component.ChemicalSolution, out var chemSolution))
return false;
for (var i = chemSolution.Contents.Count - 1; i >= 0; i--)
{
var (reagentId, _) = chemSolution.Contents[i];
if (reagentId.Prototype != excludedReagentID)
{
_solutionContainerSystem.RemoveReagent(component.ChemicalSolution.Value, reagentId, quantity);
}
}
return true;
}
public float GetBloodLevelPercentage(EntityUid uid, BloodstreamComponent? component = null)
{
if (!Resolve(uid, ref component)
|| !_solutionContainerSystem.ResolveSolution(uid, component.BloodSolutionName, ref component.BloodSolution, out var bloodSolution))
{
return 0.0f;
}
return bloodSolution.FillFraction;
}
public void SetBloodLossThreshold(EntityUid uid, float threshold, BloodstreamComponent? comp = null)
{
if (!Resolve(uid, ref comp))
return;
comp.BloodlossThreshold = threshold;
}
/// <summary>
/// Attempts to modify the blood level of this entity directly.
/// </summary>
public bool TryModifyBloodLevel(EntityUid uid, FixedPoint2 amount, BloodstreamComponent? component = null)
{
if (!Resolve(uid, ref component, logMissing: false)
|| !_solutionContainerSystem.ResolveSolution(uid, component.BloodSolutionName, ref component.BloodSolution))
{
return false;
}
if (amount >= 0)
return _solutionContainerSystem.TryAddReagent(component.BloodSolution.Value, component.BloodReagent, amount, null, GetEntityBloodData(uid));
// Removal is more involved,
// since we also wanna handle moving it to the temporary solution
// and then spilling it if necessary.
var newSol = _solutionContainerSystem.SplitSolution(component.BloodSolution.Value, -amount);
if (!_solutionContainerSystem.ResolveSolution(uid, component.BloodTemporarySolutionName, ref component.TemporarySolution, out var tempSolution))
return true;
tempSolution.AddSolution(newSol, _prototypeManager);
if (tempSolution.Volume > component.BleedPuddleThreshold)
{
// Pass some of the chemstream into the spilled blood.
if (_solutionContainerSystem.ResolveSolution(uid, component.ChemicalSolutionName, ref component.ChemicalSolution))
{
var temp = _solutionContainerSystem.SplitSolution(component.ChemicalSolution.Value, tempSolution.Volume / 10);
tempSolution.AddSolution(temp, _prototypeManager);
}
_puddleSystem.TrySpillAt(uid, tempSolution, out var puddleUid, sound: false);
tempSolution.RemoveAllSolution();
}
_solutionContainerSystem.UpdateChemicals(component.TemporarySolution.Value);
return true;
}
/// <summary>
/// Tries to make an entity bleed more or less
/// </summary>
public bool TryModifyBleedAmount(EntityUid uid, float amount, BloodstreamComponent? component = null)
{
if (!Resolve(uid, ref component, logMissing: false))
return false;
component.BleedAmount += amount;
component.BleedAmount = Math.Clamp(component.BleedAmount, 0, component.MaxBleedAmount);
if (component.BleedAmount == 0)
_alertsSystem.ClearAlert(uid, component.BleedingAlert);
else
{
var severity = (short) Math.Clamp(Math.Round(component.BleedAmount, MidpointRounding.ToZero), 0, 10);
_alertsSystem.ShowAlert(uid, component.BleedingAlert, severity);
}
return true;
}
/// <summary>
/// BLOOD FOR THE BLOOD GOD
/// </summary>
public void SpillAllSolutions(EntityUid uid, BloodstreamComponent? component = null)
{
if (!Resolve(uid, ref component))
return;
var tempSol = new Solution();
if (_solutionContainerSystem.ResolveSolution(uid, component.BloodSolutionName, ref component.BloodSolution, out var bloodSolution))
{
tempSol.MaxVolume += bloodSolution.MaxVolume;
tempSol.AddSolution(bloodSolution, _prototypeManager);
_solutionContainerSystem.RemoveAllSolution(component.BloodSolution.Value);
}
if (_solutionContainerSystem.ResolveSolution(uid, component.ChemicalSolutionName, ref component.ChemicalSolution, out var chemSolution))
{
tempSol.MaxVolume += chemSolution.MaxVolume;
tempSol.AddSolution(chemSolution, _prototypeManager);
_solutionContainerSystem.RemoveAllSolution(component.ChemicalSolution.Value);
}
if (_solutionContainerSystem.ResolveSolution(uid, component.BloodTemporarySolutionName, ref component.TemporarySolution, out var tempSolution))
{
tempSol.MaxVolume += tempSolution.MaxVolume;
tempSol.AddSolution(tempSolution, _prototypeManager);
_solutionContainerSystem.RemoveAllSolution(component.TemporarySolution.Value);
}
_puddleSystem.TrySpillAt(uid, tempSol, out var puddleUid);
}
/// <summary>
/// Change what someone's blood is made of, on the fly.
/// </summary>
public void ChangeBloodReagent(EntityUid uid, string reagent, BloodstreamComponent? component = null)
{
if (!Resolve(uid, ref component, logMissing: false)
|| reagent == component.BloodReagent)
{
return;
}
if (!_solutionContainerSystem.ResolveSolution(uid, component.BloodSolutionName, ref component.BloodSolution, out var bloodSolution))
{
component.BloodReagent = reagent;
return;
}
var currentVolume = bloodSolution.RemoveReagent(component.BloodReagent, bloodSolution.Volume, ignoreReagentData: true);
component.BloodReagent = reagent;
if (currentVolume > 0)
_solutionContainerSystem.TryAddReagent(component.BloodSolution.Value, component.BloodReagent, currentVolume, null, GetEntityBloodData(uid));
}
private void OnDnaGenerated(Entity<BloodstreamComponent> entity, ref GenerateDnaEvent args)
{
if (SolutionContainer.ResolveSolution(entity.Owner, entity.Comp.BloodSolutionName, ref entity.Comp.BloodSolution, out var bloodSolution))
if (_solutionContainerSystem.ResolveSolution(entity.Owner, entity.Comp.BloodSolutionName, ref entity.Comp.BloodSolution, out var bloodSolution))
{
foreach (var reagent in bloodSolution.Contents)
{
@@ -55,4 +500,22 @@ public sealed class BloodstreamSystem : SharedBloodstreamSystem
else
Log.Error("Unable to set bloodstream DNA, solution entity could not be resolved");
}
/// <summary>
/// Get the reagent data for blood that a specific entity should have.
/// </summary>
public List<ReagentData> GetEntityBloodData(EntityUid uid)
{
var bloodData = new List<ReagentData>();
var dnaData = new DnaData();
if (TryComp<DnaComponent>(uid, out var donorComp) && donorComp.DNA != null)
dnaData.DNA = donorComp.DNA;
else
dnaData.DNA = Loc.GetString("forensics-dna-unknown");
bloodData.Add(dnaData);
return bloodData;
}
}

View File

@@ -1,4 +1,5 @@
using System.Numerics;
using Content.Server.Body.Components;
using Content.Server.Ghost;
using Content.Server.Humanoid;
using Content.Shared.Body.Components;

View File

@@ -1,5 +1,4 @@
using Content.Server.Atmos.EntitySystems;
using Content.Server.Body.Components;
using Content.Server.Popups;
using Content.Shared.Alert;
using Content.Shared.Atmos;
@@ -59,7 +58,7 @@ public sealed class InternalsSystem : SharedInternalsSystem
if (AreInternalsWorking(ent))
{
var gasTank = Comp<GasTankComponent>(ent.Comp.GasTankEntity!.Value);
args.Gas = _gasTank.RemoveAirVolume((ent.Comp.GasTankEntity.Value, gasTank), args.Respirator.BreathVolume);
args.Gas = _gasTank.RemoveAirVolume((ent.Comp.GasTankEntity.Value, gasTank), Atmospherics.BreathVolume);
// TODO: Should listen to gas tank updates instead I guess?
_alerts.ShowAlert(ent, ent.Comp.InternalsAlert, GetSeverity(ent));
}

View File

@@ -63,9 +63,6 @@ public sealed class LungSystem : EntitySystem
_solutionContainerSystem.UpdateChemicals(lung.Solution.Value);
}
/* This should really be moved to somewhere in the atmos system and modernized,
so that other systems, like CondenserSystem, can use it.
*/
private void GasToReagent(GasMixture gas, Solution solution)
{
foreach (var gasId in Enum.GetValues<Gas>())

View File

@@ -50,8 +50,6 @@ public sealed class RespiratorSystem : EntitySystem
SubscribeLocalEvent<RespiratorComponent, MapInitEvent>(OnMapInit);
SubscribeLocalEvent<RespiratorComponent, EntityUnpausedEvent>(OnUnpaused);
SubscribeLocalEvent<RespiratorComponent, ApplyMetabolicMultiplierEvent>(OnApplyMetabolicMultiplier);
SubscribeLocalEvent<BodyComponent, InhaledGasEvent>(OnGasInhaled);
SubscribeLocalEvent<BodyComponent, ExhaledGasEvent>(OnGasExhaled);
}
private void OnMapInit(Entity<RespiratorComponent> ent, ref MapInitEvent args)
@@ -79,18 +77,18 @@ public sealed class RespiratorSystem : EntitySystem
if (_mobState.IsDead(uid))
continue;
UpdateSaturation(uid, -(float)respirator.UpdateInterval.TotalSeconds, respirator);
UpdateSaturation(uid, -(float) respirator.UpdateInterval.TotalSeconds, respirator);
if (!_mobState.IsIncapacitated(uid)) // cannot breathe in crit.
{
switch (respirator.Status)
{
case RespiratorStatus.Inhaling:
Inhale(uid);
Inhale(uid, body);
respirator.Status = RespiratorStatus.Exhaling;
break;
case RespiratorStatus.Exhaling:
Exhale(uid);
Exhale(uid, body);
respirator.Status = RespiratorStatus.Inhaling;
break;
}
@@ -101,10 +99,7 @@ public sealed class RespiratorSystem : EntitySystem
if (_gameTiming.CurTime >= respirator.LastGaspEmoteTime + respirator.GaspEmoteCooldown)
{
respirator.LastGaspEmoteTime = _gameTiming.CurTime;
_chat.TryEmoteWithChat(uid,
respirator.GaspEmote,
ChatTransmitRange.HideChat,
ignoreActionBlocker: true);
_chat.TryEmoteWithChat(uid, respirator.GaspEmote, ChatTransmitRange.HideChat, ignoreActionBlocker: true);
}
TakeSuffocationDamage((uid, respirator));
@@ -117,54 +112,68 @@ public sealed class RespiratorSystem : EntitySystem
}
}
public bool Inhale(Entity<RespiratorComponent?> entity)
public void Inhale(EntityUid uid, BodyComponent? body = null)
{
if (!Resolve(entity, ref entity.Comp, logMissing: false))
return false;
if (!Resolve(uid, ref body, logMissing: false))
return;
var organs = _bodySystem.GetBodyOrganEntityComps<LungComponent>((uid, body));
// Inhale gas
var ev = new InhaleLocationEvent
{
Respirator = entity.Comp,
};
RaiseLocalEvent(entity, ref ev);
var ev = new InhaleLocationEvent();
RaiseLocalEvent(uid, ref ev);
ev.Gas ??= _atmosSys.GetContainingMixture(entity.Owner, excite: true);
ev.Gas ??= _atmosSys.GetContainingMixture(uid, excite: true);
if (ev.Gas is null)
{
return false;
return;
}
var gas = ev.Gas.RemoveVolume(entity.Comp.BreathVolume);
var actualGas = ev.Gas.RemoveVolume(Atmospherics.BreathVolume);
var inhaleEv = new InhaledGasEvent(gas);
RaiseLocalEvent(entity, ref inhaleEv);
return inhaleEv.Handled && inhaleEv.Succeeded;
var lungRatio = 1.0f / organs.Count;
var gas = organs.Count == 1 ? actualGas : actualGas.RemoveRatio(lungRatio);
foreach (var (organUid, lung, _) in organs)
{
// Merge doesn't remove gas from the giver.
_atmosSys.Merge(lung.Air, gas);
_lungSystem.GasToReagent(organUid, lung);
}
}
public void Exhale(Entity<RespiratorComponent?> entity)
public void Exhale(EntityUid uid, BodyComponent? body = null)
{
if (!Resolve(entity, ref entity.Comp, logMissing: false))
if (!Resolve(uid, ref body, logMissing: false))
return;
var organs = _bodySystem.GetBodyOrganEntityComps<LungComponent>((uid, body));
// exhale gas
var ev = new ExhaleLocationEvent();
RaiseLocalEvent(entity, ref ev, broadcast: false);
RaiseLocalEvent(uid, ref ev, broadcast: false);
if (ev.Gas is null)
{
ev.Gas = _atmosSys.GetContainingMixture(entity.Owner, excite: true);
ev.Gas = _atmosSys.GetContainingMixture(uid, excite: true);
// Walls and grids without atmos comp return null. I guess it makes sense to not be able to exhale in walls,
// but this also means you cannot exhale on some grids.
ev.Gas ??= GasMixture.SpaceGas;
}
var exhaleEv = new ExhaledGasEvent(ev.Gas);
RaiseLocalEvent(entity, ref exhaleEv);
var outGas = new GasMixture(ev.Gas.Volume);
foreach (var (organUid, lung, _) in organs)
{
_atmosSys.Merge(outGas, lung.Air);
lung.Air.Clear();
if (_solutionContainerSystem.ResolveSolution(organUid, lung.SolutionName, ref lung.Solution))
_solutionContainerSystem.RemoveAllSolution(lung.Solution.Value);
}
_atmosSys.Merge(ev.Gas, outGas);
}
/// <summary>
@@ -190,15 +199,14 @@ public sealed class RespiratorSystem : EntitySystem
if (!Resolve(ent, ref ent.Comp))
return false;
if (!Inhale(ent))
var ev = new InhaleLocationEvent();
RaiseLocalEvent(ent, ref ev);
var gas = ev.Gas ?? _atmosSys.GetContainingMixture(ent.Owner);
if (gas == null)
return false;
// If we don't have a body we can't be poisoned by gas, yet...
var success = TryMetabolizeGas((ent, ent.Comp));
// Don't keep that gas in our lungs lest it poisons a poor nuclear operative.
Exhale(ent);
return success;
return CanMetabolizeGas(ent, gas);
}
/// <summary>
@@ -216,7 +224,7 @@ public sealed class RespiratorSystem : EntitySystem
gas = new GasMixture(gas);
var lungRatio = 1.0f / organs.Count;
gas.Multiply(MathF.Min(lungRatio * gas.Volume / ent.Comp.BreathVolume, lungRatio));
gas.Multiply(MathF.Min(lungRatio * gas.Volume/Atmospherics.BreathVolume, lungRatio));
var solution = _lungSystem.GasToReagent(gas);
float saturation = 0;
@@ -230,71 +238,6 @@ public sealed class RespiratorSystem : EntitySystem
return saturation > ent.Comp.UpdateInterval.TotalSeconds;
}
public bool TryInhaleGasToBody(Entity<BodyComponent?> entity, GasMixture gas)
{
if (!Resolve(entity, ref entity.Comp))
return false;
var organs = _bodySystem.GetBodyOrganEntityComps<LungComponent>((entity, entity.Comp));
if (organs.Count == 0)
return false;
var lungRatio = 1.0f / organs.Count;
var splitGas = organs.Count == 1 ? gas : gas.RemoveRatio(lungRatio);
foreach (var (organUid, lung, _) in organs)
{
// Merge doesn't remove gas from the giver.
_atmosSys.Merge(lung.Air, splitGas);
_lungSystem.GasToReagent(organUid, lung);
}
return true;
}
public void RemoveGasFromBody(Entity<BodyComponent> ent, GasMixture gas)
{
var outGas = new GasMixture(gas.Volume);
var organs = _bodySystem.GetBodyOrganEntityComps<LungComponent>((ent, ent.Comp));
if (organs.Count == 0)
return;
foreach (var (organUid, lung, _) in organs)
{
_atmosSys.Merge(outGas, lung.Air);
lung.Air.Clear();
if (_solutionContainerSystem.ResolveSolution(organUid, lung.SolutionName, ref lung.Solution))
_solutionContainerSystem.RemoveAllSolution(lung.Solution.Value);
}
_atmosSys.Merge(gas, outGas);
}
/// <summary>
/// Tries to safely metabolize the current solutions in a body's lungs.
/// </summary>
private bool TryMetabolizeGas(Entity<RespiratorComponent, BodyComponent?> ent)
{
if (!Resolve(ent, ref ent.Comp2))
return false;
var organs = _bodySystem.GetBodyOrganEntityComps<LungComponent>((ent, null));
if (organs.Count == 0)
return false;
float saturation = 0;
foreach (var organ in organs)
{
var solution = _lungSystem.GasToReagent(organ.Comp1.Air);
saturation += GetSaturation(solution, organ.Owner, out var toxic);
if (toxic)
return false;
}
return saturation > ent.Comp1.UpdateInterval.TotalSeconds;
}
/// <summary>
/// Get the amount of saturation that would be generated if the lung were to metabolize the given solution.
/// </summary>
@@ -358,8 +301,6 @@ public sealed class RespiratorSystem : EntitySystem
if (ent.Comp.SuffocationCycles == 2)
_adminLogger.Add(LogType.Asphyxiation, $"{ToPrettyString(ent):entity} started suffocating");
_damageableSys.TryChangeDamage(ent, ent.Comp.Damage, interruptsDoAfters: false);
if (ent.Comp.SuffocationCycles >= ent.Comp.SuffocationCycleThreshold)
{
// TODO: This is not going work with multiple different lungs, if that ever becomes a possibility
@@ -369,6 +310,8 @@ public sealed class RespiratorSystem : EntitySystem
_alertsSystem.ShowAlert(ent, entity.Comp1.Alert);
}
}
_damageableSys.TryChangeDamage(ent, ent.Comp.Damage, interruptsDoAfters: false);
}
private void StopSuffocation(Entity<RespiratorComponent> ent)
@@ -376,17 +319,18 @@ public sealed class RespiratorSystem : EntitySystem
if (ent.Comp.SuffocationCycles >= 2)
_adminLogger.Add(LogType.Asphyxiation, $"{ToPrettyString(ent):entity} stopped suffocating");
_damageableSys.TryChangeDamage(ent, ent.Comp.DamageRecovery);
// TODO: This is not going work with multiple different lungs, if that ever becomes a possibility
var organs = _bodySystem.GetBodyOrganEntityComps<LungComponent>((ent, null));
foreach (var entity in organs)
{
_alertsSystem.ClearAlert(ent, entity.Comp1.Alert);
}
_damageableSys.TryChangeDamage(ent, ent.Comp.DamageRecovery);
}
public void UpdateSaturation(EntityUid uid, float amount, RespiratorComponent? respirator = null)
public void UpdateSaturation(EntityUid uid, float amount,
RespiratorComponent? respirator = null)
{
if (!Resolve(uid, ref respirator, false))
return;
@@ -418,30 +362,10 @@ public sealed class RespiratorSystem : EntitySystem
ent.Comp.MaxSaturation /= args.Multiplier;
ent.Comp.MinSaturation /= args.Multiplier;
}
private void OnGasInhaled(Entity<BodyComponent> entity, ref InhaledGasEvent args)
{
args.Handled = true;
args.Succeeded = TryInhaleGasToBody((entity, entity.Comp), args.Gas);
}
private void OnGasExhaled(Entity<BodyComponent> entity, ref ExhaledGasEvent args)
{
args.Handled = true;
RemoveGasFromBody(entity, args.Gas);
}
}
[ByRefEvent]
public record struct InhaleLocationEvent(GasMixture? Gas, RespiratorComponent Respirator);
public record struct InhaleLocationEvent(GasMixture? Gas);
[ByRefEvent]
public record struct ExhaleLocationEvent(GasMixture? Gas);
[ByRefEvent]
public record struct InhaledGasEvent(GasMixture Gas, bool Handled = false, bool Succeeded = false);
[ByRefEvent]
public record struct ExhaledGasEvent(GasMixture Gas, bool Handled = false);

View File

@@ -1,6 +1,5 @@
using Content.Server.Atmos.EntitySystems;
using Content.Server.Botany.Components;
using Content.Server.Hands.Systems;
using Content.Server.Kitchen.Components;
using Content.Server.Popups;
using Content.Shared.Chemistry.EntitySystems;
@@ -38,7 +37,6 @@ public sealed class PlantHolderSystem : EntitySystem
[Dependency] private readonly MutationSystem _mutation = default!;
[Dependency] private readonly AppearanceSystem _appearance = default!;
[Dependency] private readonly SharedAudioSystem _audio = default!;
[Dependency] private readonly HandsSystem _hands = default!;
[Dependency] private readonly PopupSystem _popup = default!;
[Dependency] private readonly IGameTiming _gameTiming = default!;
[Dependency] private readonly SharedSolutionContainerSystem _solutionContainerSystem = default!;
@@ -47,7 +45,7 @@ public sealed class PlantHolderSystem : EntitySystem
[Dependency] private readonly IRobustRandom _random = default!;
[Dependency] private readonly ItemSlotsSystem _itemSlots = default!;
[Dependency] private readonly ISharedAdminLogManager _adminLogger = default!;
public const float HydroponicsSpeedMultiplier = 1f;
public const float HydroponicsConsumptionMultiplier = 2f;
@@ -708,9 +706,9 @@ public sealed class PlantHolderSystem : EntitySystem
if (component.Harvest && !component.Dead)
{
if (_hands.TryGetActiveItem(user, out var activeItem))
if (TryComp<HandsComponent>(user, out var hands))
{
if (!_botany.CanHarvest(component.Seed, activeItem))
if (!_botany.CanHarvest(component.Seed, hands.ActiveHandEntity))
{
_popup.PopupCursor(Loc.GetString("plant-holder-component-ligneous-cant-harvest-message"), user);
return false;

View File

@@ -626,7 +626,7 @@ namespace Content.Server.Cargo.Systems
_transformSystem.Unanchor(item, Transform(item));
// Create a sheet of paper to write the order details on
var printed = Spawn(paperProto, spawn);
var printed = EntityManager.SpawnEntity(paperProto, spawn);
if (TryComp<PaperComponent>(printed, out var paper))
{
// fill in the order data

View File

@@ -47,7 +47,7 @@ public sealed class NanoTaskCartridgeSystem : SharedNanoTaskCartridgeSystem
{
return;
}
if (!TryComp<NanoTaskPrintedComponent>(args.Used, out var printed))
if (!EntityManager.TryGetComponent<NanoTaskPrintedComponent>(args.Used, out var printed))
{
return;
}
@@ -55,7 +55,7 @@ public sealed class NanoTaskCartridgeSystem : SharedNanoTaskCartridgeSystem
{
program.Tasks.Add(new(program.Counter++, printed.Task));
args.Handled = true;
Del(args.Used);
EntityManager.DeleteEntity(args.Used);
UpdateUiState(new Entity<NanoTaskCartridgeComponent>(uid.Value, program), ent.Owner);
}
}

View File

@@ -1,9 +1,9 @@
using Content.Server.Ghost;
using Content.Server.Hands.Systems;
using Content.Shared.Administration.Logs;
using Content.Shared.Chat;
using Content.Shared.Damage;
using Content.Shared.Database;
using Content.Shared.Hands.Components;
using Content.Shared.IdentityManagement;
using Content.Shared.Interaction.Events;
using Content.Shared.Item;
@@ -22,7 +22,6 @@ public sealed class SuicideSystem : EntitySystem
{
[Dependency] private readonly EntityLookupSystem _entityLookupSystem = default!;
[Dependency] private readonly ISharedAdminLogManager _adminLogger = default!;
[Dependency] private readonly HandsSystem _hands = default!;
[Dependency] private readonly TagSystem _tagSystem = default!;
[Dependency] private readonly MobStateSystem _mobState = default!;
[Dependency] private readonly SharedPopupSystem _popup = default!;
@@ -51,7 +50,7 @@ public sealed class SuicideSystem : EntitySystem
if (!TryComp<MobStateComponent>(victim, out var mobState) || _mobState.IsDead(victim, mobState))
return false;
_adminLogger.Add(LogType.Mind, $"{ToPrettyString(victim):player} is attempting to suicide");
_adminLogger.Add(LogType.Mind, $"{EntityManager.ToPrettyString(victim):player} is attempting to suicide");
ICommonSession? session = null;
@@ -77,7 +76,7 @@ public sealed class SuicideSystem : EntitySystem
}
else
{
_adminLogger.Add(LogType.Mind, $"{ToPrettyString(victim):player} suicided.");
_adminLogger.Add(LogType.Mind, $"{EntityManager.ToPrettyString(victim):player} suicided.");
}
return true;
}
@@ -117,9 +116,10 @@ public sealed class SuicideSystem : EntitySystem
var suicideByEnvironmentEvent = new SuicideByEnvironmentEvent(victim);
// Try to suicide by raising an event on the held item
if (_hands.TryGetActiveItem(victim.Owner, out var item))
if (EntityManager.TryGetComponent(victim, out HandsComponent? handsComponent)
&& handsComponent.ActiveHandEntity is { } item)
{
RaiseLocalEvent(item.Value, suicideByEnvironmentEvent);
RaiseLocalEvent(item, suicideByEnvironmentEvent);
if (suicideByEnvironmentEvent.Handled)
{
args.Handled = suicideByEnvironmentEvent.Handled;

View File

@@ -397,7 +397,7 @@ public sealed partial class ChatSystem : SharedChatSystem
return;
}
if (!TryComp<StationDataComponent>(station, out var stationDataComp)) return;
if (!EntityManager.TryGetComponent<StationDataComponent>(station, out var stationDataComp)) return;
var filter = _stationSystem.GetInStation(stationDataComp);

View File

@@ -7,31 +7,32 @@ using Robust.Shared.Prototypes;
namespace Content.Server.Chemistry.Commands;
[AdminCommand(AdminFlags.Debug)]
public sealed class DumpReagentGuideText : LocalizedEntityCommands
public sealed class DumpReagentGuideText : IConsoleCommand
{
[Dependency] private readonly IPrototypeManager _prototype = default!;
[Dependency] private readonly IEntitySystemManager _entSys = default!;
public override string Command => "dumpreagentguidetext";
public string Command => "dumpreagentguidetext";
public string Description => "Dumps the guidebook text for a reagent to the console";
public string Help => "dumpreagentguidetext <reagent>";
public override void Execute(IConsoleShell shell, string argStr, string[] args)
public void Execute(IConsoleShell shell, string argStr, string[] args)
{
if (args.Length != 1)
{
shell.WriteError(Loc.GetString($"shell-need-exactly-one-argument"));
shell.WriteError("Must have only 1 argument");
return;
}
if (!_prototype.TryIndex<ReagentPrototype>(args[0], out var reagent))
{
shell.WriteError(Loc.GetString($"shell-argument-must-be-prototype",
("index", args[0]),
("prototype", nameof(ReagentPrototype))));
shell.WriteError($"Invalid prototype: {args[0]}");
return;
}
if (reagent.Metabolisms is null)
{
shell.WriteLine(Loc.GetString($"cmd-dumpreagentguidetext-nothing-to-dump"));
shell.WriteLine("Nothing to dump.");
return;
}
@@ -39,8 +40,7 @@ public sealed class DumpReagentGuideText : LocalizedEntityCommands
{
foreach (var effect in entry.Effects)
{
shell.WriteLine(effect.GuidebookEffectDescription(_prototype, EntityManager.EntitySysManager) ??
Loc.GetString($"cmd-dumpreagentguidetext-skipped", ("effect", effect.GetType())));
shell.WriteLine(effect.GuidebookEffectDescription(_prototype, _entSys) ?? $"[skipped effect of type {effect.GetType()}]");
}
}
}

View File

@@ -32,7 +32,7 @@ namespace Content.Server.Chemistry.EntitySystems.DeleteOnSolutionEmptySystem
if (_solutionContainerSystem.TryGetSolution((entity.Owner, solutions), entity.Comp.Solution, out _, out var solution))
if (solution.Volume <= 0)
QueueDel(entity);
EntityManager.QueueDeleteEntity(entity);
}
}
}

View File

@@ -1,10 +1,11 @@
using Content.Server.Body.Components;
using Content.Server.Body.Systems;
using Content.Shared._CP14.Farming;
using Content.Shared.Chemistry;
using Content.Shared.Chemistry.Components;
using Content.Shared.Chemistry.Components.SolutionManager;
using Content.Shared.Chemistry.EntitySystems;
using Content.Shared.Body.Components;
using Content.Shared.Chemistry.Reagent;
using Content.Shared.Database;
using Content.Shared.DoAfter;
using Content.Shared.FixedPoint;
@@ -176,12 +177,12 @@ public sealed class InjectorSystem : SharedInjectorSystem
if (injector.Comp.ToggleState == InjectorToggleMode.Inject)
{
AdminLogger.Add(LogType.ForceFeed,
$"{ToPrettyString(user):user} is attempting to inject {ToPrettyString(target):target} with a solution {SharedSolutionContainerSystem.ToPrettyString(solution):solution}");
$"{EntityManager.ToPrettyString(user):user} is attempting to inject {EntityManager.ToPrettyString(target):target} with a solution {SharedSolutionContainerSystem.ToPrettyString(solution):solution}");
}
else
{
AdminLogger.Add(LogType.ForceFeed,
$"{ToPrettyString(user):user} is attempting to draw {injector.Comp.TransferAmount.ToString()} units from {ToPrettyString(target):target}");
$"{EntityManager.ToPrettyString(user):user} is attempting to draw {injector.Comp.TransferAmount.ToString()} units from {EntityManager.ToPrettyString(target):target}");
}
}
else
@@ -192,12 +193,12 @@ public sealed class InjectorSystem : SharedInjectorSystem
if (injector.Comp.ToggleState == InjectorToggleMode.Inject)
{
AdminLogger.Add(LogType.Ingestion,
$"{ToPrettyString(user):user} is attempting to inject themselves with a solution {SharedSolutionContainerSystem.ToPrettyString(solution):solution}.");
$"{EntityManager.ToPrettyString(user):user} is attempting to inject themselves with a solution {SharedSolutionContainerSystem.ToPrettyString(solution):solution}.");
}
else
{
AdminLogger.Add(LogType.ForceFeed,
$"{ToPrettyString(user):user} is attempting to draw {injector.Comp.TransferAmount.ToString()} units from themselves.");
$"{EntityManager.ToPrettyString(user):user} is attempting to draw {injector.Comp.TransferAmount.ToString()} units from themselves.");
}
}
@@ -237,7 +238,7 @@ public sealed class InjectorSystem : SharedInjectorSystem
// Move units from attackSolution to targetSolution
var removedSolution = SolutionContainers.SplitSolution(target.Comp.ChemicalSolution.Value, realTransferAmount);
_blood.TryAddToChemicals(target.AsNullable(), removedSolution);
_blood.TryAddToChemicals(target, removedSolution, target.Comp);
_reactiveSystem.DoEntityReaction(target, removedSolution, ReactionMethod.Injection);

View File

@@ -1,7 +1,7 @@
using Content.Server.Body.Components;
using Content.Server.Body.Systems;
using Content.Server.Chemistry.Components;
using Content.Shared.Chemistry.EntitySystems;
using Content.Shared.Body.Components;
using Content.Shared.Chemistry.Events;
using Content.Shared.Inventory;
using Content.Shared.Popups;
@@ -148,7 +148,7 @@ public sealed class SolutionInjectOnCollideSystem : EntitySystem
// Take our portion of the adjusted solution for this target
var individualInjection = solutionToInject.SplitSolution(volumePerBloodstream);
// Inject our portion into the target's bloodstream
if (_bloodstream.TryAddToChemicals(targetBloodstream.AsNullable(), individualInjection))
if (_bloodstream.TryAddToChemicals(targetBloodstream.Owner, individualInjection, targetBloodstream.Comp))
anySuccess = true;
}

View File

@@ -39,7 +39,7 @@ namespace Content.Server.Chemistry.EntitySystems
private void HandleCollide(Entity<VaporComponent> entity, ref StartCollideEvent args)
{
if (!TryComp(entity.Owner, out SolutionContainerManagerComponent? contents)) return;
if (!EntityManager.TryGetComponent(entity.Owner, out SolutionContainerManagerComponent? contents)) return;
foreach (var (_, soln) in _solutionContainerSystem.EnumerateSolutions((entity.Owner, contents)))
{
@@ -50,7 +50,7 @@ namespace Content.Server.Chemistry.EntitySystems
// Check for collision with a impassable object (e.g. wall) and stop
if ((args.OtherFixture.CollisionLayer & (int)CollisionGroup.Impassable) != 0 && args.OtherFixture.Hard)
{
QueueDel(entity);
EntityManager.QueueDeleteEntity(entity);
}
}
@@ -67,7 +67,7 @@ namespace Content.Server.Chemistry.EntitySystems
despawn.Lifetime = aliveTime;
// Set Move
if (TryComp(vapor, out PhysicsComponent? physics))
if (EntityManager.TryGetComponent(vapor, out PhysicsComponent? physics))
{
_physics.SetLinearDamping(vapor, physics, 0f);
_physics.SetAngularDamping(vapor, physics, 0f);
@@ -156,7 +156,7 @@ namespace Content.Server.Chemistry.EntitySystems
// Delete the vapor entity if it has no contents
if (contents.Volume == 0)
QueueDel(uid);
EntityManager.QueueDeleteEntity(uid);
}

View File

@@ -41,33 +41,33 @@ public sealed partial class CreateEntityTileReaction : ITileReaction
IEntityManager entityManager,
List<ReagentData>? data)
{
if (reactVolume < Usage)
return FixedPoint2.Zero;
if (Whitelist != null)
if (reactVolume >= Usage)
{
var lookup = entityManager.System<EntityLookupSystem>();
int acc = 0;
foreach (var ent in lookup.GetEntitiesInTile(tile, LookupFlags.Static))
if (Whitelist != null)
{
var whitelistSystem = entityManager.System<EntityWhitelistSystem>();
if (whitelistSystem.IsWhitelistPass(Whitelist, ent))
acc += 1;
int acc = 0;
foreach (var ent in tile.GetEntitiesInTile())
{
var whitelistSystem = entityManager.System<EntityWhitelistSystem>();
if (whitelistSystem.IsWhitelistPass(Whitelist, ent))
acc += 1;
if (acc >= MaxOnTile)
return FixedPoint2.Zero;
if (acc >= MaxOnTile)
return FixedPoint2.Zero;
}
}
var random = IoCManager.Resolve<IRobustRandom>();
var xoffs = random.NextFloat(-RandomOffsetMax, RandomOffsetMax);
var yoffs = random.NextFloat(-RandomOffsetMax, RandomOffsetMax);
var center = entityManager.System<TurfSystem>().GetTileCenter(tile);
var pos = center.Offset(new Vector2(xoffs, yoffs));
entityManager.SpawnEntity(Entity, pos);
return Usage;
}
var random = IoCManager.Resolve<IRobustRandom>();
var xoffs = random.NextFloat(-RandomOffsetMax, RandomOffsetMax);
var yoffs = random.NextFloat(-RandomOffsetMax, RandomOffsetMax);
var center = entityManager.System<TurfSystem>().GetTileCenter(tile);
var pos = center.Offset(new Vector2(xoffs, yoffs));
entityManager.SpawnEntity(Entity, pos);
return Usage;
return FixedPoint2.Zero;
}
}

View File

@@ -80,7 +80,7 @@ public sealed class CloningPodSystem : EntitySystem
internal void TransferMindToClone(EntityUid mindId, MindComponent mind)
{
if (!ClonesWaitingForMind.TryGetValue(mind, out var entity) ||
!Exists(entity) ||
!EntityManager.EntityExists(entity) ||
!TryComp<MindContainerComponent>(entity, out var mindComp) ||
mindComp.Mind != null)
return;
@@ -93,11 +93,11 @@ public sealed class CloningPodSystem : EntitySystem
private void HandleMindAdded(EntityUid uid, BeingClonedComponent clonedComponent, MindAddedMessage message)
{
if (clonedComponent.Parent == EntityUid.Invalid ||
!Exists(clonedComponent.Parent) ||
!EntityManager.EntityExists(clonedComponent.Parent) ||
!TryComp<CloningPodComponent>(clonedComponent.Parent, out var cloningPodComponent) ||
uid != cloningPodComponent.BodyContainer.ContainedEntity)
{
RemComp<BeingClonedComponent>(uid);
EntityManager.RemoveComponent<BeingClonedComponent>(uid);
return;
}
UpdateStatus(clonedComponent.Parent, CloningPodStatus.Cloning, cloningPodComponent);
@@ -139,7 +139,7 @@ public sealed class CloningPodSystem : EntitySystem
var mind = mindEnt.Comp;
if (ClonesWaitingForMind.TryGetValue(mind, out var clone))
{
if (Exists(clone) &&
if (EntityManager.EntityExists(clone) &&
!_mobStateSystem.IsDead(clone) &&
TryComp<MindContainerComponent>(clone, out var cloneMindComp) &&
(cloneMindComp.Mind == null || cloneMindComp.Mind == mindEnt))
@@ -204,7 +204,7 @@ public sealed class CloningPodSystem : EntitySystem
return false;
}
var cloneMindReturn = AddComp<BeingClonedComponent>(mob.Value);
var cloneMindReturn = EntityManager.AddComponent<BeingClonedComponent>(mob.Value);
cloneMindReturn.Mind = mind;
cloneMindReturn.Parent = uid;
_containerSystem.Insert(mob.Value, clonePod.BodyContainer);
@@ -272,7 +272,7 @@ public sealed class CloningPodSystem : EntitySystem
if (clonePod.BodyContainer.ContainedEntity is not { Valid: true } entity || clonePod.CloningProgress < clonePod.CloningTime)
return;
RemComp<BeingClonedComponent>(entity);
EntityManager.RemoveComponent<BeingClonedComponent>(entity);
_containerSystem.Remove(entity, clonePod.BodyContainer);
clonePod.CloningProgress = 0f;
clonePod.UsedBiomass = 0;

View File

@@ -175,7 +175,7 @@ public sealed partial class CloningSystem : EntitySystem
if (prototype == null)
return null;
var spawned = SpawnAtPosition(prototype, coords);
var spawned = EntityManager.SpawnAtPosition(prototype, coords);
// copy over important component data
var ev = new CloningItemEvent(spawned);

View File

@@ -56,7 +56,7 @@ public sealed class CodewordSystem : EntitySystem
var factionProto = _prototypeManager.Index<CodewordFactionPrototype>(faction.Id);
var codewords = GenerateCodewords(factionProto.Generator);
var codewordsContainer = Spawn(prototype: null, MapCoordinates.Nullspace);
var codewordsContainer = EntityManager.Spawn(protoName:null, MapCoordinates.Nullspace);
EnsureComp<CodewordComponent>(codewordsContainer)
.Codewords = codewords;
manager.Codewords[faction] = codewordsContainer;

View File

@@ -58,7 +58,9 @@ namespace Content.Server.Construction.Conditions
if (!entityManager.System<SharedMapSystem>().TryGetTileRef(transform.GridUid.Value, grid, indices, out var tile))
return !HasEntity;
foreach (var ent in lookup.GetEntitiesInTile(tile, flags: LookupFlags.Approximate | LookupFlags.Static))
var entities = tile.GetEntitiesInTile(LookupFlags.Approximate | LookupFlags.Static, lookup);
foreach (var ent in entities)
{
if (entityManager.HasComponent(ent, type))
return HasEntity;

View File

@@ -60,7 +60,7 @@ public sealed partial class ConstructionSystem
if (container.ContainedEntities.Count != 0)
return;
var board = Spawn(component.BoardPrototype, Transform(ent).Coordinates);
var board = EntityManager.SpawnEntity(component.BoardPrototype, Transform(ent).Coordinates);
if (!_container.Insert(board, container))
Log.Warning($"Couldn't insert board {board} to computer {ent}!");

View File

@@ -325,7 +325,7 @@ namespace Content.Server.Construction
var newUid = EntityManager.CreateEntityUninitialized(newEntity, transform.Coordinates);
// Construction transferring.
var newConstruction = EnsureComp<ConstructionComponent>(newUid);
var newConstruction = EntityManager.EnsureComponent<ConstructionComponent>(newUid);
// Transfer all construction-owned containers.
newConstruction.Containers.UnionWith(construction.Containers);
@@ -372,7 +372,7 @@ namespace Content.Server.Construction
if (containerManager != null)
{
// Ensure the new entity has a container manager. Also for resolve goodness.
var newContainerManager = EnsureComp<ContainerManagerComponent>(newUid);
var newContainerManager = EntityManager.EnsureComponent<ContainerManagerComponent>(newUid);
// Transfer all construction-owned containers from the old entity to the new one.
foreach (var container in construction.Containers)

View File

@@ -70,7 +70,7 @@ namespace Content.Server.Construction
if(!containerSlot.ContainedEntity.HasValue)
continue;
if (TryComp(containerSlot.ContainedEntity.Value, out StorageComponent? storage))
if (EntityManager.TryGetComponent(containerSlot.ContainedEntity.Value, out StorageComponent? storage))
{
foreach (var storedEntity in storage.Container.ContainedEntities)
{
@@ -301,7 +301,7 @@ namespace Content.Server.Construction
}
var newEntityProto = graph.Nodes[edge.Target].Entity.GetId(null, user, new(EntityManager));
var newEntity = SpawnAttachedTo(newEntityProto, coords, rotation: angle);
var newEntity = EntityManager.SpawnAttachedTo(newEntityProto, coords, rotation: angle);
if (!TryComp(newEntity, out ConstructionComponent? construction))
{
@@ -502,7 +502,7 @@ namespace Content.Server.Construction
}
if (!_actionBlocker.CanInteract(user, null)
|| !TryComp(user, out HandsComponent? hands) || _handsSystem.GetActiveItem((user, hands)) == null)
|| !EntityManager.TryGetComponent(user, out HandsComponent? hands) || hands.ActiveHandEntity == null)
{
Cleanup();
return;
@@ -527,7 +527,7 @@ namespace Content.Server.Construction
var valid = false;
if (_handsSystem.GetActiveItem((user, hands)) is not {Valid: true} holding)
if (hands.ActiveHandEntity is not {Valid: true} holding)
{
Cleanup();
return;

View File

@@ -41,13 +41,13 @@ namespace Content.Server.Construction
var construction = ent.Comp;
if (GetCurrentGraph(ent, construction) is not {} graph)
{
Log.Warning($"Prototype {Comp<MetaDataComponent>(ent).EntityPrototype?.ID}'s construction component has an invalid graph specified.");
Log.Warning($"Prototype {EntityManager.GetComponent<MetaDataComponent>(ent).EntityPrototype?.ID}'s construction component has an invalid graph specified.");
return;
}
if (GetNodeFromGraph(graph, construction.Node) is not {} node)
{
Log.Warning($"Prototype {Comp<MetaDataComponent>(ent).EntityPrototype?.ID}'s construction component has an invalid node specified.");
Log.Warning($"Prototype {EntityManager.GetComponent<MetaDataComponent>(ent).EntityPrototype?.ID}'s construction component has an invalid node specified.");
return;
}
@@ -56,7 +56,7 @@ namespace Content.Server.Construction
{
if (GetEdgeFromNode(node, edgeIndex) is not {} currentEdge)
{
Log.Warning($"Prototype {Comp<MetaDataComponent>(ent).EntityPrototype?.ID}'s construction component has an invalid edge index specified.");
Log.Warning($"Prototype {EntityManager.GetComponent<MetaDataComponent>(ent).EntityPrototype?.ID}'s construction component has an invalid edge index specified.");
return;
}
@@ -67,7 +67,7 @@ namespace Content.Server.Construction
{
if (GetNodeFromGraph(graph, targetNodeId) is not { } targetNode)
{
Log.Warning($"Prototype {Comp<MetaDataComponent>(ent).EntityPrototype?.ID}'s construction component has an invalid target node specified.");
Log.Warning($"Prototype {EntityManager.GetComponent<MetaDataComponent>(ent).EntityPrototype?.ID}'s construction component has an invalid target node specified.");
return;
}

View File

@@ -9,7 +9,7 @@
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
<OutputType Condition="'$(FullRelease)' != 'True'">Exe</OutputType>
<NoWarn>1998</NoWarn>
<WarningsAsErrors>RA0032;nullable</WarningsAsErrors>
<WarningsAsErrors>nullable</WarningsAsErrors>
<Nullable>enable</Nullable>
<ServerGarbageCollection>true</ServerGarbageCollection>
</PropertyGroup>

View File

@@ -76,7 +76,7 @@ public sealed class CrayonSystem : SharedCrayonSystem
component.Charges--;
Dirty(uid, component);
_adminLogger.Add(LogType.CrayonDraw, LogImpact.Low, $"{ToPrettyString(args.User):user} drew a {component.Color:color} {component.SelectedState}");
_adminLogger.Add(LogType.CrayonDraw, LogImpact.Low, $"{EntityManager.ToPrettyString(args.User):user} drew a {component.Color:color} {component.SelectedState}");
args.Handled = true;
if (component.DeleteEmpty && component.Charges <= 0)
@@ -143,6 +143,6 @@ public sealed class CrayonSystem : SharedCrayonSystem
private void UseUpCrayon(EntityUid uid, EntityUid user)
{
_popup.PopupEntity(Loc.GetString("crayon-interact-used-up-text", ("owner", uid)), user, user);
QueueDel(uid);
EntityManager.QueueDeleteEntity(uid);
}
}

View File

@@ -251,45 +251,56 @@ public sealed class CrewManifestSystem : EntitySystem
}
[AdminCommand(AdminFlags.Admin)]
public sealed class CrewManifestCommand : LocalizedEntityCommands
public sealed class CrewManifestCommand : IConsoleCommand
{
[Dependency] private readonly CrewManifestSystem _manifestSystem = default!;
public string Command => "crewmanifest";
public string Description => "Opens the crew manifest for the given station.";
public string Help => $"Usage: {Command} <entity uid>";
public override string Command => "crewmanifest";
[Dependency] private readonly IEntityManager _entityManager = default!;
public override void Execute(IConsoleShell shell, string argStr, string[] args)
public CrewManifestCommand()
{
if (args.Length != 1)
{
shell.WriteLine(Loc.GetString($"shell-need-exactly-one-argument"));
return;
}
if (!NetEntity.TryParse(args[0], out var uidNet) || !EntityManager.TryGetEntity(uidNet, out var uid))
{
shell.WriteLine(Loc.GetString($"shell-argument-station-id-invalid", ("index", args[0])));
return;
}
if (shell.Player is not { } session)
{
shell.WriteLine(Loc.GetString($"shell-cannot-run-command-from-server"));
return;
}
_manifestSystem.OpenEui(uid.Value, session);
IoCManager.InjectDependencies(this);
}
public override CompletionResult GetCompletion(IConsoleShell shell, string[] args)
public void Execute(IConsoleShell shell, string argStr, string[] args)
{
if (args.Length != 1)
{
shell.WriteLine($"Invalid argument count.\n{Help}");
return;
}
if (!NetEntity.TryParse(args[0], out var uidNet) || !_entityManager.TryGetEntity(uidNet, out var uid))
{
shell.WriteLine($"{args[0]} is not a valid entity UID.");
return;
}
if (shell.Player == null || shell.Player is not { } session)
{
shell.WriteLine("You must run this from a client.");
return;
}
var crewManifestSystem = _entityManager.System<CrewManifestSystem>();
crewManifestSystem.OpenEui(uid.Value, session);
}
public CompletionResult GetCompletion(IConsoleShell shell, string[] args)
{
if (args.Length != 1)
{
return CompletionResult.Empty;
}
var stations = new List<CompletionOption>();
var query = EntityManager.EntityQueryEnumerator<StationDataComponent>();
var query = _entityManager.EntityQueryEnumerator<StationDataComponent>();
while (query.MoveNext(out var uid, out _))
{
var meta = EntityManager.GetComponent<MetaDataComponent>(uid);
var meta = _entityManager.GetComponent<MetaDataComponent>(uid);
stations.Add(new CompletionOption(uid.ToString(), meta.EntityName));
}

View File

@@ -31,7 +31,7 @@ namespace Content.Server.Damage.Systems
return;
if (component.WeldingDamage is {} weldingDamage
&& TryComp(args.Used, out WelderComponent? welder)
&& EntityManager.TryGetComponent(args.Used, out WelderComponent? welder)
&& itemToggle.Activated
&& !welder.TankSafe)
{

View File

@@ -54,9 +54,8 @@ namespace Content.Server.Decals.Commands
}
var mapSystem = _entManager.System<MapSystem>();
var turfSystem = _entManager.System<TurfSystem>();
var coordinates = new EntityCoordinates(gridIdRaw.Value, new Vector2(x, y));
if (turfSystem.IsSpace(mapSystem.GetTileRef(gridIdRaw.Value, grid, coordinates)))
if (mapSystem.GetTileRef(gridIdRaw.Value, grid, coordinates).IsSpace())
{
shell.WriteError($"Cannot create decal on space tile at {coordinates}.");
return;

View File

@@ -29,6 +29,7 @@ namespace Content.Server.Decals
{
[Dependency] private readonly IPlayerManager _playerManager = default!;
[Dependency] private readonly IAdminManager _adminManager = default!;
[Dependency] private readonly ITileDefinitionManager _tileDefMan = default!;
[Dependency] private readonly IParallelManager _parMan = default!;
[Dependency] private readonly ChunkingSystem _chunking = default!;
[Dependency] private readonly IConfigurationManager _conf = default!;
@@ -36,7 +37,6 @@ namespace Content.Server.Decals
[Dependency] private readonly IAdminLogManager _adminLogger = default!;
[Dependency] private readonly SharedMapSystem _mapSystem = default!;
[Dependency] private readonly SharedTransformSystem _transform = default!;
[Dependency] private readonly TurfSystem _turf = default!;
private readonly Dictionary<NetEntity, HashSet<Vector2i>> _dirtyChunks = new();
private readonly Dictionary<ICommonSession, Dictionary<NetEntity, HashSet<Vector2i>>> _previousSentChunks = new();
@@ -167,7 +167,7 @@ namespace Content.Server.Decals
foreach (var change in args.Changes)
{
if (!_turf.IsSpace(change.NewTile))
if (!change.NewTile.IsSpace(_tileDefMan))
continue;
var indices = GetChunkIndices(change.GridIndices);
@@ -308,7 +308,7 @@ namespace Content.Server.Decals
if (!TryComp(gridId, out MapGridComponent? grid))
return false;
if (_turf.IsSpace(_mapSystem.GetTileRef(gridId.Value, grid, coordinates)))
if (_mapSystem.GetTileRef(gridId.Value, grid, coordinates).IsSpace(_tileDefMan))
return false;
if (!TryComp(gridId, out DecalGridComponent? comp))

View File

@@ -1,7 +1,6 @@
using Content.Server.DeviceLinking.Components;
using Content.Server.DeviceNetwork;
using Content.Shared.Interaction;
using Content.Shared.Lock;
using Robust.Shared.Audio;
using Robust.Shared.Audio.Systems;
@@ -11,7 +10,6 @@ public sealed class SignalSwitchSystem : EntitySystem
{
[Dependency] private readonly DeviceLinkSystem _deviceLink = default!;
[Dependency] private readonly SharedAudioSystem _audio = default!;
[Dependency] private readonly LockSystem _lock = default!;
public override void Initialize()
{
@@ -31,9 +29,6 @@ public sealed class SignalSwitchSystem : EntitySystem
if (args.Handled || !args.Complex)
return;
if (_lock.IsLocked(uid))
return;
comp.State = !comp.State;
_deviceLink.InvokePort(uid, comp.State ? comp.OnPort : comp.OffPort);

View File

@@ -29,7 +29,7 @@ namespace Content.Server.DeviceNetwork.Systems
/// </summary>
private void OnBeforePacketSent(EntityUid uid, ApcNetworkComponent receiver, BeforePacketSentEvent args)
{
if (!TryComp(args.Sender, out ApcNetworkComponent? sender)) return;
if (!EntityManager.TryGetComponent(args.Sender, out ApcNetworkComponent? sender)) return;
if (sender.ConnectedNode?.NodeGroup == null || !sender.ConnectedNode.NodeGroup.Equals(receiver.ConnectedNode?.NodeGroup))
{
@@ -39,7 +39,7 @@ namespace Content.Server.DeviceNetwork.Systems
private void OnProviderConnected(EntityUid uid, ApcNetworkComponent component, ExtensionCableSystem.ProviderConnectedEvent args)
{
if (!TryComp(args.Provider.Owner, out NodeContainerComponent? nodeContainer)) return;
if (!EntityManager.TryGetComponent(args.Provider.Owner, out NodeContainerComponent? nodeContainer)) return;
if (_nodeContainer.TryGetNode(nodeContainer, "power", out CableNode? node))
{

View File

@@ -24,7 +24,7 @@ namespace Content.Server.DeviceNetwork.Systems.Devices
/// </summary>
private void OnInteracted(EntityUid uid, ApcNetSwitchComponent component, InteractHandEvent args)
{
if (!TryComp(uid, out DeviceNetworkComponent? networkComponent)) return;
if (!EntityManager.TryGetComponent(uid, out DeviceNetworkComponent? networkComponent)) return;
component.State = !component.State;
@@ -47,7 +47,7 @@ namespace Content.Server.DeviceNetwork.Systems.Devices
/// </summary>
private void OnPackedReceived(EntityUid uid, ApcNetSwitchComponent component, DeviceNetworkPacketEvent args)
{
if (!TryComp(uid, out DeviceNetworkComponent? networkComponent) || args.SenderAddress == networkComponent.Address) return;
if (!EntityManager.TryGetComponent(uid, out DeviceNetworkComponent? networkComponent) || args.SenderAddress == networkComponent.Address) return;
if (!args.Data.TryGetValue(DeviceNetworkConstants.Command, out string? command) || command != DeviceNetworkConstants.CmdSetState) return;
if (!args.Data.TryGetValue(DeviceNetworkConstants.StateEnabled, out bool enabled)) return;

View File

@@ -18,7 +18,6 @@ using Robust.Server.Audio;
using Robust.Server.GameObjects;
using Robust.Shared.Audio;
using Robust.Shared.Map.Events;
using Robust.Shared.Prototypes;
using Robust.Shared.Timing;
using Robust.Shared.Utility;
@@ -497,15 +496,14 @@ public sealed class NetworkConfiguratorSystem : SharedNetworkConfiguratorSystem
return;
var sources = _deviceLinkSystem.GetSourcePorts(sourceUid, sourceComponent);
var sinks = _deviceLinkSystem.GetSinkPortIds((sinkUid, sinkComponent));
var sinks = _deviceLinkSystem.GetSinkPorts(sinkUid, sinkComponent);
var links = _deviceLinkSystem.GetLinks(sourceUid, sinkUid, sourceComponent);
var defaults = _deviceLinkSystem.GetDefaults(sources);
var sourceIds = sources.Select(s => (ProtoId<SourcePortPrototype>)s.ID).ToArray();
var sourceAddress = Resolve(sourceUid, ref sourceNetworkComponent, false) ? sourceNetworkComponent.Address : "";
var sinkAddress = Resolve(sinkUid, ref sinkNetworkComponent, false) ? sinkNetworkComponent.Address : "";
var state = new DeviceLinkUserInterfaceState(sourceIds, sinks, links, sourceAddress, sinkAddress, defaults);
var state = new DeviceLinkUserInterfaceState(sources, sinks, links, sourceAddress, sinkAddress, defaults);
_uiSystem.SetUiState(configuratorUid, NetworkConfiguratorUiKey.Link, state);
}

View File

@@ -1,5 +1,5 @@
using Content.Server.Body.Components;
using Content.Server.Body.Systems;
using Content.Shared.Body.Events;
using Content.Shared.Chemistry.Components;
using Content.Shared.Devour;
using Content.Shared.Devour.Components;

View File

@@ -102,7 +102,7 @@ namespace Content.Server.Disposal.Tube
/// <param name="msg">A user interface message from the client.</param>
private void OnUiAction(EntityUid uid, DisposalRouterComponent router, SharedDisposalRouterComponent.UiActionMessage msg)
{
if (!Exists(msg.Actor))
if (!EntityManager.EntityExists(msg.Actor))
return;
if (TryComp<PhysicsComponent>(uid, out var physBody) && physBody.BodyType != BodyType.Static)

View File

@@ -156,7 +156,7 @@ namespace Content.Server.Disposal.Unit
holder.Air.Clear();
}
Del(uid);
EntityManager.DeleteEntity(uid);
}
// Note: This function will cause an ExitDisposals on any failure that does not make an ExitDisposals impossible.
@@ -243,7 +243,7 @@ namespace Content.Server.Disposal.Unit
holder.TimeLeft -= time;
frameTime -= time;
if (!Exists(holder.CurrentTube))
if (!EntityManager.EntityExists(holder.CurrentTube))
{
ExitDisposals(uid, holder);
break;
@@ -268,7 +268,7 @@ namespace Content.Server.Disposal.Unit
// Find next tube
var nextTube = _disposalTubeSystem.NextTubeFor(currentTube, holder.CurrentDirection);
if (!Exists(nextTube))
if (!EntityManager.EntityExists(nextTube))
{
ExitDisposals(uid, holder);
break;

View File

@@ -21,6 +21,7 @@ namespace Content.Server.Dragon;
public sealed partial class DragonSystem : EntitySystem
{
[Dependency] private readonly CarpRiftsConditionSystem _carpRifts = default!;
[Dependency] private readonly ITileDefinitionManager _tileDef = default!;
[Dependency] private readonly MovementSpeedModifierSystem _movement = default!;
[Dependency] private readonly NpcFactionSystem _faction = default!;
[Dependency] private readonly PopupSystem _popup = default!;
@@ -29,7 +30,6 @@ public sealed partial class DragonSystem : EntitySystem
[Dependency] private readonly SharedTransformSystem _transform = default!;
[Dependency] private readonly SharedMapSystem _map = default!;
[Dependency] private readonly MobStateSystem _mobState = default!;
[Dependency] private readonly TurfSystem _turf = default!;
private EntityQuery<CarpRiftsConditionComponent> _objQuery;
@@ -159,7 +159,7 @@ public sealed partial class DragonSystem : EntitySystem
// cant put a rift on solars
foreach (var tile in _map.GetTilesIntersecting(xform.GridUid.Value, grid, new Circle(_transform.GetWorldPosition(xform), RiftTileRadius), false))
{
if (!_turf.IsSpace(tile))
if (!tile.IsSpace(_tileDef))
continue;
_popup.PopupEntity(Loc.GetString("carp-rift-space-proximity", ("proximity", RiftTileRadius)), uid, uid);

View File

@@ -1,8 +1,6 @@
using Content.Server.StatusEffectNew;
using Content.Shared.Bed.Sleep;
using Content.Shared.Bed.Sleep;
using Content.Shared.Drowsiness;
using Content.Shared.StatusEffectNew;
using Content.Shared.StatusEffectNew.Components;
using Content.Shared.StatusEffect;
using Robust.Shared.Random;
using Robust.Shared.Timing;
@@ -10,6 +8,9 @@ namespace Content.Server.Drowsiness;
public sealed class DrowsinessSystem : SharedDrowsinessSystem
{
[ValidatePrototypeId<StatusEffectPrototype>]
private const string SleepKey = "ForcedSleep"; // Same one used by N2O and other sleep chems.
[Dependency] private readonly IGameTiming _timing = default!;
[Dependency] private readonly IRobustRandom _random = default!;
[Dependency] private readonly StatusEffectsSystem _statusEffects = default!;
@@ -17,37 +18,33 @@ public sealed class DrowsinessSystem : SharedDrowsinessSystem
/// <inheritdoc/>
public override void Initialize()
{
SubscribeLocalEvent<DrowsinessStatusEffectComponent, StatusEffectAppliedEvent>(OnEffectApplied);
SubscribeLocalEvent<DrowsinessComponent, ComponentStartup>(OnInit);
}
private void OnEffectApplied(Entity<DrowsinessStatusEffectComponent> ent, ref StatusEffectAppliedEvent args)
private void OnInit(EntityUid uid, DrowsinessComponent component, ComponentStartup args)
{
ent.Comp.NextIncidentTime = _timing.CurTime + TimeSpan.FromSeconds(_random.NextFloat(ent.Comp.TimeBetweenIncidents.X, ent.Comp.TimeBetweenIncidents.Y));
component.NextIncidentTime = _timing.CurTime + TimeSpan.FromSeconds(_random.NextFloat(component.TimeBetweenIncidents.X, component.TimeBetweenIncidents.Y));
}
public override void Update(float frameTime)
{
base.Update(frameTime);
var query = EntityQueryEnumerator<DrowsinessStatusEffectComponent, StatusEffectComponent>();
while (query.MoveNext(out var uid, out var drowsiness, out var statusEffect))
var query = EntityQueryEnumerator<DrowsinessComponent>();
while (query.MoveNext(out var uid, out var component))
{
if (_timing.CurTime < drowsiness.NextIncidentTime)
continue;
if (statusEffect.AppliedTo is null)
if (_timing.CurTime < component.NextIncidentTime)
continue;
// Set the new time.
drowsiness.NextIncidentTime = _timing.CurTime + TimeSpan.FromSeconds(_random.NextFloat(drowsiness.TimeBetweenIncidents.X, drowsiness.TimeBetweenIncidents.Y));
component.NextIncidentTime = _timing.CurTime + TimeSpan.FromSeconds(_random.NextFloat(component.TimeBetweenIncidents.X, component.TimeBetweenIncidents.Y));
// sleep duration
var duration = TimeSpan.FromSeconds(_random.NextFloat(drowsiness.DurationOfIncident.X, drowsiness.DurationOfIncident.Y));
var duration = TimeSpan.FromSeconds(_random.NextFloat(component.DurationOfIncident.X, component.DurationOfIncident.Y));
// Make sure the sleep time doesn't cut into the time to next incident.
drowsiness.NextIncidentTime += duration;
component.NextIncidentTime += duration;
_statusEffects.TryAddStatusEffectDuration(statusEffect.AppliedTo.Value, SleepingSystem.StatusEffectForcedSleeping, duration);
_statusEffects.TryAddStatusEffect<ForcedSleepingComponent>(uid, SleepKey, duration, false);
}
}
}

View File

@@ -3,47 +3,55 @@ using Content.Shared.Administration;
using Content.Shared.StatusEffect;
using Robust.Shared.Console;
namespace Content.Server.Electrocution;
[AdminCommand(AdminFlags.Fun)]
public sealed class ElectrocuteCommand : LocalizedEntityCommands
namespace Content.Server.Electrocution
{
[Dependency] private readonly ElectrocutionSystem _electrocution = default!;
[Dependency] private readonly StatusEffectsSystem _statusEffects = default!;
public override string Command => "electrocute";
[ValidatePrototypeId<StatusEffectPrototype>]
private const string ElectrocutionStatusEffect = "Electrocution";
public override void Execute(IConsoleShell shell, string argStr, string[] args)
[AdminCommand(AdminFlags.Fun)]
public sealed class ElectrocuteCommand : IConsoleCommand
{
if (args.Length is < 1 or > 3)
[Dependency] private readonly IEntityManager _entManager = default!;
public string Command => "electrocute";
public string Description => Loc.GetString("electrocute-command-description");
public string Help => $"{Command} <uid> <seconds> <damage>";
[ValidatePrototypeId<StatusEffectPrototype>]
public const string ElectrocutionStatusEffect = "Electrocution";
public void Execute(IConsoleShell shell, string argStr, string[] args)
{
shell.WriteError(Loc.GetString($"shell-need-between-arguments",
("lower", 1),
("upper", 3)));
return;
if (args.Length < 1)
{
// TODO: Localize this.
shell.WriteError("Not enough arguments!");
return;
}
if (!NetEntity.TryParse(args[0], out var uidNet) ||
!_entManager.TryGetEntity(uidNet, out var uid) ||
!_entManager.EntityExists(uid))
{
shell.WriteError($"Invalid entity specified!");
return;
}
if (!_entManager.EntitySysManager.GetEntitySystem<StatusEffectsSystem>().CanApplyEffect(uid.Value, ElectrocutionStatusEffect))
{
shell.WriteError(Loc.GetString("electrocute-command-entity-cannot-be-electrocuted"));
return;
}
if (args.Length < 2 || !int.TryParse(args[1], out var seconds))
{
seconds = 10;
}
if (args.Length < 3 || !int.TryParse(args[2], out var damage))
{
damage = 10;
}
_entManager.EntitySysManager.GetEntitySystem<ElectrocutionSystem>()
.TryDoElectrocution(uid.Value, null, damage, TimeSpan.FromSeconds(seconds), refresh: true, ignoreInsulation: true);
}
if (!NetEntity.TryParse(args[0], out var uidNet) || !EntityManager.TryGetEntity(uidNet, out var uid) || !EntityManager.EntityExists(uid))
{
shell.WriteError(Loc.GetString($"shell-could-not-find-entity-with-uid", ("uid", args[0])));
return;
}
if (!_statusEffects.CanApplyEffect(uid.Value, ElectrocutionStatusEffect))
{
shell.WriteError(Loc.GetString("cmd-electrocute-entity-cannot-be-electrocuted"));
return;
}
if (args.Length < 2 || !int.TryParse(args[1], out var seconds))
seconds = 10;
if (args.Length < 3 || !int.TryParse(args[2], out var damage))
damage = 10;
_electrocution.TryDoElectrocution(uid.Value, null, damage, TimeSpan.FromSeconds(seconds), refresh: true, ignoreInsulation: true);
}
}

View File

@@ -57,7 +57,6 @@ public sealed class ElectrocutionSystem : SharedElectrocutionSystem
[Dependency] private readonly SharedStutteringSystem _stuttering = default!;
[Dependency] private readonly TagSystem _tag = default!;
[Dependency] private readonly MetaDataSystem _metaData = default!;
[Dependency] private readonly TurfSystem _turf = default!;
[ValidatePrototypeId<StatusEffectPrototype>]
private const string StatusEffectKey = "Electrocution";
@@ -138,7 +137,7 @@ public sealed class ElectrocutionSystem : SharedElectrocutionSystem
return false;
if (electrified.NoWindowInTile)
{
var tileRef = _turf.GetTileRef(transform.Coordinates);
var tileRef = transform.Coordinates.GetTileRef(EntityManager, _mapManager);
if (tileRef != null)
{

View File

@@ -63,13 +63,13 @@ namespace Content.Server.Engineering.EntitySystems
if (component.Deleted || !IsTileClear())
return;
if (TryComp(uid, out StackComponent? stackComp)
if (EntityManager.TryGetComponent(uid, out StackComponent? stackComp)
&& component.RemoveOnInteract && !_stackSystem.Use(uid, 1, stackComp))
{
return;
}
Spawn(component.Prototype, args.ClickLocation.SnapToGrid(grid));
EntityManager.SpawnEntity(component.Prototype, args.ClickLocation.SnapToGrid(grid));
if (component.RemoveOnInteract && stackComp == null)
TryQueueDel(uid);

View File

@@ -10,6 +10,7 @@ using Content.Server.Botany;
using Content.Server.Chat.Systems;
using Content.Server.Emp;
using Content.Server.Explosion.EntitySystems;
using Content.Server.Flash;
using Content.Server.Fluids.EntitySystems;
using Content.Server.Ghost.Roles.Components;
using Content.Server.Medical;
@@ -22,13 +23,13 @@ using Content.Server.Temperature.Systems;
using Content.Server.Traits.Assorted;
using Content.Server.Zombies;
using Content.Shared.Atmos;
using Content.Shared.Body.Components;
using Content.Shared.Audio;
using Content.Shared.Coordinates.Helpers;
using Content.Shared.EntityEffects.EffectConditions;
using Content.Shared.EntityEffects.Effects.PlantMetabolism;
using Content.Shared.EntityEffects.Effects.StatusEffects;
using Content.Shared.EntityEffects.Effects;
using Content.Shared.EntityEffects;
using Content.Shared.Flash;
using Content.Shared.Maps;
using Content.Shared.Mind.Components;
using Content.Shared.Popups;
@@ -37,6 +38,7 @@ using Content.Shared.Zombies;
using Robust.Server.GameObjects;
using Robust.Shared.Audio;
using Robust.Shared.Audio.Systems;
using Robust.Shared.GameObjects;
using Robust.Shared.Map;
using Robust.Shared.Prototypes;
using Robust.Shared.Random;
@@ -54,7 +56,7 @@ public sealed class EntityEffectSystem : EntitySystem
[Dependency] private readonly EmpSystem _emp = default!;
[Dependency] private readonly ExplosionSystem _explosion = default!;
[Dependency] private readonly FlammableSystem _flammable = default!;
[Dependency] private readonly SharedFlashSystem _flash = default!;
[Dependency] private readonly FlashSystem _flash = default!;
[Dependency] private readonly IMapManager _mapManager = default!;
[Dependency] private readonly IPrototypeManager _protoManager = default!;
[Dependency] private readonly IRobustRandom _random = default!;
@@ -72,7 +74,6 @@ public sealed class EntityEffectSystem : EntitySystem
[Dependency] private readonly TemperatureSystem _temperature = default!;
[Dependency] private readonly SharedTransformSystem _xform = default!;
[Dependency] private readonly VomitSystem _vomit = default!;
[Dependency] private readonly TurfSystem _turf = default!;
public override void Initialize()
{
@@ -519,7 +520,7 @@ public sealed class EntityEffectSystem : EntitySystem
var spreadAmount = (int) Math.Max(0, Math.Ceiling((reagentArgs.Quantity / args.Effect.OverflowThreshold).Float()));
var splitSolution = reagentArgs.Source.SplitSolution(reagentArgs.Source.Volume);
var transform = Comp<TransformComponent>(reagentArgs.TargetEntity);
var transform = EntityManager.GetComponent<TransformComponent>(reagentArgs.TargetEntity);
var mapCoords = _xform.GetMapCoordinates(reagentArgs.TargetEntity, xform: transform);
if (!_mapManager.TryFindGridAt(mapCoords, out var gridUid, out var grid) ||
@@ -528,11 +529,11 @@ public sealed class EntityEffectSystem : EntitySystem
return;
}
if (_spreader.RequiresFloorToSpread(args.Effect.PrototypeId) && _turf.IsSpace(tileRef))
if (_spreader.RequiresFloorToSpread(args.Effect.PrototypeId) && tileRef.Tile.IsSpace())
return;
var coords = _map.MapToGrid(gridUid, mapCoords);
var ent = Spawn(args.Effect.PrototypeId, coords.SnapToGrid());
var ent = EntityManager.SpawnEntity(args.Effect.PrototypeId, coords.SnapToGrid());
_smoke.StartSmoke(ent, splitSolution, args.Effect.Duration, spreadAmount);
@@ -559,11 +560,11 @@ public sealed class EntityEffectSystem : EntitySystem
return;
cleanseRate *= reagentArgs.Scale.Float();
_bloodstream.FlushChemicals(args.Args.TargetEntity, reagentArgs.Reagent, cleanseRate);
_bloodstream.FlushChemicals(args.Args.TargetEntity, reagentArgs.Reagent.ID, cleanseRate);
}
else
{
_bloodstream.FlushChemicals(args.Args.TargetEntity, null, cleanseRate);
_bloodstream.FlushChemicals(args.Args.TargetEntity, "", cleanseRate);
}
}
@@ -642,7 +643,7 @@ public sealed class EntityEffectSystem : EntitySystem
private void OnExecuteEmpReactionEffect(ref ExecuteEntityEffectEvent<EmpReactionEffect> args)
{
var transform = Comp<TransformComponent>(args.Args.TargetEntity);
var transform = EntityManager.GetComponent<TransformComponent>(args.Args.TargetEntity);
var range = args.Effect.EmpRangePerUnit;
@@ -698,7 +699,7 @@ public sealed class EntityEffectSystem : EntitySystem
private void OnExecuteFlashReactionEffect(ref ExecuteEntityEffectEvent<FlashReactionEffect> args)
{
var transform = Comp<TransformComponent>(args.Args.TargetEntity);
var transform = EntityManager.GetComponent<TransformComponent>(args.Args.TargetEntity);
var range = 1f;
@@ -709,7 +710,7 @@ public sealed class EntityEffectSystem : EntitySystem
args.Args.TargetEntity,
null,
range,
args.Effect.Duration,
args.Effect.Duration * 1000,
slowTo: args.Effect.SlowTo,
sound: args.Effect.Sound);
@@ -765,7 +766,7 @@ public sealed class EntityEffectSystem : EntitySystem
ghostRole = AddComp<GhostRoleComponent>(uid);
EnsureComp<GhostTakeoverAvailableComponent>(uid);
var entityData = Comp<MetaDataComponent>(uid);
var entityData = EntityManager.GetComponent<MetaDataComponent>(uid);
ghostRole.RoleName = entityData.EntityName;
ghostRole.RoleDescription = Loc.GetString("ghost-role-information-cognizine-description");
}
@@ -781,7 +782,7 @@ public sealed class EntityEffectSystem : EntitySystem
amt *= reagentArgs.Scale.Float();
}
_bloodstream.TryModifyBleedAmount((args.Args.TargetEntity, blood), amt);
_bloodstream.TryModifyBleedAmount(args.Args.TargetEntity, amt, blood);
}
}
@@ -797,7 +798,7 @@ public sealed class EntityEffectSystem : EntitySystem
amt *= reagentArgs.Scale;
}
_bloodstream.TryModifyBloodLevel((args.Args.TargetEntity, blood), amt);
_bloodstream.TryModifyBloodLevel(args.Args.TargetEntity, amt, blood);
}
}
@@ -848,7 +849,7 @@ public sealed class EntityEffectSystem : EntitySystem
private void OnExecutePlantMutateChemicals(ref ExecuteEntityEffectEvent<PlantMutateChemicals> args)
{
var plantholder = Comp<PlantHolderComponent>(args.Args.TargetEntity);
var plantholder = EntityManager.GetComponent<PlantHolderComponent>(args.Args.TargetEntity);
if (plantholder.Seed == null)
return;
@@ -882,7 +883,7 @@ public sealed class EntityEffectSystem : EntitySystem
private void OnExecutePlantMutateConsumeGasses(ref ExecuteEntityEffectEvent<PlantMutateConsumeGasses> args)
{
var plantholder = Comp<PlantHolderComponent>(args.Args.TargetEntity);
var plantholder = EntityManager.GetComponent<PlantHolderComponent>(args.Args.TargetEntity);
if (plantholder.Seed == null)
return;
@@ -904,7 +905,7 @@ public sealed class EntityEffectSystem : EntitySystem
private void OnExecutePlantMutateExudeGasses(ref ExecuteEntityEffectEvent<PlantMutateExudeGasses> args)
{
var plantholder = Comp<PlantHolderComponent>(args.Args.TargetEntity);
var plantholder = EntityManager.GetComponent<PlantHolderComponent>(args.Args.TargetEntity);
if (plantholder.Seed == null)
return;
@@ -926,7 +927,7 @@ public sealed class EntityEffectSystem : EntitySystem
private void OnExecutePlantMutateHarvest(ref ExecuteEntityEffectEvent<PlantMutateHarvest> args)
{
var plantholder = Comp<PlantHolderComponent>(args.Args.TargetEntity);
var plantholder = EntityManager.GetComponent<PlantHolderComponent>(args.Args.TargetEntity);
if (plantholder.Seed == null)
return;
@@ -939,7 +940,7 @@ public sealed class EntityEffectSystem : EntitySystem
private void OnExecutePlantSpeciesChange(ref ExecuteEntityEffectEvent<PlantSpeciesChange> args)
{
var plantholder = Comp<PlantHolderComponent>(args.Args.TargetEntity);
var plantholder = EntityManager.GetComponent<PlantHolderComponent>(args.Args.TargetEntity);
if (plantholder.Seed == null)
return;

View File

@@ -51,7 +51,7 @@ namespace Content.Server.Examine
var entity = GetEntity(request.NetEntity);
if (session.AttachedEntity is not {Valid: true} playerEnt
|| !Exists(entity))
|| !EntityManager.EntityExists(entity))
{
RaiseNetworkEvent(new ExamineSystemMessages.ExamineInfoResponseMessage(
request.NetEntity, request.Id, _entityNotFoundMessage), channel);

View File

@@ -66,9 +66,9 @@ public sealed partial class ExplosionSystem
if (!_airtightMap.ContainsKey(gridId))
_airtightMap[gridId] = new();
query ??= GetEntityQuery<AirtightComponent>();
var damageQuery = GetEntityQuery<DamageableComponent>();
var destructibleQuery = GetEntityQuery<DestructibleComponent>();
query ??= EntityManager.GetEntityQuery<AirtightComponent>();
var damageQuery = EntityManager.GetEntityQuery<DamageableComponent>();
var destructibleQuery = EntityManager.GetEntityQuery<DestructibleComponent>();
var anchoredEnumerator = _mapSystem.GetAnchoredEntitiesEnumerator(gridId, grid, tile);
while (anchoredEnumerator.MoveNext(out var uid))
@@ -99,7 +99,7 @@ public sealed partial class ExplosionSystem
if (!airtight.AirBlocked)
return;
if (!TryComp(uid, out TransformComponent? transform) || !transform.Anchored)
if (!EntityManager.TryGetComponent(uid, out TransformComponent? transform) || !transform.Anchored)
return;
if (!TryComp<MapGridComponent>(transform.GridUid, out var grid))

View File

@@ -102,7 +102,7 @@ public sealed partial class ExplosionSystem
continue;
}
var xforms = GetEntityQuery<TransformComponent>();
var xforms = EntityManager.GetEntityQuery<TransformComponent>();
var xform = xforms.GetComponent(gridToTransform);
var (_, gridWorldRotation, gridWorldMatrix, invGridWorldMatrid) = _transformSystem.GetWorldPositionRotationMatrixWithInv(xform, xforms);

View File

@@ -913,10 +913,10 @@ sealed class Explosion
/// <summary>
/// Data needed to spawn an explosion with <see cref="ExplosionSystem.SpawnExplosion"/>.
/// </summary>
public sealed class QueuedExplosion(ExplosionPrototype proto)
public sealed class QueuedExplosion
{
public MapCoordinates Epicenter;
public ExplosionPrototype Proto = proto;
public ExplosionPrototype Proto = new();
public float TotalIntensity, Slope, MaxTileIntensity, TileBreakScale;
public int MaxTileBreak;
public bool CanCreateVacuum;

View File

@@ -167,7 +167,7 @@ public sealed partial class ExplosionSystem : SharedExplosionSystem
user);
if (explosive.DeleteAfterExplosion ?? delete)
QueueDel(uid);
EntityManager.QueueDeleteEntity(uid);
}
/// <summary>
@@ -306,9 +306,10 @@ public sealed partial class ExplosionSystem : SharedExplosionSystem
return;
}
var boom = new QueuedExplosion(type)
var boom = new QueuedExplosion()
{
Epicenter = epicenter,
Proto = type,
TotalIntensity = totalIntensity,
Slope = slope,
MaxTileIntensity = maxTileIntensity,

View File

@@ -20,7 +20,6 @@ public sealed class SmokeOnTriggerSystem : SharedSmokeOnTriggerSystem
[Dependency] private readonly SmokeSystem _smoke = default!;
[Dependency] private readonly TransformSystem _transform = default!;
[Dependency] private readonly SpreaderSystem _spreader = default!;
[Dependency] private readonly TurfSystem _turf = default!;
public override void Initialize()
{
@@ -40,7 +39,7 @@ public sealed class SmokeOnTriggerSystem : SharedSmokeOnTriggerSystem
return;
}
if (_spreader.RequiresFloorToSpread(comp.SmokePrototype.ToString()) && _turf.IsSpace(tileRef))
if (_spreader.RequiresFloorToSpread(comp.SmokePrototype.ToString()) && tileRef.Tile.IsSpace())
return;
var coords = _map.MapToGrid(gridUid, mapCoords);

View File

@@ -82,7 +82,7 @@ public sealed partial class TriggerSystem
private void SetProximityAppearance(EntityUid uid, TriggerOnProximityComponent component)
{
if (TryComp(uid, out AppearanceComponent? appearance))
if (EntityManager.TryGetComponent(uid, out AppearanceComponent? appearance))
{
_appearance.SetData(uid, ProximityTriggerVisualState.State, component.Enabled ? ProximityTriggerVisuals.Inactive : ProximityTriggerVisuals.Off, appearance);
}
@@ -107,7 +107,7 @@ public sealed partial class TriggerSystem
// Queue a visual update for when the animation is complete.
component.NextVisualUpdate = curTime + component.AnimationDuration;
if (TryComp(uid, out AppearanceComponent? appearance))
if (EntityManager.TryGetComponent(uid, out AppearanceComponent? appearance))
{
_appearance.SetData(uid, ProximityTriggerVisualState.State, ProximityTriggerVisuals.Active, appearance);
}

View File

@@ -1,7 +1,7 @@
using Content.Server.Administration.Logs;
using Content.Server.Body.Systems;
using Content.Server.Explosion.Components;
using Content.Shared.Flash;
using Content.Server.Flash;
using Content.Server.Electrocution;
using Content.Server.Pinpointer;
using Content.Shared.Chemistry.EntitySystems;
@@ -69,7 +69,7 @@ namespace Content.Server.Explosion.EntitySystems
{
[Dependency] private readonly ExplosionSystem _explosions = default!;
[Dependency] private readonly FixtureSystem _fixtures = default!;
[Dependency] private readonly SharedFlashSystem _flashSystem = default!;
[Dependency] private readonly FlashSystem _flashSystem = default!;
[Dependency] private readonly SharedBroadphaseSystem _broadphase = default!;
[Dependency] private readonly IAdminLogManager _adminLogger = default!;
[Dependency] private readonly SharedContainerSystem _container = default!;
@@ -196,13 +196,14 @@ namespace Content.Server.Explosion.EntitySystems
private void HandleFlashTrigger(EntityUid uid, FlashOnTriggerComponent component, TriggerEvent args)
{
_flashSystem.FlashArea(uid, args.User, component.Range, component.Duration, probability: component.Probability);
// TODO Make flash durations sane ffs.
_flashSystem.FlashArea(uid, args.User, component.Range, component.Duration * 1000f, probability: component.Probability);
args.Handled = true;
}
private void HandleDeleteTrigger(EntityUid uid, DeleteOnTriggerComponent component, TriggerEvent args)
{
QueueDel(uid);
EntityManager.QueueDeleteEntity(uid);
args.Handled = true;
}

View File

@@ -36,7 +36,7 @@ public sealed class TwoStageTriggerSystem : EntitySystem
RemComp(uid, c);
_serializationManager.CopyTo(entry.Component, ref temp);
AddComp(uid, comp);
EntityManager.AddComponent(uid, comp);
}
component.ComponentsIsLoaded = true;
}

View File

@@ -591,7 +591,7 @@ public sealed class FaxSystem : EntitySystem
var printout = component.PrintingQueue.Dequeue();
var entityToSpawn = printout.PrototypeId.Length == 0 ? component.PrintPaperId.ToString() : printout.PrototypeId;
var printed = Spawn(entityToSpawn, Transform(uid).Coordinates);
var printed = EntityManager.SpawnEntity(entityToSpawn, Transform(uid).Coordinates);
if (TryComp<PaperComponent>(printed, out var paper))
{

View File

@@ -0,0 +1,14 @@
using Content.Shared.Damage;
using Robust.Shared.Prototypes;
namespace Content.Server.Flash.Components;
[RegisterComponent, Access(typeof(DamagedByFlashingSystem))]
public sealed partial class DamagedByFlashingComponent : Component
{
/// <summary>
/// damage from flashing
/// </summary>
[DataField(required: true), ViewVariables(VVAccess.ReadWrite)]
public DamageSpecifier FlashDamage = new();
}

Some files were not shown because too many files have changed in this diff Show More