Merge branch 'master-upstream' into expl_int_analyzer

# Conflicts:
#	Content.Server/GameObjects/Components/Body/Part/BodyPartComponent.cs
#	Content.Server/GameObjects/Components/Botany/PlantHolderComponent.cs
#	Content.Server/GameObjects/Components/Chemistry/PillComponent.cs
#	Content.Server/GameObjects/Components/Interactable/TilePryingComponent.cs
#	Content.Server/GameObjects/Components/Items/FloorTileItemComponent.cs
#	Content.Server/GameObjects/Components/Items/RCD/RCDAmmoComponent.cs
#	Content.Server/GameObjects/Components/Items/RCD/RCDComponent.cs
#	Content.Server/GameObjects/Components/Medical/HealingComponent.cs
#	Content.Server/GameObjects/Components/Power/WirePlacerComponent.cs
#	Content.Shared/Chemistry/Solution.cs
This commit is contained in:
Paul
2021-02-04 17:50:28 +01:00
499 changed files with 6357 additions and 8689 deletions

View File

@@ -79,7 +79,7 @@ namespace Content.Benchmarks
{ {
var count = 0; var count = 0;
foreach (var _ in _componentManager.EntityQuery<DummyComponent>()) foreach (var _ in _componentManager.EntityQuery<DummyComponent>(true))
{ {
count += 1; count += 1;
} }

View File

@@ -0,0 +1,56 @@
using Robust.Client.Animations;
using Robust.Client.GameObjects;
using Robust.Client.GameObjects.Components.Animations;
using Robust.Shared.Animations;
using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.Interfaces.GameObjects.Components;
using Robust.Shared.Log;
using Robust.Shared.Map;
using Robust.Shared.Maths;
using System;
namespace Content.Client.Animations
{
public static class ReusableAnimations
{
public static void AnimateEntityPickup(IEntity entity, EntityCoordinates initialPosition, Vector2 finalPosition)
{
var animatableClone = entity.EntityManager.SpawnEntity("clientsideclone", initialPosition);
animatableClone.Name = entity.Name;
if(!entity.TryGetComponent(out SpriteComponent sprite0))
{
Logger.Error($"Entity ({0}) couldn't be animated for pickup since it doesn't have a {1}!", entity.Name, nameof(SpriteComponent));
return;
}
var sprite = animatableClone.GetComponent<SpriteComponent>();
sprite.CopyFrom(sprite0);
var animations = animatableClone.GetComponent<AnimationPlayerComponent>();
animations.AnimationCompleted += (s) => {
animatableClone.Delete();
};
animations.Play(new Animation
{
Length = TimeSpan.FromMilliseconds(125),
AnimationTracks =
{
new AnimationTrackComponentProperty
{
ComponentType = typeof(ITransformComponent),
Property = nameof(ITransformComponent.WorldPosition),
InterpolationMode = AnimationInterpolationMode.Linear,
KeyFrames =
{
new AnimationTrackComponentProperty.KeyFrame(initialPosition.Position, 0),
new AnimationTrackComponentProperty.KeyFrame(finalPosition, 0.125f)
}
}
}
}, "fancy_pickup_anim");
}
}
}

View File

@@ -78,7 +78,7 @@ namespace Content.Client.Chat
private ChatChannel _filteredChannels; private ChatChannel _filteredChannels;
[Dependency] private readonly IClientNetManager _netManager = default!; [Dependency] private readonly IClientNetManager _netManager = default!;
[Dependency] private readonly IClientConsole _console = default!; [Dependency] private readonly IClientConsoleHost _consoleHost = default!;
[Dependency] private readonly IEntityManager _entityManager = default!; [Dependency] private readonly IEntityManager _entityManager = default!;
[Dependency] private readonly IEyeManager _eyeManager = default!; [Dependency] private readonly IEyeManager _eyeManager = default!;
[Dependency] private readonly IUserInterfaceManager _userInterfaceManager = default!; [Dependency] private readonly IUserInterfaceManager _userInterfaceManager = default!;
@@ -255,7 +255,7 @@ namespace Content.Client.Chat
{ {
// run locally // run locally
var conInput = text.Substring(1); var conInput = text.Substring(1);
_console.ProcessCommand(conInput); _consoleHost.ExecuteCommand(conInput);
break; break;
} }
case OOCAlias: case OOCAlias:
@@ -263,7 +263,7 @@ namespace Content.Client.Chat
var conInput = text.Substring(1); var conInput = text.Substring(1);
if (string.IsNullOrWhiteSpace(conInput)) if (string.IsNullOrWhiteSpace(conInput))
return; return;
_console.ProcessCommand($"ooc \"{CommandParsing.Escape(conInput)}\""); _consoleHost.ExecuteCommand($"ooc \"{CommandParsing.Escape(conInput)}\"");
break; break;
} }
case AdminChatAlias: case AdminChatAlias:
@@ -273,11 +273,11 @@ namespace Content.Client.Chat
return; return;
if (_groupController.CanCommand("asay")) if (_groupController.CanCommand("asay"))
{ {
_console.ProcessCommand($"asay \"{CommandParsing.Escape(conInput)}\""); _consoleHost.ExecuteCommand($"asay \"{CommandParsing.Escape(conInput)}\"");
} }
else else
{ {
_console.ProcessCommand($"ooc \"{CommandParsing.Escape(conInput)}\""); _consoleHost.ExecuteCommand($"ooc \"{CommandParsing.Escape(conInput)}\"");
} }
break; break;
@@ -287,7 +287,7 @@ namespace Content.Client.Chat
var conInput = text.Substring(1); var conInput = text.Substring(1);
if (string.IsNullOrWhiteSpace(conInput)) if (string.IsNullOrWhiteSpace(conInput))
return; return;
_console.ProcessCommand($"me \"{CommandParsing.Escape(conInput)}\""); _consoleHost.ExecuteCommand($"me \"{CommandParsing.Escape(conInput)}\"");
break; break;
} }
default: default:
@@ -295,7 +295,7 @@ namespace Content.Client.Chat
var conInput = _currentChatBox?.DefaultChatFormat != null var conInput = _currentChatBox?.DefaultChatFormat != null
? string.Format(_currentChatBox.DefaultChatFormat, CommandParsing.Escape(text)) ? string.Format(_currentChatBox.DefaultChatFormat, CommandParsing.Escape(text))
: text; : text;
_console.ProcessCommand(conInput); _consoleHost.ExecuteCommand(conInput);
break; break;
} }
} }

View File

@@ -4,12 +4,12 @@ using System.Collections.Generic;
using Content.Client.Interfaces; using Content.Client.Interfaces;
using Content.Client.UserInterface.Stylesheets; using Content.Client.UserInterface.Stylesheets;
using Content.Shared; using Content.Shared;
using Robust.Client.Interfaces.Console;
using Robust.Client.Interfaces.Graphics.ClientEye; using Robust.Client.Interfaces.Graphics.ClientEye;
using Robust.Client.Interfaces.Input; using Robust.Client.Interfaces.Input;
using Robust.Client.Interfaces.UserInterface; using Robust.Client.Interfaces.UserInterface;
using Robust.Client.Player; using Robust.Client.Player;
using Robust.Client.UserInterface.Controls; using Robust.Client.UserInterface.Controls;
using Robust.Shared.Console;
using Robust.Shared.Interfaces.GameObjects; using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.Interfaces.Network; using Robust.Shared.Interfaces.Network;
using Robust.Shared.IoC; using Robust.Shared.IoC;
@@ -168,12 +168,11 @@ namespace Content.Client
public string Description => ""; public string Description => "";
public string Help => ""; public string Help => "";
public bool Execute(IDebugConsole console, params string[] args) public void Execute(IConsoleShell shell, string argStr, string[] args)
{ {
var arg = args[0]; var arg = args[0];
var mgr = IoCManager.Resolve<IClientNotifyManager>(); var mgr = IoCManager.Resolve<IClientNotifyManager>();
mgr.PopupMessage(arg); mgr.PopupMessage(arg);
return false;
} }
} }
} }

View File

@@ -1,9 +1,9 @@
using JetBrains.Annotations; using JetBrains.Annotations;
using Robust.Client.Interfaces.Console;
using Content.Client.GameObjects.EntitySystems; using Content.Client.GameObjects.EntitySystems;
using Robust.Shared.GameObjects.Systems; using Robust.Shared.GameObjects.Systems;
using Content.Shared.Atmos; using Content.Shared.Atmos;
using System; using System;
using Robust.Shared.Console;
namespace Content.Client.Commands namespace Content.Client.Commands
{ {
@@ -13,32 +13,31 @@ namespace Content.Client.Commands
public string Command => "atvrange"; public string Command => "atvrange";
public string Description => "Sets the atmos debug range (as two floats, start [red] and end [blue])"; public string Description => "Sets the atmos debug range (as two floats, start [red] and end [blue])";
public string Help => "atvrange <start> <end>"; public string Help => "atvrange <start> <end>";
public bool Execute(IDebugConsole console, params string[] args) public void Execute(IConsoleShell shell, string argStr, string[] args)
{ {
if (args.Length != 2) if (args.Length != 2)
{ {
console.AddLine(Help); shell.WriteLine(Help);
return false; return;
} }
if (!float.TryParse(args[0], out var xStart)) if (!float.TryParse(args[0], out var xStart))
{ {
console.AddLine("Bad float START"); shell.WriteLine("Bad float START");
return false; return;
} }
if (!float.TryParse(args[1], out var xEnd)) if (!float.TryParse(args[1], out var xEnd))
{ {
console.AddLine("Bad float END"); shell.WriteLine("Bad float END");
return false; return;
} }
if (xStart == xEnd) if (xStart == xEnd)
{ {
console.AddLine("Scale cannot be zero, as this would cause a division by zero in AtmosDebugOverlay."); shell.WriteLine("Scale cannot be zero, as this would cause a division by zero in AtmosDebugOverlay.");
return false; return;
} }
var sys = EntitySystem.Get<AtmosDebugOverlaySystem>(); var sys = EntitySystem.Get<AtmosDebugOverlaySystem>();
sys.CfgBase = xStart; sys.CfgBase = xStart;
sys.CfgScale = xEnd - xStart; sys.CfgScale = xEnd - xStart;
return false;
} }
} }
@@ -48,17 +47,17 @@ namespace Content.Client.Commands
public string Command => "atvmode"; public string Command => "atvmode";
public string Description => "Sets the atmos debug mode. This will automatically reset the scale."; public string Description => "Sets the atmos debug mode. This will automatically reset the scale.";
public string Help => "atvmode <TotalMoles/GasMoles/Temperature> [<gas ID (for GasMoles)>]"; public string Help => "atvmode <TotalMoles/GasMoles/Temperature> [<gas ID (for GasMoles)>]";
public bool Execute(IDebugConsole console, params string[] args) public void Execute(IConsoleShell shell, string argStr, string[] args)
{ {
if (args.Length < 1) if (args.Length < 1)
{ {
console.AddLine(Help); shell.WriteLine(Help);
return false; return;
} }
if (!Enum.TryParse<AtmosDebugOverlayMode>(args[0], out var xMode)) if (!Enum.TryParse<AtmosDebugOverlayMode>(args[0], out var xMode))
{ {
console.AddLine("Invalid mode"); shell.WriteLine("Invalid mode");
return false; return;
} }
int xSpecificGas = 0; int xSpecificGas = 0;
float xBase = 0; float xBase = 0;
@@ -67,21 +66,21 @@ namespace Content.Client.Commands
{ {
if (args.Length != 2) if (args.Length != 2)
{ {
console.AddLine("A target gas must be provided for this mode."); shell.WriteLine("A target gas must be provided for this mode.");
return false; return;
} }
if (!AtmosCommandUtils.TryParseGasID(args[1], out xSpecificGas)) if (!AtmosCommandUtils.TryParseGasID(args[1], out xSpecificGas))
{ {
console.AddLine("Gas ID not parsable or out of range."); shell.WriteLine("Gas ID not parsable or out of range.");
return false; return;
} }
} }
else else
{ {
if (args.Length != 1) if (args.Length != 1)
{ {
console.AddLine("No further information is required for this mode."); shell.WriteLine("No further information is required for this mode.");
return false; return;
} }
if (xMode == AtmosDebugOverlayMode.Temperature) if (xMode == AtmosDebugOverlayMode.Temperature)
{ {
@@ -95,7 +94,6 @@ namespace Content.Client.Commands
sys.CfgSpecificGas = xSpecificGas; sys.CfgSpecificGas = xSpecificGas;
sys.CfgBase = xBase; sys.CfgBase = xBase;
sys.CfgScale = xScale; sys.CfgScale = xScale;
return false;
} }
} }
@@ -105,21 +103,20 @@ namespace Content.Client.Commands
public string Command => "atvcbm"; public string Command => "atvcbm";
public string Description => "Changes from red/green/blue to greyscale"; public string Description => "Changes from red/green/blue to greyscale";
public string Help => "atvcbm <true/false>"; public string Help => "atvcbm <true/false>";
public bool Execute(IDebugConsole console, params string[] args) public void Execute(IConsoleShell shell, string argStr, string[] args)
{ {
if (args.Length != 1) if (args.Length != 1)
{ {
console.AddLine(Help); shell.WriteLine(Help);
return false; return;
} }
if (!bool.TryParse(args[0], out var xFlag)) if (!bool.TryParse(args[0], out var xFlag))
{ {
console.AddLine("Invalid flag"); shell.WriteLine("Invalid flag");
return false; return;
} }
var sys = EntitySystem.Get<AtmosDebugOverlaySystem>(); var sys = EntitySystem.Get<AtmosDebugOverlaySystem>();
sys.CfgCBM = xFlag; sys.CfgCBM = xFlag;
return false;
} }
} }
} }

View File

@@ -1,6 +1,6 @@
using Content.Client.UserInterface; using Content.Client.UserInterface;
using JetBrains.Annotations; using JetBrains.Annotations;
using Robust.Client.Interfaces.Console; using Robust.Shared.Console;
namespace Content.Client.Commands namespace Content.Client.Commands
{ {
@@ -11,10 +11,9 @@ namespace Content.Client.Commands
public string Description => "Opens the credits window"; public string Description => "Opens the credits window";
public string Help => "credits"; public string Help => "credits";
public bool Execute(IDebugConsole console, params string[] args) public void Execute(IConsoleShell shell, string argStr, string[] args)
{ {
new CreditsWindow().Open(); new CreditsWindow().Open();
return false;
} }
} }
} }

View File

@@ -1,6 +1,6 @@
using Content.Client.GameObjects.EntitySystems.AI; using Content.Client.GameObjects.EntitySystems.AI;
using JetBrains.Annotations; using JetBrains.Annotations;
using Robust.Client.Interfaces.Console; using Robust.Shared.Console;
using Robust.Shared.GameObjects.Systems; using Robust.Shared.GameObjects.Systems;
namespace Content.Client.Commands namespace Content.Client.Commands
@@ -16,12 +16,13 @@ namespace Content.Client.Commands
public string Description => "Handles all tooltip debugging above AI mobs"; public string Description => "Handles all tooltip debugging above AI mobs";
public string Help => "debugai [hide/paths/thonk]"; public string Help => "debugai [hide/paths/thonk]";
public bool Execute(IDebugConsole console, params string[] args) public void Execute(IConsoleShell shell, string argStr, string[] args)
{ {
#if DEBUG #if DEBUG
if (args.Length < 1) if (args.Length < 1)
{ {
return true; shell.RemoteExecuteCommand(argStr);
return;
} }
var anyAction = false; var anyAction = false;
@@ -50,9 +51,10 @@ namespace Content.Client.Commands
} }
} }
return !anyAction; if(!anyAction)
shell.RemoteExecuteCommand(argStr);
#else #else
return true; shell.RemoteExecuteCommand(argStr);
#endif #endif
} }
} }

View File

@@ -1,9 +1,10 @@
using System;
using Content.Client.GameObjects.Components; using Content.Client.GameObjects.Components;
using Content.Client.GameObjects.EntitySystems; using Content.Client.GameObjects.EntitySystems;
using Content.Client.Interfaces; using Content.Client.Interfaces;
using Content.Shared.GameObjects; using Content.Shared.GameObjects;
using Robust.Client.Interfaces.Console;
using Robust.Client.Interfaces.GameObjects.Components; using Robust.Client.Interfaces.GameObjects.Components;
using Robust.Shared.Console;
using Robust.Shared.GameObjects.Systems; using Robust.Shared.GameObjects.Systems;
using Robust.Shared.Interfaces.GameObjects; using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.IoC; using Robust.Shared.IoC;
@@ -17,12 +18,10 @@ namespace Content.Client.Commands
public string Description => "Toggles visibility of markers such as spawn points."; public string Description => "Toggles visibility of markers such as spawn points.";
public string Help => ""; public string Help => "";
public bool Execute(IDebugConsole console, params string[] args) public void Execute(IConsoleShell shell, string argStr, string[] args)
{ {
EntitySystem.Get<MarkerSystem>() EntitySystem.Get<MarkerSystem>()
.MarkersVisible ^= true; .MarkersVisible ^= true;
return false;
} }
} }
@@ -33,12 +32,10 @@ namespace Content.Client.Commands
public string Description => "Makes entities below the floor always visible."; public string Description => "Makes entities below the floor always visible.";
public string Help => $"Usage: {Command}"; public string Help => $"Usage: {Command}";
public bool Execute(IDebugConsole console, params string[] args) public void Execute(IConsoleShell shell, string argStr, string[] args)
{ {
EntitySystem.Get<SubFloorHideSystem>() EntitySystem.Get<SubFloorHideSystem>()
.EnableAll ^= true; .EnableAll ^= true;
return false;
} }
} }
@@ -49,13 +46,13 @@ namespace Content.Client.Commands
public string Description => "Makes entities below the floor always visible until the client is restarted."; public string Description => "Makes entities below the floor always visible until the client is restarted.";
public string Help => $"Usage: {Command}"; public string Help => $"Usage: {Command}";
public bool Execute(IDebugConsole console, params string[] args) public void Execute(IConsoleShell shell, string argStr, string[] args)
{ {
EntitySystem.Get<SubFloorHideSystem>() EntitySystem.Get<SubFloorHideSystem>()
.EnableAll = true; .EnableAll = true;
var components = IoCManager.Resolve<IEntityManager>().ComponentManager var components = IoCManager.Resolve<IEntityManager>().ComponentManager
.EntityQuery<SubFloorHideComponent>(); .EntityQuery<SubFloorHideComponent>(true);
foreach (var component in components) foreach (var component in components)
{ {
@@ -64,8 +61,6 @@ namespace Content.Client.Commands
sprite.DrawDepth = (int) DrawDepth.Overlays; sprite.DrawDepth = (int) DrawDepth.Overlays;
} }
} }
return false;
} }
} }
@@ -75,14 +70,12 @@ namespace Content.Client.Commands
public string Description => "Send a notify client side."; public string Description => "Send a notify client side.";
public string Help => "notify <message>"; public string Help => "notify <message>";
public bool Execute(IDebugConsole console, params string[] args) public void Execute(IConsoleShell shell, string argStr, string[] args)
{ {
var message = args[0]; var message = args[0];
var notifyManager = IoCManager.Resolve<IClientNotifyManager>(); var notifyManager = IoCManager.Resolve<IClientNotifyManager>();
notifyManager.PopupMessage(message); notifyManager.PopupMessage(message);
return false;
} }
} }
@@ -92,18 +85,18 @@ namespace Content.Client.Commands
public string Description => "Creates and teleports you to a new uninitialized map for mapping."; public string Description => "Creates and teleports you to a new uninitialized map for mapping.";
public string Help => $"Usage: {Command} <mapname> / {Command} <id> <mapname>"; public string Help => $"Usage: {Command} <mapname> / {Command} <id> <mapname>";
public bool Execute(IDebugConsole console, params string[] args) public void Execute(IConsoleShell shell, string argStr, string[] args)
{ {
if (args.Length == 0) if (args.Length == 0)
{ {
console.AddLine(Help); shell.WriteLine(Help);
return false; return;
} }
console.Commands["togglelight"].Execute(console); shell.ConsoleHost.RegisteredCommands["togglelight"].Execute(shell, string.Empty, Array.Empty<string>());
console.Commands["showsubfloorforever"].Execute(console); shell.ConsoleHost.RegisteredCommands["showsubfloorforever"].Execute(shell, string.Empty, Array.Empty<string>());
return true; shell.RemoteExecuteCommand(argStr);
} }
} }
} }

View File

@@ -1,6 +1,6 @@
using Content.Client.GameObjects.EntitySystems.AI; using Content.Client.GameObjects.EntitySystems.AI;
using JetBrains.Annotations; using JetBrains.Annotations;
using Robust.Client.Interfaces.Console; using Robust.Shared.Console;
using Robust.Shared.GameObjects.Systems; using Robust.Shared.GameObjects.Systems;
namespace Content.Client.Commands namespace Content.Client.Commands
@@ -13,12 +13,13 @@ namespace Content.Client.Commands
public string Description => "Toggles visibility of pathfinding debuggers."; public string Description => "Toggles visibility of pathfinding debuggers.";
public string Help => "pathfinder [hide/nodes/routes/graph/regioncache/regions]"; public string Help => "pathfinder [hide/nodes/routes/graph/regioncache/regions]";
public bool Execute(IDebugConsole console, params string[] args) public void Execute(IConsoleShell shell, string argStr, string[] args)
{ {
#if DEBUG #if DEBUG
if (args.Length < 1) if (args.Length < 1)
{ {
return true; shell.RemoteExecuteCommand(argStr);
return;
} }
var anyAction = false; var anyAction = false;
@@ -63,9 +64,10 @@ namespace Content.Client.Commands
} }
} }
return !anyAction; if(!anyAction)
shell.RemoteExecuteCommand(argStr);
#else #else
return true; shell.RemoteExecuteCommand(argStr);
#endif #endif
} }
} }

View File

@@ -1,7 +1,7 @@
using Content.Shared.GameObjects.Components.Body.Mechanism; using Content.Shared.GameObjects.Components.Body.Mechanism;
using Robust.Client.Console; using Robust.Client.Console;
using Robust.Client.GameObjects; using Robust.Client.GameObjects;
using Robust.Client.Interfaces.Console; using Robust.Shared.Console;
using Robust.Shared.Containers; using Robust.Shared.Containers;
using Robust.Shared.Interfaces.GameObjects; using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.IoC; using Robust.Shared.IoC;
@@ -14,10 +14,10 @@ namespace Content.Client.Commands
public string Description => $"Reverts the effects of {ShowMechanismsCommand.CommandName}"; public string Description => $"Reverts the effects of {ShowMechanismsCommand.CommandName}";
public string Help => $"{Command}"; public string Help => $"{Command}";
public bool Execute(IDebugConsole console, params string[] args) public void Execute(IConsoleShell shell, string argStr, string[] args)
{ {
var componentManager = IoCManager.Resolve<IComponentManager>(); var componentManager = IoCManager.Resolve<IComponentManager>();
var mechanisms = componentManager.EntityQuery<IMechanism>(); var mechanisms = componentManager.EntityQuery<IMechanism>(true);
foreach (var mechanism in mechanisms) foreach (var mechanism in mechanisms)
{ {
@@ -41,9 +41,7 @@ namespace Content.Client.Commands
} }
} }
IoCManager.Resolve<IClientConsole>().ProcessCommand("hidecontainedcontext"); IoCManager.Resolve<IClientConsoleHost>().ExecuteCommand("hidecontainedcontext");
return false;
} }
} }
} }

View File

@@ -1,7 +1,7 @@
using Content.Shared.GameObjects.Components.Body.Mechanism; using Content.Shared.GameObjects.Components.Body.Mechanism;
using Robust.Client.Console; using Robust.Client.Console;
using Robust.Client.GameObjects; using Robust.Client.GameObjects;
using Robust.Client.Interfaces.Console; using Robust.Shared.Console;
using Robust.Shared.Interfaces.GameObjects; using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.IoC; using Robust.Shared.IoC;
@@ -16,10 +16,10 @@ namespace Content.Client.Commands
public string Description => "Makes mechanisms visible, even when they shouldn't be."; public string Description => "Makes mechanisms visible, even when they shouldn't be.";
public string Help => $"{Command}"; public string Help => $"{Command}";
public bool Execute(IDebugConsole console, params string[] args) public void Execute(IConsoleShell shell, string argStr, string[] args)
{ {
var componentManager = IoCManager.Resolve<IComponentManager>(); var componentManager = IoCManager.Resolve<IComponentManager>();
var mechanisms = componentManager.EntityQuery<IMechanism>(); var mechanisms = componentManager.EntityQuery<IMechanism>(true);
foreach (var mechanism in mechanisms) foreach (var mechanism in mechanisms)
{ {
@@ -29,9 +29,7 @@ namespace Content.Client.Commands
} }
} }
IoCManager.Resolve<IClientConsole>().ProcessCommand("showcontainedcontext"); IoCManager.Resolve<IClientConsoleHost>().ExecuteCommand("showcontainedcontext");
return false;
} }
} }
} }

View File

@@ -1,5 +1,5 @@
using Content.Shared; using Content.Shared;
using Robust.Client.Interfaces.Console; using Robust.Shared.Console;
using Robust.Shared.Interfaces.Configuration; using Robust.Shared.Interfaces.Configuration;
using Robust.Shared.IoC; using Robust.Shared.IoC;
@@ -13,16 +13,14 @@ namespace Content.Client.Commands
public string Help => ""; public string Help => "";
public bool Execute(IDebugConsole console, params string[] args) public void Execute(IConsoleShell shell, string argStr, string[] args)
{ {
var configurationManager = IoCManager.Resolve<IConfigurationManager>(); var configurationManager = IoCManager.Resolve<IConfigurationManager>();
var cvar = CCVars.OutlineEnabled; var cvar = CCVars.OutlineEnabled;
var old = configurationManager.GetCVar(cvar); var old = configurationManager.GetCVar(cvar);
configurationManager.SetCVar(cvar, !old); configurationManager.SetCVar(cvar, !old);
console.AddLine($"Draw outlines set to: {configurationManager.GetCVar(cvar)}"); shell.WriteLine($"Draw outlines set to: {configurationManager.GetCVar(cvar)}");
return false;
} }
} }
} }

View File

@@ -13,6 +13,7 @@ using Content.Client.StationEvents;
using Content.Client.UserInterface; using Content.Client.UserInterface;
using Content.Client.UserInterface.AdminMenu; using Content.Client.UserInterface.AdminMenu;
using Content.Client.UserInterface.Stylesheets; using Content.Client.UserInterface.Stylesheets;
using Content.Client.Graphics.Overlays;
using Content.Shared.Actions; using Content.Shared.Actions;
using Content.Shared.GameObjects.Components; using Content.Shared.GameObjects.Components;
using Content.Shared.GameObjects.Components.Cargo; using Content.Shared.GameObjects.Components.Cargo;
@@ -149,7 +150,12 @@ namespace Content.Client
IoCManager.Resolve<IGameHud>().Initialize(); IoCManager.Resolve<IGameHud>().Initialize();
IoCManager.Resolve<IClientNotifyManager>().Initialize(); IoCManager.Resolve<IClientNotifyManager>().Initialize();
IoCManager.Resolve<IClientGameTicker>().Initialize(); IoCManager.Resolve<IClientGameTicker>().Initialize();
IoCManager.Resolve<IOverlayManager>().AddOverlay(new ParallaxOverlay()); var overlayMgr = IoCManager.Resolve<IOverlayManager>();
overlayMgr.AddOverlay(new ParallaxOverlay());
overlayMgr.AddOverlay(new GradientCircleMaskOverlay());
overlayMgr.AddOverlay(new CircleMaskOverlay());
overlayMgr.AddOverlay(new FlashOverlay());
overlayMgr.AddOverlay(new RadiationPulseOverlay());
IoCManager.Resolve<IChatManager>().Initialize(); IoCManager.Resolve<IChatManager>().Initialize();
IoCManager.Resolve<ISandboxManager>().Initialize(); IoCManager.Resolve<ISandboxManager>().Initialize();
IoCManager.Resolve<IClientPreferencesManager>().Initialize(); IoCManager.Resolve<IClientPreferencesManager>().Initialize();

View File

@@ -1,4 +1,4 @@
using Content.Client.State; using Content.Client.State;
using Content.Client.UserInterface; using Content.Client.UserInterface;
using Robust.Client.Console; using Robust.Client.Console;
using Robust.Client.Interfaces.Input; using Robust.Client.Interfaces.Input;
@@ -12,7 +12,7 @@ namespace Content.Client
{ {
internal sealed class EscapeMenuOwner : IEscapeMenuOwner internal sealed class EscapeMenuOwner : IEscapeMenuOwner
{ {
[Dependency] private readonly IClientConsole _clientConsole = default!; [Dependency] private readonly IClientConsoleHost _consoleHost = default!;
[Dependency] private readonly IInputManager _inputManager = default!; [Dependency] private readonly IInputManager _inputManager = default!;
[Dependency] private readonly IStateManager _stateManager = default!; [Dependency] private readonly IStateManager _stateManager = default!;
[Dependency] private readonly IGameHud _gameHud = default!; [Dependency] private readonly IGameHud _gameHud = default!;
@@ -31,7 +31,7 @@ namespace Content.Client
if (obj.NewState is GameScreenBase) if (obj.NewState is GameScreenBase)
{ {
// Switched TO GameScreen. // Switched TO GameScreen.
_escapeMenu = new EscapeMenu(_clientConsole); _escapeMenu = new EscapeMenu(_consoleHost);
_escapeMenu.OnClose += () => _gameHud.EscapeButtonDown = false; _escapeMenu.OnClose += () => _gameHud.EscapeButtonDown = false;

View File

@@ -0,0 +1,74 @@
#nullable enable
using System;
using Content.Shared.GameObjects.Components.Chemistry;
using JetBrains.Annotations;
using Robust.Client.Animations;
using Robust.Client.GameObjects;
using Robust.Client.GameObjects.Components.Animations;
using Robust.Client.Interfaces.GameObjects.Components;
using Robust.Shared.Maths;
using Robust.Shared.Utility;
using YamlDotNet.RepresentationModel;
namespace Content.Client.GameObjects.Components.Chemistry
{
[UsedImplicitly]
public class FoamVisualizer : AppearanceVisualizer
{
private const string AnimationKey = "foamdissolve_animation";
private Animation _foamDissolve = new();
public override void LoadData(YamlMappingNode node)
{
base.LoadData(node);
var delay = 0.6f;
var state = "foam-dissolve";
if (node.TryGetNode("animationTime", out var delayNode))
{
delay = delayNode.AsFloat();
}
if (node.TryGetNode("animationState", out var stateNode))
{
state = stateNode.AsString();
}
_foamDissolve = new Animation {Length = TimeSpan.FromSeconds(delay)};
var flick = new AnimationTrackSpriteFlick();
_foamDissolve.AnimationTracks.Add(flick);
flick.LayerKey = FoamVisualLayers.Base;
flick.KeyFrames.Add(new AnimationTrackSpriteFlick.KeyFrame(state, 0f));
}
public override void OnChangeData(AppearanceComponent component)
{
base.OnChangeData(component);
if (component.TryGetData<bool>(FoamVisuals.State, out var state))
{
if (state)
{
if (component.Owner.TryGetComponent(out AnimationPlayerComponent? animPlayer))
{
if (!animPlayer.HasRunningAnimation(AnimationKey))
animPlayer.Play(_foamDissolve, AnimationKey);
}
}
}
if (component.TryGetData<Color>(FoamVisuals.Color, out var color))
{
if (component.Owner.TryGetComponent(out ISpriteComponent? sprite))
{
sprite.Color = color;
}
}
}
}
public enum FoamVisualLayers : byte
{
Base
}
}

View File

@@ -0,0 +1,68 @@
using Content.Client.UserInterface.Stylesheets;
using Content.Client.Utility;
using Content.Shared.Chemistry;
using Content.Shared.GameObjects.Components.Chemistry;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls;
using Robust.Shared.GameObjects;
using Robust.Shared.Localization;
using Robust.Shared.Timing;
using Robust.Shared.ViewVariables;
#nullable enable
namespace Content.Client.GameObjects.Components.Chemistry
{
[RegisterComponent]
public sealed class HyposprayComponent : SharedHyposprayComponent, IItemStatus
{
[ViewVariables] private ReagentUnit CurrentVolume { get; set; }
[ViewVariables] private ReagentUnit TotalVolume { get; set; }
[ViewVariables(VVAccess.ReadWrite)] private bool _uiUpdateNeeded;
public override void HandleComponentState(ComponentState? curState, ComponentState? nextState)
{
if (curState is not HyposprayComponentState cState)
return;
CurrentVolume = cState.CurVolume;
TotalVolume = cState.MaxVolume;
_uiUpdateNeeded = true;
}
Control IItemStatus.MakeControl()
{
return new StatusControl(this);
}
private sealed class StatusControl : Control
{
private readonly HyposprayComponent _parent;
private readonly RichTextLabel _label;
public StatusControl(HyposprayComponent parent)
{
_parent = parent;
_label = new RichTextLabel {StyleClasses = {StyleNano.StyleClassItemStatus}};
AddChild(_label);
parent._uiUpdateNeeded = true;
}
protected override void Update(FrameEventArgs args)
{
base.Update(args);
if (!_parent._uiUpdateNeeded)
{
return;
}
_parent._uiUpdateNeeded = false;
_label.SetMarkup(Loc.GetString(
"Volume: [color=white]{0}/{1}[/color]",
_parent.CurrentVolume, _parent.TotalVolume));
}
}
}
}

View File

@@ -48,7 +48,10 @@ namespace Content.Client.GameObjects.Components.Chemistry.ReagentDispenser
_window.DispenseButton1.OnPressed += _ => ButtonPressed(UiButton.SetDispenseAmount1); _window.DispenseButton1.OnPressed += _ => ButtonPressed(UiButton.SetDispenseAmount1);
_window.DispenseButton5.OnPressed += _ => ButtonPressed(UiButton.SetDispenseAmount5); _window.DispenseButton5.OnPressed += _ => ButtonPressed(UiButton.SetDispenseAmount5);
_window.DispenseButton10.OnPressed += _ => ButtonPressed(UiButton.SetDispenseAmount10); _window.DispenseButton10.OnPressed += _ => ButtonPressed(UiButton.SetDispenseAmount10);
_window.DispenseButton15.OnPressed += _ => ButtonPressed(UiButton.SetDispenseAmount15);
_window.DispenseButton20.OnPressed += _ => ButtonPressed(UiButton.SetDispenseAmount20);
_window.DispenseButton25.OnPressed += _ => ButtonPressed(UiButton.SetDispenseAmount25); _window.DispenseButton25.OnPressed += _ => ButtonPressed(UiButton.SetDispenseAmount25);
_window.DispenseButton30.OnPressed += _ => ButtonPressed(UiButton.SetDispenseAmount30);
_window.DispenseButton50.OnPressed += _ => ButtonPressed(UiButton.SetDispenseAmount50); _window.DispenseButton50.OnPressed += _ => ButtonPressed(UiButton.SetDispenseAmount50);
_window.DispenseButton100.OnPressed += _ => ButtonPressed(UiButton.SetDispenseAmount100); _window.DispenseButton100.OnPressed += _ => ButtonPressed(UiButton.SetDispenseAmount100);
} }

View File

@@ -34,9 +34,18 @@ namespace Content.Client.GameObjects.Components.Chemistry.ReagentDispenser
/// <summary>Sets the dispense amount to 10 when pressed.</summary> /// <summary>Sets the dispense amount to 10 when pressed.</summary>
public Button DispenseButton10 { get; } public Button DispenseButton10 { get; }
/// <summary>Sets the dispense amount to 15 when pressed.</summary>
public Button DispenseButton15 { get; }
/// <summary>Sets the dispense amount to 20 when pressed.</summary>
public Button DispenseButton20 { get; }
/// <summary>Sets the dispense amount to 25 when pressed.</summary> /// <summary>Sets the dispense amount to 25 when pressed.</summary>
public Button DispenseButton25 { get; } public Button DispenseButton25 { get; }
/// <summary>Sets the dispense amount to 30 when pressed.</summary>
public Button DispenseButton30 { get; }
/// <summary>Sets the dispense amount to 50 when pressed.</summary> /// <summary>Sets the dispense amount to 50 when pressed.</summary>
public Button DispenseButton50 { get; } public Button DispenseButton50 { get; }
@@ -79,7 +88,10 @@ namespace Content.Client.GameObjects.Components.Chemistry.ReagentDispenser
(DispenseButton1 = new Button {Text = "1", Group = dispenseAmountGroup, StyleClasses = { StyleBase.ButtonOpenRight }}), (DispenseButton1 = new Button {Text = "1", Group = dispenseAmountGroup, StyleClasses = { StyleBase.ButtonOpenRight }}),
(DispenseButton5 = new Button {Text = "5", Group = dispenseAmountGroup, StyleClasses = { StyleBase.ButtonOpenBoth }}), (DispenseButton5 = new Button {Text = "5", Group = dispenseAmountGroup, StyleClasses = { StyleBase.ButtonOpenBoth }}),
(DispenseButton10 = new Button {Text = "10", Group = dispenseAmountGroup, StyleClasses = { StyleBase.ButtonOpenBoth }}), (DispenseButton10 = new Button {Text = "10", Group = dispenseAmountGroup, StyleClasses = { StyleBase.ButtonOpenBoth }}),
(DispenseButton15 = new Button {Text = "15", Group = dispenseAmountGroup, StyleClasses = { StyleBase.ButtonOpenBoth }}),
(DispenseButton20 = new Button {Text = "20", Group = dispenseAmountGroup, StyleClasses = { StyleBase.ButtonOpenBoth }}),
(DispenseButton25 = new Button {Text = "25", Group = dispenseAmountGroup, StyleClasses = { StyleBase.ButtonOpenBoth }}), (DispenseButton25 = new Button {Text = "25", Group = dispenseAmountGroup, StyleClasses = { StyleBase.ButtonOpenBoth }}),
(DispenseButton30 = new Button {Text = "30", Group = dispenseAmountGroup, StyleClasses = { StyleBase.ButtonOpenBoth }}),
(DispenseButton50 = new Button {Text = "50", Group = dispenseAmountGroup, StyleClasses = { StyleBase.ButtonOpenBoth }}), (DispenseButton50 = new Button {Text = "50", Group = dispenseAmountGroup, StyleClasses = { StyleBase.ButtonOpenBoth }}),
(DispenseButton100 = new Button {Text = "100", Group = dispenseAmountGroup, StyleClasses = { StyleBase.ButtonOpenLeft }}), (DispenseButton100 = new Button {Text = "100", Group = dispenseAmountGroup, StyleClasses = { StyleBase.ButtonOpenLeft }}),
} }
@@ -215,9 +227,18 @@ namespace Content.Client.GameObjects.Components.Chemistry.ReagentDispenser
case 10: case 10:
DispenseButton10.Pressed = true; DispenseButton10.Pressed = true;
break; break;
case 15:
DispenseButton15.Pressed = true;
break;
case 20:
DispenseButton20.Pressed = true;
break;
case 25: case 25:
DispenseButton25.Pressed = true; DispenseButton25.Pressed = true;
break; break;
case 30:
DispenseButton30.Pressed = true;
break;
case 50: case 50:
DispenseButton50.Pressed = true; DispenseButton50.Pressed = true;
break; break;

View File

@@ -0,0 +1,26 @@
#nullable enable
using Content.Shared.GameObjects.Components.Chemistry;
using JetBrains.Annotations;
using Robust.Client.GameObjects;
using Robust.Client.Interfaces.GameObjects.Components;
using Robust.Shared.Maths;
namespace Content.Client.GameObjects.Components.Chemistry
{
[UsedImplicitly]
public class SmokeVisualizer : AppearanceVisualizer
{
public override void OnChangeData(AppearanceComponent component)
{
base.OnChangeData(component);
if (component.TryGetData<Color>(SmokeVisuals.Color, out var color))
{
if (component.Owner.TryGetComponent(out ISpriteComponent? sprite))
{
sprite.Color = color;
}
}
}
}
}

View File

@@ -3,7 +3,6 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using Content.Client.GameObjects.EntitySystems; using Content.Client.GameObjects.EntitySystems;
using Content.Shared;
using Content.Shared.GameObjects.Components.Instruments; using Content.Shared.GameObjects.Components.Instruments;
using Content.Shared.Physics; using Content.Shared.Physics;
using Robust.Client.Audio.Midi; using Robust.Client.Audio.Midi;
@@ -11,13 +10,11 @@ using Robust.Shared.Audio.Midi;
using Robust.Shared.GameObjects; using Robust.Shared.GameObjects;
using Robust.Shared.GameObjects.Components.Timers; using Robust.Shared.GameObjects.Components.Timers;
using Robust.Shared.GameObjects.Systems; using Robust.Shared.GameObjects.Systems;
using Robust.Shared.Interfaces.Configuration;
using Robust.Shared.Interfaces.Network; using Robust.Shared.Interfaces.Network;
using Robust.Shared.Interfaces.Timing; using Robust.Shared.Interfaces.Timing;
using Robust.Shared.IoC; using Robust.Shared.IoC;
using Robust.Shared.Players; using Robust.Shared.Players;
using Robust.Shared.Serialization; using Robust.Shared.Serialization;
using Robust.Shared.Timers;
using Robust.Shared.ViewVariables; using Robust.Shared.ViewVariables;
namespace Content.Client.GameObjects.Components.Instruments namespace Content.Client.GameObjects.Components.Instruments
@@ -162,6 +159,41 @@ namespace Content.Client.GameObjects.Components.Instruments
[ViewVariables] [ViewVariables]
public bool IsRendererAlive => _renderer != null; public bool IsRendererAlive => _renderer != null;
[ViewVariables]
public int PlayerTotalTick => _renderer?.PlayerTotalTick ?? 0;
[ViewVariables]
public int PlayerTick
{
get => _renderer?.PlayerTick ?? 0;
set
{
if (!IsRendererAlive || _renderer!.Status != MidiRendererStatus.File) return;
_midiEventBuffer.Clear();
_renderer.PlayerTick = value;
var tick = _renderer.SequencerTick;
// We add a "all notes off" message.
for (byte i = 0; i < 16; i++)
{
_midiEventBuffer.Add(new MidiEvent()
{
Tick = tick, Type = 176,
Control = 123, Velocity = 0, Channel = i,
});
}
// Now we add a Reset All Controllers message.
_midiEventBuffer.Add(new MidiEvent()
{
Tick = tick, Type = 176,
Control = 121, Value = 0,
});
}
}
public override void Initialize() public override void Initialize()
{ {
base.Initialize(); base.Initialize();
@@ -390,20 +422,6 @@ namespace Content.Client.GameObjects.Components.Instruments
/// <param name="midiEvent">The received midi event</param> /// <param name="midiEvent">The received midi event</param>
private void RendererOnMidiEvent(MidiEvent midiEvent) private void RendererOnMidiEvent(MidiEvent midiEvent)
{ {
// avoid of out-of-band, unimportant or unsupported events
switch (midiEvent.Type)
{
case 0x80: // NOTE_OFF
case 0x90: // NOTE_ON
case 0xa0: // KEY_PRESSURE
case 0xb0: // CONTROL_CHANGE
case 0xd0: // CHANNEL_PRESSURE
case 0xe0: // PITCH_BEND
break;
default:
return;
}
_midiEventBuffer.Add(midiEvent); _midiEventBuffer.Add(midiEvent);
} }

View File

@@ -1,14 +1,23 @@
#nullable enable #nullable enable
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
using System.Linq; using System.Linq;
using Content.Client.Animations;
using Content.Client.UserInterface; using Content.Client.UserInterface;
using Content.Shared.GameObjects.Components.Items; using Content.Shared.GameObjects.Components.Items;
using Robust.Client.Animations;
using Robust.Client.GameObjects; using Robust.Client.GameObjects;
using Robust.Client.GameObjects.Components.Animations;
using Robust.Client.Interfaces.GameObjects.Components; using Robust.Client.Interfaces.GameObjects.Components;
using Robust.Shared.Animations;
using Robust.Shared.GameObjects; using Robust.Shared.GameObjects;
using Robust.Shared.Interfaces.GameObjects; using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.Interfaces.GameObjects.Components;
using Robust.Shared.Interfaces.Network;
using Robust.Shared.IoC; using Robust.Shared.IoC;
using Robust.Shared.Log;
using Robust.Shared.Players;
using Robust.Shared.ViewVariables; using Robust.Shared.ViewVariables;
namespace Content.Client.GameObjects.Components.Items namespace Content.Client.GameObjects.Components.Items
@@ -244,6 +253,23 @@ namespace Content.Client.GameObjects.Components.Items
} }
} }
public override void HandleNetworkMessage(ComponentMessage message, INetChannel netChannel, ICommonSession? session = null)
{
base.HandleNetworkMessage(message, netChannel, session);
switch (message)
{
case AnimatePickupEntityMessage msg:
{
if (Owner.EntityManager.TryGetEntity(msg.EntityId, out var entity))
{
ReusableAnimations.AnimateEntityPickup(entity, msg.EntityPosition, Owner.Transform.WorldPosition);
}
break;
}
}
}
public void SendChangeHand(string index) public void SendChangeHand(string index)
{ {
SendNetworkMessage(new ClientChangedHandMsg(index)); SendNetworkMessage(new ClientChangedHandMsg(index));

View File

@@ -1,169 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Content.Shared.GameObjects.Components.Mobs;
using Content.Shared.Interfaces;
using Robust.Client.GameObjects;
using Robust.Client.Graphics.Overlays;
using Robust.Client.Interfaces.Graphics.Overlays;
using Robust.Shared.GameObjects;
using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.Interfaces.Network;
using Robust.Shared.Interfaces.Reflection;
using Robust.Shared.IoC;
using Robust.Shared.Log;
using Robust.Shared.Players;
using Robust.Shared.ViewVariables;
namespace Content.Client.GameObjects.Components.Mobs
{
/// <summary>
/// A character UI component which shows the current damage state of the mob (living/dead)
/// </summary>
[RegisterComponent]
[ComponentReference(typeof(SharedOverlayEffectsComponent))]
public sealed class ClientOverlayEffectsComponent : SharedOverlayEffectsComponent//, ICharacterUI
{
[Dependency] private readonly IOverlayManager _overlayManager = default!;
[Dependency] private readonly IReflectionManager _reflectionManager = default!;
[Dependency] private readonly IClientNetManager _netManager = default!;
/// <summary>
/// A list of overlay containers representing the current overlays applied
/// </summary>
private List<OverlayContainer> _currentEffects = new();
[ViewVariables(VVAccess.ReadOnly)]
public List<OverlayContainer> ActiveOverlays
{
get => _currentEffects;
set => SetEffects(value);
}
public override void Initialize()
{
base.Initialize();
UpdateOverlays();
}
public override void HandleMessage(ComponentMessage message, IComponent component)
{
switch (message)
{
case PlayerAttachedMsg _:
UpdateOverlays();
break;
case PlayerDetachedMsg _:
ActiveOverlays.ForEach(o => _overlayManager.RemoveOverlay(o.ID));
break;
}
}
public override void HandleNetworkMessage(ComponentMessage message, INetChannel netChannel, ICommonSession session = null)
{
base.HandleNetworkMessage(message, netChannel, session);
if (message is OverlayEffectComponentMessage overlayMessage)
{
SetEffects(overlayMessage.Overlays);
}
}
private void UpdateOverlays()
{
_currentEffects = _overlayManager.AllOverlays
.Where(overlay => Enum.IsDefined(typeof(SharedOverlayID), overlay.ID))
.Select(overlay => new OverlayContainer(overlay.ID))
.ToList();
foreach (var overlayContainer in ActiveOverlays)
{
if (!_overlayManager.HasOverlay(overlayContainer.ID))
{
if (TryCreateOverlay(overlayContainer, out var overlay))
{
_overlayManager.AddOverlay(overlay);
}
}
}
SendNetworkMessage(new ResendOverlaysMessage(), _netManager.ServerChannel);
}
private void SetEffects(List<OverlayContainer> newOverlays)
{
foreach (var container in ActiveOverlays.ToArray())
{
if (!newOverlays.Contains(container))
{
RemoveOverlay(container);
}
}
foreach (var container in newOverlays)
{
if (!ActiveOverlays.Contains(container))
{
AddOverlay(container);
}
else
{
UpdateOverlayConfiguration(container, _overlayManager.GetOverlay(container.ID));
}
}
_currentEffects = newOverlays;
}
private void RemoveOverlay(OverlayContainer container)
{
ActiveOverlays.Remove(container);
_overlayManager.RemoveOverlay(container.ID);
}
private void AddOverlay(OverlayContainer container)
{
if (_overlayManager.HasOverlay(container.ID))
{
return;
}
ActiveOverlays.Add(container);
if (TryCreateOverlay(container, out var overlay))
{
_overlayManager.AddOverlay(overlay);
}
else
{
Logger.ErrorS("overlay", $"Could not add overlay {container.ID}");
}
}
private void UpdateOverlayConfiguration(OverlayContainer container, Overlay overlay)
{
if (overlay is IConfigurableOverlay configurable)
{
foreach (var param in container.Parameters)
{
configurable.Configure(param);
}
}
}
private bool TryCreateOverlay(OverlayContainer container, out Overlay overlay)
{
var overlayTypes = _reflectionManager.GetAllChildren<Overlay>();
var overlayType = overlayTypes.FirstOrDefault(t => t.Name == container.ID);
if (overlayType != null)
{
overlay = IoCManager.Resolve<IDynamicTypeFactory>().CreateInstance<Overlay>(overlayType);
UpdateOverlayConfiguration(container, overlay);
return true;
}
overlay = default;
return false;
}
}
}

View File

@@ -46,7 +46,7 @@ namespace Content.Client.GameObjects.Components.Observer
private void SetGhostVisibility(bool visibility) private void SetGhostVisibility(bool visibility)
{ {
foreach (var ghost in _componentManager.GetAllComponents(typeof(GhostComponent))) foreach (var ghost in _componentManager.GetAllComponents(typeof(GhostComponent), true))
{ {
if (ghost.Owner.TryGetComponent(out SpriteComponent? component)) if (ghost.Owner.TryGetComponent(out SpriteComponent? component))
{ {

View File

@@ -1,17 +1,23 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using Content.Client.Animations;
using Content.Client.GameObjects.Components.Items; using Content.Client.GameObjects.Components.Items;
using Content.Shared.GameObjects.Components.Storage; using Content.Shared.GameObjects.Components.Storage;
using Content.Shared.Interfaces.GameObjects.Components; using Content.Shared.Interfaces.GameObjects.Components;
using Robust.Client.Animations;
using Robust.Client.GameObjects;
using Robust.Client.GameObjects.Components.Animations;
using Robust.Client.Graphics.Drawing; using Robust.Client.Graphics.Drawing;
using Robust.Client.Interfaces.GameObjects.Components; using Robust.Client.Interfaces.GameObjects.Components;
using Robust.Client.Player; using Robust.Client.Player;
using Robust.Client.UserInterface; using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls; using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.CustomControls; using Robust.Client.UserInterface.CustomControls;
using Robust.Shared.Animations;
using Robust.Shared.GameObjects; using Robust.Shared.GameObjects;
using Robust.Shared.Interfaces.GameObjects; using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.Interfaces.GameObjects.Components;
using Robust.Shared.Interfaces.Network; using Robust.Shared.Interfaces.Network;
using Robust.Shared.IoC; using Robust.Shared.IoC;
using Robust.Shared.Maths; using Robust.Shared.Maths;
@@ -77,6 +83,9 @@ namespace Content.Client.GameObjects.Components.Storage
case CloseStorageUIMessage _: case CloseStorageUIMessage _:
CloseUI(); CloseUI();
break; break;
case AnimateInsertingEntitiesMessage msg:
HandleAnimatingInsertingEntities(msg);
break;
} }
} }
@@ -92,6 +101,24 @@ namespace Content.Client.GameObjects.Components.Storage
Window.BuildEntityList(); Window.BuildEntityList();
} }
/// <summary>
/// Animate the newly stored entities in <paramref name="msg"/> flying towards this storage's position
/// </summary>
/// <param name="msg"></param>
private void HandleAnimatingInsertingEntities(AnimateInsertingEntitiesMessage msg)
{
for (var i = 0; msg.StoredEntities.Count > i; i++)
{
var entityId = msg.StoredEntities[i];
var initialPosition = msg.EntityPositions[i];
if (Owner.EntityManager.TryGetEntity(entityId, out var entity))
{
ReusableAnimations.AnimateEntityPickup(entity, initialPosition, Owner.Transform.WorldPosition);
}
}
}
/// <summary> /// <summary>
/// Opens the storage UI if closed. Closes it if opened. /// Opens the storage UI if closed. Closes it if opened.
/// </summary> /// </summary>
@@ -284,7 +311,7 @@ namespace Content.Client.GameObjects.Components.Storage
/// <summary> /// <summary>
/// Button created for each entity that represents that item in the storage UI, with a texture, and name and size label /// Button created for each entity that represents that item in the storage UI, with a texture, and name and size label
/// </summary> /// </summary>
private class EntityButton : PanelContainer private class EntityButton : Control
{ {
public EntityUid EntityUid { get; set; } public EntityUid EntityUid { get; set; }
public Button ActualButton { get; } public Button ActualButton { get; }

View File

@@ -1,5 +1,6 @@
using System; using System;
using System.Threading; using System.Threading;
using Content.Client.Graphics.Overlays;
using Content.Shared.GameObjects.Components.Weapons; using Content.Shared.GameObjects.Components.Weapons;
using Robust.Client.Graphics.Drawing; using Robust.Client.Graphics.Drawing;
using Robust.Client.Graphics.Overlays; using Robust.Client.Graphics.Overlays;
@@ -19,10 +20,8 @@ namespace Content.Client.GameObjects.Components.Weapons
[RegisterComponent] [RegisterComponent]
public sealed class FlashableComponent : SharedFlashableComponent public sealed class FlashableComponent : SharedFlashableComponent
{ {
private CancellationTokenSource _cancelToken;
private TimeSpan _startTime; private TimeSpan _startTime;
private double _duration; private double _duration;
private FlashOverlay _overlay;
public override void HandleComponentState(ComponentState curState, ComponentState nextState) public override void HandleComponentState(ComponentState curState, ComponentState nextState)
{ {
@@ -57,94 +56,15 @@ namespace Content.Client.GameObjects.Components.Weapons
if (currentTime > newEndTime) if (currentTime > newEndTime)
{ {
DisableOverlay();
return; return;
} }
_startTime = newState.Time; _startTime = newState.Time;
_duration = newState.Duration; _duration = newState.Duration;
EnableOverlay(newEndTime - currentTime);
}
private void EnableOverlay(double duration)
{
// If the timer gets reset
if (_overlay != null)
{
_overlay.Duration = _duration;
_overlay.StartTime = _startTime;
_cancelToken.Cancel();
}
else
{
var overlayManager = IoCManager.Resolve<IOverlayManager>();
_overlay = new FlashOverlay(_duration);
overlayManager.AddOverlay(_overlay);
}
_cancelToken = new CancellationTokenSource();
Owner.SpawnTimer((int) duration * 1000, DisableOverlay, _cancelToken.Token);
}
private void DisableOverlay()
{
if (_overlay == null)
{
return;
}
var overlayManager = IoCManager.Resolve<IOverlayManager>(); var overlayManager = IoCManager.Resolve<IOverlayManager>();
overlayManager.RemoveOverlay(_overlay.ID); var overlay = overlayManager.GetOverlay<FlashOverlay>(nameof(FlashOverlay));
_overlay = null; overlay.ReceiveFlash(_duration);
_cancelToken.Cancel();
_cancelToken = null;
}
}
public sealed class FlashOverlay : Overlay
{
public override OverlaySpace Space => OverlaySpace.ScreenSpace;
private readonly IGameTiming _timer;
private readonly IClyde _displayManager;
public TimeSpan StartTime { get; set; }
public double Duration { get; set; }
public FlashOverlay(double duration) : base(nameof(FlashOverlay))
{
_timer = IoCManager.Resolve<IGameTiming>();
_displayManager = IoCManager.Resolve<IClyde>();
StartTime = _timer.CurTime;
Duration = duration;
}
protected override void Draw(DrawingHandleBase handle, OverlaySpace currentSpace)
{
var elapsedTime = (_timer.CurTime - StartTime).TotalSeconds;
if (elapsedTime > Duration)
{
return;
}
var screenHandle = (DrawingHandleScreen) handle;
screenHandle.DrawRect(
new UIBox2(0.0f, 0.0f, _displayManager.ScreenSize.X, _displayManager.ScreenSize.Y),
Color.White.WithAlpha(GetAlpha(elapsedTime / Duration))
);
}
private float GetAlpha(double ratio)
{
// Ideally you just want a smooth slope to finish it so it's not jarring at the end
// By all means put in a better curve
const float slope = -9.0f;
const float exponent = 0.1f;
const float yOffset = 9.0f;
const float xOffset = 0.0f;
// Overkill but easy to adjust if you want to mess around with the design
var result = (float) MathHelper.Clamp(slope * (float) Math.Pow(ratio - xOffset, exponent) + yOffset, 0.0, 1.0);
DebugTools.Assert(!float.IsNaN(result));
return result;
} }
} }
} }

View File

@@ -11,7 +11,7 @@ namespace Content.Client.GameObjects.EntitySystems
{ {
base.FrameUpdate(frameTime); base.FrameUpdate(frameTime);
foreach (var recoil in EntityManager.ComponentManager.EntityQuery<CameraRecoilComponent>()) foreach (var recoil in EntityManager.ComponentManager.EntityQuery<CameraRecoilComponent>(true))
{ {
recoil.FrameUpdate(frameTime); recoil.FrameUpdate(frameTime);
} }

View File

@@ -61,7 +61,7 @@ namespace Content.Client.GameObjects.EntitySystems.DoAfter
if (_attachedEntity == null || _attachedEntity.Deleted) if (_attachedEntity == null || _attachedEntity.Deleted)
return; return;
foreach (var comp in ComponentManager.EntityQuery<DoAfterComponent>()) foreach (var comp in ComponentManager.EntityQuery<DoAfterComponent>(true))
{ {
if (!_knownComponents.Contains(comp)) if (!_knownComponents.Contains(comp))
{ {

View File

@@ -302,6 +302,8 @@ namespace Content.Client.GameObjects.EntitySystems
foreach (var entity in entities) foreach (var entity in entities)
{ {
if (entity == _dragDropHelper.Dragged) continue;
// check if it's able to be dropped on by current dragged entity // check if it's able to be dropped on by current dragged entity
var dropArgs = new DragDropEventArgs(_dragger, args.Coordinates, _dragDropHelper.Dragged, entity); var dropArgs = new DragDropEventArgs(_dragger, args.Coordinates, _dragDropHelper.Dragged, entity);
var valid = true; var valid = true;
@@ -381,10 +383,9 @@ namespace Content.Client.GameObjects.EntitySystems
var pvsEntities = EntityManager.GetEntitiesIntersecting(_eyeManager.CurrentMap, bounds, true); var pvsEntities = EntityManager.GetEntitiesIntersecting(_eyeManager.CurrentMap, bounds, true);
foreach (var pvsEntity in pvsEntities) foreach (var pvsEntity in pvsEntities)
{ {
if (!pvsEntity.TryGetComponent(out ISpriteComponent? inRangeSprite)) continue; if (!pvsEntity.TryGetComponent(out ISpriteComponent? inRangeSprite) ||
!inRangeSprite.Visible ||
// can't highlight if there's no sprite or it's not visible pvsEntity == _dragDropHelper.Dragged) continue;
if (inRangeSprite.Visible == false) continue;
var valid = (bool?) null; var valid = (bool?) null;
// check if it's able to be dropped on by current dragged entity // check if it's able to be dropped on by current dragged entity

View File

@@ -44,7 +44,7 @@ namespace Content.Client.GameObjects.EntitySystems
return; return;
} }
foreach (var instrumentComponent in EntityManager.ComponentManager.EntityQuery<InstrumentComponent>()) foreach (var instrumentComponent in EntityManager.ComponentManager.EntityQuery<InstrumentComponent>(true))
{ {
instrumentComponent.Update(frameTime); instrumentComponent.Update(frameTime);
} }

View File

@@ -19,7 +19,7 @@ namespace Content.Client.GameObjects.EntitySystems
private void UpdateMarkers() private void UpdateMarkers()
{ {
foreach (var markerComponent in EntityManager.ComponentManager.EntityQuery<MarkerComponent>()) foreach (var markerComponent in EntityManager.ComponentManager.EntityQuery<MarkerComponent>(true))
{ {
markerComponent.UpdateVisibility(); markerComponent.UpdateVisibility();
} }

View File

@@ -11,7 +11,7 @@ namespace Content.Client.GameObjects.EntitySystems
{ {
base.FrameUpdate(frameTime); base.FrameUpdate(frameTime);
foreach (var meleeLungeComponent in EntityManager.ComponentManager.EntityQuery<MeleeLungeComponent>()) foreach (var meleeLungeComponent in EntityManager.ComponentManager.EntityQuery<MeleeLungeComponent>(true))
{ {
meleeLungeComponent.Update(frameTime); meleeLungeComponent.Update(frameTime);
} }

View File

@@ -1,4 +1,4 @@
using System; using System;
using Content.Client.GameObjects.Components.Mobs; using Content.Client.GameObjects.Components.Mobs;
using Content.Client.GameObjects.Components.Weapons.Melee; using Content.Client.GameObjects.Components.Weapons.Melee;
using Content.Shared.GameObjects.Components.Weapons.Melee; using Content.Shared.GameObjects.Components.Weapons.Melee;
@@ -14,7 +14,6 @@ using Robust.Shared.IoC;
using Robust.Shared.Log; using Robust.Shared.Log;
using Robust.Shared.Maths; using Robust.Shared.Maths;
using Robust.Shared.Prototypes; using Robust.Shared.Prototypes;
using Robust.Shared.Timers;
using static Content.Shared.GameObjects.EntitySystemMessages.MeleeWeaponSystemMessages; using static Content.Shared.GameObjects.EntitySystemMessages.MeleeWeaponSystemMessages;
namespace Content.Client.GameObjects.EntitySystems namespace Content.Client.GameObjects.EntitySystems
@@ -35,7 +34,7 @@ namespace Content.Client.GameObjects.EntitySystems
{ {
base.FrameUpdate(frameTime); base.FrameUpdate(frameTime);
foreach (var arcAnimationComponent in EntityManager.ComponentManager.EntityQuery<MeleeWeaponArcAnimationComponent>()) foreach (var arcAnimationComponent in EntityManager.ComponentManager.EntityQuery<MeleeWeaponArcAnimationComponent>(true))
{ {
arcAnimationComponent.Update(frameTime); arcAnimationComponent.Update(frameTime);
} }
@@ -49,7 +48,12 @@ namespace Content.Client.GameObjects.EntitySystems
return; return;
} }
var attacker = EntityManager.GetEntity(msg.Attacker); if (!EntityManager.TryGetEntity(msg.Attacker, out var attacker))
{
//FIXME: This should never happen.
Logger.Error($"Tried to play a weapon arc {msg.ArcPrototype}, but the attacker does not exist. attacker={msg.Attacker}, source={msg.Source}");
return;
}
if (!attacker.Deleted) if (!attacker.Deleted)
{ {

View File

@@ -35,7 +35,7 @@ namespace Content.Client.GameObjects.EntitySystems
private void UpdateAll() private void UpdateAll()
{ {
foreach (var comp in EntityManager.ComponentManager.EntityQuery<SubFloorHideComponent>()) foreach (var comp in EntityManager.ComponentManager.EntityQuery<SubFloorHideComponent>(true))
{ {
if (!_mapManager.TryGetGrid(comp.Owner.Transform.GridID, out var grid)) return; if (!_mapManager.TryGetGrid(comp.Owner.Transform.GridID, out var grid)) return;

View File

@@ -0,0 +1,23 @@
using System;
using Content.Shared.GameObjects.EntitySystemMessages;
using Robust.Shared.GameObjects.Systems;
namespace Content.Client.GameObjects.EntitySystems
{
public sealed class SuspicionEndTimerSystem : EntitySystem
{
public TimeSpan? EndTime { get; private set; }
public override void Initialize()
{
base.Initialize();
SubscribeNetworkEvent<SuspicionMessages.SetSuspicionEndTimerMessage>(RxTimerMessage);
}
private void RxTimerMessage(SuspicionMessages.SetSuspicionEndTimerMessage ev)
{
EndTime = ev.EndTime;
}
}
}

View File

@@ -3,6 +3,7 @@ using Robust.Client.Graphics.Drawing;
using Robust.Client.Graphics.Overlays; using Robust.Client.Graphics.Overlays;
using Robust.Client.Graphics.Shaders; using Robust.Client.Graphics.Shaders;
using Robust.Client.Interfaces.Graphics.ClientEye; using Robust.Client.Interfaces.Graphics.ClientEye;
using Robust.Client.Player;
using Robust.Shared.IoC; using Robust.Shared.IoC;
using Robust.Shared.Maths; using Robust.Shared.Maths;
using Robust.Shared.Prototypes; using Robust.Shared.Prototypes;
@@ -13,11 +14,12 @@ namespace Content.Client.Graphics.Overlays
{ {
[Dependency] private readonly IPrototypeManager _prototypeManager = default!; [Dependency] private readonly IPrototypeManager _prototypeManager = default!;
[Dependency] private readonly IEyeManager _eyeManager = default!; [Dependency] private readonly IEyeManager _eyeManager = default!;
[Dependency] private readonly IPlayerManager _playerManager = default!;
public override OverlaySpace Space => OverlaySpace.WorldSpace; public override OverlaySpace Space => OverlaySpace.WorldSpace;
private readonly ShaderInstance _shader; private readonly ShaderInstance _shader;
public CircleMaskOverlay() : base(nameof(SharedOverlayID.CircleMaskOverlay)) public CircleMaskOverlay() : base(nameof(CircleMaskOverlay))
{ {
IoCManager.InjectDependencies(this); IoCManager.InjectDependencies(this);
_shader = _prototypeManager.Index<ShaderPrototype>("CircleMask").Instance(); _shader = _prototypeManager.Index<ShaderPrototype>("CircleMask").Instance();
@@ -25,6 +27,8 @@ namespace Content.Client.Graphics.Overlays
protected override void Draw(DrawingHandleBase handle, OverlaySpace currentSpace) protected override void Draw(DrawingHandleBase handle, OverlaySpace currentSpace)
{ {
if (!GradientCircleMaskOverlay.LocalPlayerHasState(_playerManager, false, true))
return;
handle.UseShader(_shader); handle.UseShader(_shader);
var worldHandle = (DrawingHandleWorld)handle; var worldHandle = (DrawingHandleWorld)handle;
var viewport = _eyeManager.GetWorldViewport(); var viewport = _eyeManager.GetWorldViewport();

View File

@@ -1,5 +1,6 @@
using Content.Shared.GameObjects.Components.Mobs; using Content.Shared.GameObjects.Components.Mobs;
using Content.Shared.Interfaces; using Content.Shared.Interfaces;
using Content.Shared.Network.NetMessages;
using Robust.Client.Graphics; using Robust.Client.Graphics;
using Robust.Client.Graphics.Drawing; using Robust.Client.Graphics.Drawing;
using Robust.Client.Graphics.Overlays; using Robust.Client.Graphics.Overlays;
@@ -14,7 +15,7 @@ using SixLabors.ImageSharp.PixelFormats;
namespace Content.Client.Graphics.Overlays namespace Content.Client.Graphics.Overlays
{ {
public class FlashOverlay : Overlay, IConfigurableOverlay public class FlashOverlay : Overlay
{ {
[Dependency] private readonly IPrototypeManager _prototypeManager = default!; [Dependency] private readonly IPrototypeManager _prototypeManager = default!;
[Dependency] private readonly IClyde _displayManager = default!; [Dependency] private readonly IClyde _displayManager = default!;
@@ -22,27 +23,33 @@ namespace Content.Client.Graphics.Overlays
public override OverlaySpace Space => OverlaySpace.ScreenSpace; public override OverlaySpace Space => OverlaySpace.ScreenSpace;
private readonly ShaderInstance _shader; private readonly ShaderInstance _shader;
private readonly double _startTime; private double _startTime = -1;
private int _lastsFor = 5000; private double _lastsFor = 1;
private Texture _screenshotTexture; private Texture _screenshotTexture;
public FlashOverlay() : base(nameof(SharedOverlayID.FlashOverlay)) public FlashOverlay() : base(nameof(FlashOverlay))
{ {
IoCManager.InjectDependencies(this); IoCManager.InjectDependencies(this);
_shader = _prototypeManager.Index<ShaderPrototype>("FlashedEffect").Instance().Duplicate(); _shader = _prototypeManager.Index<ShaderPrototype>("FlashedEffect").Instance().Duplicate();
}
_startTime = _gameTiming.CurTime.TotalMilliseconds; public void ReceiveFlash(double duration)
{
_displayManager.Screenshot(ScreenshotType.BeforeUI, image => _displayManager.Screenshot(ScreenshotType.BeforeUI, image =>
{ {
var rgba32Image = image.CloneAs<Rgba32>(Configuration.Default); var rgba32Image = image.CloneAs<Rgba32>(Configuration.Default);
_screenshotTexture = _displayManager.LoadTextureFromImage(rgba32Image); _screenshotTexture = _displayManager.LoadTextureFromImage(rgba32Image);
}); });
_startTime = _gameTiming.CurTime.TotalSeconds;
_lastsFor = duration;
} }
protected override void Draw(DrawingHandleBase handle, OverlaySpace currentSpace) protected override void Draw(DrawingHandleBase handle, OverlaySpace currentSpace)
{ {
var percentComplete = (float) ((_gameTiming.CurTime.TotalSeconds - _startTime) / _lastsFor);
if (percentComplete >= 1.0f)
return;
handle.UseShader(_shader); handle.UseShader(_shader);
var percentComplete = (float) ((_gameTiming.CurTime.TotalMilliseconds - _startTime) / _lastsFor);
_shader?.SetParameter("percentComplete", percentComplete); _shader?.SetParameter("percentComplete", percentComplete);
var screenSpaceHandle = handle as DrawingHandleScreen; var screenSpaceHandle = handle as DrawingHandleScreen;
@@ -60,13 +67,5 @@ namespace Content.Client.Graphics.Overlays
_screenshotTexture = null; _screenshotTexture = null;
} }
public void Configure(OverlayParameter parameters)
{
if (parameters is TimedOverlayParameter timedParams)
{
_lastsFor = timedParams.Length;
}
}
} }
} }

View File

@@ -1,8 +1,10 @@
using Content.Shared.GameObjects.Components.Mobs; using Content.Shared.GameObjects.Components.Mobs;
using Content.Shared.GameObjects.Components.Mobs.State;
using Robust.Client.Graphics.Drawing; using Robust.Client.Graphics.Drawing;
using Robust.Client.Graphics.Overlays; using Robust.Client.Graphics.Overlays;
using Robust.Client.Graphics.Shaders; using Robust.Client.Graphics.Shaders;
using Robust.Client.Interfaces.Graphics.ClientEye; using Robust.Client.Interfaces.Graphics.ClientEye;
using Robust.Client.Player;
using Robust.Shared.IoC; using Robust.Shared.IoC;
using Robust.Shared.Maths; using Robust.Shared.Maths;
using Robust.Shared.Prototypes; using Robust.Shared.Prototypes;
@@ -13,18 +15,43 @@ namespace Content.Client.Graphics.Overlays
{ {
[Dependency] private readonly IPrototypeManager _prototypeManager = default!; [Dependency] private readonly IPrototypeManager _prototypeManager = default!;
[Dependency] private readonly IEyeManager _eyeManager = default!; [Dependency] private readonly IEyeManager _eyeManager = default!;
[Dependency] private readonly IPlayerManager _playerManager = default!;
public override OverlaySpace Space => OverlaySpace.WorldSpace; public override OverlaySpace Space => OverlaySpace.WorldSpace;
private readonly ShaderInstance _shader; private readonly ShaderInstance _shader;
public GradientCircleMaskOverlay() : base(nameof(SharedOverlayID.GradientCircleMaskOverlay)) public GradientCircleMaskOverlay() : base(nameof(GradientCircleMaskOverlay))
{ {
IoCManager.InjectDependencies(this); IoCManager.InjectDependencies(this);
_shader = _prototypeManager.Index<ShaderPrototype>("GradientCircleMask").Instance(); _shader = _prototypeManager.Index<ShaderPrototype>("GradientCircleMask").Instance();
} }
public static bool LocalPlayerHasState(IPlayerManager pm, bool critical, bool dead) {
var playerEntity = pm.LocalPlayer?.ControlledEntity;
if (playerEntity == null)
{
return false;
}
if (playerEntity.TryGetComponent<IMobStateComponent>(out var mobState))
{
if (critical)
if (mobState.IsCritical())
return true;
if (dead)
if (mobState.IsDead())
return true;
}
return false;
}
protected override void Draw(DrawingHandleBase handle, OverlaySpace currentSpace) protected override void Draw(DrawingHandleBase handle, OverlaySpace currentSpace)
{ {
if (!LocalPlayerHasState(_playerManager, true, false))
return;
handle.UseShader(_shader); handle.UseShader(_shader);
var worldHandle = (DrawingHandleWorld)handle; var worldHandle = (DrawingHandleWorld)handle;
var viewport = _eyeManager.GetWorldViewport(); var viewport = _eyeManager.GetWorldViewport();

View File

@@ -235,11 +235,14 @@ namespace Content.Client
"SliceableFood", "SliceableFood",
"DamageOtherOnHit", "DamageOtherOnHit",
"DamageOnLand", "DamageOnLand",
"SmokeSolutionAreaEffect",
"FoamSolutionAreaEffect",
"GasFilter", "GasFilter",
"Recyclable", "Recyclable",
"SecretStash", "SecretStash",
"Toilet", "Toilet",
"ClusterFlash" "ClusterFlash",
"GasGenerator"
}; };
} }
} }

View File

@@ -0,0 +1,23 @@
<cc:SS14Window xmlns:cc="clr-namespace:Robust.Client.UserInterface.CustomControls;assembly=Robust.Client"
xmlns:uic="clr-namespace:Robust.Client.UserInterface.Controls;assembly=Robust.Client"
xmlns:ui="clr-namespace:Robust.Client.UserInterface;assembly=Robust.Client">
<uic:MarginContainer Name="Margin" SizeFlagsVertical="FillExpand" SizeFlagsHorizontal="Fill">
<uic:VBoxContainer SizeFlagsVertical="FillExpand" SizeFlagsHorizontal="FillExpand" SeparationOverride="5">
<uic:HBoxContainer SizeFlagsVertical="FillExpand" SizeFlagsHorizontal="FillExpand">
<uic:Button Name="InputButton" ToggleMode="True" Text="MIDI Input" TextAlign="Center" SizeFlagsHorizontal="FillExpand" SizeFlagsStretchRatio="1"/>
<ui:Control SizeFlagsHorizontal="FillExpand" SizeFlagsStretchRatio="2" />
<uic:Button Name="FileButton" Text="Play MIDI File" TextAlign="Center" SizeFlagsHorizontal="FillExpand" SizeFlagsStretchRatio="1"/>
</uic:HBoxContainer>
<uic:HBoxContainer SizeFlagsVertical="FillExpand" SizeFlagsHorizontal="Fill">
<uic:Button Name="LoopButton" ToggleMode="True" Text="Loop" TextAlign="Center" SizeFlagsHorizontal="FillExpand" SizeFlagsStretchRatio="1"/>
<ui:Control SizeFlagsHorizontal="FillExpand" SizeFlagsStretchRatio="2" />
<uic:Button Name="StopButton" Text="Stop" TextAlign="Center" SizeFlagsHorizontal="FillExpand" SizeFlagsStretchRatio="1"/>
</uic:HBoxContainer>
<uic:HBoxContainer SizeFlagsVertical="ShrinkEnd" SizeFlagsHorizontal="FillExpand">
<ui:Control SizeFlagsHorizontal="FillExpand" SizeFlagsStretchRatio="0.125"/>
<uic:Slider Name="PlaybackSlider" SizeFlagsHorizontal="FillExpand" />
<ui:Control SizeFlagsHorizontal="FillExpand" SizeFlagsStretchRatio="0.125"/>
</uic:HBoxContainer>
</uic:VBoxContainer>
</uic:MarginContainer>
</cc:SS14Window>

View File

@@ -5,35 +5,39 @@ using Content.Client.GameObjects.Components.Instruments;
using Content.Client.UserInterface.Stylesheets; using Content.Client.UserInterface.Stylesheets;
using Content.Client.Utility; using Content.Client.Utility;
using Robust.Client.Audio.Midi; using Robust.Client.Audio.Midi;
using Robust.Client.AutoGenerated;
using Robust.Client.Graphics.Drawing; using Robust.Client.Graphics.Drawing;
using Robust.Client.Interfaces.UserInterface; using Robust.Client.Interfaces.UserInterface;
using Robust.Client.Player; using Robust.Client.Player;
using Robust.Client.UserInterface; using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls; using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.CustomControls; using Robust.Client.UserInterface.CustomControls;
using Robust.Client.UserInterface.XAML;
using Robust.Shared.Containers; using Robust.Shared.Containers;
using Robust.Shared.Input;
using Robust.Shared.IoC; using Robust.Shared.IoC;
using Robust.Shared.Localization; using Robust.Shared.Localization;
using Robust.Shared.Log; using Robust.Shared.Log;
using Robust.Shared.Maths; using Robust.Shared.Maths;
using Robust.Shared.Timers; using Robust.Shared.Timers;
using Robust.Shared.Timing;
using Range = Robust.Client.UserInterface.Controls.Range;
namespace Content.Client.Instruments namespace Content.Client.Instruments
{ {
public class InstrumentMenu : SS14Window [GenerateTypedNameReferences]
public partial class InstrumentMenu : SS14Window
{ {
[Dependency] private readonly IMidiManager _midiManager = default!; [Dependency] private readonly IMidiManager _midiManager = default!;
[Dependency] private readonly IFileDialogManager _fileDialogManager = default!; [Dependency] private readonly IFileDialogManager _fileDialogManager = default!;
private readonly InstrumentBoundUserInterface _owner; private readonly InstrumentBoundUserInterface _owner;
private readonly Button _midiLoopButton;
private readonly Button _midiStopButton;
private readonly Button _midiInputButton;
protected override Vector2? CustomSize => (400, 150); protected override Vector2? CustomSize => (400, 150);
public InstrumentMenu(InstrumentBoundUserInterface owner) public InstrumentMenu(InstrumentBoundUserInterface owner)
{ {
RobustXamlLoader.Load(this);
IoCManager.InjectDependencies(this); IoCManager.InjectDependencies(this);
_owner = owner; _owner = owner;
@@ -42,108 +46,14 @@ namespace Content.Client.Instruments
Title = _owner.Instrument.Owner.Name; Title = _owner.Instrument.Owner.Name;
var margin = new MarginContainer() LoopButton.Disabled = !_owner.Instrument.IsMidiOpen;
{ LoopButton.Pressed = _owner.Instrument.LoopMidi;
SizeFlagsVertical = SizeFlags.FillExpand, StopButton.Disabled = !_owner.Instrument.IsMidiOpen;
SizeFlagsHorizontal = SizeFlags.FillExpand, PlaybackSlider.MouseFilter = _owner.Instrument.IsMidiOpen ? MouseFilterMode.Pass : MouseFilterMode.Ignore;
};
var vBox = new VBoxContainer()
{
SizeFlagsVertical = SizeFlags.FillExpand,
SeparationOverride = 5,
};
var hBoxTopButtons = new HBoxContainer()
{
SizeFlagsHorizontal = SizeFlags.FillExpand,
SizeFlagsVertical = SizeFlags.FillExpand,
SizeFlagsStretchRatio = 1,
Align = BoxContainer.AlignMode.Center
};
_midiInputButton = new Button()
{
Text = Loc.GetString("MIDI Input"),
TextAlign = Label.AlignMode.Center,
SizeFlagsHorizontal = SizeFlags.FillExpand,
SizeFlagsStretchRatio = 1,
ToggleMode = true,
Pressed = _owner.Instrument.IsInputOpen,
};
_midiInputButton.OnToggled += MidiInputButtonOnOnToggled;
var topSpacer = new Control()
{
SizeFlagsHorizontal = SizeFlags.FillExpand,
SizeFlagsStretchRatio = 2,
};
var midiFileButton = new Button()
{
Text = Loc.GetString("Play MIDI File"),
TextAlign = Label.AlignMode.Center,
SizeFlagsHorizontal = SizeFlags.FillExpand,
SizeFlagsStretchRatio = 1,
};
midiFileButton.OnPressed += MidiFileButtonOnOnPressed;
var hBoxBottomButtons = new HBoxContainer()
{
SizeFlagsHorizontal = SizeFlags.FillExpand,
SizeFlagsVertical = SizeFlags.FillExpand,
SizeFlagsStretchRatio = 1,
Align = BoxContainer.AlignMode.Center
};
_midiLoopButton = new Button()
{
Text = Loc.GetString("Loop"),
TextAlign = Label.AlignMode.Center,
SizeFlagsHorizontal = SizeFlags.FillExpand,
SizeFlagsStretchRatio = 1,
ToggleMode = true,
Disabled = !_owner.Instrument.IsMidiOpen,
Pressed = _owner.Instrument.LoopMidi,
};
_midiLoopButton.OnToggled += MidiLoopButtonOnOnToggled;
var bottomSpacer = new Control()
{
SizeFlagsHorizontal = SizeFlags.FillExpand,
SizeFlagsStretchRatio = 2,
};
_midiStopButton = new Button()
{
Text = Loc.GetString("Stop"),
TextAlign = Label.AlignMode.Center,
SizeFlagsHorizontal = SizeFlags.FillExpand,
SizeFlagsStretchRatio = 1,
Disabled = !_owner.Instrument.IsMidiOpen,
};
_midiStopButton.OnPressed += MidiStopButtonOnPressed;
hBoxBottomButtons.AddChild(_midiLoopButton);
hBoxBottomButtons.AddChild(bottomSpacer);
hBoxBottomButtons.AddChild(_midiStopButton);
hBoxTopButtons.AddChild(_midiInputButton);
hBoxTopButtons.AddChild(topSpacer);
hBoxTopButtons.AddChild(midiFileButton);
vBox.AddChild(hBoxTopButtons);
vBox.AddChild(hBoxBottomButtons);
margin.AddChild(vBox);
if (!_midiManager.IsAvailable) if (!_midiManager.IsAvailable)
{ {
margin.AddChild(new PanelContainer Margin.AddChild(new PanelContainer
{ {
MouseFilter = MouseFilterMode.Stop, MouseFilter = MouseFilterMode.Stop,
PanelOverride = new StyleBoxFlat {BackgroundColor = Color.Black.WithAlpha(0.90f)}, PanelOverride = new StyleBoxFlat {BackgroundColor = Color.Black.WithAlpha(0.90f)},
@@ -159,9 +69,17 @@ namespace Content.Client.Instruments
} }
} }
}); });
// We return early as to not give the buttons behavior.
return;
} }
Contents.AddChild(margin); InputButton.OnToggled += MidiInputButtonOnOnToggled;
FileButton.OnPressed += MidiFileButtonOnOnPressed;
LoopButton.OnToggled += MidiLoopButtonOnOnToggled;
StopButton.OnPressed += MidiStopButtonOnPressed;
PlaybackSlider.OnValueChanged += PlaybackSliderSeek;
PlaybackSlider.OnKeyBindUp += PlaybackSliderKeyUp;
} }
private void InstrumentOnMidiPlaybackEnded() private void InstrumentOnMidiPlaybackEnded()
@@ -171,14 +89,17 @@ namespace Content.Client.Instruments
public void MidiPlaybackSetButtonsDisabled(bool disabled) public void MidiPlaybackSetButtonsDisabled(bool disabled)
{ {
_midiLoopButton.Disabled = disabled; LoopButton.Disabled = disabled;
_midiStopButton.Disabled = disabled; StopButton.Disabled = disabled;
// Whether to allow the slider to receive events..
PlaybackSlider.MouseFilter = !disabled ? MouseFilterMode.Pass : MouseFilterMode.Ignore;
} }
private async void MidiFileButtonOnOnPressed(BaseButton.ButtonEventArgs obj) private async void MidiFileButtonOnOnPressed(BaseButton.ButtonEventArgs obj)
{ {
var filters = new FileDialogFilters(new FileDialogFilters.Group("mid", "midi")); var filters = new FileDialogFilters(new FileDialogFilters.Group("mid", "midi"));
var file = await _fileDialogManager.OpenFile(filters); await using var file = await _fileDialogManager.OpenFile(filters);
// The following checks are only in place to prevent players from playing MIDI songs locally. // The following checks are only in place to prevent players from playing MIDI songs locally.
// There are equivalents for these checks on the server. // There are equivalents for these checks on the server.
@@ -195,7 +116,7 @@ namespace Content.Client.Instruments
return; return;
MidiStopButtonOnPressed(null); MidiStopButtonOnPressed(null);
var memStream = new MemoryStream((int) file.Length); await using var memStream = new MemoryStream((int) file.Length);
// 100ms delay is due to a race condition or something idk. // 100ms delay is due to a race condition or something idk.
// While we're waiting, load it into memory. // While we're waiting, load it into memory.
await Task.WhenAll(Timer.Delay(100), file.CopyToAsync(memStream)); await Task.WhenAll(Timer.Delay(100), file.CopyToAsync(memStream));
@@ -204,8 +125,8 @@ namespace Content.Client.Instruments
return; return;
MidiPlaybackSetButtonsDisabled(false); MidiPlaybackSetButtonsDisabled(false);
if (_midiInputButton.Pressed) if (InputButton.Pressed)
_midiInputButton.Pressed = false; InputButton.Pressed = false;
} }
private void MidiInputButtonOnOnToggled(BaseButton.ButtonToggledEventArgs obj) private void MidiInputButtonOnOnToggled(BaseButton.ButtonToggledEventArgs obj)
@@ -253,5 +174,36 @@ namespace Content.Client.Instruments
{ {
_owner.Instrument.LoopMidi = obj.Pressed; _owner.Instrument.LoopMidi = obj.Pressed;
} }
private void PlaybackSliderSeek(Range _)
{
// Do not seek while still grabbing.
if (PlaybackSlider.Grabbed) return;
_owner.Instrument.PlayerTick = (int)Math.Ceiling(PlaybackSlider.Value);
}
private void PlaybackSliderKeyUp(GUIBoundKeyEventArgs args)
{
if (args.Function != EngineKeyFunctions.UIClick) return;
_owner.Instrument.PlayerTick = (int)Math.Ceiling(PlaybackSlider.Value);
}
protected override void Update(FrameEventArgs args)
{
base.Update(args);
if (!_owner.Instrument.IsMidiOpen)
{
PlaybackSlider.MaxValue = 1;
PlaybackSlider.SetValueWithoutEvent(0);
return;
}
if (PlaybackSlider.Grabbed) return;
PlaybackSlider.MaxValue = _owner.Instrument.PlayerTotalTick;
PlaybackSlider.SetValueWithoutEvent(_owner.Instrument.PlayerTick);
}
} }
} }

View File

@@ -54,7 +54,7 @@ namespace Content.Client.Parallax
{ {
using (var reader = new StreamReader(configStream, EncodingHelpers.UTF8)) using (var reader = new StreamReader(configStream, EncodingHelpers.UTF8))
{ {
contents = reader.ReadToEnd(); contents = reader.ReadToEnd().Replace(Environment.NewLine, "\n");
} }
if (!debugParallax && _resourceCache.UserData.Exists(ParallaxConfigOld)) if (!debugParallax && _resourceCache.UserData.Exists(ParallaxConfigOld))

View File

@@ -102,7 +102,7 @@ namespace Content.Client.Sandbox
internal class SandboxManager : SharedSandboxManager, ISandboxManager internal class SandboxManager : SharedSandboxManager, ISandboxManager
{ {
[Dependency] private readonly IClientConsole _console = default!; [Dependency] private readonly IClientConsoleHost _consoleHost = default!;
[Dependency] private readonly IGameHud _gameHud = default!; [Dependency] private readonly IGameHud _gameHud = default!;
[Dependency] private readonly IClientNetManager _netManager = default!; [Dependency] private readonly IClientNetManager _netManager = default!;
[Dependency] private readonly IPlacementManager _placementManager = default!; [Dependency] private readonly IPlacementManager _placementManager = default!;
@@ -314,37 +314,37 @@ namespace Content.Client.Sandbox
private void ToggleLight() private void ToggleLight()
{ {
_console.ProcessCommand("togglelight"); _consoleHost.ExecuteCommand("togglelight");
} }
private void ToggleFov() private void ToggleFov()
{ {
_console.ProcessCommand("togglefov"); _consoleHost.ExecuteCommand("togglefov");
} }
private void ToggleShadows() private void ToggleShadows()
{ {
_console.ProcessCommand("toggleshadows"); _consoleHost.ExecuteCommand("toggleshadows");
} }
private void ToggleSubFloor() private void ToggleSubFloor()
{ {
_console.ProcessCommand("showsubfloor"); _consoleHost.ExecuteCommand("showsubfloor");
} }
private void ShowMarkers() private void ShowMarkers()
{ {
_console.ProcessCommand("showmarkers"); _consoleHost.ExecuteCommand("showmarkers");
} }
private void ShowBb() private void ShowBb()
{ {
_console.ProcessCommand("showbb"); _consoleHost.ExecuteCommand("showbb");
} }
private void LinkMachines() private void LinkMachines()
{ {
_console.ProcessCommand("signallink"); _consoleHost.ExecuteCommand("signallink");
} }
} }
} }

View File

@@ -26,7 +26,7 @@ namespace Content.Client.State
public class LobbyState : Robust.Client.State.State public class LobbyState : Robust.Client.State.State
{ {
[Dependency] private readonly IBaseClient _baseClient = default!; [Dependency] private readonly IBaseClient _baseClient = default!;
[Dependency] private readonly IClientConsole _console = default!; [Dependency] private readonly IClientConsoleHost _consoleHost = default!;
[Dependency] private readonly IChatManager _chatManager = default!; [Dependency] private readonly IChatManager _chatManager = default!;
[Dependency] private readonly IInputManager _inputManager = default!; [Dependency] private readonly IInputManager _inputManager = default!;
[Dependency] private readonly IEntityManager _entityManager = default!; [Dependency] private readonly IEntityManager _entityManager = default!;
@@ -87,7 +87,7 @@ namespace Content.Client.State
_userInterfaceManager.StateRoot.AddChild(_characterSetup); _userInterfaceManager.StateRoot.AddChild(_characterSetup);
}; };
_lobby.ObserveButton.OnPressed += args => _console.ProcessCommand("observe"); _lobby.ObserveButton.OnPressed += args => _consoleHost.ExecuteCommand("observe");
_lobby.ReadyButton.OnPressed += args => _lobby.ReadyButton.OnPressed += args =>
{ {
if (!_clientGameTicker.IsGameStarted) if (!_clientGameTicker.IsGameStarted)
@@ -104,7 +104,7 @@ namespace Content.Client.State
SetReady(args.Pressed); SetReady(args.Pressed);
}; };
_lobby.LeaveButton.OnPressed += args => _console.ProcessCommand("disconnect"); _lobby.LeaveButton.OnPressed += args => _consoleHost.ExecuteCommand("disconnect");
_lobby.OptionsButton.OnPressed += args => new OptionsMenu().Open(); _lobby.OptionsButton.OnPressed += args => new OptionsMenu().Open();
UpdatePlayerList(); UpdatePlayerList();
@@ -259,7 +259,7 @@ namespace Content.Client.State
return; return;
} }
_console.ProcessCommand($"toggleready {newReady}"); _consoleHost.ExecuteCommand($"toggleready {newReady}");
UpdatePlayerList(); UpdatePlayerList();
} }
} }

View File

@@ -47,7 +47,7 @@ namespace Content.Client.StationEvents
// TODO: When worldHandle can do DrawCircle change this. // TODO: When worldHandle can do DrawCircle change this.
public override OverlaySpace Space => OverlaySpace.ScreenSpace; public override OverlaySpace Space => OverlaySpace.ScreenSpace;
public RadiationPulseOverlay() : base(nameof(SharedOverlayID.RadiationPulseOverlay)) public RadiationPulseOverlay() : base(nameof(RadiationPulseOverlay))
{ {
IoCManager.InjectDependencies(this); IoCManager.InjectDependencies(this);
_lastTick = _gameTiming.CurTime; _lastTick = _gameTiming.CurTime;
@@ -124,7 +124,7 @@ namespace Content.Client.StationEvents
_lastTick = _gameTiming.CurTime; _lastTick = _gameTiming.CurTime;
var radiationPulses = _componentManager var radiationPulses = _componentManager
.EntityQuery<RadiationPulseComponent>() .EntityQuery<RadiationPulseComponent>(true)
.ToList(); .ToList();
var screenHandle = (DrawingHandleScreen) handle; var screenHandle = (DrawingHandleScreen) handle;

View File

@@ -122,23 +122,25 @@ namespace Content.Client.UserInterface
hotbarContainer.AddChild(settingsContainer); hotbarContainer.AddChild(settingsContainer);
settingsContainer.AddChild(new Control { SizeFlagsHorizontal = SizeFlags.FillExpand, SizeFlagsStretchRatio = 1 }); settingsContainer.AddChild(new Control { SizeFlagsHorizontal = SizeFlags.FillExpand, SizeFlagsStretchRatio = 1 });
_lockTexture = resourceCache.GetTexture("/Textures/Interface/Nano/lock.svg.png"); _lockTexture = resourceCache.GetTexture("/Textures/Interface/Nano/lock.svg.192dpi.png");
_unlockTexture = resourceCache.GetTexture("/Textures/Interface/Nano/lock_open.svg.png"); _unlockTexture = resourceCache.GetTexture("/Textures/Interface/Nano/lock_open.svg.192dpi.png");
_lockButton = new TextureButton _lockButton = new TextureButton
{ {
TextureNormal = _unlockTexture, TextureNormal = _unlockTexture,
SizeFlagsHorizontal = SizeFlags.ShrinkCenter, SizeFlagsHorizontal = SizeFlags.ShrinkCenter,
SizeFlagsVertical = SizeFlags.ShrinkCenter, SizeFlagsVertical = SizeFlags.ShrinkCenter,
SizeFlagsStretchRatio = 1 SizeFlagsStretchRatio = 1,
Scale = (0.5f, 0.5f)
}; };
settingsContainer.AddChild(_lockButton); settingsContainer.AddChild(_lockButton);
settingsContainer.AddChild(new Control { SizeFlagsHorizontal = SizeFlags.FillExpand, SizeFlagsStretchRatio = 2 }); settingsContainer.AddChild(new Control { SizeFlagsHorizontal = SizeFlags.FillExpand, SizeFlagsStretchRatio = 2 });
_settingsButton = new TextureButton _settingsButton = new TextureButton
{ {
TextureNormal = resourceCache.GetTexture("/Textures/Interface/Nano/gear.svg.png"), TextureNormal = resourceCache.GetTexture("/Textures/Interface/Nano/gear.svg.192dpi.png"),
SizeFlagsHorizontal = SizeFlags.ShrinkCenter, SizeFlagsHorizontal = SizeFlags.ShrinkCenter,
SizeFlagsVertical = SizeFlags.ShrinkCenter, SizeFlagsVertical = SizeFlags.ShrinkCenter,
SizeFlagsStretchRatio = 1 SizeFlagsStretchRatio = 1,
Scale = (0.5f, 0.5f)
}; };
settingsContainer.AddChild(_settingsButton); settingsContainer.AddChild(_settingsButton);
settingsContainer.AddChild(new Control { SizeFlagsHorizontal = SizeFlags.FillExpand, SizeFlagsStretchRatio = 1 }); settingsContainer.AddChild(new Control { SizeFlagsHorizontal = SizeFlags.FillExpand, SizeFlagsStretchRatio = 1 });
@@ -160,10 +162,11 @@ namespace Content.Client.UserInterface
_loadoutContainer.AddChild(new Control { SizeFlagsHorizontal = SizeFlags.FillExpand, SizeFlagsStretchRatio = 1 }); _loadoutContainer.AddChild(new Control { SizeFlagsHorizontal = SizeFlags.FillExpand, SizeFlagsStretchRatio = 1 });
var previousHotbarIcon = new TextureRect() var previousHotbarIcon = new TextureRect()
{ {
Texture = resourceCache.GetTexture("/Textures/Interface/Nano/left_arrow.svg.png"), Texture = resourceCache.GetTexture("/Textures/Interface/Nano/left_arrow.svg.192dpi.png"),
SizeFlagsHorizontal = SizeFlags.ShrinkCenter, SizeFlagsHorizontal = SizeFlags.ShrinkCenter,
SizeFlagsVertical = SizeFlags.ShrinkCenter, SizeFlagsVertical = SizeFlags.ShrinkCenter,
SizeFlagsStretchRatio = 1 SizeFlagsStretchRatio = 1,
TextureScale = (0.5f, 0.5f)
}; };
_loadoutContainer.AddChild(previousHotbarIcon); _loadoutContainer.AddChild(previousHotbarIcon);
_loadoutContainer.AddChild(new Control { SizeFlagsHorizontal = SizeFlags.FillExpand, SizeFlagsStretchRatio = 2 }); _loadoutContainer.AddChild(new Control { SizeFlagsHorizontal = SizeFlags.FillExpand, SizeFlagsStretchRatio = 2 });
@@ -176,10 +179,11 @@ namespace Content.Client.UserInterface
_loadoutContainer.AddChild(new Control { SizeFlagsHorizontal = SizeFlags.FillExpand, SizeFlagsStretchRatio = 2 }); _loadoutContainer.AddChild(new Control { SizeFlagsHorizontal = SizeFlags.FillExpand, SizeFlagsStretchRatio = 2 });
var nextHotbarIcon = new TextureRect var nextHotbarIcon = new TextureRect
{ {
Texture = resourceCache.GetTexture("/Textures/Interface/Nano/right_arrow.svg.png"), Texture = resourceCache.GetTexture("/Textures/Interface/Nano/right_arrow.svg.192dpi.png"),
SizeFlagsHorizontal = SizeFlags.ShrinkCenter, SizeFlagsHorizontal = SizeFlags.ShrinkCenter,
SizeFlagsVertical = SizeFlags.ShrinkCenter, SizeFlagsVertical = SizeFlags.ShrinkCenter,
SizeFlagsStretchRatio = 1 SizeFlagsStretchRatio = 1,
TextureScale = (0.5f, 0.5f)
}; };
_loadoutContainer.AddChild(nextHotbarIcon); _loadoutContainer.AddChild(nextHotbarIcon);
_loadoutContainer.AddChild(new Control { SizeFlagsHorizontal = SizeFlags.FillExpand, SizeFlagsStretchRatio = 1 }); _loadoutContainer.AddChild(new Control { SizeFlagsHorizontal = SizeFlags.FillExpand, SizeFlagsStretchRatio = 1 });

View File

@@ -0,0 +1,172 @@
using Content.Client.Eui;
using Content.Shared.Administration;
using Content.Shared.Chemistry;
using Content.Shared.Eui;
using JetBrains.Annotations;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.CustomControls;
using Robust.Shared.IoC;
using Robust.Shared.Localization;
using Robust.Shared.Prototypes;
namespace Content.Client.UserInterface
{
[UsedImplicitly]
public sealed class AdminAddReagentEui : BaseEui
{
[Dependency] private readonly IPrototypeManager _prototypes = default!;
private readonly Menu _window;
private bool _closed;
public AdminAddReagentEui()
{
_window = new Menu(this);
_window.OnClose += () => SendMessage(new AdminAddReagentEuiMsg.Close());
}
public override void Opened()
{
_window.OpenCentered();
}
public override void Closed()
{
_closed = true;
_window.Close();
}
public override void HandleState(EuiStateBase state)
{
_window.HandleState((AdminAddReagentEuiState) state);
}
private void DoAdd(bool close, string reagentId, ReagentUnit amount)
{
SendMessage(new AdminAddReagentEuiMsg.DoAdd
{
Amount = amount,
ReagentId = reagentId,
CloseAfter = close
});
}
private sealed class Menu : SS14Window
{
private readonly AdminAddReagentEui _eui;
private readonly Label _volumeLabel;
private readonly LineEdit _reagentIdEdit;
private readonly LineEdit _amountEdit;
private readonly Label _errorLabel;
private readonly Button _addButton;
private readonly Button _addCloseButton;
public Menu(AdminAddReagentEui eui)
{
_eui = eui;
Title = Loc.GetString("Add reagent...");
Contents.AddChild(new VBoxContainer
{
Children =
{
new GridContainer
{
Columns = 2,
Children =
{
new Label {Text = Loc.GetString("Cur volume: ")},
(_volumeLabel = new Label()),
new Label {Text = Loc.GetString("Reagent: ")},
(_reagentIdEdit = new LineEdit {PlaceHolder = Loc.GetString("Reagent ID...")}),
new Label {Text = Loc.GetString("Amount: ")},
(_amountEdit = new LineEdit
{
PlaceHolder = Loc.GetString("A number..."),
SizeFlagsHorizontal = SizeFlags.FillExpand
}),
},
SizeFlagsHorizontal = SizeFlags.FillExpand,
SizeFlagsVertical = SizeFlags.FillExpand
},
new HBoxContainer
{
Children =
{
(_errorLabel = new Label
{
SizeFlagsHorizontal = SizeFlags.FillExpand,
ClipText = true
}),
(_addButton = new Button {Text = Loc.GetString("Add")}),
(_addCloseButton = new Button {Text = Loc.GetString("Add & Close")})
}
}
}
});
_reagentIdEdit.OnTextChanged += _ => CheckErrors();
_amountEdit.OnTextChanged += _ => CheckErrors();
_addButton.OnPressed += _ => DoAdd(false);
_addCloseButton.OnPressed += _ => DoAdd(true);
CheckErrors();
}
private void DoAdd(bool close)
{
_eui.DoAdd(
close,
_reagentIdEdit.Text,
ReagentUnit.New(float.Parse(_amountEdit.Text)));
}
private void CheckErrors()
{
if (string.IsNullOrWhiteSpace(_reagentIdEdit.Text))
{
DoError(Loc.GetString("Must specify reagent ID"));
return;
}
if (!_eui._prototypes.HasIndex<ReagentPrototype>(_reagentIdEdit.Text))
{
DoError(Loc.GetString("'{0}' does not exist.", _reagentIdEdit.Text));
return;
}
if (string.IsNullOrWhiteSpace(_amountEdit.Text))
{
DoError(Loc.GetString("Must specify reagent amount"));
return;
}
if (!float.TryParse(_amountEdit.Text, out _))
{
DoError(Loc.GetString("Invalid amount"));
return;
}
_addButton.Disabled = false;
_addCloseButton.Disabled = false;
_errorLabel.Text = "";
void DoError(string text)
{
_errorLabel.Text = text;
_addButton.Disabled = true;
_addCloseButton.Disabled = true;
}
}
public void HandleState(AdminAddReagentEuiState state)
{
_volumeLabel.Text = Loc.GetString("{0}/{1}u", state.CurVolume, state.MaxVolume);
}
}
}
}

View File

@@ -440,7 +440,7 @@ namespace Content.Client.UserInterface.AdminMenu
public override void ButtonPressed(ButtonEventArgs args) public override void ButtonPressed(ButtonEventArgs args)
{ {
IoCManager.Resolve<IClientConsole>().ProcessCommand(RequiredCommand); IoCManager.Resolve<IClientConsoleHost>().ExecuteCommand(RequiredCommand);
} }
} }
#endregion #endregion
@@ -504,7 +504,7 @@ namespace Content.Client.UserInterface.AdminMenu
Name = "Pause", Name = "Pause",
Handler = () => Handler = () =>
{ {
IoCManager.Resolve<IClientConsole>().ProcessCommand("events pause"); IoCManager.Resolve<IClientConsoleHost>().ExecuteCommand("events pause");
}, },
}, },
new CommandUIButton new CommandUIButton
@@ -512,14 +512,14 @@ namespace Content.Client.UserInterface.AdminMenu
Name = "Resume", Name = "Resume",
Handler = () => Handler = () =>
{ {
IoCManager.Resolve<IClientConsole>().ProcessCommand("events resume"); IoCManager.Resolve<IClientConsoleHost>().ExecuteCommand("events resume");
}, },
}, },
}; };
public override void Submit() public override void Submit()
{ {
IoCManager.Resolve<IClientConsole>().ProcessCommand($"events run \"{_eventsDropDown.GetValue()}\""); IoCManager.Resolve<IClientConsoleHost>().ExecuteCommand($"events run \"{_eventsDropDown.GetValue()}\"");
} }
} }
@@ -548,7 +548,7 @@ namespace Content.Client.UserInterface.AdminMenu
public override void Submit() public override void Submit()
{ {
IoCManager.Resolve<IClientConsole>().ProcessCommand($"kick \"{_playerDropDown.GetValue()}\" \"{CommandParsing.Escape(_reason.GetValue())}\""); IoCManager.Resolve<IClientConsoleHost>().ExecuteCommand($"kick \"{_playerDropDown.GetValue()}\" \"{CommandParsing.Escape(_reason.GetValue())}\"");
} }
} }
@@ -572,7 +572,7 @@ namespace Content.Client.UserInterface.AdminMenu
public override void Submit() public override void Submit()
{ {
IoCManager.Resolve<IClientConsole>().ProcessCommand($"tpto \"{_playerDropDown.GetValue()}\""); IoCManager.Resolve<IClientConsoleHost>().ExecuteCommand($"tpto \"{_playerDropDown.GetValue()}\"");
} }
} }
@@ -596,7 +596,7 @@ namespace Content.Client.UserInterface.AdminMenu
public override void Submit() public override void Submit()
{ {
IoCManager.Resolve<IClientConsole>().ProcessCommand($"addatmos {_grid.GetValue()}"); IoCManager.Resolve<IClientConsoleHost>().ExecuteCommand($"addatmos {_grid.GetValue()}");
} }
} }
@@ -639,7 +639,7 @@ namespace Content.Client.UserInterface.AdminMenu
public override void Submit() public override void Submit()
{ {
IoCManager.Resolve<IClientConsole>().ProcessCommand($"fillgas {_grid.GetValue()} {_gas.GetValue()} {_amount.GetValue()}"); IoCManager.Resolve<IClientConsoleHost>().ExecuteCommand($"fillgas {_grid.GetValue()} {_gas.GetValue()} {_amount.GetValue()}");
} }
} }
#endregion #endregion

View File

@@ -22,7 +22,7 @@ namespace Content.Client.UserInterface.AdminMenu.SetOutfit
public partial class SetOutfitMenu : SS14Window public partial class SetOutfitMenu : SS14Window
{ {
[Dependency] private readonly IPrototypeManager _prototypeManager = default!; [Dependency] private readonly IPrototypeManager _prototypeManager = default!;
[Dependency] private readonly IClientConsole _console = default!; [Dependency] private readonly IClientConsoleHost _consoleHost = default!;
public EntityUid? TargetEntityId { get; set; } public EntityUid? TargetEntityId { get; set; }
protected override Vector2? CustomSize => (250, 320); protected override Vector2? CustomSize => (250, 320);
@@ -49,7 +49,7 @@ namespace Content.Client.UserInterface.AdminMenu.SetOutfit
if (TargetEntityId == null || _selectedOutfit == null) if (TargetEntityId == null || _selectedOutfit == null)
return; return;
var command = $"setoutfit {TargetEntityId} {_selectedOutfit.ID}"; var command = $"setoutfit {TargetEntityId} {_selectedOutfit.ID}";
_console.ProcessCommand(command); _consoleHost.ExecuteCommand(command);
Close(); Close();
} }

View File

@@ -3,7 +3,6 @@ using System;
using Content.Shared.Alert; using Content.Shared.Alert;
using Robust.Client.UserInterface; using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls; using Robust.Client.UserInterface.Controls;
using Robust.Client.Utility;
using Robust.Shared.Interfaces.Timing; using Robust.Shared.Interfaces.Timing;
using Robust.Shared.IoC; using Robust.Shared.IoC;
using Robust.Shared.Maths; using Robust.Shared.Maths;
@@ -34,11 +33,12 @@ namespace Content.Client.UserInterface.Controls
} }
} }
} }
private (TimeSpan Start, TimeSpan End)? _cooldown; private (TimeSpan Start, TimeSpan End)? _cooldown;
private short? _severity; private short? _severity;
private readonly IGameTiming _gameTiming; private readonly IGameTiming _gameTiming;
private readonly TextureRect _icon; private readonly AnimatedTextureRect _icon;
private readonly CooldownGraphic _cooldownGraphic; private readonly CooldownGraphic _cooldownGraphic;
/// <summary> /// <summary>
@@ -53,17 +53,17 @@ namespace Content.Client.UserInterface.Controls
TooltipSupplier = SupplyTooltip; TooltipSupplier = SupplyTooltip;
Alert = alert; Alert = alert;
_severity = severity; _severity = severity;
var texture = alert.GetIcon(_severity).Frame0(); var specifier = alert.GetIcon(_severity);
_icon = new TextureRect _icon = new AnimatedTextureRect
{ {
TextureScale = (2, 2), DisplayRect = {TextureScale = (2, 2)}
Texture = texture
}; };
_icon.SetFromSpriteSpecifier(specifier);
Children.Add(_icon); Children.Add(_icon);
_cooldownGraphic = new CooldownGraphic(); _cooldownGraphic = new CooldownGraphic();
Children.Add(_cooldownGraphic); Children.Add(_cooldownGraphic);
} }
private Control SupplyTooltip(Control? sender) private Control SupplyTooltip(Control? sender)
@@ -79,7 +79,7 @@ namespace Content.Client.UserInterface.Controls
if (_severity != severity) if (_severity != severity)
{ {
_severity = severity; _severity = severity;
_icon.Texture = Alert.GetIcon(_severity).Frame0(); _icon.SetFromSpriteSpecifier(Alert.GetIcon(_severity));
} }
} }
@@ -99,7 +99,7 @@ namespace Content.Client.UserInterface.Controls
var progress = (curTime - Cooldown.Value.Start).TotalSeconds / length; var progress = (curTime - Cooldown.Value.Start).TotalSeconds / length;
var ratio = (progress <= 1 ? (1 - progress) : (curTime - Cooldown.Value.End).TotalSeconds * -5); var ratio = (progress <= 1 ? (1 - progress) : (curTime - Cooldown.Value.End).TotalSeconds * -5);
_cooldownGraphic.Progress = MathHelper.Clamp((float)ratio, -1, 1); _cooldownGraphic.Progress = MathHelper.Clamp((float) ratio, -1, 1);
_cooldownGraphic.Visible = ratio > -1f; _cooldownGraphic.Visible = ratio > -1f;
} }
} }

View File

@@ -8,16 +8,16 @@ namespace Content.Client.UserInterface
{ {
internal sealed class EscapeMenu : SS14Window internal sealed class EscapeMenu : SS14Window
{ {
private readonly IClientConsole _console; private readonly IClientConsoleHost _consoleHost;
private BaseButton DisconnectButton; private BaseButton DisconnectButton;
private BaseButton QuitButton; private BaseButton QuitButton;
private BaseButton OptionsButton; private BaseButton OptionsButton;
private OptionsMenu optionsMenu; private OptionsMenu optionsMenu;
public EscapeMenu(IClientConsole console) public EscapeMenu(IClientConsoleHost consoleHost)
{ {
_console = console; _consoleHost = consoleHost;
IoCManager.InjectDependencies(this); IoCManager.InjectDependencies(this);
@@ -50,13 +50,13 @@ namespace Content.Client.UserInterface
private void OnQuitButtonClicked(BaseButton.ButtonEventArgs args) private void OnQuitButtonClicked(BaseButton.ButtonEventArgs args)
{ {
_console.ProcessCommand("quit"); _consoleHost.ExecuteCommand("quit");
Dispose(); Dispose();
} }
private void OnDisconnectButtonClicked(BaseButton.ButtonEventArgs args) private void OnDisconnectButtonClicked(BaseButton.ButtonEventArgs args)
{ {
_console.ProcessCommand("disconnect"); _consoleHost.ExecuteCommand("disconnect");
Dispose(); Dispose();
} }

View File

@@ -21,7 +21,7 @@ namespace Content.Client.UserInterface
public sealed class LateJoinGui : SS14Window public sealed class LateJoinGui : SS14Window
{ {
[Dependency] private readonly IPrototypeManager _prototypeManager = default!; [Dependency] private readonly IPrototypeManager _prototypeManager = default!;
[Dependency] private readonly IClientConsole _console = default!; [Dependency] private readonly IClientConsoleHost _consoleHost = default!;
[Dependency] private readonly IClientGameTicker _gameTicker = default!; [Dependency] private readonly IClientGameTicker _gameTicker = default!;
protected override Vector2? CustomSize => (360, 560); protected override Vector2? CustomSize => (360, 560);
@@ -147,7 +147,7 @@ namespace Content.Client.UserInterface
SelectedId += jobId => SelectedId += jobId =>
{ {
Logger.InfoS("latejoin", $"Late joining as ID: {jobId}"); Logger.InfoS("latejoin", $"Late joining as ID: {jobId}");
_console.ProcessCommand($"joingame {CommandParsing.Escape(jobId)}"); _consoleHost.ExecuteCommand($"joingame {CommandParsing.Escape(jobId)}");
Close(); Close();
}; };

View File

@@ -0,0 +1,8 @@
<ui:Control xmlns:uic="clr-namespace:Robust.Client.UserInterface.Controls;assembly=Robust.Client"
xmlns:ui="clr-namespace:Robust.Client.UserInterface;assembly=Robust.Client">
<uic:VBoxContainer SeparationOverride="0">
<uic:Button Name="RoleButton">
<uic:Label Name="TimerLabel" SizeFlagsHorizontal="ShrinkEnd" SizeFlagsVertical="ShrinkEnd" />
</uic:Button>
</uic:VBoxContainer>
</ui:Control>

View File

@@ -1,48 +1,42 @@
using System; using System;
using System.Diagnostics.CodeAnalysis;
using System.Globalization; using System.Globalization;
using System.Linq; using System.Linq;
using Content.Client.GameObjects.Components.Suspicion; using Content.Client.GameObjects.Components.Suspicion;
using Content.Client.GameObjects.EntitySystems;
using Content.Shared.Interfaces; using Content.Shared.Interfaces;
using Robust.Client.AutoGenerated;
using Robust.Client.Player; using Robust.Client.Player;
using Robust.Client.UserInterface; using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls; using Robust.Client.UserInterface.XAML;
using Robust.Shared.Interfaces.GameObjects; using Robust.Shared.GameObjects.Systems;
using Robust.Shared.Interfaces.Timing;
using Robust.Shared.IoC; using Robust.Shared.IoC;
using Robust.Shared.Localization; using Robust.Shared.Localization;
using Robust.Shared.Maths; using Robust.Shared.Maths;
using Robust.Shared.Timing; using Robust.Shared.Timing;
using static Robust.Client.UserInterface.Controls.BaseButton; using static Robust.Client.UserInterface.Controls.BaseButton;
#nullable enable
namespace Content.Client.UserInterface.Suspicion namespace Content.Client.UserInterface.Suspicion
{ {
public class SuspicionGui : Control [GenerateTypedNameReferences]
public partial class SuspicionGui : Control
{ {
[Dependency] private readonly IPlayerManager _playerManager = default!; [Dependency] private readonly IPlayerManager _playerManager = default!;
[Dependency] private readonly IGameTiming _timing = default!;
private readonly VBoxContainer _container; private string? _previousRoleName;
private readonly Button _roleButton;
private string _previousRoleName;
private bool _previousAntagonist; private bool _previousAntagonist;
public SuspicionGui() public SuspicionGui()
{ {
RobustXamlLoader.Load(this);
IoCManager.InjectDependencies(this); IoCManager.InjectDependencies(this);
AddChild(_container = new VBoxContainer RoleButton.OnPressed += RoleButtonPressed;
{ RoleButton.CustomMinimumSize = (200, 60);
SeparationOverride = 0,
Children =
{
(_roleButton = new Button
{
Name = "Suspicion Role Button"
})
}
});
_roleButton.CustomMinimumSize = (200, 60);
_roleButton.OnPressed += RoleButtonPressed;
} }
private void RoleButtonPressed(ButtonEventArgs obj) private void RoleButtonPressed(ButtonEventArgs obj)
@@ -67,11 +61,15 @@ namespace Content.Client.UserInterface.Suspicion
role.Owner.PopupMessage(message); role.Owner.PopupMessage(message);
} }
private bool TryGetComponent(out SuspicionRoleComponent suspicion) private bool TryGetComponent([NotNullWhen(true)] out SuspicionRoleComponent? suspicion)
{ {
suspicion = default; suspicion = default;
if (_playerManager.LocalPlayer?.ControlledEntity == null)
{
return false;
}
return _playerManager?.LocalPlayer?.ControlledEntity?.TryGetComponent(out suspicion) == true; return _playerManager.LocalPlayer.ControlledEntity.TryGetComponent(out suspicion);
} }
public void UpdateLabel() public void UpdateLabel()
@@ -88,6 +86,22 @@ namespace Content.Client.UserInterface.Suspicion
return; return;
} }
var endTime = EntitySystem.Get<SuspicionEndTimerSystem>().EndTime;
if (endTime == null)
{
TimerLabel.Visible = false;
}
else
{
var diff = endTime.Value - _timing.CurTime;
if (diff < TimeSpan.Zero)
{
diff = TimeSpan.Zero;
}
TimerLabel.Visible = true;
TimerLabel.Text = $"{diff:mm\\:ss}";
}
if (_previousRoleName == suspicion.Role && _previousAntagonist == suspicion.Antagonist) if (_previousRoleName == suspicion.Role && _previousAntagonist == suspicion.Antagonist)
{ {
return; return;
@@ -99,8 +113,8 @@ namespace Content.Client.UserInterface.Suspicion
var buttonText = CultureInfo.CurrentCulture.TextInfo.ToTitleCase(_previousRoleName); var buttonText = CultureInfo.CurrentCulture.TextInfo.ToTitleCase(_previousRoleName);
buttonText = Loc.GetString(buttonText); buttonText = Loc.GetString(buttonText);
_roleButton.Text = buttonText; RoleButton.Text = buttonText;
_roleButton.ModulateSelfOverride = _previousAntagonist ? Color.Red : Color.Green; RoleButton.ModulateSelfOverride = _previousAntagonist ? Color.Red : Color.Green;
Visible = true; Visible = true;
} }

View File

@@ -6,7 +6,6 @@ using Content.Shared.Roles;
using Content.Shared.Preferences; using Content.Shared.Preferences;
using Content.Server.Mobs; using Content.Server.Mobs;
using Robust.Server.Interfaces.Player; using Robust.Server.Interfaces.Player;
using Robust.Server.Interfaces.Console;
using Robust.Shared.Interfaces.GameObjects; using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.Map; using Robust.Shared.Map;
using Robust.Shared.Timing; using Robust.Shared.Timing;

View File

@@ -1,4 +1,5 @@
using System.Threading.Tasks; using System;
using System.Threading.Tasks;
using Content.Server.Commands.GameTicking; using Content.Server.Commands.GameTicking;
using Content.Server.GameTicking; using Content.Server.GameTicking;
using Content.Server.Interfaces.GameTicking; using Content.Server.Interfaces.GameTicking;
@@ -40,7 +41,7 @@ namespace Content.IntegrationTests.Tests.Commands
tickBeforeRestart = entityManager.CurrentTick; tickBeforeRestart = entityManager.CurrentTick;
var command = new NewRoundCommand(); var command = new NewRoundCommand();
command.Execute(null, null, new string[] { }); command.Execute(null, string.Empty, Array.Empty<string>());
if (lobbyEnabled) if (lobbyEnabled)
{ {

View File

@@ -1,4 +1,4 @@
#nullable enable #nullable enable
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Content.Client.GameObjects.Components.Items; using Content.Client.GameObjects.Components.Items;
@@ -7,7 +7,7 @@ using Content.Server.GameObjects.Components.Body;
using Content.Server.Interfaces.GameObjects.Components.Items; using Content.Server.Interfaces.GameObjects.Components.Items;
using Content.Shared.GameObjects.Components.Body; using Content.Shared.GameObjects.Components.Body;
using NUnit.Framework; using NUnit.Framework;
using Robust.Server.Interfaces.Console; using Robust.Server.Console;
using Robust.Shared.Interfaces.GameObjects; using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.Interfaces.Map; using Robust.Shared.Interfaces.Map;
using Robust.Shared.IoC; using Robust.Shared.IoC;
@@ -96,8 +96,8 @@ namespace Content.IntegrationTests.Tests.GameObjects.Components.ActionBlocking
private void AddHand(IEntity to) private void AddHand(IEntity to)
{ {
var shell = IoCManager.Resolve<IConsoleShell>(); var host = IoCManager.Resolve<IServerConsoleHost>();
shell.ExecuteCommand($"addhand {to.Uid}"); host.ExecuteCommand(null, $"addhand {to.Uid}");
} }
} }
} }

View File

@@ -27,7 +27,7 @@ namespace Content.IntegrationTests.Tests.Networking
await Task.WhenAll(client.WaitIdleAsync(), server.WaitIdleAsync()); await Task.WhenAll(client.WaitIdleAsync(), server.WaitIdleAsync());
await client.WaitPost(() => IoCManager.Resolve<IClientConsole>().ProcessCommand("disconnect")); await client.WaitPost(() => IoCManager.Resolve<IClientConsoleHost>().ExecuteCommand("disconnect"));
// Run some ticks for the disconnect to complete and such. // Run some ticks for the disconnect to complete and such.
await RunTicksSync(client, server, 5); await RunTicksSync(client, server, 5);

View File

@@ -77,7 +77,7 @@ namespace Content.IntegrationTests.Tests
/// Loads the default map, runs it for 5 ticks, then assert that it did not change. /// Loads the default map, runs it for 5 ticks, then assert that it did not change.
/// </summary> /// </summary>
[Test] [Test]
public async Task LoadSaveTicksSaveStationStation() public async Task LoadSaveTicksSaveSaltern()
{ {
var server = StartServerDummyTicker(); var server = StartServerDummyTicker();
await server.WaitIdleAsync(); await server.WaitIdleAsync();
@@ -92,7 +92,8 @@ namespace Content.IntegrationTests.Tests
{ {
var mapId = mapManager.CreateMap(); var mapId = mapManager.CreateMap();
pauseMgr.AddUninitializedMap(mapId); pauseMgr.AddUninitializedMap(mapId);
grid = mapLoader.LoadBlueprint(mapId, "Maps/stationstation.yml"); pauseMgr.SetMapPaused(mapId, true);
grid = mapLoader.LoadBlueprint(mapId, "Maps/saltern.yml");
mapLoader.SaveBlueprint(grid.Index, "load save ticks save 1.yml"); mapLoader.SaveBlueprint(grid.Index, "load save ticks save 1.yml");
}); });

View File

@@ -0,0 +1,224 @@
#nullable enable
using System.Collections.Generic;
using System.Threading.Tasks;
using Content.Shared.GameObjects.Components.Tag;
using Content.Shared.Prototypes.Tag;
using NUnit.Framework;
using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.Interfaces.Map;
using Robust.Shared.Map;
using Robust.Shared.Prototypes;
namespace Content.IntegrationTests.Tests.Tag
{
[TestFixture]
[TestOf(typeof(TagComponent))]
public class TagTest : ContentIntegrationTest
{
private const string TagEntityId = "TagTestDummy";
// Register these three into the prototype manager
private const string StartingTag = "A";
private const string AddedTag = "EIOU";
private const string UnusedTag = "E";
// Do not register this one
private const string UnregisteredTag = "AAAAAAAAA";
private static readonly string Prototypes = $@"
- type: Tag
id: {StartingTag}
- type: Tag
id: {AddedTag}
- type: Tag
id: {UnusedTag}
- type: entity
id: {TagEntityId}
name: {TagEntityId}
components:
- type: Tag
tags:
- {StartingTag}";
[Test]
public async Task TagComponentTest()
{
var options = new ServerContentIntegrationOption {ExtraPrototypes = Prototypes};
var server = StartServerDummyTicker(options);
await server.WaitIdleAsync();
var sMapManager = server.ResolveDependency<IMapManager>();
var sEntityManager = server.ResolveDependency<IEntityManager>();
var sPrototypeManager = server.ResolveDependency<IPrototypeManager>();
IEntity sTagDummy = null!;
TagComponent sTagComponent = null!;
await server.WaitPost(() =>
{
sMapManager.CreateNewMapEntity(MapId.Nullspace);
sTagDummy = sEntityManager.SpawnEntity(TagEntityId, MapCoordinates.Nullspace);
sTagComponent = sTagDummy.GetComponent<TagComponent>();
});
await server.WaitAssertion(() =>
{
// Has one tag, the starting tag
Assert.That(sTagComponent.Tags.Count, Is.EqualTo(1));
sPrototypeManager.Index<TagPrototype>(StartingTag);
Assert.That(sTagComponent.Tags, Contains.Item(StartingTag));
// Single
Assert.True(sTagDummy.HasTag(StartingTag));
Assert.True(sTagComponent.HasTag(StartingTag));
// Any
Assert.True(sTagDummy.HasAnyTag(StartingTag));
Assert.True(sTagComponent.HasAnyTag(StartingTag));
// All
Assert.True(sTagDummy.HasAllTags(StartingTag));
Assert.True(sTagComponent.HasAllTags(StartingTag));
// Does not have the added tag
var addedTagPrototype = sPrototypeManager.Index<TagPrototype>(AddedTag);
Assert.That(sTagComponent.Tags, Does.Not.Contains(addedTagPrototype));
// Single
Assert.False(sTagDummy.HasTag(AddedTag));
Assert.False(sTagComponent.HasTag(AddedTag));
// Any
Assert.False(sTagDummy.HasAnyTag(AddedTag));
Assert.False(sTagComponent.HasAnyTag(AddedTag));
// All
Assert.False(sTagDummy.HasAllTags(AddedTag));
Assert.False(sTagComponent.HasAllTags(AddedTag));
// Does not have the unused tag
var unusedTagPrototype = sPrototypeManager.Index<TagPrototype>(UnusedTag);
Assert.That(sTagComponent.Tags, Does.Not.Contains(unusedTagPrototype));
// Single
Assert.False(sTagDummy.HasTag(UnusedTag));
Assert.False(sTagComponent.HasTag(UnusedTag));
// Any
Assert.False(sTagDummy.HasAnyTag(UnusedTag));
Assert.False(sTagComponent.HasAnyTag(UnusedTag));
// All
Assert.False(sTagDummy.HasAllTags(UnusedTag));
Assert.False(sTagComponent.HasAllTags(UnusedTag));
// Throws when checking for an unregistered tag
Assert.Throws<UnknownPrototypeException>(() =>
{
sPrototypeManager.Index<TagPrototype>(UnregisteredTag);
});
// Single
Assert.Throws<UnknownPrototypeException>(() =>
{
sTagDummy.HasTag(UnregisteredTag);
});
Assert.Throws<UnknownPrototypeException>(() =>
{
sTagComponent.HasTag(UnregisteredTag);
});
// Any
Assert.Throws<UnknownPrototypeException>(() =>
{
sTagDummy.HasAnyTag(UnregisteredTag);
});
Assert.Throws<UnknownPrototypeException>(() =>
{
sTagComponent.HasAnyTag(UnregisteredTag);
});
// All
Assert.Throws<UnknownPrototypeException>(() =>
{
sTagDummy.HasAllTags(UnregisteredTag);
});
Assert.Throws<UnknownPrototypeException>(() =>
{
sTagComponent.HasAllTags(UnregisteredTag);
});
// Cannot add the starting tag again
Assert.That(sTagComponent.AddTag(StartingTag), Is.False);
Assert.That(sTagComponent.AddTags(StartingTag, StartingTag), Is.False);
Assert.That(sTagComponent.AddTags(new List<string> {StartingTag, StartingTag}), Is.False);
// Has the starting tag
Assert.That(sTagComponent.HasTag(StartingTag), Is.True);
Assert.That(sTagComponent.HasAllTags(StartingTag, StartingTag), Is.True);
Assert.That(sTagComponent.HasAllTags(new List<string> {StartingTag, StartingTag}), Is.True);
Assert.That(sTagComponent.HasAnyTag(StartingTag, StartingTag), Is.True);
Assert.That(sTagComponent.HasAnyTag(new List<string> {StartingTag, StartingTag}), Is.True);
// Does not have the added tag yet
Assert.That(sTagComponent.HasTag(AddedTag), Is.False);
Assert.That(sTagComponent.HasAllTags(AddedTag, AddedTag), Is.False);
Assert.That(sTagComponent.HasAllTags(new List<string> {AddedTag, AddedTag}), Is.False);
Assert.That(sTagComponent.HasAnyTag(AddedTag, AddedTag), Is.False);
Assert.That(sTagComponent.HasAnyTag(new List<string> {AddedTag, AddedTag}), Is.False);
// Has a combination of the two tags
Assert.That(sTagComponent.HasAnyTag(StartingTag, AddedTag), Is.True);
Assert.That(sTagComponent.HasAnyTag(new List<string> {StartingTag, AddedTag}), Is.True);
// Does not have both tags
Assert.That(sTagComponent.HasAllTags(StartingTag, AddedTag), Is.False);
Assert.That(sTagComponent.HasAllTags(new List<string> {StartingTag, AddedTag}), Is.False);
// Cannot remove a tag that does not exist
Assert.That(sTagComponent.RemoveTag(AddedTag), Is.False);
Assert.That(sTagComponent.RemoveTags(AddedTag, AddedTag), Is.False);
Assert.That(sTagComponent.RemoveTags(new List<string> {AddedTag, AddedTag}), Is.False);
// Can add the new tag
Assert.That(sTagComponent.AddTag(AddedTag), Is.True);
// Cannot add it twice
Assert.That(sTagComponent.AddTag(AddedTag), Is.False);
// Cannot add existing tags
Assert.That(sTagComponent.AddTags(StartingTag, AddedTag), Is.False);
Assert.That(sTagComponent.AddTags(new List<string> {StartingTag, AddedTag}), Is.False);
// Now has two tags
Assert.That(sTagComponent.Tags.Count, Is.EqualTo(2));
// Has both tags
Assert.That(sTagComponent.HasTag(StartingTag), Is.True);
Assert.That(sTagComponent.HasTag(AddedTag), Is.True);
Assert.That(sTagComponent.HasAllTags(StartingTag, StartingTag), Is.True);
Assert.That(sTagComponent.HasAllTags(AddedTag, StartingTag), Is.True);
Assert.That(sTagComponent.HasAllTags(new List<string> {StartingTag, AddedTag}), Is.True);
Assert.That(sTagComponent.HasAllTags(new List<string> {AddedTag, StartingTag}), Is.True);
Assert.That(sTagComponent.HasAnyTag(StartingTag, AddedTag), Is.True);
Assert.That(sTagComponent.HasAnyTag(AddedTag, StartingTag), Is.True);
// Remove the existing starting tag
Assert.That(sTagComponent.RemoveTag(StartingTag), Is.True);
// Remove the existing added tag
Assert.That(sTagComponent.RemoveTags(AddedTag, AddedTag), Is.True);
// No tags left to remove
Assert.That(sTagComponent.RemoveTags(new List<string> {StartingTag, AddedTag}), Is.False);
// No tags left in the component
Assert.That(sTagComponent.Tags, Is.Empty);
});
}
}
}

View File

@@ -1,7 +1,7 @@
using System; using System;
using Content.Shared.Administration; using Content.Shared.Administration;
using JetBrains.Annotations; using JetBrains.Annotations;
using Robust.Server.Interfaces.Console; using Robust.Shared.Console;
namespace Content.Server.Administration namespace Content.Server.Administration
{ {
@@ -13,7 +13,7 @@ namespace Content.Server.Administration
/// </remarks> /// </remarks>
/// <seealso cref="AnyCommandAttribute"/> /// <seealso cref="AnyCommandAttribute"/>
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)] [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
[BaseTypeRequired(typeof(IClientCommand))] [BaseTypeRequired(typeof(IConsoleCommand))]
[MeansImplicitUse] [MeansImplicitUse]
public sealed class AdminCommandAttribute : Attribute public sealed class AdminCommandAttribute : Attribute
{ {

View File

@@ -1,4 +1,4 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
@@ -12,9 +12,9 @@ using Content.Shared;
using Content.Shared.Administration; using Content.Shared.Administration;
using Content.Shared.Network.NetMessages; using Content.Shared.Network.NetMessages;
using Robust.Server.Console; using Robust.Server.Console;
using Robust.Server.Interfaces.Console;
using Robust.Server.Interfaces.Player; using Robust.Server.Interfaces.Player;
using Robust.Server.Player; using Robust.Server.Player;
using Robust.Shared.Console;
using Robust.Shared.Enums; using Robust.Shared.Enums;
using Robust.Shared.Interfaces.Configuration; using Robust.Shared.Interfaces.Configuration;
using Robust.Shared.Interfaces.Network; using Robust.Shared.Interfaces.Network;
@@ -37,7 +37,7 @@ namespace Content.Server.Administration
[Dependency] private readonly IServerNetManager _netMgr = default!; [Dependency] private readonly IServerNetManager _netMgr = default!;
[Dependency] private readonly IConGroupController _conGroup = default!; [Dependency] private readonly IConGroupController _conGroup = default!;
[Dependency] private readonly IResourceManager _res = default!; [Dependency] private readonly IResourceManager _res = default!;
[Dependency] private readonly IConsoleShell _consoleShell = default!; [Dependency] private readonly IServerConsoleHost _consoleHost = default!;
[Dependency] private readonly IChatManager _chat = default!; [Dependency] private readonly IChatManager _chat = default!;
private readonly Dictionary<IPlayerSession, AdminReg> _admins = new(); private readonly Dictionary<IPlayerSession, AdminReg> _admins = new();
@@ -171,7 +171,7 @@ namespace Content.Server.Administration
_netMgr.RegisterNetMessage<MsgUpdateAdminStatus>(MsgUpdateAdminStatus.NAME); _netMgr.RegisterNetMessage<MsgUpdateAdminStatus>(MsgUpdateAdminStatus.NAME);
// Cache permissions for loaded console commands with the requisite attributes. // Cache permissions for loaded console commands with the requisite attributes.
foreach (var (cmdName, cmd) in _consoleShell.AvailableCommands) foreach (var (cmdName, cmd) in _consoleHost.RegisteredCommands)
{ {
var (isAvail, flagsReq) = GetRequiredFlag(cmd); var (isAvail, flagsReq) = GetRequiredFlag(cmd);
@@ -420,7 +420,7 @@ namespace Content.Server.Administration
return false; return false;
} }
private static (bool isAvail, AdminFlags[] flagsReq) GetRequiredFlag(IClientCommand cmd) private static (bool isAvail, AdminFlags[] flagsReq) GetRequiredFlag(IConsoleCommand cmd)
{ {
var type = cmd.GetType(); var type = cmd.GetType();
if (Attribute.IsDefined(type, typeof(AnyCommandAttribute))) if (Attribute.IsDefined(type, typeof(AnyCommandAttribute)))

View File

@@ -1,6 +1,6 @@
using System; using System;
using JetBrains.Annotations; using JetBrains.Annotations;
using Robust.Server.Interfaces.Console; using Robust.Shared.Console;
namespace Content.Server.Administration namespace Content.Server.Administration
{ {
@@ -9,7 +9,7 @@ namespace Content.Server.Administration
/// </summary> /// </summary>
/// <seealso cref="AdminCommandAttribute"/> /// <seealso cref="AdminCommandAttribute"/>
[AttributeUsage(AttributeTargets.Class)] [AttributeUsage(AttributeTargets.Class)]
[BaseTypeRequired(typeof(IClientCommand))] [BaseTypeRequired(typeof(IConsoleCommand))]
[MeansImplicitUse] [MeansImplicitUse]
public sealed class AnyCommandAttribute : Attribute public sealed class AnyCommandAttribute : Attribute
{ {

View File

@@ -3,25 +3,26 @@ using Content.Server.GameObjects.Components.Observer;
using Content.Server.Interfaces.GameTicking; using Content.Server.Interfaces.GameTicking;
using Content.Server.Players; using Content.Server.Players;
using Content.Shared.Administration; using Content.Shared.Administration;
using Robust.Server.Interfaces.Console;
using Robust.Server.Interfaces.Player; using Robust.Server.Interfaces.Player;
using Robust.Shared.Console;
using Robust.Shared.Interfaces.GameObjects; using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.IoC; using Robust.Shared.IoC;
namespace Content.Server.Administration.Commands namespace Content.Server.Administration.Commands
{ {
[AdminCommand(AdminFlags.Admin)] [AdminCommand(AdminFlags.Admin)]
public class AGhost : IClientCommand public class AGhost : IConsoleCommand
{ {
public string Command => "aghost"; public string Command => "aghost";
public string Description => "Makes you an admin ghost."; public string Description => "Makes you an admin ghost.";
public string Help => "aghost"; public string Help => "aghost";
public void Execute(IConsoleShell shell, IPlayerSession player, string[] args) public void Execute(IConsoleShell shell, string argStr, string[] args)
{ {
var player = shell.Player as IPlayerSession;
if (player == null) if (player == null)
{ {
shell.SendText((IPlayerSession) null, "Nah"); shell.WriteLine("Nah");
return; return;
} }
@@ -29,7 +30,7 @@ namespace Content.Server.Administration.Commands
if (mind == null) if (mind == null)
{ {
shell.SendText(player, "You can't ghost here!"); shell.WriteLine("You can't ghost here!");
return; return;
} }

View File

@@ -1,8 +1,8 @@
using System; using System;
using Content.Server.Database; using Content.Server.Database;
using Content.Shared.Administration; using Content.Shared.Administration;
using Robust.Server.Interfaces.Console;
using Robust.Server.Interfaces.Player; using Robust.Server.Interfaces.Player;
using Robust.Shared.Console;
using Robust.Shared.IoC; using Robust.Shared.IoC;
using Robust.Shared.Network; using Robust.Shared.Network;
@@ -11,14 +11,15 @@ using Robust.Shared.Network;
namespace Content.Server.Administration.Commands namespace Content.Server.Administration.Commands
{ {
[AdminCommand(AdminFlags.Ban)] [AdminCommand(AdminFlags.Ban)]
public sealed class BanCommand : IClientCommand public sealed class BanCommand : IConsoleCommand
{ {
public string Command => "ban"; public string Command => "ban";
public string Description => "Bans somebody"; public string Description => "Bans somebody";
public string Help => "Usage: <name or user ID> <reason> <duration in minutes, or 0 for permanent ban>"; public string Help => "Usage: <name or user ID> <reason> <duration in minutes, or 0 for permanent ban>";
public async void Execute(IConsoleShell shell, IPlayerSession? player, string[] args) public async void Execute(IConsoleShell shell, string argStr, string[] args)
{ {
var player = shell.Player as IPlayerSession;
var plyMgr = IoCManager.Resolve<IPlayerManager>(); var plyMgr = IoCManager.Resolve<IPlayerManager>();
var dbMan = IoCManager.Resolve<IServerDbManager>(); var dbMan = IoCManager.Resolve<IServerDbManager>();
@@ -37,7 +38,7 @@ namespace Content.Server.Administration.Commands
} }
else else
{ {
shell.SendText(player, "Unable to find user with that name."); shell.WriteLine("Unable to find user with that name.");
return; return;
} }

View File

@@ -2,8 +2,8 @@ using Content.Server.GameObjects.Components.Mobs;
using Content.Server.GameObjects.Components.Observer; using Content.Server.GameObjects.Components.Observer;
using Content.Server.Players; using Content.Server.Players;
using Content.Shared.Administration; using Content.Shared.Administration;
using Robust.Server.Interfaces.Console;
using Robust.Server.Interfaces.Player; using Robust.Server.Interfaces.Player;
using Robust.Shared.Console;
using Robust.Shared.GameObjects; using Robust.Shared.GameObjects;
using Robust.Shared.Interfaces.GameObjects; using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.IoC; using Robust.Shared.IoC;
@@ -12,23 +12,24 @@ using Robust.Shared.Localization;
namespace Content.Server.Administration.Commands namespace Content.Server.Administration.Commands
{ {
[AdminCommand(AdminFlags.Admin)] [AdminCommand(AdminFlags.Admin)]
class ControlMob : IClientCommand class ControlMob : IConsoleCommand
{ {
public string Command => "controlmob"; public string Command => "controlmob";
public string Description => Loc.GetString("Transfers user mind to the specified entity."); public string Description => Loc.GetString("Transfers user mind to the specified entity.");
public string Help => Loc.GetString("Usage: controlmob <mobUid>."); public string Help => Loc.GetString("Usage: controlmob <mobUid>.");
public void Execute(IConsoleShell shell, IPlayerSession player, string[] args) public void Execute(IConsoleShell shell, string argStr, string[] args)
{ {
var player = shell.Player as IPlayerSession;
if (player == null) if (player == null)
{ {
shell.SendText((IPlayerSession) null, "Server cannot do this."); shell.WriteLine("Server cannot do this.");
return; return;
} }
if (args.Length != 1) if (args.Length != 1)
{ {
shell.SendText(player, Loc.GetString("Wrong number of arguments.")); shell.WriteLine(Loc.GetString("Wrong number of arguments."));
return; return;
} }
@@ -38,7 +39,7 @@ namespace Content.Server.Administration.Commands
if (!int.TryParse(args[0], out var targetId)) if (!int.TryParse(args[0], out var targetId))
{ {
shell.SendText(player, Loc.GetString("Argument must be a number.")); shell.WriteLine(Loc.GetString("Argument must be a number."));
return; return;
} }
@@ -46,14 +47,14 @@ namespace Content.Server.Administration.Commands
if (!eUid.IsValid() || !entityManager.EntityExists(eUid)) if (!eUid.IsValid() || !entityManager.EntityExists(eUid))
{ {
shell.SendText(player, Loc.GetString("Invalid entity ID.")); shell.WriteLine(Loc.GetString("Invalid entity ID."));
return; return;
} }
var target = entityManager.GetEntity(eUid); var target = entityManager.GetEntity(eUid);
if (!target.TryGetComponent(out MindComponent mindComponent)) if (!target.TryGetComponent(out MindComponent mindComponent))
{ {
shell.SendText(player, Loc.GetString("Target entity is not a mob!")); shell.WriteLine(Loc.GetString("Target entity is not a mob!"));
return; return;
} }

View File

@@ -1,14 +1,14 @@
using Content.Server.Interfaces.Chat; using Content.Server.Interfaces.Chat;
using Content.Shared.Administration; using Content.Shared.Administration;
using Robust.Server.Interfaces.Console;
using Robust.Server.Interfaces.Player; using Robust.Server.Interfaces.Player;
using Robust.Shared.Console;
using Robust.Shared.IoC; using Robust.Shared.IoC;
using Robust.Shared.Localization; using Robust.Shared.Localization;
namespace Content.Server.Administration.Commands namespace Content.Server.Administration.Commands
{ {
[AdminCommand(AdminFlags.Admin)] [AdminCommand(AdminFlags.Admin)]
class DSay : IClientCommand class DSay : IConsoleCommand
{ {
public string Command => "dsay"; public string Command => "dsay";
@@ -16,11 +16,12 @@ namespace Content.Server.Administration.Commands
public string Help => Loc.GetString($"Usage: {Command} <message>"); public string Help => Loc.GetString($"Usage: {Command} <message>");
public void Execute(IConsoleShell shell, IPlayerSession player, string[] args) public void Execute(IConsoleShell shell, string argStr, string[] args)
{ {
var player = shell.Player as IPlayerSession;
if (player == null) if (player == null)
{ {
shell.SendText((IPlayerSession) null, "Only players can use this command"); shell.WriteLine("Only players can use this command");
return; return;
} }

View File

@@ -1,7 +1,7 @@
using Content.Shared.Administration; using Content.Shared.Administration;
using JetBrains.Annotations; using JetBrains.Annotations;
using Robust.Server.Interfaces.Console;
using Robust.Server.Interfaces.Player; using Robust.Server.Interfaces.Player;
using Robust.Shared.Console;
using Robust.Shared.IoC; using Robust.Shared.IoC;
#nullable enable #nullable enable
@@ -10,17 +10,18 @@ namespace Content.Server.Administration.Commands
{ {
[UsedImplicitly] [UsedImplicitly]
[AdminCommand(AdminFlags.None)] [AdminCommand(AdminFlags.None)]
public class DeAdminCommand : IClientCommand public class DeAdminCommand : IConsoleCommand
{ {
public string Command => "deadmin"; public string Command => "deadmin";
public string Description => "Temporarily de-admins you so you can experience the round as a normal player."; public string Description => "Temporarily de-admins you so you can experience the round as a normal player.";
public string Help => "Usage: deadmin\nUse readmin to re-admin after using this."; public string Help => "Usage: deadmin\nUse readmin to re-admin after using this.";
public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args) public void Execute(IConsoleShell shell, string argStr, string[] args)
{ {
var player = shell.Player as IPlayerSession;
if (player == null) if (player == null)
{ {
shell.SendText(player, "You cannot use this command from the server console."); shell.WriteLine("You cannot use this command from the server console.");
return; return;
} }

View File

@@ -1,25 +1,25 @@
#nullable enable #nullable enable
using Content.Shared.Administration; using Content.Shared.Administration;
using Robust.Server.Interfaces.Console;
using Robust.Server.Interfaces.Player; using Robust.Server.Interfaces.Player;
using Robust.Shared.Console;
using Robust.Shared.Interfaces.GameObjects; using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.IoC; using Robust.Shared.IoC;
namespace Content.Server.Administration.Commands namespace Content.Server.Administration.Commands
{ {
[AdminCommand(AdminFlags.Admin)] [AdminCommand(AdminFlags.Admin)]
public class DeleteComponent : IClientCommand public class DeleteComponent : IConsoleCommand
{ {
public string Command => "deletecomponent"; public string Command => "deletecomponent";
public string Description => "Deletes all instances of the specified component."; public string Description => "Deletes all instances of the specified component.";
public string Help => $"Usage: {Command} <name>"; public string Help => $"Usage: {Command} <name>";
public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args) public void Execute(IConsoleShell shell, string argStr, string[] args)
{ {
switch (args.Length) switch (args.Length)
{ {
case 0: case 0:
shell.SendText(player, $"Not enough arguments.\n{Help}"); shell.WriteLine($"Not enough arguments.\n{Help}");
break; break;
default: default:
var name = string.Join(" ", args); var name = string.Join(" ", args);
@@ -28,12 +28,12 @@ namespace Content.Server.Administration.Commands
if (!componentFactory.TryGetRegistration(name, out var registration)) if (!componentFactory.TryGetRegistration(name, out var registration))
{ {
shell.SendText(player, $"No component exists with name {name}."); shell.WriteLine($"No component exists with name {name}.");
break; break;
} }
var componentType = registration.Type; var componentType = registration.Type;
var components = entityManager.ComponentManager.GetAllComponents(componentType); var components = entityManager.ComponentManager.GetAllComponents(componentType, true);
var i = 0; var i = 0;
@@ -44,7 +44,7 @@ namespace Content.Server.Administration.Commands
i++; i++;
} }
shell.SendText(player, $"Removed {i} components with name {name}."); shell.WriteLine($"Removed {i} components with name {name}.");
break; break;
} }

View File

@@ -1,8 +1,8 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using Content.Shared.Administration; using Content.Shared.Administration;
using Robust.Server.Interfaces.Console;
using Robust.Server.Interfaces.Player; using Robust.Server.Interfaces.Player;
using Robust.Shared.Console;
using Robust.Shared.GameObjects; using Robust.Shared.GameObjects;
using Robust.Shared.Interfaces.GameObjects; using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.IoC; using Robust.Shared.IoC;
@@ -11,7 +11,7 @@ using Robust.Shared.Localization;
namespace Content.Server.Administration.Commands namespace Content.Server.Administration.Commands
{ {
[AdminCommand(AdminFlags.Admin)] [AdminCommand(AdminFlags.Admin)]
class DeleteEntitiesWithComponent : IClientCommand class DeleteEntitiesWithComponent : IConsoleCommand
{ {
public string Command => "deleteewc"; public string Command => "deleteewc";
public string Description public string Description
@@ -29,11 +29,11 @@ namespace Content.Server.Administration.Commands
} }
} }
public void Execute(IConsoleShell shell, IPlayerSession player, string[] args) public void Execute(IConsoleShell shell, string argStr, string[] args)
{ {
if (args.Length < 1) if (args.Length < 1)
{ {
shell.SendText(player, Help); shell.WriteLine(Help);
return; return;
} }
@@ -54,7 +54,7 @@ namespace Content.Server.Administration.Commands
count += 1; count += 1;
} }
shell.SendText(player, Loc.GetString("Deleted {0} entities", count)); shell.WriteLine(Loc.GetString("Deleted {0} entities", count));
} }
} }
} }

View File

@@ -1,7 +1,7 @@
#nullable enable #nullable enable
using Content.Shared.Administration; using Content.Shared.Administration;
using Robust.Server.Interfaces.Console;
using Robust.Server.Interfaces.Player; using Robust.Server.Interfaces.Player;
using Robust.Shared.Console;
using Robust.Shared.GameObjects; using Robust.Shared.GameObjects;
using Robust.Shared.Interfaces.GameObjects; using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.IoC; using Robust.Shared.IoC;
@@ -9,17 +9,17 @@ using Robust.Shared.IoC;
namespace Content.Server.Administration.Commands namespace Content.Server.Administration.Commands
{ {
[AdminCommand(AdminFlags.Admin)] [AdminCommand(AdminFlags.Admin)]
public class DeleteEntitiesWithId : IClientCommand public class DeleteEntitiesWithId : IConsoleCommand
{ {
public string Command => "deleteewi"; public string Command => "deleteewi";
public string Description => "Deletes entities with the specified prototype ID."; public string Description => "Deletes entities with the specified prototype ID.";
public string Help => $"Usage: {Command} <prototypeID>"; public string Help => $"Usage: {Command} <prototypeID>";
public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args) public void Execute(IConsoleShell shell, string argStr, string[] args)
{ {
if (args.Length != 1) if (args.Length != 1)
{ {
shell.SendText(player, Help); shell.WriteLine(Help);
return; return;
} }
@@ -35,7 +35,7 @@ namespace Content.Server.Administration.Commands
i++; i++;
} }
shell.SendText(player, $"Deleted all entities with id {id}. Occurrences: {i}"); shell.WriteLine($"Deleted all entities with id {id}. Occurrences: {i}");
} }
} }
} }

View File

@@ -0,0 +1,42 @@
using Content.Server.Explosions;
using Content.Shared.Administration;
using Robust.Server.Interfaces.Player;
using Robust.Shared.Console;
using Robust.Shared.Map;
#nullable enable
namespace Content.Server.Administration.Commands
{
[AdminCommand(AdminFlags.Fun)]
public sealed class ExplosionCommand : IConsoleCommand
{
public string Command => "explode";
public string Description => "Train go boom";
public string Help => "Usage: explode <x> <y> <dev> <heavy> <light> <flash>\n" +
"The explosion happens on the same map as the user.";
public void Execute(IConsoleShell shell, string argStr, string[] args)
{
var player = shell.Player as IPlayerSession;
if (player?.AttachedEntity == null)
{
shell.WriteLine("You must have an attached entity.");
return;
}
var x = float.Parse(args[0]);
var y = float.Parse(args[1]);
var dev = int.Parse(args[2]);
var hvy = int.Parse(args[3]);
var lgh = int.Parse(args[4]);
var fla = int.Parse(args[5]);
var mapTransform = player.AttachedEntity.Transform.GetMapTransform();
var coords = new EntityCoordinates(mapTransform.Owner.Uid, x, y);
ExplosionHelper.SpawnExplosion(coords, dev, hvy, lgh, fla);
}
}
}

View File

@@ -1,7 +1,7 @@
using Content.Server.Eui; using Content.Server.Eui;
using Content.Shared.Administration; using Content.Shared.Administration;
using Robust.Server.Interfaces.Console;
using Robust.Server.Interfaces.Player; using Robust.Server.Interfaces.Player;
using Robust.Shared.Console;
using Robust.Shared.IoC; using Robust.Shared.IoC;
#nullable enable #nullable enable
@@ -9,17 +9,18 @@ using Robust.Shared.IoC;
namespace Content.Server.Administration.Commands namespace Content.Server.Administration.Commands
{ {
[AdminCommand(AdminFlags.Permissions)] [AdminCommand(AdminFlags.Permissions)]
public sealed class OpenPermissionsCommand : IClientCommand public sealed class OpenPermissionsCommand : IConsoleCommand
{ {
public string Command => "permissions"; public string Command => "permissions";
public string Description => "Opens the admin permissions panel."; public string Description => "Opens the admin permissions panel.";
public string Help => "Usage: permissions"; public string Help => "Usage: permissions";
public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args) public void Execute(IConsoleShell shell, string argStr, string[] args)
{ {
var player = shell.Player as IPlayerSession;
if (player == null) if (player == null)
{ {
shell.SendText(player, "This does not work from the server console."); shell.WriteLine("This does not work from the server console.");
return; return;
} }

View File

@@ -1,30 +1,30 @@
#nullable enable #nullable enable
using JetBrains.Annotations; using JetBrains.Annotations;
using Robust.Server.Interfaces.Console;
using Robust.Server.Interfaces.Player; using Robust.Server.Interfaces.Player;
using Robust.Shared.Console;
using Robust.Shared.IoC; using Robust.Shared.IoC;
namespace Content.Server.Administration.Commands namespace Content.Server.Administration.Commands
{ {
[UsedImplicitly] [UsedImplicitly]
public sealed class PromoteHostCommand : IClientCommand public sealed class PromoteHostCommand : IConsoleCommand
{ {
public string Command => "promotehost"; public string Command => "promotehost";
public string Description => "Grants client temporary full host admin privileges. Use this to bootstrap admins."; public string Description => "Grants client temporary full host admin privileges. Use this to bootstrap admins.";
public string Help => "Usage promotehost <player>"; public string Help => "Usage promotehost <player>";
public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args) public void Execute(IConsoleShell shell, string argStr, string[] args)
{ {
if (args.Length != 1) if (args.Length != 1)
{ {
shell.SendText(player, "Expected exactly one argument."); shell.WriteLine("Expected exactly one argument.");
return; return;
} }
var plyMgr = IoCManager.Resolve<IPlayerManager>(); var plyMgr = IoCManager.Resolve<IPlayerManager>();
if (!plyMgr.TryGetSessionByUsername(args[0], out var targetPlayer)) if (!plyMgr.TryGetSessionByUsername(args[0], out var targetPlayer))
{ {
shell.SendText(player, "Unable to find a player by that name."); shell.WriteLine("Unable to find a player by that name.");
return; return;
} }

View File

@@ -1,5 +1,5 @@
using Robust.Server.Interfaces.Console;
using Robust.Server.Interfaces.Player; using Robust.Server.Interfaces.Player;
using Robust.Shared.Console;
using Robust.Shared.IoC; using Robust.Shared.IoC;
#nullable enable #nullable enable
@@ -7,17 +7,18 @@ using Robust.Shared.IoC;
namespace Content.Server.Administration.Commands namespace Content.Server.Administration.Commands
{ {
[AnyCommand] [AnyCommand]
public class ReAdminCommand : IClientCommand public class ReAdminCommand : IConsoleCommand
{ {
public string Command => "readmin"; public string Command => "readmin";
public string Description => "Re-admins you if you previously de-adminned."; public string Description => "Re-admins you if you previously de-adminned.";
public string Help => "Usage: readmin"; public string Help => "Usage: readmin";
public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args) public void Execute(IConsoleShell shell, string argStr, string[] args)
{ {
var player = shell.Player as IPlayerSession;
if (player == null) if (player == null)
{ {
shell.SendText(player, "You cannot use this command from the server console."); shell.WriteLine("You cannot use this command from the server console.");
return; return;
} }
@@ -25,7 +26,7 @@ namespace Content.Server.Administration.Commands
if (mgr.GetAdminData(player, includeDeAdmin: true) == null) if (mgr.GetAdminData(player, includeDeAdmin: true) == null)
{ {
shell.SendText(player, "You're not an admin."); shell.WriteLine("You're not an admin.");
return; return;
} }

View File

@@ -2,19 +2,19 @@
using Content.Server.GameTicking; using Content.Server.GameTicking;
using Content.Server.Interfaces.GameTicking; using Content.Server.Interfaces.GameTicking;
using Content.Shared.Administration; using Content.Shared.Administration;
using Robust.Server.Interfaces.Console;
using Robust.Server.Interfaces.Player; using Robust.Server.Interfaces.Player;
using Robust.Shared.Console;
using Robust.Shared.IoC; using Robust.Shared.IoC;
namespace Content.Server.Administration.Commands namespace Content.Server.Administration.Commands
{ {
[AdminCommand(AdminFlags.Server)] [AdminCommand(AdminFlags.Server)]
public class ReadyAll : IClientCommand public class ReadyAll : IConsoleCommand
{ {
public string Command => "readyall"; public string Command => "readyall";
public string Description => "Readies up all players in the lobby."; public string Description => "Readies up all players in the lobby.";
public string Help => $"{Command} | ̣{Command} <ready>"; public string Help => $"{Command} | ̣{Command} <ready>";
public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args) public void Execute(IConsoleShell shell, string argStr, string[] args)
{ {
var ready = true; var ready = true;
@@ -29,7 +29,7 @@ namespace Content.Server.Administration.Commands
if (gameTicker.RunLevel != GameRunLevel.PreRoundLobby) if (gameTicker.RunLevel != GameRunLevel.PreRoundLobby)
{ {
shell.SendText(player, "This command can only be ran while in the lobby!"); shell.WriteLine("This command can only be ran while in the lobby!");
return; return;
} }

View File

@@ -1,7 +1,7 @@
using Content.Server.GlobalVerbs; using Content.Server.GlobalVerbs;
using Content.Shared.Administration; using Content.Shared.Administration;
using Robust.Server.Interfaces.Console;
using Robust.Server.Interfaces.Player; using Robust.Server.Interfaces.Player;
using Robust.Shared.Console;
using Robust.Shared.GameObjects; using Robust.Shared.GameObjects;
using Robust.Shared.Interfaces.GameObjects; using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.IoC; using Robust.Shared.IoC;
@@ -10,7 +10,7 @@ using Robust.Shared.Localization;
namespace Content.Server.Administration.Commands namespace Content.Server.Administration.Commands
{ {
[AdminCommand(AdminFlags.Admin)] [AdminCommand(AdminFlags.Admin)]
class Rejuvenate : IClientCommand class Rejuvenate : IConsoleCommand
{ {
public string Command => "rejuvenate"; public string Command => "rejuvenate";
public string Description public string Description
@@ -28,14 +28,15 @@ namespace Content.Server.Administration.Commands
} }
} }
public void Execute(IConsoleShell shell, IPlayerSession player, string[] args) public void Execute(IConsoleShell shell, string argStr, string[] args)
{ {
var player = shell.Player as IPlayerSession;
if (args.Length < 1 && player != null) //Try to heal the users mob if applicable if (args.Length < 1 && player != null) //Try to heal the users mob if applicable
{ {
shell.SendText(player, Loc.GetString("Healing the user's mob since no arguments were provided.")); shell.WriteLine(Loc.GetString("Healing the user's mob since no arguments were provided."));
if (player.AttachedEntity == null) if (player.AttachedEntity == null)
{ {
shell.SendText(player, Loc.GetString("There's no entity attached to the user.")); shell.WriteLine(Loc.GetString("There's no entity attached to the user."));
return; return;
} }
RejuvenateVerb.PerformRejuvenate(player.AttachedEntity); RejuvenateVerb.PerformRejuvenate(player.AttachedEntity);
@@ -46,7 +47,7 @@ namespace Content.Server.Administration.Commands
{ {
if(!EntityUid.TryParse(arg, out var uid) || !entityManager.TryGetEntity(uid, out var entity)) if(!EntityUid.TryParse(arg, out var uid) || !entityManager.TryGetEntity(uid, out var entity))
{ {
shell.SendText(player, Loc.GetString("Could not find entity {0}", arg)); shell.WriteLine(Loc.GetString("Could not find entity {0}", arg));
continue; continue;
} }
RejuvenateVerb.PerformRejuvenate(entity); RejuvenateVerb.PerformRejuvenate(entity);

View File

@@ -0,0 +1,82 @@
#nullable enable
using Content.Server.GameObjects.Components.Mobs;
using Content.Server.Mobs;
using Content.Server.Players;
using Content.Shared.Administration;
using Robust.Server.Interfaces.Player;
using Robust.Shared.Console;
using Robust.Shared.GameObjects;
using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Localization;
namespace Content.Server.Administration.Commands
{
[AdminCommand(AdminFlags.Admin)]
class SetMindCommand : IConsoleCommand
{
public string Command => "setmind";
public string Description => Loc.GetString("Transfers a mind to the specified entity. The entity must have a MindComponent.");
public string Help => Loc.GetString("Usage: {0} <entityUid> <username>", Command);
public void Execute(IConsoleShell shell, string argStr, string[] args)
{
if (args.Length != 2)
{
shell.WriteLine(Loc.GetString("Wrong number of arguments."));
return;
}
if (!int.TryParse(args[0], out var entityUid))
{
shell.WriteLine(Loc.GetString("EntityUid must be a number."));
return;
}
var entityManager = IoCManager.Resolve<IEntityManager>();
var eUid = new EntityUid(entityUid);
if (!eUid.IsValid() || !entityManager.EntityExists(eUid))
{
shell.WriteLine(Loc.GetString("Invalid entity ID."));
return;
}
var target = entityManager.GetEntity(eUid);
if (!target.TryGetComponent<MindComponent>(out var mindComponent))
{
shell.WriteLine(Loc.GetString("Target entity does not have a mind (did you forget to make sentient?)"));
return;
}
if (!IoCManager.Resolve<IPlayerManager>().TryGetSessionByUsername(args[1], out var session))
{
shell.WriteLine(Loc.GetString("Target player does not exist"));
return;
}
// hm, does player have a mind? if not we may need to give them one
var playerCData = session.ContentData();
if (playerCData == null)
{
shell.WriteLine(Loc.GetString("Target player does not have content data (wtf?)"));
return;
}
var mind = playerCData.Mind;
if (mind == null)
{
mind = new Mind(session.UserId)
{
CharacterName = target.Name
};
playerCData.Mind = mind;
}
mind.TransferTo(target);
}
}
}

View File

@@ -3,8 +3,8 @@ using Content.Server.GameObjects.Components.GUI;
using Content.Server.GameObjects.Components.Items.Storage; using Content.Server.GameObjects.Components.Items.Storage;
using Content.Shared.Administration; using Content.Shared.Administration;
using Content.Shared.Roles; using Content.Shared.Roles;
using Robust.Server.Interfaces.Console;
using Robust.Server.Interfaces.Player; using Robust.Server.Interfaces.Player;
using Robust.Shared.Console;
using Robust.Shared.GameObjects; using Robust.Shared.GameObjects;
using Robust.Shared.Interfaces.GameObjects; using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.IoC; using Robust.Shared.IoC;
@@ -14,7 +14,7 @@ using Robust.Shared.Prototypes;
namespace Content.Server.Administration.Commands namespace Content.Server.Administration.Commands
{ {
[AdminCommand(AdminFlags.Admin)] [AdminCommand(AdminFlags.Admin)]
class SetOutfitCommand : IClientCommand class SetOutfitCommand : IConsoleCommand
{ {
public string Command => "setoutfit"; public string Command => "setoutfit";
@@ -22,17 +22,17 @@ namespace Content.Server.Administration.Commands
public string Help => Loc.GetString("Usage: {0} <entityUid> | {0} <entityUid> <outfitId>", Command); public string Help => Loc.GetString("Usage: {0} <entityUid> | {0} <entityUid> <outfitId>", Command);
public void Execute(IConsoleShell shell, IPlayerSession player, string[] args) public void Execute(IConsoleShell shell, string argStr, string[] args)
{ {
if (args.Length < 1) if (args.Length < 1)
{ {
shell.SendText(player, Loc.GetString("Wrong number of arguments.")); shell.WriteLine(Loc.GetString("Wrong number of arguments."));
return; return;
} }
if (!int.TryParse(args[0], out var entityUid)) if (!int.TryParse(args[0], out var entityUid))
{ {
shell.SendText(player, Loc.GetString("EntityUid must be a number.")); shell.WriteLine(Loc.GetString("EntityUid must be a number."));
return; return;
} }
@@ -42,7 +42,7 @@ namespace Content.Server.Administration.Commands
if (!eUid.IsValid() || !entityManager.EntityExists(eUid)) if (!eUid.IsValid() || !entityManager.EntityExists(eUid))
{ {
shell.SendText(player, Loc.GetString("Invalid entity ID.")); shell.WriteLine(Loc.GetString("Invalid entity ID."));
return; return;
} }
@@ -50,7 +50,7 @@ namespace Content.Server.Administration.Commands
if (!target.TryGetComponent<InventoryComponent>(out var inventoryComponent)) if (!target.TryGetComponent<InventoryComponent>(out var inventoryComponent))
{ {
shell.SendText(player, Loc.GetString("Target entity does not have an inventory!")); shell.WriteLine(Loc.GetString("Target entity does not have an inventory!"));
return; return;
} }
@@ -58,6 +58,7 @@ namespace Content.Server.Administration.Commands
{ {
var eui = IoCManager.Resolve<EuiManager>(); var eui = IoCManager.Resolve<EuiManager>();
var ui = new SetOutfitEui(target); var ui = new SetOutfitEui(target);
var player = shell.Player as IPlayerSession;
eui.OpenEui(ui, player); eui.OpenEui(ui, player);
return; return;
} }
@@ -65,7 +66,7 @@ namespace Content.Server.Administration.Commands
var prototypeManager = IoCManager.Resolve<IPrototypeManager>(); var prototypeManager = IoCManager.Resolve<IPrototypeManager>();
if (!prototypeManager.TryIndex<StartingGearPrototype>(args[1], out var startingGear)) if (!prototypeManager.TryIndex<StartingGearPrototype>(args[1], out var startingGear))
{ {
shell.SendText(player, Loc.GetString("Invalid outfit id")); shell.WriteLine(Loc.GetString("Invalid outfit id"));
return; return;
} }

View File

@@ -1,9 +1,9 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using Content.Server.GameObjects.Components.Markers; using Content.Server.GameObjects.Components.Markers;
using Content.Shared.Administration; using Content.Shared.Administration;
using Robust.Server.Interfaces.Console;
using Robust.Server.Interfaces.Player; using Robust.Server.Interfaces.Player;
using Robust.Shared.Console;
using Robust.Shared.Enums; using Robust.Shared.Enums;
using Robust.Shared.GameObjects.Components; using Robust.Shared.GameObjects.Components;
using Robust.Shared.Interfaces.GameObjects; using Robust.Shared.Interfaces.GameObjects;
@@ -14,7 +14,7 @@ using Robust.Shared.Map;
namespace Content.Server.Administration.Commands namespace Content.Server.Administration.Commands
{ {
[AdminCommand(AdminFlags.Admin)] [AdminCommand(AdminFlags.Admin)]
public class WarpCommand : IClientCommand public class WarpCommand : IConsoleCommand
{ {
public string Command => "warp"; public string Command => "warp";
public string Description => "Teleports you to predefined areas on the map."; public string Description => "Teleports you to predefined areas on the map.";
@@ -23,17 +23,18 @@ namespace Content.Server.Administration.Commands
"warp <location>\nLocations you can teleport to are predefined by the map. " + "warp <location>\nLocations you can teleport to are predefined by the map. " +
"You can specify '?' as location to get a list of valid locations."; "You can specify '?' as location to get a list of valid locations.";
public void Execute(IConsoleShell shell, IPlayerSession player, string[] args) public void Execute(IConsoleShell shell, string argStr, string[] args)
{ {
var player = shell.Player as IPlayerSession;
if (player == null) if (player == null)
{ {
shell.SendText((IPlayerSession) null, "Only players can use this command"); shell.WriteLine("Only players can use this command");
return; return;
} }
if (args.Length != 1) if (args.Length != 1)
{ {
shell.SendText(player, "Expected a single argument."); shell.WriteLine("Expected a single argument.");
return; return;
} }
@@ -42,19 +43,19 @@ namespace Content.Server.Administration.Commands
if (location == "?") if (location == "?")
{ {
var locations = string.Join(", ", var locations = string.Join(", ",
comp.EntityQuery<WarpPointComponent>() comp.EntityQuery<WarpPointComponent>(true)
.Select(p => p.Location) .Select(p => p.Location)
.Where(p => p != null) .Where(p => p != null)
.OrderBy(p => p) .OrderBy(p => p)
.Distinct()); .Distinct());
shell.SendText(player, locations); shell.WriteLine(locations);
} }
else else
{ {
if (player.Status != SessionStatus.InGame || player.AttachedEntity == null) if (player.Status != SessionStatus.InGame || player.AttachedEntity == null)
{ {
shell.SendText(player, "You are not in-game!"); shell.WriteLine("You are not in-game!");
return; return;
} }
@@ -63,7 +64,7 @@ namespace Content.Server.Administration.Commands
var currentGrid = player.AttachedEntity.Transform.GridID; var currentGrid = player.AttachedEntity.Transform.GridID;
var entityManager = IoCManager.Resolve<IEntityManager>(); var entityManager = IoCManager.Resolve<IEntityManager>();
var found = comp.EntityQuery<WarpPointComponent>() var found = comp.EntityQuery<WarpPointComponent>(true)
.Where(p => p.Location == location) .Where(p => p.Location == location)
.Select(p => p.Owner.Transform.Coordinates) .Select(p => p.Owner.Transform.Coordinates)
.OrderBy(p => p, Comparer<EntityCoordinates>.Create((a, b) => .OrderBy(p => p, Comparer<EntityCoordinates>.Create((a, b) =>
@@ -121,7 +122,7 @@ namespace Content.Server.Administration.Commands
} }
else else
{ {
shell.SendText(player, "That location does not exist!"); shell.WriteLine("That location does not exist!");
} }
} }
} }

View File

@@ -0,0 +1,162 @@
#nullable enable
using System;
using Content.Server.GameObjects.Components.Chemistry;
using Content.Server.Interfaces.Chemistry;
using Content.Server.Utility;
using Content.Shared.Audio;
using JetBrains.Annotations;
using Robust.Server.GameObjects.EntitySystems;
using Robust.Shared.GameObjects.Systems;
using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.Interfaces.Map;
using Robust.Shared.IoC;
using Robust.Shared.Log;
using Robust.Shared.Serialization;
namespace Content.Server.Chemistry.ReactionEffects
{
/// <summary>
/// Basically smoke and foam reactions.
/// </summary>
[UsedImplicitly]
public abstract class AreaReactionEffect : IReactionEffect
{
[Dependency] private readonly IMapManager _mapManager = default!;
/// <summary>
/// Used for calculating the spread range of the effect based on the intensity of the reaction.
/// </summary>
private float _rangeConstant;
private float _rangeMultiplier;
private int _maxRange;
/// <summary>
/// If true the reagents get diluted or concentrated depending on the range of the effect
/// </summary>
private bool _diluteReagents;
/// <summary>
/// At what range should the reagents volume stay the same. If the effect range is higher than this then the reagents
/// will get diluted. If the effect range is lower than this then the reagents will get concentrated.
/// </summary>
private int _reagentDilutionStart;
/// <summary>
/// Used to calculate dilution. Increasing this makes the reagents get more diluted. This means that a lower range
/// will be needed to make the reagents volume get closer to zero.
/// </summary>
private float _reagentDilutionFactor;
/// <summary>
/// Used to calculate concentration. Reagents get linearly more concentrated as the range goes from
/// _reagentDilutionStart to zero. When the range is zero the reagents volume gets multiplied by this.
/// </summary>
private float _reagentMaxConcentrationFactor;
/// <summary>
/// How many seconds will the effect stay, counting after fully spreading.
/// </summary>
private float _duration;
/// <summary>
/// How many seconds between each spread step.
/// </summary>
private float _spreadDelay;
/// <summary>
/// How many seconds between each remove step.
/// </summary>
private float _removeDelay;
/// <summary>
/// The entity prototype that will be spawned as the effect. It needs a component derived from SolutionAreaEffectComponent.
/// </summary>
private string? _prototypeId;
/// <summary>
/// Sound that will get played when this reaction effect occurs.
/// </summary>
private string? _sound;
protected AreaReactionEffect()
{
IoCManager.InjectDependencies(this);
}
public void ExposeData(ObjectSerializer serializer)
{
serializer.DataField(ref _rangeConstant, "rangeConstant",0f);
serializer.DataField(ref _rangeMultiplier, "rangeMultiplier",1.1f);
serializer.DataField(ref _maxRange, "maxRange", 10);
serializer.DataField(ref _diluteReagents, "diluteReagents", false);
serializer.DataField(ref _reagentDilutionStart, "reagentDilutionStart", 4);
serializer.DataField(ref _reagentDilutionFactor, "reagentDilutionFactor", 1f);
serializer.DataField(ref _reagentMaxConcentrationFactor, "reagentMaxConcentrationFactor",2f);
serializer.DataField(ref _duration, "duration", 10f);
serializer.DataField(ref _spreadDelay, "spreadDelay", 0.5f);
serializer.DataField(ref _removeDelay, "removeDelay", 0.5f);
serializer.DataField(ref _sound, "sound", null);
serializer.DataField(ref _prototypeId, "prototypeId", null);
if (_prototypeId == null)
Logger.Error("prototypeId wasn't provided to AreaReactionEffect, check yaml");
}
public void React(IEntity solutionEntity, double intensity)
{
if (!solutionEntity.TryGetComponent(out SolutionContainerComponent? contents))
return;
var solution = contents.SplitSolution(contents.MaxVolume);
// We take the square root so it becomes harder to reach higher amount values
var amount = (int) Math.Round(_rangeConstant + _rangeMultiplier*Math.Sqrt(intensity));
amount = Math.Min(amount, _maxRange);
if (_diluteReagents)
{
// The maximum value of solutionFraction is _reagentMaxConcentrationFactor, achieved when amount = 0
// The infimum of solutionFraction is 0, which is approached when amount tends to infinity
// solutionFraction is equal to 1 only when amount equals _reagentDilutionStart
float solutionFraction;
if (amount >= _reagentDilutionStart)
{
// Weird formulas here but basically when amount increases, solutionFraction gets closer to 0 in a reciprocal manner
// _reagentDilutionFactor defines how fast solutionFraction gets closer to 0
solutionFraction = 1 / (_reagentDilutionFactor*(amount - _reagentDilutionStart) + 1);
}
else
{
// Here when amount decreases, solutionFraction gets closer to _reagentMaxConcentrationFactor in a linear manner
solutionFraction = amount * (1 - _reagentMaxConcentrationFactor) / _reagentDilutionStart +
_reagentMaxConcentrationFactor;
}
solution.RemoveSolution(solution.TotalVolume*(1-solutionFraction));
}
if (!_mapManager.TryFindGridAt(solutionEntity.Transform.MapPosition, out var grid)) return;
var coords = grid.MapToGrid(solutionEntity.Transform.MapPosition);
var ent = solutionEntity.EntityManager.SpawnEntity(_prototypeId, coords.SnapToGrid());
var areaEffectComponent = GetAreaEffectComponent(ent);
if (areaEffectComponent == null)
{
Logger.Error("Couldn't get AreaEffectComponent from " + _prototypeId);
ent.Delete();
return;
}
areaEffectComponent.TryAddSolution(solution);
areaEffectComponent.Start(amount, _duration, _spreadDelay, _removeDelay);
if (!string.IsNullOrEmpty(_sound))
{
EntitySystem.Get<AudioSystem>().PlayFromEntity(_sound, solutionEntity, AudioHelpers.WithVariation(0.125f));
}
}
protected abstract SolutionAreaEffectComponent? GetAreaEffectComponent(IEntity entity);
}
}

View File

@@ -0,0 +1,16 @@
#nullable enable
using Content.Server.GameObjects.Components.Chemistry;
using JetBrains.Annotations;
using Robust.Shared.Interfaces.GameObjects;
namespace Content.Server.Chemistry.ReactionEffects
{
[UsedImplicitly]
public class FoamAreaReactionEffect : AreaReactionEffect
{
protected override SolutionAreaEffectComponent? GetAreaEffectComponent(IEntity entity)
{
return entity.GetComponentOrNull<FoamSolutionAreaEffectComponent>();
}
}
}

View File

@@ -0,0 +1,16 @@
#nullable enable
using Content.Server.GameObjects.Components.Chemistry;
using JetBrains.Annotations;
using Robust.Shared.Interfaces.GameObjects;
namespace Content.Server.Chemistry.ReactionEffects
{
[UsedImplicitly]
public class SmokeAreaReactionEffect : AreaReactionEffect
{
protected override SolutionAreaEffectComponent? GetAreaEffectComponent(IEntity entity)
{
return entity.GetComponentOrNull<SmokeSolutionAreaEffectComponent>();
}
}
}

View File

@@ -4,8 +4,8 @@ using Content.Server.GameObjects.Components.Movement;
using Content.Server.GameObjects.EntitySystems.AI; using Content.Server.GameObjects.EntitySystems.AI;
using Content.Shared.Administration; using Content.Shared.Administration;
using Content.Shared.GameObjects.Components.Movement; using Content.Shared.GameObjects.Components.Movement;
using Robust.Server.Interfaces.Console;
using Robust.Server.Interfaces.Player; using Robust.Server.Interfaces.Player;
using Robust.Shared.Console;
using Robust.Shared.GameObjects; using Robust.Shared.GameObjects;
using Robust.Shared.GameObjects.Systems; using Robust.Shared.GameObjects.Systems;
using Robust.Shared.Interfaces.GameObjects; using Robust.Shared.Interfaces.GameObjects;
@@ -14,7 +14,7 @@ using Robust.Shared.IoC;
namespace Content.Server.Commands.AI namespace Content.Server.Commands.AI
{ {
[AdminCommand(AdminFlags.Fun)] [AdminCommand(AdminFlags.Fun)]
public class AddAiCommand : IClientCommand public class AddAiCommand : IConsoleCommand
{ {
public string Command => "addai"; public string Command => "addai";
public string Description => "Add an ai component with a given processor to an entity."; public string Description => "Add an ai component with a given processor to an entity.";
@@ -22,11 +22,11 @@ namespace Content.Server.Commands.AI
+ "\n processorId: Class that inherits AiLogicProcessor and has an AiLogicProcessor attribute." + "\n processorId: Class that inherits AiLogicProcessor and has an AiLogicProcessor attribute."
+ "\n entityID: Uid of entity to add the AiControllerComponent to. Open its VV menu to find this."; + "\n entityID: Uid of entity to add the AiControllerComponent to. Open its VV menu to find this.";
public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args) public void Execute(IConsoleShell shell, string argStr, string[] args)
{ {
if(args.Length != 2) if(args.Length != 2)
{ {
shell.SendText(player, "Wrong number of args."); shell.WriteLine("Wrong number of args.");
return; return;
} }
@@ -37,12 +37,12 @@ namespace Content.Server.Commands.AI
if (!aiSystem.ProcessorTypeExists(processorId)) if (!aiSystem.ProcessorTypeExists(processorId))
{ {
shell.SendText(player, "Invalid processor type. Processor must inherit AiLogicProcessor and have an AiLogicProcessor attribute."); shell.WriteLine("Invalid processor type. Processor must inherit AiLogicProcessor and have an AiLogicProcessor attribute.");
return; return;
} }
if (ent.HasComponent<AiControllerComponent>()) if (ent.HasComponent<AiControllerComponent>())
{ {
shell.SendText(player, "Entity already has an AI component."); shell.WriteLine("Entity already has an AI component.");
return; return;
} }
@@ -53,7 +53,7 @@ namespace Content.Server.Commands.AI
var comp = ent.AddComponent<AiControllerComponent>(); var comp = ent.AddComponent<AiControllerComponent>();
comp.LogicName = processorId; comp.LogicName = processorId;
shell.SendText(player, "AI component added."); shell.WriteLine("AI component added.");
} }
} }
} }

View File

@@ -4,22 +4,22 @@ using Content.Server.Administration;
using Content.Server.GameObjects.Components.AI; using Content.Server.GameObjects.Components.AI;
using Content.Server.GameObjects.EntitySystems.AI; using Content.Server.GameObjects.EntitySystems.AI;
using Content.Shared.Administration; using Content.Shared.Administration;
using Robust.Server.Interfaces.Console;
using Robust.Server.Interfaces.Player; using Robust.Server.Interfaces.Player;
using Robust.Shared.Console;
using Robust.Shared.GameObjects.Systems; using Robust.Shared.GameObjects.Systems;
using Robust.Shared.Localization; using Robust.Shared.Localization;
namespace Content.Server.Commands.AI namespace Content.Server.Commands.AI
{ {
[AdminCommand(AdminFlags.Fun)] [AdminCommand(AdminFlags.Fun)]
public sealed class FactionCommand : IClientCommand public sealed class FactionCommand : IConsoleCommand
{ {
public string Command => "factions"; public string Command => "factions";
public string Description => "Update / list factional relationships for NPCs."; public string Description => "Update / list factional relationships for NPCs.";
public string Help => "faction <source> <friendly/hostile> target\n" + public string Help => "faction <source> <friendly/hostile> target\n" +
"faction <source> list: hostile factions"; "faction <source> list: hostile factions";
public void Execute(IConsoleShell shell, IPlayerSession player, string[] args) public void Execute(IConsoleShell shell, string argStr, string[] args)
{ {
if (args.Length == 0) if (args.Length == 0)
{ {
@@ -31,19 +31,19 @@ namespace Content.Server.Commands.AI
result.Append(value + "\n"); result.Append(value + "\n");
} }
shell.SendText(player, result.ToString()); shell.WriteLine(result.ToString());
return; return;
} }
if (args.Length < 2) if (args.Length < 2)
{ {
shell.SendText(player, Loc.GetString("Need more args")); shell.WriteLine(Loc.GetString("Need more args"));
return; return;
} }
if (!Enum.TryParse(args[0], true, out Faction faction)) if (!Enum.TryParse(args[0], true, out Faction faction))
{ {
shell.SendText(player, Loc.GetString("Invalid faction")); shell.WriteLine(Loc.GetString("Invalid faction"));
return; return;
} }
@@ -54,40 +54,40 @@ namespace Content.Server.Commands.AI
case "friendly": case "friendly":
if (args.Length < 3) if (args.Length < 3)
{ {
shell.SendText(player, Loc.GetString("Need to supply a target faction")); shell.WriteLine(Loc.GetString("Need to supply a target faction"));
return; return;
} }
if (!Enum.TryParse(args[2], true, out targetFaction)) if (!Enum.TryParse(args[2], true, out targetFaction))
{ {
shell.SendText(player, Loc.GetString("Invalid target faction")); shell.WriteLine(Loc.GetString("Invalid target faction"));
return; return;
} }
EntitySystem.Get<AiFactionTagSystem>().MakeFriendly(faction, targetFaction); EntitySystem.Get<AiFactionTagSystem>().MakeFriendly(faction, targetFaction);
shell.SendText(player, Loc.GetString("Command successful")); shell.WriteLine(Loc.GetString("Command successful"));
break; break;
case "hostile": case "hostile":
if (args.Length < 3) if (args.Length < 3)
{ {
shell.SendText(player, Loc.GetString("Need to supply a target faction")); shell.WriteLine(Loc.GetString("Need to supply a target faction"));
return; return;
} }
if (!Enum.TryParse(args[2], true, out targetFaction)) if (!Enum.TryParse(args[2], true, out targetFaction))
{ {
shell.SendText(player, Loc.GetString("Invalid target faction")); shell.WriteLine(Loc.GetString("Invalid target faction"));
return; return;
} }
EntitySystem.Get<AiFactionTagSystem>().MakeHostile(faction, targetFaction); EntitySystem.Get<AiFactionTagSystem>().MakeHostile(faction, targetFaction);
shell.SendText(player, Loc.GetString("Command successful")); shell.WriteLine(Loc.GetString("Command successful"));
break; break;
case "list": case "list":
shell.SendText(player, EntitySystem.Get<AiFactionTagSystem>().GetHostileFactions(faction).ToString()); shell.WriteLine(EntitySystem.Get<AiFactionTagSystem>().GetHostileFactions(faction).ToString());
break; break;
default: default:
shell.SendText(player, Loc.GetString("Unknown faction arg")); shell.WriteLine(Loc.GetString("Unknown faction arg"));
break; break;
} }

View File

@@ -1,25 +1,26 @@
#nullable enable #nullable enable
using System; using System;
using Content.Server.Administration; using Content.Server.Administration;
using Content.Server.GameObjects.Components.Mobs; using Content.Server.GameObjects.Components.Mobs;
using Content.Shared.Actions; using Content.Shared.Actions;
using Content.Shared.Administration; using Content.Shared.Administration;
using Robust.Server.Interfaces.Console;
using Robust.Server.Interfaces.Player; using Robust.Server.Interfaces.Player;
using Robust.Shared.Console;
using Robust.Shared.Interfaces.Timing; using Robust.Shared.Interfaces.Timing;
using Robust.Shared.IoC; using Robust.Shared.IoC;
namespace Content.Server.Commands.Actions namespace Content.Server.Commands.Actions
{ {
[AdminCommand(AdminFlags.Debug)] [AdminCommand(AdminFlags.Debug)]
public sealed class CooldownAction : IClientCommand public sealed class CooldownAction : IConsoleCommand
{ {
public string Command => "coolaction"; public string Command => "coolaction";
public string Description => "Sets a cooldown on an action for a player, defaulting to current player"; public string Description => "Sets a cooldown on an action for a player, defaulting to current player";
public string Help => "coolaction <actionType> <seconds> <name or userID, omit for current player>"; public string Help => "coolaction <actionType> <seconds> <name or userID, omit for current player>";
public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args) public void Execute(IConsoleShell shell, string argStr, string[] args)
{ {
var player = shell.Player as IPlayerSession;
if (player == null) return; if (player == null) return;
var attachedEntity = player.AttachedEntity; var attachedEntity = player.AttachedEntity;
if (args.Length > 2) if (args.Length > 2)
@@ -31,29 +32,29 @@ namespace Content.Server.Commands.Actions
if (attachedEntity == null) return; if (attachedEntity == null) return;
if (!attachedEntity.TryGetComponent(out ServerActionsComponent? actionsComponent)) if (!attachedEntity.TryGetComponent(out ServerActionsComponent? actionsComponent))
{ {
shell.SendText(player, "user has no actions component"); shell.WriteLine("user has no actions component");
return; return;
} }
var actionTypeRaw = args[0]; var actionTypeRaw = args[0];
if (!Enum.TryParse<ActionType>(actionTypeRaw, out var actionType)) if (!Enum.TryParse<ActionType>(actionTypeRaw, out var actionType))
{ {
shell.SendText(player, "unrecognized ActionType enum value, please" + shell.WriteLine("unrecognized ActionType enum value, please" +
" ensure you used correct casing: " + actionTypeRaw); " ensure you used correct casing: " + actionTypeRaw);
return; return;
} }
var actionMgr = IoCManager.Resolve<ActionManager>(); var actionMgr = IoCManager.Resolve<ActionManager>();
if (!actionMgr.TryGet(actionType, out var action)) if (!actionMgr.TryGet(actionType, out var action))
{ {
shell.SendText(player, "unrecognized actionType " + actionType); shell.WriteLine("unrecognized actionType " + actionType);
return; return;
} }
var cooldownStart = IoCManager.Resolve<IGameTiming>().CurTime; var cooldownStart = IoCManager.Resolve<IGameTiming>().CurTime;
if (!uint.TryParse(args[1], out var seconds)) if (!uint.TryParse(args[1], out var seconds))
{ {
shell.SendText(player, "cannot parse seconds: " + args[1]); shell.WriteLine("cannot parse seconds: " + args[1]);
return; return;
} }

View File

@@ -1,23 +1,24 @@
#nullable enable #nullable enable
using System; using System;
using Content.Server.Administration; using Content.Server.Administration;
using Content.Server.GameObjects.Components.Mobs; using Content.Server.GameObjects.Components.Mobs;
using Content.Shared.Actions; using Content.Shared.Actions;
using Content.Shared.Administration; using Content.Shared.Administration;
using Robust.Server.Interfaces.Console;
using Robust.Server.Interfaces.Player; using Robust.Server.Interfaces.Player;
using Robust.Shared.Console;
using Robust.Shared.IoC; using Robust.Shared.IoC;
namespace Content.Server.Commands.Actions namespace Content.Server.Commands.Actions
{ {
[AdminCommand(AdminFlags.Debug)] [AdminCommand(AdminFlags.Debug)]
public sealed class GrantAction : IClientCommand public sealed class GrantAction : IConsoleCommand
{ {
public string Command => "grantaction"; public string Command => "grantaction";
public string Description => "Grants an action to a player, defaulting to current player"; public string Description => "Grants an action to a player, defaulting to current player";
public string Help => "grantaction <actionType> <name or userID, omit for current player>"; public string Help => "grantaction <actionType> <name or userID, omit for current player>";
public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args) public void Execute(IConsoleShell shell, string argStr, string[] args)
{ {
var player = shell.Player as IPlayerSession;
if (player == null) return; if (player == null) return;
var attachedEntity = player.AttachedEntity; var attachedEntity = player.AttachedEntity;
if (args.Length > 1) if (args.Length > 1)
@@ -29,21 +30,21 @@ namespace Content.Server.Commands.Actions
if (attachedEntity == null) return; if (attachedEntity == null) return;
if (!attachedEntity.TryGetComponent(out ServerActionsComponent? actionsComponent)) if (!attachedEntity.TryGetComponent(out ServerActionsComponent? actionsComponent))
{ {
shell.SendText(player, "user has no actions component"); shell.WriteLine("user has no actions component");
return; return;
} }
var actionTypeRaw = args[0]; var actionTypeRaw = args[0];
if (!Enum.TryParse<ActionType>(actionTypeRaw, out var actionType)) if (!Enum.TryParse<ActionType>(actionTypeRaw, out var actionType))
{ {
shell.SendText(player, "unrecognized ActionType enum value, please" + shell.WriteLine("unrecognized ActionType enum value, please" +
" ensure you used correct casing: " + actionTypeRaw); " ensure you used correct casing: " + actionTypeRaw);
return; return;
} }
var actionMgr = IoCManager.Resolve<ActionManager>(); var actionMgr = IoCManager.Resolve<ActionManager>();
if (!actionMgr.TryGet(actionType, out var action)) if (!actionMgr.TryGet(actionType, out var action))
{ {
shell.SendText(player, "unrecognized actionType " + actionType); shell.WriteLine("unrecognized actionType " + actionType);
return; return;
} }
actionsComponent.Grant(action.ActionType); actionsComponent.Grant(action.ActionType);

View File

@@ -1,24 +1,25 @@
#nullable enable #nullable enable
using System; using System;
using Content.Server.Administration; using Content.Server.Administration;
using Content.Server.GameObjects.Components.Mobs; using Content.Server.GameObjects.Components.Mobs;
using Content.Shared.Actions; using Content.Shared.Actions;
using Content.Shared.Administration; using Content.Shared.Administration;
using Robust.Server.Interfaces.Console;
using Robust.Server.Interfaces.Player; using Robust.Server.Interfaces.Player;
using Robust.Shared.Console;
using Robust.Shared.IoC; using Robust.Shared.IoC;
namespace Content.Server.Commands.Actions namespace Content.Server.Commands.Actions
{ {
[AdminCommand(AdminFlags.Debug)] [AdminCommand(AdminFlags.Debug)]
public sealed class RevokeAction : IClientCommand public sealed class RevokeAction : IConsoleCommand
{ {
public string Command => "revokeaction"; public string Command => "revokeaction";
public string Description => "Revokes an action from a player, defaulting to current player"; public string Description => "Revokes an action from a player, defaulting to current player";
public string Help => "revokeaction <actionType> <name or userID, omit for current player>"; public string Help => "revokeaction <actionType> <name or userID, omit for current player>";
public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args) public void Execute(IConsoleShell shell, string argStr, string[] args)
{ {
var player = shell.Player as IPlayerSession;
if (player == null) return; if (player == null) return;
var attachedEntity = player.AttachedEntity; var attachedEntity = player.AttachedEntity;
if (args.Length > 1) if (args.Length > 1)
@@ -29,21 +30,21 @@ namespace Content.Server.Commands.Actions
if (attachedEntity == null) return; if (attachedEntity == null) return;
if (!attachedEntity.TryGetComponent(out ServerActionsComponent? actionsComponent)) if (!attachedEntity.TryGetComponent(out ServerActionsComponent? actionsComponent))
{ {
shell.SendText(player, "user has no actions component"); shell.WriteLine("user has no actions component");
return; return;
} }
var actionTypeRaw = args[0]; var actionTypeRaw = args[0];
if (!Enum.TryParse<ActionType>(actionTypeRaw, out var actionType)) if (!Enum.TryParse<ActionType>(actionTypeRaw, out var actionType))
{ {
shell.SendText(player, "unrecognized ActionType enum value, please" + shell.WriteLine("unrecognized ActionType enum value, please" +
" ensure you used correct casing: " + actionTypeRaw); " ensure you used correct casing: " + actionTypeRaw);
return; return;
} }
var actionMgr = IoCManager.Resolve<ActionManager>(); var actionMgr = IoCManager.Resolve<ActionManager>();
if (!actionMgr.TryGet(actionType, out var action)) if (!actionMgr.TryGet(actionType, out var action))
{ {
shell.SendText(player, "unrecognized actionType " + actionType); shell.WriteLine("unrecognized actionType " + actionType);
return; return;
} }

View File

@@ -1,27 +1,28 @@
#nullable enable #nullable enable
using System; using System;
using Content.Server.Administration; using Content.Server.Administration;
using Content.Server.GameObjects.Components.Mobs; using Content.Server.GameObjects.Components.Mobs;
using Content.Shared.Administration; using Content.Shared.Administration;
using Content.Shared.Alert; using Content.Shared.Alert;
using Robust.Server.Interfaces.Console;
using Robust.Server.Interfaces.Player; using Robust.Server.Interfaces.Player;
using Robust.Shared.Console;
using Robust.Shared.IoC; using Robust.Shared.IoC;
namespace Content.Server.Commands.Alerts namespace Content.Server.Commands.Alerts
{ {
[AdminCommand(AdminFlags.Debug)] [AdminCommand(AdminFlags.Debug)]
public sealed class ClearAlert : IClientCommand public sealed class ClearAlert : IConsoleCommand
{ {
public string Command => "clearalert"; public string Command => "clearalert";
public string Description => "Clears an alert for a player, defaulting to current player"; public string Description => "Clears an alert for a player, defaulting to current player";
public string Help => "clearalert <alertType> <name or userID, omit for current player>"; public string Help => "clearalert <alertType> <name or userID, omit for current player>";
public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args) public void Execute(IConsoleShell shell, string argStr, string[] args)
{ {
var player = shell.Player as IPlayerSession;
if (player?.AttachedEntity == null) if (player?.AttachedEntity == null)
{ {
shell.SendText(player, "You don't have an entity."); shell.WriteLine("You don't have an entity.");
return; return;
} }
@@ -35,7 +36,7 @@ namespace Content.Server.Commands.Alerts
if (!attachedEntity.TryGetComponent(out ServerAlertsComponent? alertsComponent)) if (!attachedEntity.TryGetComponent(out ServerAlertsComponent? alertsComponent))
{ {
shell.SendText(player, "user has no alerts component"); shell.WriteLine("user has no alerts component");
return; return;
} }
@@ -43,7 +44,7 @@ namespace Content.Server.Commands.Alerts
var alertMgr = IoCManager.Resolve<AlertManager>(); var alertMgr = IoCManager.Resolve<AlertManager>();
if (!alertMgr.TryGet(Enum.Parse<AlertType>(alertType), out var alert)) if (!alertMgr.TryGet(Enum.Parse<AlertType>(alertType), out var alert))
{ {
shell.SendText(player, "unrecognized alertType " + alertType); shell.WriteLine("unrecognized alertType " + alertType);
return; return;
} }

View File

@@ -1,27 +1,28 @@
#nullable enable #nullable enable
using System; using System;
using Content.Server.Administration; using Content.Server.Administration;
using Content.Server.GameObjects.Components.Mobs; using Content.Server.GameObjects.Components.Mobs;
using Content.Shared.Administration; using Content.Shared.Administration;
using Content.Shared.Alert; using Content.Shared.Alert;
using Robust.Server.Interfaces.Console;
using Robust.Server.Interfaces.Player; using Robust.Server.Interfaces.Player;
using Robust.Shared.Console;
using Robust.Shared.IoC; using Robust.Shared.IoC;
namespace Content.Server.Commands.Alerts namespace Content.Server.Commands.Alerts
{ {
[AdminCommand(AdminFlags.Debug)] [AdminCommand(AdminFlags.Debug)]
public sealed class ShowAlert : IClientCommand public sealed class ShowAlert : IConsoleCommand
{ {
public string Command => "showalert"; public string Command => "showalert";
public string Description => "Shows an alert for a player, defaulting to current player"; public string Description => "Shows an alert for a player, defaulting to current player";
public string Help => "showalert <alertType> <severity, -1 if no severity> <name or userID, omit for current player>"; public string Help => "showalert <alertType> <severity, -1 if no severity> <name or userID, omit for current player>";
public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args) public void Execute(IConsoleShell shell, string argStr, string[] args)
{ {
var player = shell.Player as IPlayerSession;
if (player == null) if (player == null)
{ {
shell.SendText(player, "You cannot run this command from the server."); shell.WriteLine("You cannot run this command from the server.");
return; return;
} }
@@ -29,7 +30,7 @@ namespace Content.Server.Commands.Alerts
if (attachedEntity == null) if (attachedEntity == null)
{ {
shell.SendText(player, "You don't have an entity."); shell.WriteLine("You don't have an entity.");
return; return;
} }
@@ -41,7 +42,7 @@ namespace Content.Server.Commands.Alerts
if (!attachedEntity.TryGetComponent(out ServerAlertsComponent? alertsComponent)) if (!attachedEntity.TryGetComponent(out ServerAlertsComponent? alertsComponent))
{ {
shell.SendText(player, "user has no alerts component"); shell.WriteLine("user has no alerts component");
return; return;
} }
@@ -50,12 +51,12 @@ namespace Content.Server.Commands.Alerts
var alertMgr = IoCManager.Resolve<AlertManager>(); var alertMgr = IoCManager.Resolve<AlertManager>();
if (!alertMgr.TryGet(Enum.Parse<AlertType>(alertType), out var alert)) if (!alertMgr.TryGet(Enum.Parse<AlertType>(alertType), out var alert))
{ {
shell.SendText(player, "unrecognized alertType " + alertType); shell.WriteLine("unrecognized alertType " + alertType);
return; return;
} }
if (!short.TryParse(severity, out var sevint)) if (!short.TryParse(severity, out var sevint))
{ {
shell.SendText(player, "invalid severity " + sevint); shell.WriteLine("invalid severity " + sevint);
return; return;
} }
alertsComponent.ShowAlert(alert.AlertType, sevint == -1 ? (short?) null : sevint); alertsComponent.ShowAlert(alert.AlertType, sevint == -1 ? (short?) null : sevint);

View File

@@ -3,8 +3,8 @@ using Content.Server.Administration;
using Content.Server.Atmos; using Content.Server.Atmos;
using Content.Server.GameObjects.Components.Atmos; using Content.Server.GameObjects.Components.Atmos;
using Content.Shared.Administration; using Content.Shared.Administration;
using Robust.Server.Interfaces.Console;
using Robust.Server.Interfaces.Player; using Robust.Server.Interfaces.Player;
using Robust.Shared.Console;
using Robust.Shared.Interfaces.GameObjects; using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.Interfaces.Map; using Robust.Shared.Interfaces.Map;
using Robust.Shared.IoC; using Robust.Shared.IoC;
@@ -13,23 +13,23 @@ using Robust.Shared.Map;
namespace Content.Server.Commands.Atmos namespace Content.Server.Commands.Atmos
{ {
[AdminCommand(AdminFlags.Debug)] [AdminCommand(AdminFlags.Debug)]
public class AddAtmosCommand : IClientCommand public class AddAtmosCommand : IConsoleCommand
{ {
public string Command => "addatmos"; public string Command => "addatmos";
public string Description => "Adds atmos support to a grid."; public string Description => "Adds atmos support to a grid.";
public string Help => $"{Command} <GridId>"; public string Help => $"{Command} <GridId>";
public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args) public void Execute(IConsoleShell shell, string argStr, string[] args)
{ {
if (args.Length < 1) if (args.Length < 1)
{ {
shell.SendText(player, Help); shell.WriteLine(Help);
return; return;
} }
if (!int.TryParse(args[0], out var id)) if (!int.TryParse(args[0], out var id))
{ {
shell.SendText(player, $"{args[0]} is not a valid integer."); shell.WriteLine($"{args[0]} is not a valid integer.");
return; return;
} }
@@ -39,7 +39,7 @@ namespace Content.Server.Commands.Atmos
if (!gridId.IsValid() || !mapMan.TryGetGrid(gridId, out var gridComp)) if (!gridId.IsValid() || !mapMan.TryGetGrid(gridId, out var gridComp))
{ {
shell.SendText(player, $"{gridId} is not a valid grid id."); shell.WriteLine($"{gridId} is not a valid grid id.");
return; return;
} }
@@ -47,19 +47,19 @@ namespace Content.Server.Commands.Atmos
if (!entMan.TryGetEntity(gridComp.GridEntityId, out var grid)) if (!entMan.TryGetEntity(gridComp.GridEntityId, out var grid))
{ {
shell.SendText(player, "Failed to get grid entity."); shell.WriteLine("Failed to get grid entity.");
return; return;
} }
if (grid.HasComponent<IGridAtmosphereComponent>()) if (grid.HasComponent<IGridAtmosphereComponent>())
{ {
shell.SendText(player, "Grid already has an atmosphere."); shell.WriteLine("Grid already has an atmosphere.");
return; return;
} }
grid.AddComponent<GridAtmosphereComponent>(); grid.AddComponent<GridAtmosphereComponent>();
shell.SendText(player, $"Added atmosphere to grid {id}."); shell.WriteLine($"Added atmosphere to grid {id}.");
} }
} }
} }

View File

@@ -3,8 +3,8 @@ using Content.Server.Administration;
using Content.Server.GameObjects.Components.Atmos; using Content.Server.GameObjects.Components.Atmos;
using Content.Shared.Administration; using Content.Shared.Administration;
using Content.Shared.Atmos; using Content.Shared.Atmos;
using Robust.Server.Interfaces.Console;
using Robust.Server.Interfaces.Player; using Robust.Server.Interfaces.Player;
using Robust.Shared.Console;
using Robust.Shared.Interfaces.GameObjects; using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.Interfaces.Map; using Robust.Shared.Interfaces.Map;
using Robust.Shared.IoC; using Robust.Shared.IoC;
@@ -14,13 +14,13 @@ using Robust.Shared.Maths;
namespace Content.Server.Commands.Atmos namespace Content.Server.Commands.Atmos
{ {
[AdminCommand(AdminFlags.Debug)] [AdminCommand(AdminFlags.Debug)]
public class AddGasCommand : IClientCommand public class AddGasCommand : IConsoleCommand
{ {
public string Command => "addgas"; public string Command => "addgas";
public string Description => "Adds gas at a certain position."; public string Description => "Adds gas at a certain position.";
public string Help => "addgas <X> <Y> <GridId> <Gas> <moles>"; public string Help => "addgas <X> <Y> <GridId> <Gas> <moles>";
public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args) public void Execute(IConsoleShell shell, string argStr, string[] args)
{ {
if (args.Length < 5) return; if (args.Length < 5) return;
if(!int.TryParse(args[0], out var x) if(!int.TryParse(args[0], out var x)
@@ -35,7 +35,7 @@ namespace Content.Server.Commands.Atmos
if (!gridId.IsValid() || !mapMan.TryGetGrid(gridId, out var gridComp)) if (!gridId.IsValid() || !mapMan.TryGetGrid(gridId, out var gridComp))
{ {
shell.SendText(player, "Invalid grid ID."); shell.WriteLine("Invalid grid ID.");
return; return;
} }
@@ -43,13 +43,13 @@ namespace Content.Server.Commands.Atmos
if (!entMan.TryGetEntity(gridComp.GridEntityId, out var grid)) if (!entMan.TryGetEntity(gridComp.GridEntityId, out var grid))
{ {
shell.SendText(player, "Failed to get grid entity."); shell.WriteLine("Failed to get grid entity.");
return; return;
} }
if (!grid.HasComponent<GridAtmosphereComponent>()) if (!grid.HasComponent<GridAtmosphereComponent>())
{ {
shell.SendText(player, "Grid doesn't have an atmosphere."); shell.WriteLine("Grid doesn't have an atmosphere.");
return; return;
} }
@@ -59,13 +59,13 @@ namespace Content.Server.Commands.Atmos
if (tile == null) if (tile == null)
{ {
shell.SendText(player, "Invalid coordinates."); shell.WriteLine("Invalid coordinates.");
return; return;
} }
if (tile.Air == null) if (tile.Air == null)
{ {
shell.SendText(player, "Can't add gas to that tile."); shell.WriteLine("Can't add gas to that tile.");
return; return;
} }

View File

@@ -3,8 +3,8 @@ using Content.Server.Administration;
using Content.Server.Atmos; using Content.Server.Atmos;
using Content.Server.GameObjects.Components.Atmos; using Content.Server.GameObjects.Components.Atmos;
using Content.Shared.Administration; using Content.Shared.Administration;
using Robust.Server.Interfaces.Console;
using Robust.Server.Interfaces.Player; using Robust.Server.Interfaces.Player;
using Robust.Shared.Console;
using Robust.Shared.Interfaces.GameObjects; using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.Interfaces.Map; using Robust.Shared.Interfaces.Map;
using Robust.Shared.IoC; using Robust.Shared.IoC;
@@ -13,23 +13,23 @@ using Robust.Shared.Map;
namespace Content.Server.Commands.Atmos namespace Content.Server.Commands.Atmos
{ {
[AdminCommand(AdminFlags.Debug)] [AdminCommand(AdminFlags.Debug)]
public class AddUnsimulatedAtmosCommand : IClientCommand public class AddUnsimulatedAtmosCommand : IConsoleCommand
{ {
public string Command => "addunsimulatedatmos"; public string Command => "addunsimulatedatmos";
public string Description => "Adds unimulated atmos support to a grid."; public string Description => "Adds unimulated atmos support to a grid.";
public string Help => $"{Command} <GridId>"; public string Help => $"{Command} <GridId>";
public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args) public void Execute(IConsoleShell shell, string argStr, string[] args)
{ {
if (args.Length < 1) if (args.Length < 1)
{ {
shell.SendText(player, Help); shell.WriteLine(Help);
return; return;
} }
if (!int.TryParse(args[0], out var id)) if (!int.TryParse(args[0], out var id))
{ {
shell.SendText(player, $"{args[0]} is not a valid integer."); shell.WriteLine($"{args[0]} is not a valid integer.");
return; return;
} }
@@ -39,7 +39,7 @@ namespace Content.Server.Commands.Atmos
if (!gridId.IsValid() || !mapMan.TryGetGrid(gridId, out var gridComp)) if (!gridId.IsValid() || !mapMan.TryGetGrid(gridId, out var gridComp))
{ {
shell.SendText(player, $"{gridId} is not a valid grid id."); shell.WriteLine($"{gridId} is not a valid grid id.");
return; return;
} }
@@ -47,19 +47,19 @@ namespace Content.Server.Commands.Atmos
if (!entMan.TryGetEntity(gridComp.GridEntityId, out var grid)) if (!entMan.TryGetEntity(gridComp.GridEntityId, out var grid))
{ {
shell.SendText(player, "Failed to get grid entity."); shell.WriteLine("Failed to get grid entity.");
return; return;
} }
if (grid.HasComponent<IGridAtmosphereComponent>()) if (grid.HasComponent<IGridAtmosphereComponent>())
{ {
shell.SendText(player, "Grid already has an atmosphere."); shell.WriteLine("Grid already has an atmosphere.");
return; return;
} }
grid.AddComponent<UnsimulatedGridAtmosphereComponent>(); grid.AddComponent<UnsimulatedGridAtmosphereComponent>();
shell.SendText(player, $"Added unsimulated atmosphere to grid {id}."); shell.WriteLine($"Added unsimulated atmosphere to grid {id}.");
} }
} }

View File

@@ -1,11 +1,11 @@
#nullable enable #nullable enable
using System; using System;
using Content.Server.Administration; using Content.Server.Administration;
using Content.Server.GameObjects.Components.Atmos; using Content.Server.GameObjects.Components.Atmos;
using Content.Shared.Administration; using Content.Shared.Administration;
using Content.Shared.Atmos; using Content.Shared.Atmos;
using Robust.Server.Interfaces.Console;
using Robust.Server.Interfaces.Player; using Robust.Server.Interfaces.Player;
using Robust.Shared.Console;
using Robust.Shared.Interfaces.GameObjects; using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.Interfaces.Map; using Robust.Shared.Interfaces.Map;
using Robust.Shared.IoC; using Robust.Shared.IoC;
@@ -14,14 +14,15 @@ using Robust.Shared.Map;
namespace Content.Server.Commands.Atmos namespace Content.Server.Commands.Atmos
{ {
[AdminCommand(AdminFlags.Debug)] [AdminCommand(AdminFlags.Debug)]
public class DeleteGasCommand : IClientCommand public class DeleteGasCommand : IConsoleCommand
{ {
public string Command => "deletegas"; public string Command => "deletegas";
public string Description => "Removes all gases from a grid, or just of one type if specified."; public string Description => "Removes all gases from a grid, or just of one type if specified.";
public string Help => $"Usage: {Command} <GridId> <Gas> / {Command} <GridId> / {Command} <Gas> / {Command}"; public string Help => $"Usage: {Command} <GridId> <Gas> / {Command} <GridId> / {Command} <Gas> / {Command}";
public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args) public void Execute(IConsoleShell shell, string argStr, string[] args)
{ {
var player = shell.Player as IPlayerSession;
GridId gridId; GridId gridId;
Gas? gas = null; Gas? gas = null;
@@ -30,13 +31,13 @@ namespace Content.Server.Commands.Atmos
case 0: case 0:
if (player == null) if (player == null)
{ {
shell.SendText(player, "A grid must be specified when the command isn't used by a player."); shell.WriteLine("A grid must be specified when the command isn't used by a player.");
return; return;
} }
if (player.AttachedEntity == null) if (player.AttachedEntity == null)
{ {
shell.SendText(player, "You have no entity to get a grid from."); shell.WriteLine("You have no entity to get a grid from.");
return; return;
} }
@@ -44,7 +45,7 @@ namespace Content.Server.Commands.Atmos
if (gridId == GridId.Invalid) if (gridId == GridId.Invalid)
{ {
shell.SendText(player, "You aren't on a grid to delete gas from."); shell.WriteLine("You aren't on a grid to delete gas from.");
return; return;
} }
@@ -56,13 +57,13 @@ namespace Content.Server.Commands.Atmos
// Argument is a gas // Argument is a gas
if (player == null) if (player == null)
{ {
shell.SendText(player, "A grid id must be specified if not using this command as a player."); shell.WriteLine("A grid id must be specified if not using this command as a player.");
return; return;
} }
if (player.AttachedEntity == null) if (player.AttachedEntity == null)
{ {
shell.SendText(player, "You have no entity from which to get a grid id."); shell.WriteLine("You have no entity from which to get a grid id.");
return; return;
} }
@@ -70,13 +71,13 @@ namespace Content.Server.Commands.Atmos
if (gridId == GridId.Invalid) if (gridId == GridId.Invalid)
{ {
shell.SendText(player, "You aren't on a grid to delete gas from."); shell.WriteLine("You aren't on a grid to delete gas from.");
return; return;
} }
if (!Enum.TryParse<Gas>(args[0], true, out var parsedGas)) if (!Enum.TryParse<Gas>(args[0], true, out var parsedGas))
{ {
shell.SendText(player, $"{args[0]} is not a valid gas name."); shell.WriteLine($"{args[0]} is not a valid gas name.");
return; return;
} }
@@ -89,7 +90,7 @@ namespace Content.Server.Commands.Atmos
if (gridId == GridId.Invalid) if (gridId == GridId.Invalid)
{ {
shell.SendText(player, $"{gridId} is not a valid grid id."); shell.WriteLine($"{gridId} is not a valid grid id.");
return; return;
} }
@@ -99,7 +100,7 @@ namespace Content.Server.Commands.Atmos
{ {
if (!int.TryParse(args[0], out var first)) if (!int.TryParse(args[0], out var first))
{ {
shell.SendText(player, $"{args[0]} is not a valid integer for a grid id."); shell.WriteLine($"{args[0]} is not a valid integer for a grid id.");
return; return;
} }
@@ -107,13 +108,13 @@ namespace Content.Server.Commands.Atmos
if (gridId == GridId.Invalid) if (gridId == GridId.Invalid)
{ {
shell.SendText(player, $"{gridId} is not a valid grid id."); shell.WriteLine($"{gridId} is not a valid grid id.");
return; return;
} }
if (!Enum.TryParse<Gas>(args[1], true, out var parsedGas)) if (!Enum.TryParse<Gas>(args[1], true, out var parsedGas))
{ {
shell.SendText(player, $"{args[1]} is not a valid gas."); shell.WriteLine($"{args[1]} is not a valid gas.");
return; return;
} }
@@ -122,7 +123,7 @@ namespace Content.Server.Commands.Atmos
break; break;
} }
default: default:
shell.SendText(player, Help); shell.WriteLine(Help);
return; return;
} }
@@ -130,7 +131,7 @@ namespace Content.Server.Commands.Atmos
if (!mapManager.TryGetGrid(gridId, out var grid)) if (!mapManager.TryGetGrid(gridId, out var grid))
{ {
shell.SendText(player, $"No grid exists with id {gridId}"); shell.WriteLine($"No grid exists with id {gridId}");
return; return;
} }
@@ -138,13 +139,13 @@ namespace Content.Server.Commands.Atmos
if (!entityManager.TryGetEntity(grid.GridEntityId, out var gridEntity)) if (!entityManager.TryGetEntity(grid.GridEntityId, out var gridEntity))
{ {
shell.SendText(player, $"Grid {gridId} has no entity."); shell.WriteLine($"Grid {gridId} has no entity.");
return; return;
} }
if (!gridEntity.TryGetComponent(out GridAtmosphereComponent? atmosphere)) if (!gridEntity.TryGetComponent(out GridAtmosphereComponent? atmosphere))
{ {
shell.SendText(player, $"Grid {gridId} has no {nameof(GridAtmosphereComponent)}"); shell.WriteLine($"Grid {gridId} has no {nameof(GridAtmosphereComponent)}");
return; return;
} }
@@ -182,11 +183,11 @@ namespace Content.Server.Commands.Atmos
if (gas == null) if (gas == null)
{ {
shell.SendText(player, $"Removed {moles} moles from {tiles} tiles."); shell.WriteLine($"Removed {moles} moles from {tiles} tiles.");
return; return;
} }
shell.SendText(player, $"Removed {moles} moles of gas {gas} from {tiles} tiles."); shell.WriteLine($"Removed {moles} moles of gas {gas} from {tiles} tiles.");
} }
} }

View File

@@ -3,8 +3,8 @@ using Content.Server.Administration;
using Content.Server.GameObjects.Components.Atmos; using Content.Server.GameObjects.Components.Atmos;
using Content.Shared.Administration; using Content.Shared.Administration;
using Content.Shared.Atmos; using Content.Shared.Atmos;
using Robust.Server.Interfaces.Console;
using Robust.Server.Interfaces.Player; using Robust.Server.Interfaces.Player;
using Robust.Shared.Console;
using Robust.Shared.Interfaces.GameObjects; using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.Interfaces.Map; using Robust.Shared.Interfaces.Map;
using Robust.Shared.IoC; using Robust.Shared.IoC;
@@ -13,13 +13,13 @@ using Robust.Shared.Map;
namespace Content.Server.Commands.Atmos namespace Content.Server.Commands.Atmos
{ {
[AdminCommand(AdminFlags.Debug)] [AdminCommand(AdminFlags.Debug)]
public class FillGas : IClientCommand public class FillGas : IConsoleCommand
{ {
public string Command => "fillgas"; public string Command => "fillgas";
public string Description => "Adds gas to all tiles in a grid."; public string Description => "Adds gas to all tiles in a grid.";
public string Help => "fillgas <GridId> <Gas> <moles>"; public string Help => "fillgas <GridId> <Gas> <moles>";
public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args) public void Execute(IConsoleShell shell, string argStr, string[] args)
{ {
if (args.Length < 3) return; if (args.Length < 3) return;
if(!int.TryParse(args[0], out var id) if(!int.TryParse(args[0], out var id)
@@ -32,7 +32,7 @@ namespace Content.Server.Commands.Atmos
if (!gridId.IsValid() || !mapMan.TryGetGrid(gridId, out var gridComp)) if (!gridId.IsValid() || !mapMan.TryGetGrid(gridId, out var gridComp))
{ {
shell.SendText(player, "Invalid grid ID."); shell.WriteLine("Invalid grid ID.");
return; return;
} }
@@ -40,13 +40,13 @@ namespace Content.Server.Commands.Atmos
if (!entMan.TryGetEntity(gridComp.GridEntityId, out var grid)) if (!entMan.TryGetEntity(gridComp.GridEntityId, out var grid))
{ {
shell.SendText(player, "Failed to get grid entity."); shell.WriteLine("Failed to get grid entity.");
return; return;
} }
if (!grid.HasComponent<GridAtmosphereComponent>()) if (!grid.HasComponent<GridAtmosphereComponent>())
{ {
shell.SendText(player, "Grid doesn't have an atmosphere."); shell.WriteLine("Grid doesn't have an atmosphere.");
return; return;
} }

View File

@@ -2,26 +2,26 @@
using Content.Server.Administration; using Content.Server.Administration;
using Content.Server.GameObjects.EntitySystems; using Content.Server.GameObjects.EntitySystems;
using Content.Shared.Administration; using Content.Shared.Administration;
using Robust.Server.Interfaces.Console;
using Robust.Server.Interfaces.Player; using Robust.Server.Interfaces.Player;
using Robust.Shared.Console;
using Robust.Shared.GameObjects.Systems; using Robust.Shared.GameObjects.Systems;
namespace Content.Server.Commands.Atmos namespace Content.Server.Commands.Atmos
{ {
[AdminCommand(AdminFlags.Debug)] [AdminCommand(AdminFlags.Debug)]
public class ListGasesCommand : IClientCommand public class ListGasesCommand : IConsoleCommand
{ {
public string Command => "listgases"; public string Command => "listgases";
public string Description => "Prints a list of gases and their indices."; public string Description => "Prints a list of gases and their indices.";
public string Help => "listgases"; public string Help => "listgases";
public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args) public void Execute(IConsoleShell shell, string argStr, string[] args)
{ {
var atmosSystem = EntitySystem.Get<AtmosphereSystem>(); var atmosSystem = EntitySystem.Get<AtmosphereSystem>();
foreach (var gasPrototype in atmosSystem.Gases) foreach (var gasPrototype in atmosSystem.Gases)
{ {
shell.SendText(player, $"{gasPrototype.Name} ID: {gasPrototype.ID}"); shell.WriteLine($"{gasPrototype.Name} ID: {gasPrototype.ID}");
} }
} }
} }

View File

@@ -2,8 +2,8 @@
using Content.Server.Administration; using Content.Server.Administration;
using Content.Server.GameObjects.Components.Atmos; using Content.Server.GameObjects.Components.Atmos;
using Content.Shared.Administration; using Content.Shared.Administration;
using Robust.Server.Interfaces.Console;
using Robust.Server.Interfaces.Player; using Robust.Server.Interfaces.Player;
using Robust.Shared.Console;
using Robust.Shared.Interfaces.GameObjects; using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.Interfaces.Map; using Robust.Shared.Interfaces.Map;
using Robust.Shared.IoC; using Robust.Shared.IoC;
@@ -13,13 +13,13 @@ using Robust.Shared.Maths;
namespace Content.Server.Commands.Atmos namespace Content.Server.Commands.Atmos
{ {
[AdminCommand(AdminFlags.Debug)] [AdminCommand(AdminFlags.Debug)]
public class RemoveGasCommand : IClientCommand public class RemoveGasCommand : IConsoleCommand
{ {
public string Command => "removegas"; public string Command => "removegas";
public string Description => "Removes an amount of gases."; public string Description => "Removes an amount of gases.";
public string Help => "removegas <X> <Y> <GridId> <amount> <ratio>\nIf <ratio> is true, amount will be treated as the ratio of gas to be removed."; public string Help => "removegas <X> <Y> <GridId> <amount> <ratio>\nIf <ratio> is true, amount will be treated as the ratio of gas to be removed.";
public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args) public void Execute(IConsoleShell shell, string argStr, string[] args)
{ {
if (args.Length < 5) return; if (args.Length < 5) return;
if(!int.TryParse(args[0], out var x) if(!int.TryParse(args[0], out var x)
@@ -34,7 +34,7 @@ namespace Content.Server.Commands.Atmos
if (!gridId.IsValid() || !mapMan.TryGetGrid(gridId, out var gridComp)) if (!gridId.IsValid() || !mapMan.TryGetGrid(gridId, out var gridComp))
{ {
shell.SendText(player, "Invalid grid ID."); shell.WriteLine("Invalid grid ID.");
return; return;
} }
@@ -42,13 +42,13 @@ namespace Content.Server.Commands.Atmos
if (!entMan.TryGetEntity(gridComp.GridEntityId, out var grid)) if (!entMan.TryGetEntity(gridComp.GridEntityId, out var grid))
{ {
shell.SendText(player, "Failed to get grid entity."); shell.WriteLine("Failed to get grid entity.");
return; return;
} }
if (!grid.HasComponent<GridAtmosphereComponent>()) if (!grid.HasComponent<GridAtmosphereComponent>())
{ {
shell.SendText(player, "Grid doesn't have an atmosphere."); shell.WriteLine("Grid doesn't have an atmosphere.");
return; return;
} }
@@ -58,13 +58,13 @@ namespace Content.Server.Commands.Atmos
if (tile == null) if (tile == null)
{ {
shell.SendText(player, "Invalid coordinates."); shell.WriteLine("Invalid coordinates.");
return; return;
} }
if (tile.Air == null) if (tile.Air == null)
{ {
shell.SendText(player, "Can't remove gas from that tile."); shell.WriteLine("Can't remove gas from that tile.");
return; return;
} }

View File

@@ -3,8 +3,8 @@ using Content.Server.Administration;
using Content.Server.GameObjects.Components.Atmos; using Content.Server.GameObjects.Components.Atmos;
using Content.Shared.Administration; using Content.Shared.Administration;
using Content.Shared.Atmos; using Content.Shared.Atmos;
using Robust.Server.Interfaces.Console;
using Robust.Server.Interfaces.Player; using Robust.Server.Interfaces.Player;
using Robust.Shared.Console;
using Robust.Shared.Interfaces.GameObjects; using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.Interfaces.Map; using Robust.Shared.Interfaces.Map;
using Robust.Shared.IoC; using Robust.Shared.IoC;
@@ -13,13 +13,13 @@ using Robust.Shared.Map;
namespace Content.Server.Commands.Atmos namespace Content.Server.Commands.Atmos
{ {
[AdminCommand(AdminFlags.Debug)] [AdminCommand(AdminFlags.Debug)]
public class SetAtmosTemperatureCommand : IClientCommand public class SetAtmosTemperatureCommand : IConsoleCommand
{ {
public string Command => "setatmostemp"; public string Command => "setatmostemp";
public string Description => "Sets a grid's temperature (in kelvin)."; public string Description => "Sets a grid's temperature (in kelvin).";
public string Help => "Usage: setatmostemp <GridId> <Temperature>"; public string Help => "Usage: setatmostemp <GridId> <Temperature>";
public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args) public void Execute(IConsoleShell shell, string argStr, string[] args)
{ {
if (args.Length < 2) return; if (args.Length < 2) return;
if(!int.TryParse(args[0], out var id) if(!int.TryParse(args[0], out var id)
@@ -31,13 +31,13 @@ namespace Content.Server.Commands.Atmos
if (temperature < Atmospherics.TCMB) if (temperature < Atmospherics.TCMB)
{ {
shell.SendText(player, "Invalid temperature."); shell.WriteLine("Invalid temperature.");
return; return;
} }
if (!gridId.IsValid() || !mapMan.TryGetGrid(gridId, out var gridComp)) if (!gridId.IsValid() || !mapMan.TryGetGrid(gridId, out var gridComp))
{ {
shell.SendText(player, "Invalid grid ID."); shell.WriteLine("Invalid grid ID.");
return; return;
} }
@@ -45,13 +45,13 @@ namespace Content.Server.Commands.Atmos
if (!entMan.TryGetEntity(gridComp.GridEntityId, out var grid)) if (!entMan.TryGetEntity(gridComp.GridEntityId, out var grid))
{ {
shell.SendText(player, "Failed to get grid entity."); shell.WriteLine("Failed to get grid entity.");
return; return;
} }
if (!grid.HasComponent<GridAtmosphereComponent>()) if (!grid.HasComponent<GridAtmosphereComponent>())
{ {
shell.SendText(player, "Grid doesn't have an atmosphere."); shell.WriteLine("Grid doesn't have an atmosphere.");
return; return;
} }
@@ -69,7 +69,7 @@ namespace Content.Server.Commands.Atmos
tile.Invalidate(); tile.Invalidate();
} }
shell.SendText(player, $"Changed the temperature of {tiles} tiles."); shell.WriteLine($"Changed the temperature of {tiles} tiles.");
} }
} }
} }

View File

@@ -3,8 +3,8 @@ using Content.Server.Administration;
using Content.Server.GameObjects.Components.Atmos; using Content.Server.GameObjects.Components.Atmos;
using Content.Shared.Administration; using Content.Shared.Administration;
using Content.Shared.Atmos; using Content.Shared.Atmos;
using Robust.Server.Interfaces.Console;
using Robust.Server.Interfaces.Player; using Robust.Server.Interfaces.Player;
using Robust.Shared.Console;
using Robust.Shared.Interfaces.GameObjects; using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.Interfaces.Map; using Robust.Shared.Interfaces.Map;
using Robust.Shared.IoC; using Robust.Shared.IoC;
@@ -14,13 +14,13 @@ using Robust.Shared.Maths;
namespace Content.Server.Commands.Atmos namespace Content.Server.Commands.Atmos
{ {
[AdminCommand(AdminFlags.Debug)] [AdminCommand(AdminFlags.Debug)]
public class SetTemperatureCommand : IClientCommand public class SetTemperatureCommand : IConsoleCommand
{ {
public string Command => "settemp"; public string Command => "settemp";
public string Description => "Sets a tile's temperature (in kelvin)."; public string Description => "Sets a tile's temperature (in kelvin).";
public string Help => "Usage: settemp <X> <Y> <GridId> <Temperature>"; public string Help => "Usage: settemp <X> <Y> <GridId> <Temperature>";
public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args) public void Execute(IConsoleShell shell, string argStr, string[] args)
{ {
if (args.Length < 4) return; if (args.Length < 4) return;
if(!int.TryParse(args[0], out var x) if(!int.TryParse(args[0], out var x)
@@ -34,13 +34,13 @@ namespace Content.Server.Commands.Atmos
if (temperature < Atmospherics.TCMB) if (temperature < Atmospherics.TCMB)
{ {
shell.SendText(player, "Invalid temperature."); shell.WriteLine("Invalid temperature.");
return; return;
} }
if (!gridId.IsValid() || !mapMan.TryGetGrid(gridId, out var gridComp)) if (!gridId.IsValid() || !mapMan.TryGetGrid(gridId, out var gridComp))
{ {
shell.SendText(player, "Invalid grid ID."); shell.WriteLine("Invalid grid ID.");
return; return;
} }
@@ -48,13 +48,13 @@ namespace Content.Server.Commands.Atmos
if (!entMan.TryGetEntity(gridComp.GridEntityId, out var grid)) if (!entMan.TryGetEntity(gridComp.GridEntityId, out var grid))
{ {
shell.SendText(player, "Failed to get grid entity."); shell.WriteLine("Failed to get grid entity.");
return; return;
} }
if (!grid.HasComponent<GridAtmosphereComponent>()) if (!grid.HasComponent<GridAtmosphereComponent>())
{ {
shell.SendText(player, "Grid doesn't have an atmosphere."); shell.WriteLine("Grid doesn't have an atmosphere.");
return; return;
} }
@@ -64,13 +64,13 @@ namespace Content.Server.Commands.Atmos
if (tile == null) if (tile == null)
{ {
shell.SendText(player, "Invalid coordinates."); shell.WriteLine("Invalid coordinates.");
return; return;
} }
if (tile.Air == null) if (tile.Air == null)
{ {
shell.SendText(player, "Can't change that tile's temperature."); shell.WriteLine("Can't change that tile's temperature.");
return; return;
} }

View File

@@ -1,32 +1,33 @@
#nullable enable #nullable enable
using Content.Server.Administration; using Content.Server.Administration;
using Content.Server.GameObjects.EntitySystems.Atmos; using Content.Server.GameObjects.EntitySystems.Atmos;
using Content.Shared.Administration; using Content.Shared.Administration;
using Robust.Server.Interfaces.Console;
using Robust.Server.Interfaces.Player; using Robust.Server.Interfaces.Player;
using Robust.Shared.Console;
using Robust.Shared.GameObjects.Systems; using Robust.Shared.GameObjects.Systems;
namespace Content.Server.Commands.Atmos namespace Content.Server.Commands.Atmos
{ {
[AdminCommand(AdminFlags.Debug)] [AdminCommand(AdminFlags.Debug)]
public class ShowAtmos : IClientCommand public class ShowAtmos : IConsoleCommand
{ {
public string Command => "showatmos"; public string Command => "showatmos";
public string Description => "Toggles seeing atmos debug overlay."; public string Description => "Toggles seeing atmos debug overlay.";
public string Help => $"Usage: {Command}"; public string Help => $"Usage: {Command}";
public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args) public void Execute(IConsoleShell shell, string argStr, string[] args)
{ {
var player = shell.Player as IPlayerSession;
if (player == null) if (player == null)
{ {
shell.SendText(player, "You must be a player to use this command."); shell.WriteLine("You must be a player to use this command.");
return; return;
} }
var atmosDebug = EntitySystem.Get<AtmosDebugOverlaySystem>(); var atmosDebug = EntitySystem.Get<AtmosDebugOverlaySystem>();
var enabled = atmosDebug.ToggleObserver(player); var enabled = atmosDebug.ToggleObserver(player);
shell.SendText(player, enabled shell.WriteLine(enabled
? "Enabled the atmospherics debug overlay." ? "Enabled the atmospherics debug overlay."
: "Disabled the atmospherics debug overlay."); : "Disabled the atmospherics debug overlay.");
} }

View File

@@ -1,11 +1,11 @@
#nullable enable #nullable enable
using Content.Server.Administration; using Content.Server.Administration;
using Content.Server.GameObjects.Components.Body.Part; using Content.Server.GameObjects.Components.Body.Part;
using Content.Shared.Administration; using Content.Shared.Administration;
using Content.Shared.GameObjects.Components.Body; using Content.Shared.GameObjects.Components.Body;
using Content.Shared.GameObjects.Components.Body.Part; using Content.Shared.GameObjects.Components.Body.Part;
using Robust.Server.Interfaces.Console;
using Robust.Server.Interfaces.Player; using Robust.Server.Interfaces.Player;
using Robust.Shared.Console;
using Robust.Shared.GameObjects; using Robust.Shared.GameObjects;
using Robust.Shared.Interfaces.GameObjects; using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.IoC; using Robust.Shared.IoC;
@@ -13,14 +13,15 @@ using Robust.Shared.IoC;
namespace Content.Server.Commands namespace Content.Server.Commands
{ {
[AdminCommand(AdminFlags.Fun)] [AdminCommand(AdminFlags.Fun)]
public class AttachBodyPartCommand : IClientCommand public class AttachBodyPartCommand : IConsoleCommand
{ {
public string Command => "attachbodypart"; public string Command => "attachbodypart";
public string Description => "Attaches a body part to you or someone else."; public string Description => "Attaches a body part to you or someone else.";
public string Help => $"{Command} <partEntityUid> / {Command} <entityUid> <partEntityUid>"; public string Help => $"{Command} <partEntityUid> / {Command} <entityUid> <partEntityUid>";
public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args) public void Execute(IConsoleShell shell, string argStr, string[] args)
{ {
var player = shell.Player as IPlayerSession;
var entityManager = IoCManager.Resolve<IEntityManager>(); var entityManager = IoCManager.Resolve<IEntityManager>();
IEntity entity; IEntity entity;
@@ -31,19 +32,19 @@ namespace Content.Server.Commands
case 1: case 1:
if (player == null) if (player == null)
{ {
shell.SendText(player, $"You need to specify an entity to attach the part to if you aren't a player.\n{Help}"); shell.WriteLine($"You need to specify an entity to attach the part to if you aren't a player.\n{Help}");
return; return;
} }
if (player.AttachedEntity == null) if (player.AttachedEntity == null)
{ {
shell.SendText(player, $"You need to specify an entity to attach the part to if you aren't attached to an entity.\n{Help}"); shell.WriteLine($"You need to specify an entity to attach the part to if you aren't attached to an entity.\n{Help}");
return; return;
} }
if (!EntityUid.TryParse(args[0], out partUid)) if (!EntityUid.TryParse(args[0], out partUid))
{ {
shell.SendText(player, $"{args[0]} is not a valid entity uid."); shell.WriteLine($"{args[0]} is not a valid entity uid.");
return; return;
} }
@@ -53,50 +54,50 @@ namespace Content.Server.Commands
case 2: case 2:
if (!EntityUid.TryParse(args[0], out var entityUid)) if (!EntityUid.TryParse(args[0], out var entityUid))
{ {
shell.SendText(player, $"{args[0]} is not a valid entity uid."); shell.WriteLine($"{args[0]} is not a valid entity uid.");
return; return;
} }
if (!EntityUid.TryParse(args[1], out partUid)) if (!EntityUid.TryParse(args[1], out partUid))
{ {
shell.SendText(player, $"{args[1]} is not a valid entity uid."); shell.WriteLine($"{args[1]} is not a valid entity uid.");
return; return;
} }
if (!entityManager.TryGetEntity(entityUid, out var tempEntity)) if (!entityManager.TryGetEntity(entityUid, out var tempEntity))
{ {
shell.SendText(player, $"{entityUid} is not a valid entity."); shell.WriteLine($"{entityUid} is not a valid entity.");
return; return;
} }
entity = tempEntity; entity = tempEntity;
break; break;
default: default:
shell.SendText(player, Help); shell.WriteLine(Help);
return; return;
} }
if (!entity.TryGetComponent(out IBody? body)) if (!entity.TryGetComponent(out IBody? body))
{ {
shell.SendText(player, $"Entity {entity.Name} with uid {entity.Uid} does not have a {nameof(IBody)} component."); shell.WriteLine($"Entity {entity.Name} with uid {entity.Uid} does not have a {nameof(IBody)} component.");
return; return;
} }
if (!entityManager.TryGetEntity(partUid, out var partEntity)) if (!entityManager.TryGetEntity(partUid, out var partEntity))
{ {
shell.SendText(player, $"{partUid} is not a valid entity."); shell.WriteLine($"{partUid} is not a valid entity.");
return; return;
} }
if (!partEntity.TryGetComponent(out IBodyPart? part)) if (!partEntity.TryGetComponent(out IBodyPart? part))
{ {
shell.SendText(player, $"Entity {partEntity.Name} with uid {args[0]} does not have a {nameof(IBodyPart)} component."); shell.WriteLine($"Entity {partEntity.Name} with uid {args[0]} does not have a {nameof(IBodyPart)} component.");
return; return;
} }
if (body.HasPart(part)) if (body.HasPart(part))
{ {
shell.SendText(player, $"Body part {partEntity.Name} with uid {partEntity.Uid} is already attached to entity {entity.Name} with uid {entity.Uid}"); shell.WriteLine($"Body part {partEntity.Name} with uid {partEntity.Uid} is already attached to entity {entity.Name} with uid {entity.Uid}");
return; return;
} }

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