Merge branch 'master' into xamlui

This commit is contained in:
Pieter-Jan Briers
2020-12-21 03:08:05 +01:00
228 changed files with 2516 additions and 1277 deletions

View File

@@ -19,7 +19,7 @@ namespace Content.Client.GameObjects.Components.Body.Surgery
public SurgeryWindow()
{
Title = Loc.GetString("Select surgery target...");
Title = Loc.GetString("Surgery");
RectClipContent = true;
var vSplitContainer = new VBoxContainer

View File

@@ -1,4 +1,4 @@
using Content.Shared.GameObjects.Components.Buckle;
using Content.Shared.GameObjects.Components.Buckle;
using Robust.Client.GameObjects;
using Robust.Shared.GameObjects;
using Robust.Shared.Interfaces.GameObjects;
@@ -27,6 +27,8 @@ namespace Content.Client.GameObjects.Components.Buckle
}
_buckled = buckle.Buckled;
LastEntityBuckledTo = buckle.LastEntityBuckledTo;
DontCollide = buckle.DontCollide;
if (!Owner.TryGetComponent(out SpriteComponent ownerSprite))
{

View File

@@ -46,7 +46,7 @@ namespace Content.Client.GameObjects.Components
var localPos = Owner.Transform.InvWorldMatrix.Transform(worldPos);
var worldRotation = Owner.Transform.WorldRotation;
var worldRotation = new Angle(Owner.Transform.WorldRotation - sprite.Rotation);
if (sprite.Directional)
{
localPos = new Angle(worldRotation).RotateVec(localPos);

View File

@@ -52,6 +52,8 @@ namespace Content.Client.GameObjects.Components.Instruments
private bool _allowProgramChange;
private bool _respectMidiLimits;
/// <summary>
/// A queue of MidiEvents to be sent to the server.
/// </summary>
@@ -239,6 +241,7 @@ namespace Content.Client.GameObjects.Components.Instruments
serializer.DataField(ref _instrumentBank, "bank", (byte) 0);
serializer.DataField(ref _allowPercussion, "allowPercussion", false);
serializer.DataField(ref _allowProgramChange, "allowProgramChange", false);
serializer.DataField(ref _respectMidiLimits, "respectMidiLimits", true);
}
public override void HandleNetworkMessage(ComponentMessage message, INetChannel channel, ICommonSession? session = null)
@@ -429,7 +432,9 @@ namespace Content.Client.GameObjects.Components.Instruments
if (_midiEventBuffer.Count == 0) return;
var max = Math.Min(_instrumentSystem.MaxMidiEventsPerBatch, _instrumentSystem.MaxMidiEventsPerSecond - _sentWithinASec);
var max = _respectMidiLimits ?
Math.Min(_instrumentSystem.MaxMidiEventsPerBatch, _instrumentSystem.MaxMidiEventsPerSecond - _sentWithinASec)
: _midiEventBuffer.Count;
if (max <= 0)
{

View File

@@ -55,7 +55,7 @@ namespace Content.Client.GameObjects.Components.Items
return Hands.FirstOrDefault(hand => hand.Name == name);
}
private bool TryHand(string name, [MaybeNullWhen(false)] out Hand hand)
private bool TryHand(string name, [NotNullWhen(true)] out Hand? hand)
{
return (hand = GetHand(name)) != null;
}

View File

@@ -1,4 +1,4 @@
namespace Content.Client
namespace Content.Client
{
public static class IgnoredComponents
{
@@ -225,7 +225,10 @@
"MachineFrame",
"MachineBoard",
"ChemicalAmmo",
"BiologicalSurgeryData"
"BiologicalSurgeryData",
"CargoTelepad",
"TraitorDeathMatchRedemption",
"GlassBeaker"
};
}
}

View File

@@ -109,7 +109,8 @@ namespace Content.Client.UserInterface.Cargo
var buttons = new HBoxContainer();
CallShuttleButton = new Button()
{
Text = Loc.GetString("Call Shuttle"),
//Text = Loc.GetString("Call Shuttle"),
Text = Loc.GetString("Activate Telepad"), //Shuttle code pending
TextAlign = Label.AlignMode.Center,
SizeFlagsHorizontal = SizeFlags.FillExpand
};

View File

@@ -43,8 +43,11 @@ namespace Content.Client.UserInterface
private readonly Button _sexClassifiedButton;
private readonly HairStylePicker _hairPicker;
private readonly FacialHairStylePicker _facialHairPicker;
private readonly List<JobPrioritySelector> _jobPriorities;
private readonly OptionButton _preferenceUnavailableButton;
private readonly Dictionary<string, VBoxContainer> _jobCategories;
private readonly List<AntagPreferenceSelector> _antagPreferences;
private readonly IEntity _previewDummy;
@@ -313,31 +316,79 @@ namespace Content.Client.UserInterface
};
_jobPriorities = new List<JobPrioritySelector>();
_jobCategories = new Dictionary<string, VBoxContainer>();
var firstCategory = true;
foreach (var job in prototypeManager.EnumeratePrototypes<JobPrototype>().OrderBy(j => j.Name))
{
var selector = new JobPrioritySelector(job);
jobList.AddChild(selector);
_jobPriorities.Add(selector);
selector.PriorityChanged += priority =>
foreach (var department in job.Departments)
{
Profile = Profile.WithJobPriority(job.ID, priority);
IsDirty = true;
if (priority == JobPriority.High)
if (!_jobCategories.TryGetValue(department, out var category))
{
// Lower any other high priorities to medium.
category = new VBoxContainer
{
Name = department,
ToolTip = Loc.GetString("Jobs in the {0} department", department)
};
if (firstCategory)
{
firstCategory = false;
}
else
{
category.AddChild(new Control
{
CustomMinimumSize = new Vector2(0, 23),
});
}
category.AddChild(new PanelContainer
{
PanelOverride = new StyleBoxFlat {BackgroundColor = Color.FromHex("#464966")},
Children =
{
new Label
{
Text = Loc.GetString("{0} jobs", department)
}
}
});
_jobCategories[department] = category;
jobList.AddChild(category);
}
var selector = new JobPrioritySelector(job);
category.AddChild(selector);
_jobPriorities.Add(selector);
selector.PriorityChanged += priority =>
{
Profile = Profile.WithJobPriority(job.ID, priority);
IsDirty = true;
foreach (var jobSelector in _jobPriorities)
{
if (jobSelector != selector && jobSelector.Priority == JobPriority.High)
// Sync other selectors with the same job in case of multiple department jobs
if (jobSelector.Job == selector.Job)
{
jobSelector.Priority = JobPriority.Medium;
Profile = Profile.WithJobPriority(jobSelector.Job.ID, JobPriority.Medium);
jobSelector.Priority = priority;
}
// Lower any other high priorities to medium.
if (priority == JobPriority.High)
{
if (jobSelector.Job != selector.Job && jobSelector.Priority == JobPriority.High)
{
jobSelector.Priority = JobPriority.Medium;
Profile = Profile.WithJobPriority(jobSelector.Job.ID, JobPriority.Medium);
}
}
}
}
};
};
}
}
}

View File

@@ -4,6 +4,8 @@ using System.Linq;
using Content.Client.Interfaces;
using Content.Shared.Roles;
using Robust.Client.Console;
using Robust.Client.Graphics.Drawing;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.CustomControls;
using Robust.Client.Utility;
@@ -27,6 +29,7 @@ namespace Content.Client.UserInterface
public event Action<string> SelectedId;
private readonly Dictionary<string, JobButton> _jobButtons = new();
private readonly Dictionary<string, VBoxContainer> _jobCategories = new();
public LateJoinGui()
{
@@ -37,65 +40,108 @@ namespace Content.Client.UserInterface
var jobList = new VBoxContainer();
var vBox = new VBoxContainer
{
Children =
Children =
{
new ScrollContainer
{
new ScrollContainer
SizeFlagsVertical = SizeFlags.FillExpand,
Children =
{
SizeFlagsVertical = SizeFlags.FillExpand,
Children =
{
jobList
}
jobList
}
}
};
}
};
Contents.AddChild(vBox);
var firstCategory = true;
foreach (var job in _prototypeManager.EnumeratePrototypes<JobPrototype>().OrderBy(j => j.Name))
{
var jobButton = new JobButton
foreach (var department in job.Departments)
{
JobId = job.ID
};
if (!_jobCategories.TryGetValue(department, out var category))
{
category = new VBoxContainer
{
Name = department,
ToolTip = Loc.GetString("Jobs in the {0} department", department)
};
var jobSelector = new HBoxContainer
{
SizeFlagsHorizontal = SizeFlags.FillExpand
};
if (firstCategory)
{
firstCategory = false;
}
else
{
category.AddChild(new Control
{
CustomMinimumSize = new Vector2(0, 23),
});
}
var icon = new TextureRect
{
TextureScale = (2, 2),
Stretch = TextureRect.StretchMode.KeepCentered
};
category.AddChild(new PanelContainer
{
PanelOverride = new StyleBoxFlat {BackgroundColor = Color.FromHex("#464966")},
Children =
{
new Label
{
Text = Loc.GetString("{0} jobs", department)
}
}
});
if (job.Icon != null)
{
var specifier = new SpriteSpecifier.Rsi(new ResourcePath("/Textures/Interface/Misc/job_icons.rsi"), job.Icon);
icon.Texture = specifier.Frame0();
_jobCategories[department] = category;
jobList.AddChild(category);
}
var jobButton = new JobButton
{
JobId = job.ID
};
var jobSelector = new HBoxContainer
{
SizeFlagsHorizontal = SizeFlags.FillExpand
};
var icon = new TextureRect
{
TextureScale = (2, 2),
Stretch = TextureRect.StretchMode.KeepCentered
};
if (job.Icon != null)
{
var specifier = new SpriteSpecifier.Rsi(new ResourcePath("/Textures/Interface/Misc/job_icons.rsi"), job.Icon);
icon.Texture = specifier.Frame0();
}
jobSelector.AddChild(icon);
var jobLabel = new Label
{
Text = job.Name
};
jobSelector.AddChild(jobLabel);
jobButton.AddChild(jobSelector);
category.AddChild(jobButton);
jobButton.OnPressed += _ =>
{
SelectedId?.Invoke(jobButton.JobId);
};
if (!_gameTicker.JobsAvailable.Contains(job.ID))
{
jobButton.Disabled = true;
}
_jobButtons[job.ID] = jobButton;
}
jobSelector.AddChild(icon);
var jobLabel = new Label
{
Text = job.Name
};
jobSelector.AddChild(jobLabel);
jobButton.AddChild(jobSelector);
jobList.AddChild(jobButton);
jobButton.OnPressed += args =>
{
SelectedId?.Invoke(jobButton.JobId);
};
if (!_gameTicker.JobsAvailable.Contains(job.ID))
{
jobButton.Disabled = true;
}
_jobButtons[job.ID] = jobButton;
}
SelectedId += jobId =>
@@ -108,11 +154,6 @@ namespace Content.Client.UserInterface
_gameTicker.LobbyJobsAvailableUpdated += JobsAvailableUpdated;
}
public string ReturnId()
{
return SelectedId.ToString();
}
private void JobsAvailableUpdated(IReadOnlyList<string> jobs)
{
foreach (var (id, button) in _jobButtons)
@@ -129,6 +170,7 @@ namespace Content.Client.UserInterface
{
_gameTicker.LobbyJobsAvailableUpdated -= JobsAvailableUpdated;
_jobButtons.Clear();
_jobCategories.Clear();
}
}
}

View File

@@ -7,6 +7,8 @@ using Content.Shared.GameObjects.Components.Body;
using Content.Shared.GameObjects.Components.Body.Part;
using Content.Shared.GameObjects.Components.Buckle;
using Content.Shared.GameObjects.EntitySystems;
using Content.Shared.GameObjects.EntitySystems.ActionBlocker;
using Content.Shared.GameObjects.EntitySystems.EffectBlocker;
using Content.Shared.Utility;
using NUnit.Framework;
using Robust.Shared.Interfaces.GameObjects;

View File

@@ -147,5 +147,53 @@ namespace Content.IntegrationTests.Tests.Damageable
}
});
}
[Test]
public async Task TotalDamageTest()
{
var server = StartServerDummyTicker(new ServerContentIntegrationOption
{
ExtraPrototypes = Prototypes
});
await server.WaitIdleAsync();
var sEntityManager = server.ResolveDependency<IEntityManager>();
var sMapManager = server.ResolveDependency<IMapManager>();
IEntity sDamageableEntity;
IDamageableComponent sDamageableComponent = null;
await server.WaitPost(() =>
{
var mapId = sMapManager.NextMapId();
var coordinates = new MapCoordinates(0, 0, mapId);
sMapManager.CreateMap(mapId);
sDamageableEntity = sEntityManager.SpawnEntity(DamageableEntityId, coordinates);
sDamageableComponent = sDamageableEntity.GetComponent<IDamageableComponent>();
});
await server.WaitAssertion(() =>
{
var damageType = DamageClass.Brute;
var damage = 10;
Assert.True(sDamageableComponent.ChangeDamage(DamageClass.Brute, damage, true));
Assert.That(sDamageableComponent.TotalDamage, Is.EqualTo(10));
var totalTypeDamage = 0;
foreach (var type in damageType.ToTypes())
{
Assert.True(sDamageableComponent.TryGetDamage(type, out var typeDamage));
Assert.That(typeDamage, Is.LessThanOrEqualTo(damage));
totalTypeDamage += typeDamage;
}
Assert.That(totalTypeDamage, Is.EqualTo(damage));
});
}
}
}

View File

@@ -0,0 +1,31 @@
using System;
using Content.Server.Database;
using Content.Shared.Preferences;
using NUnit.Framework;
namespace Content.IntegrationTests.Tests.Job
{
[TestFixture]
[TestOf(typeof(JobPriority))]
[TestOf(typeof(DbJobPriority))]
public class JobPriorityTest
{
[Test]
public void JobPriorityEnumParityTest()
{
var priorities = Enum.GetValues<JobPriority>();
var dbPriorities = Enum.GetValues<DbJobPriority>();
Assert.That(priorities.Length, Is.EqualTo(dbPriorities.Length));
for (var i = 0; i < priorities.Length; i++)
{
var priority = priorities[i];
var dbPriority = dbPriorities[i];
Assert.That((int) priority, Is.EqualTo((int) dbPriority));
Assert.That(priority.ToString(), Is.EqualTo(dbPriority.ToString()));
}
}
}
}

View File

@@ -119,7 +119,7 @@ namespace Content.Server.Database
public enum DbJobPriority
{
// These enum values HAVE to match the ones in JobPriority in Shared.
// These enum values HAVE to match the ones in JobPriority in Content.Shared
Never = 0,
Low = 1,
Medium = 2,

View File

@@ -1,6 +1,7 @@
using Content.Server.AI.WorldState;
using Content.Server.AI.WorldState.States;
using Content.Shared.GameObjects.EntitySystems;
using Content.Shared.GameObjects.EntitySystems.ActionBlocker;
namespace Content.Server.AI.Utility.Considerations.ActionBlocker
{

View File

@@ -5,6 +5,7 @@ using Content.Shared.Actions;
using Content.Shared.Audio;
using Content.Shared.GameObjects.Components.Mobs;
using Content.Shared.GameObjects.EntitySystems;
using Content.Shared.GameObjects.EntitySystems.ActionBlocker;
using Content.Shared.Preferences;
using Content.Shared.Utility;
using JetBrains.Annotations;

View File

@@ -13,7 +13,7 @@ namespace Content.Server.Atmos
{
public static class AtmosHelpers
{
public static TileAtmosphere GetTileAtmosphere(this EntityCoordinates coordinates, IEntityManager? entityManager = null)
public static TileAtmosphere? GetTileAtmosphere(this EntityCoordinates coordinates, IEntityManager? entityManager = null)
{
entityManager ??= IoCManager.Resolve<IEntityManager>();
@@ -24,19 +24,19 @@ namespace Content.Server.Atmos
public static GasMixture? GetTileAir(this EntityCoordinates coordinates, IEntityManager? entityManager = null)
{
return coordinates.GetTileAtmosphere(entityManager).Air;
return coordinates.GetTileAtmosphere(entityManager)?.Air;
}
public static bool TryGetTileAtmosphere(this EntityCoordinates coordinates, [MaybeNullWhen(false)] out TileAtmosphere atmosphere)
public static bool TryGetTileAtmosphere(this EntityCoordinates coordinates, [NotNullWhen(true)] out TileAtmosphere? atmosphere)
{
// ReSharper disable once ConditionIsAlwaysTrueOrFalse
return !Equals(atmosphere = coordinates.GetTileAtmosphere()!, default);
return !Equals(atmosphere = coordinates.GetTileAtmosphere(), default);
}
public static bool TryGetTileAir(this EntityCoordinates coordinates, [MaybeNullWhen(false)] out GasMixture air, IEntityManager? entityManager = null)
public static bool TryGetTileAir(this EntityCoordinates coordinates, [NotNullWhen(true)] out GasMixture? air, IEntityManager? entityManager = null)
{
// ReSharper disable once ConditionIsAlwaysTrueOrFalse
return !Equals(air = coordinates.GetTileAir(entityManager)!, default);
return !Equals(air = coordinates.GetTileAir(entityManager), default);
}
public static bool IsTileAirProbablySafe(this EntityCoordinates coordinates)
@@ -56,7 +56,7 @@ namespace Content.Server.Atmos
return true;
}
public static TileAtmosphere GetTileAtmosphere(this Vector2i indices, GridId gridId)
public static TileAtmosphere? GetTileAtmosphere(this Vector2i indices, GridId gridId)
{
var gridAtmos = EntitySystem.Get<AtmosphereSystem>().GetGridAtmosphere(gridId);
@@ -69,28 +69,25 @@ namespace Content.Server.Atmos
}
public static bool TryGetTileAtmosphere(this Vector2i indices, GridId gridId,
[MaybeNullWhen(false)] out TileAtmosphere atmosphere)
[NotNullWhen(true)] out TileAtmosphere? atmosphere)
{
// ReSharper disable once ConditionIsAlwaysTrueOrFalse
return !Equals(atmosphere = indices.GetTileAtmosphere(gridId)!, default);
return !Equals(atmosphere = indices.GetTileAtmosphere(gridId), default);
}
public static bool TryGetTileAir(this Vector2i indices, GridId gridId, [MaybeNullWhen(false)] out GasMixture air)
public static bool TryGetTileAir(this Vector2i indices, GridId gridId, [NotNullWhen(true)] out GasMixture? air)
{
// ReSharper disable once ConditionIsAlwaysTrueOrFalse
return !Equals(air = indices.GetTileAir(gridId)!, default);
return !Equals(air = indices.GetTileAir(gridId), default);
}
public static bool InvalidateTileAir(this ITransformComponent transform, AtmosphereSystem? atmosSystem = null)
{
return InvalidateTileAir(transform.Coordinates, atmosSystem);
return InvalidateTileAir(transform.Coordinates);
}
public static bool InvalidateTileAir(this EntityCoordinates coordinates, AtmosphereSystem? atmosSystem = null, IEntityManager? entityManager = null)
public static bool InvalidateTileAir(this EntityCoordinates coordinates)
{
atmosSystem ??= EntitySystem.Get<AtmosphereSystem>();
entityManager ??= IoCManager.Resolve<IEntityManager>();
if (!coordinates.TryGetTileAtmosphere(out var tileAtmos))
{
return false;

View File

@@ -1,4 +1,5 @@
using System.Collections.Generic;
#nullable enable
using System.Collections.Generic;
using Content.Server.GameObjects.Components.Atmos;
using Content.Server.GameObjects.Components.Atmos.Piping;
using Content.Server.GameObjects.Components.NodeContainer.NodeGroups;
@@ -120,7 +121,7 @@ namespace Content.Server.Atmos
/// <param name="indices"></param>
/// <param name="createSpace"></param>
/// <returns></returns>
TileAtmosphere GetTile(Vector2i indices, bool createSpace = true);
TileAtmosphere? GetTile(Vector2i indices, bool createSpace = true);
/// <summary>
/// Returns a tile.
@@ -128,7 +129,7 @@ namespace Content.Server.Atmos
/// <param name="coordinates"></param>
/// <param name="createSpace"></param>
/// <returns></returns>
TileAtmosphere GetTile(EntityCoordinates coordinates, bool createSpace = true);
TileAtmosphere? GetTile(EntityCoordinates coordinates, bool createSpace = true);
/// <summary>
/// Returns if the tile in question is air-blocked.

View File

@@ -11,6 +11,7 @@ using Content.Server.Interfaces.Chat;
using Content.Shared.Chat;
using Content.Shared.GameObjects.Components.Inventory;
using Content.Shared.GameObjects.EntitySystems;
using Content.Shared.GameObjects.EntitySystems.ActionBlocker;
using Content.Shared.Interfaces;
using Robust.Server.Interfaces.GameObjects;
using Robust.Server.Interfaces.Player;

View File

@@ -0,0 +1,50 @@
#nullable enable
using System;
using Content.Server.Administration;
using Content.Server.Interfaces.GameTicking;
using Content.Shared;
using Content.Shared.Administration;
using Robust.Server.Interfaces.Console;
using Robust.Server.Interfaces.Player;
using Robust.Shared.Interfaces.Configuration;
using Robust.Shared.IoC;
using Robust.Shared.Localization;
namespace Content.Server.Commands.GameTicking
{
[AdminCommand(AdminFlags.Server)]
public class GoLobbyCommand : IClientCommand
{
public string Command => "golobby";
public string Description => "Enables the lobby and restarts the round.";
public string Help => $"Usage: {Command} / {Command} <preset>";
public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args)
{
Type? preset = null;
var presetName = string.Join(" ", args);
var ticker = IoCManager.Resolve<IGameTicker>();
if (args.Length > 0)
{
if (!ticker.TryGetPreset(presetName, out preset))
{
shell.SendText(player, $"No preset found with name {presetName}");
return;
}
}
var config = IoCManager.Resolve<IConfigurationManager>();
config.SetCVar(CCVars.GameLobbyEnabled, true);
ticker.RestartRound();
if (preset != null)
{
ticker.SetStartPreset(preset);
}
shell.SendText(player, $"Enabling the lobby and restarting the round.{(preset == null ? "" : $"\nPreset set to {presetName}")}");
}
}
}

View File

@@ -11,6 +11,7 @@ using Content.Shared.Interfaces;
using Content.Shared.Interfaces.GameObjects.Components;
using Content.Shared.GameObjects.Verbs;
using Content.Shared.GameObjects.EntitySystems;
using Content.Shared.GameObjects.EntitySystems.ActionBlocker;
using Robust.Server.GameObjects.Components.Container;
using Robust.Server.GameObjects.Components.UserInterface;
using Robust.Server.Interfaces.GameObjects;

View File

@@ -10,6 +10,7 @@ using Content.Shared.Alert;
using Content.Shared.GameObjects.Components.ActionBlocking;
using Content.Shared.GameObjects.Components.Mobs;
using Content.Shared.GameObjects.EntitySystems;
using Content.Shared.GameObjects.EntitySystems.ActionBlocker;
using Content.Shared.GameObjects.Verbs;
using Content.Shared.Interfaces;
using Content.Shared.Utility;

View File

@@ -5,6 +5,7 @@ using Content.Server.GameObjects.Components.Mobs;
using Content.Server.GameObjects.EntitySystems.DoAfter;
using Content.Shared.GameObjects.Components.ActionBlocking;
using Content.Shared.GameObjects.EntitySystems;
using Content.Shared.GameObjects.EntitySystems.ActionBlocker;
using Content.Shared.Interfaces;
using Content.Shared.Interfaces.GameObjects.Components;
using Content.Shared.Utility;

View File

@@ -42,7 +42,7 @@ namespace Content.Server.GameObjects.Components
/// <param name="utilizing">The tool being used, can be null if forcing it</param>
/// <param name="force">Whether or not to check if the tool is valid</param>
/// <returns>true if it is valid, false otherwise</returns>
private async Task<bool> Valid(IEntity user, IEntity? utilizing, [MaybeNullWhen(false)] bool force = false)
private async Task<bool> Valid(IEntity user, IEntity? utilizing, [NotNullWhen(true)] bool force = false)
{
if (!Owner.HasComponent<IPhysicsComponent>())
{

View File

@@ -8,6 +8,7 @@ using Content.Server.Utility;
using Content.Shared.Arcade;
using Content.Shared.GameObjects;
using Content.Shared.GameObjects.EntitySystems;
using Content.Shared.GameObjects.EntitySystems.ActionBlocker;
using Content.Shared.Interfaces.GameObjects.Components;
using Robust.Server.GameObjects.Components.UserInterface;
using Robust.Server.Interfaces.GameObjects;

View File

@@ -6,6 +6,7 @@ using Content.Server.Utility;
using Content.Shared.GameObjects.Components;
using Content.Shared.GameObjects.Components.Arcade;
using Content.Shared.GameObjects.EntitySystems;
using Content.Shared.GameObjects.EntitySystems.ActionBlocker;
using Content.Shared.Interfaces.GameObjects.Components;
using Robust.Server.GameObjects.Components.UserInterface;
using Robust.Server.GameObjects.EntitySystems;

View File

@@ -12,6 +12,7 @@ using Content.Shared.GameObjects.Components.Atmos;
using Content.Shared.GameObjects.Components.Damage;
using Content.Shared.GameObjects.Components.Mobs;
using Content.Shared.GameObjects.EntitySystems;
using Content.Shared.GameObjects.EntitySystems.ActionBlocker;
using Content.Shared.Interfaces;
using Content.Shared.Interfaces.GameObjects.Components;
using Robust.Server.GameObjects;

View File

@@ -130,7 +130,7 @@ namespace Content.Server.GameObjects.Components.Atmos
// Already get the pressure before Dirty(), because we can't get the EntitySystem in that thread or smth
var pressure = 0f;
var gam = EntitySystem.Get<AtmosphereSystem>().GetGridAtmosphere(Owner.Transform.GridID);
var tile = gam?.GetTile(Owner.Transform.Coordinates).Air;
var tile = gam?.GetTile(Owner.Transform.Coordinates)?.Air;
if (tile != null)
{
pressure = tile.Pressure;
@@ -190,7 +190,7 @@ namespace Content.Server.GameObjects.Components.Atmos
var atmosSystem = EntitySystem.Get<AtmosphereSystem>();
var gam = atmosSystem.GetGridAtmosphere(pos.GetGridId(Owner.EntityManager));
var tile = gam?.GetTile(pos).Air;
var tile = gam.GetTile(pos)?.Air;
if (tile == null)
{
error = "No Atmosphere!";

View File

@@ -17,6 +17,7 @@ using Content.Shared.GameObjects.EntitySystems;
using Content.Shared.Interfaces;
using Content.Shared.Interfaces.GameObjects.Components;
using Content.Shared.Atmos;
using Content.Shared.GameObjects.EntitySystems.ActionBlocker;
using Robust.Server.GameObjects;
using Robust.Server.GameObjects.Components.UserInterface;
using Robust.Server.Interfaces.GameObjects;

View File

@@ -11,6 +11,7 @@ using Content.Shared.Audio;
using Content.Shared.GameObjects.Components.Atmos.GasTank;
using Content.Shared.GameObjects.Components.Mobs;
using Content.Shared.GameObjects.EntitySystems;
using Content.Shared.GameObjects.EntitySystems.ActionBlocker;
using Content.Shared.GameObjects.Verbs;
using Content.Shared.Interfaces.GameObjects.Components;
using JetBrains.Annotations;

View File

@@ -2,7 +2,6 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Runtime.CompilerServices;
using Content.Server.Atmos;
@@ -10,7 +9,6 @@ using Content.Server.GameObjects.Components.Atmos.Piping;
using Content.Server.GameObjects.Components.NodeContainer.NodeGroups;
using Content.Server.GameObjects.EntitySystems;
using Content.Server.GameObjects.EntitySystems.Atmos;
using Content.Shared;
using Content.Shared.Atmos;
using Content.Shared.Maps;
using Robust.Server.GameObjects.EntitySystems.TileLookup;
@@ -19,7 +17,6 @@ using Robust.Shared.GameObjects;
using Robust.Shared.GameObjects.ComponentDependencies;
using Robust.Shared.GameObjects.Components.Map;
using Robust.Shared.GameObjects.Systems;
using Robust.Shared.Interfaces.Configuration;
using Robust.Shared.Interfaces.Map;
using Robust.Shared.Log;
using Robust.Shared.Map;

View File

@@ -0,0 +1,12 @@
namespace Content.Server.GameObjects.Components.Body.Surgery.Messages
{
public class SurgeryWindowCloseMessage
{
public SurgeryWindowCloseMessage(SurgeryToolComponent tool)
{
Tool = tool;
}
public SurgeryToolComponent Tool { get; }
}
}

View File

@@ -0,0 +1,14 @@
using Robust.Shared.GameObjects;
namespace Content.Server.GameObjects.Components.Body.Surgery.Messages
{
public class SurgeryWindowOpenMessage : ComponentMessage
{
public SurgeryWindowOpenMessage(SurgeryToolComponent tool)
{
Tool = tool;
}
public SurgeryToolComponent Tool { get; }
}
}

View File

@@ -2,6 +2,7 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Content.Server.GameObjects.Components.Body.Surgery.Messages;
using Content.Server.Utility;
using Content.Shared.GameObjects;
using Content.Shared.GameObjects.Components.Body;
@@ -37,18 +38,18 @@ namespace Content.Server.GameObjects.Components.Body.Surgery
private float _baseOperateTime;
private IBody? _bodyCache;
private ISurgeon.MechanismRequestCallback? _callbackCache;
private int _idHash;
private IEntity? _performerCache;
private SurgeryType _surgeryType;
[ViewVariables] private BoundUserInterface? UserInterface => Owner.GetUIOrNull(SurgeryUIKey.Key);
public IBody? BodyCache { get; private set; }
public IEntity? PerformerCache { get; private set; }
async Task IAfterInteract.AfterInteract(AfterInteractEventArgs eventArgs)
{
if (eventArgs.Target == null)
@@ -62,11 +63,6 @@ namespace Content.Server.GameObjects.Components.Body.Surgery
}
CloseAllSurgeryUIs();
_optionsCache.Clear();
_performerCache = null;
_bodyCache = null;
_callbackCache = null;
// Attempt surgery on a body by sending a list of operable parts for the client to choose from
if (eventArgs.Target.TryGetComponent(out IBody? body))
@@ -88,8 +84,8 @@ namespace Content.Server.GameObjects.Components.Body.Surgery
{
OpenSurgeryUI(actor.playerSession);
UpdateSurgeryUIBodyPartRequest(actor.playerSession, toSend);
_performerCache = eventArgs.User; // Also, cache the data.
_bodyCache = body;
PerformerCache = eventArgs.User; // Also, cache the data.
BodyCache = body;
}
else // If surgery cannot be performed, show message saying so.
{
@@ -99,7 +95,7 @@ namespace Content.Server.GameObjects.Components.Body.Surgery
else if (eventArgs.Target.TryGetComponent<IBodyPart>(out var part))
{
// Attempt surgery on a DroppedBodyPart - there's only one possible target so no need for selection UI
_performerCache = eventArgs.User;
PerformerCache = eventArgs.User;
// If surgery can be performed...
if (!part.SurgeryCheck(_surgeryType))
@@ -132,10 +128,10 @@ namespace Content.Server.GameObjects.Components.Body.Surgery
toSend.Add(mechanism.Name, _idHash++);
}
if (_optionsCache.Count > 0 && _performerCache != null)
if (_optionsCache.Count > 0 && PerformerCache != null)
{
OpenSurgeryUI(_performerCache.GetComponent<BasicActorComponent>().playerSession);
UpdateSurgeryUIMechanismRequest(_performerCache.GetComponent<BasicActorComponent>().playerSession,
OpenSurgeryUI(PerformerCache.GetComponent<BasicActorComponent>().playerSession);
UpdateSurgeryUIMechanismRequest(PerformerCache.GetComponent<BasicActorComponent>().playerSession,
toSend);
_callbackCache = callback;
}
@@ -146,6 +142,14 @@ namespace Content.Server.GameObjects.Components.Body.Surgery
}
}
public override void ExposeData(ObjectSerializer serializer)
{
base.ExposeData(serializer);
serializer.DataField(ref _surgeryType, "surgeryType", SurgeryType.Incision);
serializer.DataField(ref _baseOperateTime, "baseOperateTime", 5);
}
public override void Initialize()
{
base.Initialize();
@@ -156,10 +160,14 @@ namespace Content.Server.GameObjects.Components.Body.Surgery
}
}
// TODO BODY add checks to close UI if user walks too far away from tool or target.
private void OpenSurgeryUI(IPlayerSession session)
{
UserInterface?.Open(session);
var message = new SurgeryWindowOpenMessage(this);
SendMessage(message);
Owner.EntityManager.EventBus.RaiseEvent(EventSource.Local, message);
}
private void UpdateSurgeryUIBodyPartRequest(IPlayerSession session, Dictionary<string, int> options)
@@ -172,14 +180,25 @@ namespace Content.Server.GameObjects.Components.Body.Surgery
UserInterface?.SendMessage(new RequestMechanismSurgeryUIMessage(options), session);
}
private void ClearUIData()
{
_optionsCache.Clear();
PerformerCache = null;
BodyCache = null;
_callbackCache = null;
}
private void CloseSurgeryUI(IPlayerSession session)
{
UserInterface?.Close(session);
ClearUIData();
}
private void CloseAllSurgeryUIs()
public void CloseAllSurgeryUIs()
{
UserInterface?.CloseAll();
ClearUIData();
}
private void UserInterfaceOnOnReceiveMessage(ServerBoundUserInterfaceMessage message)
@@ -201,8 +220,8 @@ namespace Content.Server.GameObjects.Components.Body.Surgery
/// </summary>
private void HandleReceiveBodyPart(int key)
{
if (_performerCache == null ||
!_performerCache.TryGetComponent(out IActorComponent? actor))
if (PerformerCache == null ||
!PerformerCache.TryGetComponent(out IActorComponent? actor))
{
return;
}
@@ -210,7 +229,7 @@ namespace Content.Server.GameObjects.Components.Body.Surgery
CloseSurgeryUI(actor.playerSession);
// TODO: sanity checks to see whether user is in range, user is still able-bodied, target is still the same, etc etc
if (!_optionsCache.TryGetValue(key, out var targetObject) ||
_bodyCache == null)
BodyCache == null)
{
NotUsefulAnymorePopup();
return;
@@ -219,7 +238,7 @@ namespace Content.Server.GameObjects.Components.Body.Surgery
var target = (IBodyPart) targetObject!;
// TODO BODY Reconsider
if (!target.AttemptSurgery(_surgeryType, _bodyCache, this, _performerCache))
if (!target.AttemptSurgery(_surgeryType, BodyCache, this, PerformerCache))
{
NotUsefulAnymorePopup();
}
@@ -233,8 +252,8 @@ namespace Content.Server.GameObjects.Components.Body.Surgery
{
// TODO: sanity checks to see whether user is in range, user is still able-bodied, target is still the same, etc etc
if (!_optionsCache.TryGetValue(key, out var targetObject) ||
_performerCache == null ||
!_performerCache.TryGetComponent(out IActorComponent? actor))
PerformerCache == null ||
!PerformerCache.TryGetComponent(out IActorComponent? actor))
{
NotUsefulAnymorePopup();
return;
@@ -243,27 +262,19 @@ namespace Content.Server.GameObjects.Components.Body.Surgery
var target = targetObject as MechanismComponent;
CloseSurgeryUI(actor.playerSession);
_callbackCache?.Invoke(target, _bodyCache, this, _performerCache);
_callbackCache?.Invoke(target, BodyCache, this, PerformerCache);
}
private void NotUsefulPopup()
{
_bodyCache?.Owner.PopupMessage(_performerCache,
BodyCache?.Owner.PopupMessage(PerformerCache,
Loc.GetString("You see no useful way to use {0:theName}.", Owner));
}
private void NotUsefulAnymorePopup()
{
_bodyCache?.Owner.PopupMessage(_performerCache,
BodyCache?.Owner.PopupMessage(PerformerCache,
Loc.GetString("You see no useful way to use {0:theName} anymore.", Owner));
}
public override void ExposeData(ObjectSerializer serializer)
{
base.ExposeData(serializer);
serializer.DataField(ref _surgeryType, "surgeryType", SurgeryType.Incision);
serializer.DataField(ref _baseOperateTime, "baseOperateTime", 5);
}
}
}

View File

@@ -1,5 +1,6 @@
using System.Threading.Tasks;
using Content.Shared.GameObjects.EntitySystems;
using Content.Shared.GameObjects.EntitySystems.ActionBlocker;
using Content.Shared.Interfaces.GameObjects.Components;
using Content.Shared.Utility;
using Robust.Shared.GameObjects;

View File

@@ -13,6 +13,7 @@ using Content.Shared.Audio;
using Content.Shared.Chemistry;
using Content.Shared.GameObjects.Components.Botany;
using Content.Shared.GameObjects.EntitySystems;
using Content.Shared.GameObjects.EntitySystems.ActionBlocker;
using Content.Shared.Interfaces;
using Content.Shared.Interfaces.GameObjects.Components;
using Content.Shared.Utility;

View File

@@ -9,9 +9,9 @@ using Content.Server.GameObjects.Components.Strap;
using Content.Server.GameObjects.EntitySystems;
using Content.Shared.Alert;
using Content.Shared.GameObjects.Components.Buckle;
using Content.Shared.GameObjects.Components.Mobs;
using Content.Shared.GameObjects.Components.Strap;
using Content.Shared.GameObjects.EntitySystems;
using Content.Shared.GameObjects.EntitySystems.ActionBlocker;
using Content.Shared.GameObjects.Verbs;
using Content.Shared.Interfaces;
using Content.Shared.Interfaces.GameObjects.Components;
@@ -49,7 +49,6 @@ namespace Content.Server.GameObjects.Components.Buckle
/// </summary>
[ViewVariables]
private float _range;
/// <summary>
/// The amount of time that must pass for this entity to
/// be able to unbuckle after recently buckling.
@@ -70,6 +69,7 @@ namespace Content.Server.GameObjects.Components.Buckle
private StrapComponent? _buckledTo;
/// <summary>
/// The strap that this component is buckled to.
/// </summary>
@@ -156,7 +156,7 @@ namespace Content.Server.GameObjects.Components.Buckle
}
}
private bool CanBuckle(IEntity? user, IEntity to, [MaybeNullWhen(false)] out StrapComponent strap)
private bool CanBuckle(IEntity? user, IEntity to, [NotNullWhen(true)] out StrapComponent? strap)
{
strap = null;
@@ -266,6 +266,8 @@ namespace Content.Server.GameObjects.Components.Buckle
AppearanceComponent?.SetData(BuckleVisuals.Buckled, true);
BuckledTo = strap;
LastEntityBuckledTo = BuckledTo.Owner.Uid;
DontCollide = true;
ReAttach(strap);
UpdateBuckleStatus();
@@ -419,7 +421,8 @@ namespace Content.Server.GameObjects.Components.Buckle
drawDepth = BuckledTo.SpriteComponent.DrawDepth - 1;
}
return new BuckleComponentState(Buckled, drawDepth);
return new BuckleComponentState(Buckled, drawDepth, LastEntityBuckledTo, DontCollide);
}
bool IInteractHand.InteractHand(InteractHandEventArgs eventArgs)
@@ -427,6 +430,24 @@ namespace Content.Server.GameObjects.Components.Buckle
return TryUnbuckle(eventArgs.User);
}
public void Update()
{
if (!DontCollide || Body == null)
return;
Body.WakeBody();
if (!IsOnStrapEntityThisFrame && DontCollide)
{
DontCollide = false;
TryUnbuckle(Owner);
Dirty();
}
IsOnStrapEntityThisFrame = false;
}
/// <summary>
/// Allows the unbuckling of the owning entity through a verb if
/// anyone right clicks them.

View File

@@ -1,4 +1,4 @@
#nullable enable
#nullable enable
using Content.Server.Cargo;
using Content.Server.GameObjects.Components.Power.ApcNetComponents;
using Content.Server.GameObjects.EntitySystems;
@@ -10,10 +10,15 @@ using Robust.Server.GameObjects.Components.UserInterface;
using Robust.Server.Interfaces.GameObjects;
using Robust.Shared.GameObjects;
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.Maths;
using Robust.Shared.Serialization;
using Robust.Shared.ViewVariables;
using System.Collections.Generic;
using System.Linq;
namespace Content.Server.GameObjects.Components.Cargo
{
@@ -22,6 +27,7 @@ namespace Content.Server.GameObjects.Components.Cargo
public class CargoConsoleComponent : SharedCargoConsoleComponent, IActivate
{
[Dependency] private readonly ICargoOrderDataManager _cargoOrderDataManager = default!;
[Dependency] private readonly IMapManager _mapManager = default!;
[ViewVariables]
public int Points = 1000;
@@ -113,59 +119,88 @@ namespace Content.Server.GameObjects.Components.Cargo
switch (message)
{
case CargoConsoleAddOrderMessage msg:
{
if (msg.Amount <= 0 || _bankAccount == null)
{
break;
}
_cargoOrderDataManager.AddOrder(orders.Database.Id, msg.Requester, msg.Reason, msg.ProductId, msg.Amount, _bankAccount.Id);
break;
}
case CargoConsoleRemoveOrderMessage msg:
{
_cargoOrderDataManager.RemoveOrder(orders.Database.Id, msg.OrderNumber);
break;
}
case CargoConsoleApproveOrderMessage msg:
{
if (_requestOnly ||
!orders.Database.TryGetOrder(msg.OrderNumber, out var order) ||
_bankAccount == null)
{
break;
}
PrototypeManager.TryIndex(order.ProductId, out CargoProductPrototype product);
if (product == null!)
break;
var capacity = _cargoOrderDataManager.GetCapacity(orders.Database.Id);
if (capacity.CurrentCapacity == capacity.MaxCapacity)
break;
if (!_cargoConsoleSystem.ChangeBalance(_bankAccount.Id, (-product.PointCost) * order.Amount))
break;
_cargoOrderDataManager.ApproveOrder(orders.Database.Id, msg.OrderNumber);
UpdateUIState();
break;
}
case CargoConsoleShuttleMessage _:
{
var approvedOrders = _cargoOrderDataManager.RemoveAndGetApprovedFrom(orders.Database);
orders.Database.ClearOrderCapacity();
// TODO replace with shuttle code
// TEMPORARY loop for spawning stuff on top of console
foreach (var order in approvedOrders)
{
if (!PrototypeManager.TryIndex(order.ProductId, out CargoProductPrototype product))
continue;
for (var i = 0; i < order.Amount; i++)
if (msg.Amount <= 0 || _bankAccount == null)
{
Owner.EntityManager.SpawnEntity(product.Product, Owner.Transform.Coordinates);
break;
}
_cargoOrderDataManager.AddOrder(orders.Database.Id, msg.Requester, msg.Reason, msg.ProductId, msg.Amount, _bankAccount.Id);
break;
}
case CargoConsoleRemoveOrderMessage msg:
{
_cargoOrderDataManager.RemoveOrder(orders.Database.Id, msg.OrderNumber);
break;
}
case CargoConsoleApproveOrderMessage msg:
{
if (_requestOnly ||
!orders.Database.TryGetOrder(msg.OrderNumber, out var order) ||
_bankAccount == null)
{
break;
}
PrototypeManager.TryIndex(order.ProductId, out CargoProductPrototype product);
if (product == null!)
break;
var capacity = _cargoOrderDataManager.GetCapacity(orders.Database.Id);
if (capacity.CurrentCapacity == capacity.MaxCapacity)
break;
if (!_cargoConsoleSystem.ChangeBalance(_bankAccount.Id, (-product.PointCost) * order.Amount))
break;
_cargoOrderDataManager.ApproveOrder(orders.Database.Id, msg.OrderNumber);
UpdateUIState();
break;
}
case CargoConsoleShuttleMessage _:
{
//var approvedOrders = _cargoOrderDataManager.RemoveAndGetApprovedFrom(orders.Database);
//orders.Database.ClearOrderCapacity();
// TODO replace with shuttle code
// TEMPORARY loop for spawning stuff on telepad (looks for a telepad adjacent to the console)
IEntity? cargoTelepad = null;
var indices = Owner.Transform.Coordinates.ToVector2i(Owner.EntityManager, _mapManager);
var offsets = new Vector2i[] { new Vector2i(0, 1), new Vector2i(1, 1), new Vector2i(1, 0), new Vector2i(1, -1),
new Vector2i(0, -1), new Vector2i(-1, -1), new Vector2i(-1, 0), new Vector2i(-1, 1), };
var adjacentEntities = new List<IEnumerable<IEntity>>(); //Probably better than IEnumerable.concat
foreach (var offset in offsets)
{
adjacentEntities.Add((indices+offset).GetEntitiesInTileFast(Owner.Transform.GridID));
}
foreach (var enumerator in adjacentEntities)
{
foreach (IEntity entity in enumerator)
{
if (entity.HasComponent<CargoTelepadComponent>() && entity.TryGetComponent<PowerReceiverComponent>(out var powerReceiver) && powerReceiver.Powered)
{
cargoTelepad = entity;
break;
}
}
}
if (cargoTelepad != null)
{
if (cargoTelepad.TryGetComponent<CargoTelepadComponent>(out var telepadComponent))
{
var approvedOrders = _cargoOrderDataManager.RemoveAndGetApprovedFrom(orders.Database);
orders.Database.ClearOrderCapacity();
foreach (var order in approvedOrders)
{
if (!PrototypeManager.TryIndex(order.ProductId, out CargoProductPrototype product))
continue;
for (var i = 0; i < order.Amount; i++)
{
telepadComponent.QueueTeleport(product);
}
}
}
}
break;
}
break;
}
}
}

View File

@@ -0,0 +1,101 @@
#nullable enable
using Content.Server.GameObjects.Components.Power.ApcNetComponents;
using Content.Shared.Interfaces.GameObjects.Components;
using Content.Shared.Prototypes.Cargo;
using Robust.Server.GameObjects;
using Robust.Server.GameObjects.EntitySystems;
using Robust.Shared.Audio;
using Robust.Shared.GameObjects;
using Robust.Shared.GameObjects.Components.Timers;
using Robust.Shared.GameObjects.Systems;
using System.Collections.Generic;
namespace Content.Server.GameObjects.Components.Cargo
{
//This entire class is a PLACEHOLDER for the cargo shuttle.
[RegisterComponent]
public class CargoTelepadComponent : Component
{
public override string Name => "CargoTelepad";
private const float TeleportDuration = 0.5f;
private const float TeleportDelay = 15f;
private List<CargoProductPrototype> _teleportQueue = new List<CargoProductPrototype>();
private CargoTelepadState _currentState = CargoTelepadState.Unpowered;
public override void OnAdd()
{
base.OnAdd();
var receiver = Owner.EnsureComponent<PowerReceiverComponent>();
receiver.OnPowerStateChanged += PowerUpdate;
}
public override void OnRemove()
{
if (Owner.TryGetComponent(out PowerReceiverComponent? receiver))
{
receiver.OnPowerStateChanged -= PowerUpdate;
}
base.OnRemove();
}
public void QueueTeleport(CargoProductPrototype product)
{
_teleportQueue.Add(product);
TeleportLoop();
}
private void PowerUpdate(object? sender, PowerStateEventArgs args)
{
if (args.Powered && _currentState == CargoTelepadState.Unpowered) {
_currentState = CargoTelepadState.Idle;
if(Owner.TryGetComponent<SpriteComponent>(out var spriteComponent))
spriteComponent.LayerSetState(0, "pad-idle");
TeleportLoop();
}
else if (!args.Powered)
{
_currentState = CargoTelepadState.Unpowered;
if (Owner.TryGetComponent<SpriteComponent>(out var spriteComponent))
spriteComponent.LayerSetState(0, "pad-offline");
}
}
private void TeleportLoop()
{
if (_currentState == CargoTelepadState.Idle && _teleportQueue.Count > 0)
{
_currentState = CargoTelepadState.Charging;
if (Owner.TryGetComponent<SpriteComponent>(out var spriteComponent))
spriteComponent.LayerSetState(0, "pad-idle");
Owner.SpawnTimer((int) (TeleportDelay * 1000), () =>
{
if (!Deleted && !Owner.Deleted && _currentState == CargoTelepadState.Charging && _teleportQueue.Count > 0)
{
_currentState = CargoTelepadState.Teleporting;
if (Owner.TryGetComponent<SpriteComponent>(out var spriteComponent))
spriteComponent.LayerSetState(0, "pad-beam");
Owner.SpawnTimer((int) (TeleportDuration * 1000), () =>
{
if (!Deleted && !Owner.Deleted && _currentState == CargoTelepadState.Teleporting && _teleportQueue.Count > 0)
{
EntitySystem.Get<AudioSystem>().PlayFromEntity("/Audio/machines/phasein.ogg", Owner, AudioParams.Default.WithVolume(-8f));
Owner.EntityManager.SpawnEntity(_teleportQueue[0].Product, Owner.Transform.Coordinates);
_teleportQueue.RemoveAt(0);
if (Owner.TryGetComponent<SpriteComponent>(out var spriteComponent))
spriteComponent.LayerSetState(0, "pad-idle");
_currentState = CargoTelepadState.Idle;
TeleportLoop();
}
});
}
});
}
}
private enum CargoTelepadState { Unpowered, Idle, Charging, Teleporting };
}
}

View File

@@ -12,6 +12,7 @@ using Content.Server.Utility;
using Content.Shared.Chemistry;
using Content.Shared.GameObjects.Components.Chemistry.ChemMaster;
using Content.Shared.GameObjects.EntitySystems;
using Content.Shared.GameObjects.EntitySystems.ActionBlocker;
using Content.Shared.Interfaces;
using Content.Shared.Interfaces.GameObjects.Components;
using Content.Shared.Utility;

View File

@@ -11,6 +11,7 @@ using Content.Server.Utility;
using Content.Shared.Chemistry;
using Content.Shared.GameObjects.Components.Chemistry.ReagentDispenser;
using Content.Shared.GameObjects.EntitySystems;
using Content.Shared.GameObjects.EntitySystems.ActionBlocker;
using Content.Shared.Interfaces;
using Content.Shared.Interfaces.GameObjects.Components;
using Content.Shared.GameObjects.Verbs;

View File

@@ -6,6 +6,7 @@ using Content.Server.GameObjects.EntitySystems;
using Content.Shared.Chemistry;
using Content.Shared.GameObjects.Components.Chemistry;
using Content.Shared.GameObjects.EntitySystems;
using Content.Shared.GameObjects.EntitySystems.ActionBlocker;
using Content.Shared.GameObjects.Verbs;
using Content.Shared.Utility;
using Robust.Server.GameObjects;

View File

@@ -1,4 +1,4 @@
#nullable enable
#nullable enable
using Content.Server.GameObjects.Components.Power.ApcNetComponents;
using Content.Server.GameObjects.EntitySystems;
using Content.Server.Utility;
@@ -77,11 +77,12 @@ namespace Content.Server.GameObjects.Components.Command
{
if (!eventArgs.User.TryGetComponent(out IActorComponent? actor))
return;
/*
if (!Powered)
{
return;
}
*/
OpenUserInterface(actor.playerSession);
}
}

View File

@@ -1,4 +1,5 @@
using Content.Shared.GameObjects.EntitySystems;
using Content.Shared.GameObjects.EntitySystems.ActionBlocker;
using Content.Shared.GameObjects.Verbs;
using Content.Shared.Interfaces;
using Robust.Shared.GameObjects;

View File

@@ -1,4 +1,4 @@
#nullable enable
#nullable enable
using System.Threading.Tasks;
using Content.Server.GameObjects.Components.Interactable;
using Content.Server.GameObjects.Components.Items.Storage;
@@ -28,6 +28,8 @@ namespace Content.Server.GameObjects.Components.Conveyor
{
public override string Name => "Conveyor";
[ViewVariables] private bool Powered => !Owner.TryGetComponent(out PowerReceiverComponent? receiver) || receiver.Powered;
/// <summary>
/// The angle to move entities by in relation to the owner's rotation.
/// </summary>
@@ -41,7 +43,6 @@ namespace Content.Server.GameObjects.Components.Conveyor
private float _speed;
private ConveyorState _state;
/// <summary>
/// The current state of this conveyor
/// </summary>
@@ -52,13 +53,45 @@ namespace Content.Server.GameObjects.Components.Conveyor
set
{
_state = value;
UpdateAppearance();
}
}
if (!Owner.TryGetComponent(out AppearanceComponent? appearance))
public override void OnAdd()
{
base.OnAdd();
if (Owner.TryGetComponent(out PowerReceiverComponent? receiver))
{
receiver.OnPowerStateChanged += OnPowerChanged;
}
}
public override void OnRemove()
{
base.OnRemove();
if (Owner.TryGetComponent(out PowerReceiverComponent? receiver))
{
receiver.OnPowerStateChanged -= OnPowerChanged;
}
}
private void OnPowerChanged(object? sender, PowerStateEventArgs e)
{
UpdateAppearance();
}
private void UpdateAppearance()
{
if (Owner.TryGetComponent<AppearanceComponent>(out var appearance))
{
if (Powered)
{
return;
appearance.SetData(ConveyorVisuals.State, _state);
}
else
{
appearance.SetData(ConveyorVisuals.State, ConveyorState.Off);
}
appearance.SetData(ConveyorVisuals.State, value);
}
}

View File

@@ -17,6 +17,7 @@ using Content.Shared.GameObjects.Components;
using Content.Shared.GameObjects.Components.Body;
using Content.Shared.GameObjects.Components.Disposal;
using Content.Shared.GameObjects.EntitySystems;
using Content.Shared.GameObjects.EntitySystems.ActionBlocker;
using Content.Shared.GameObjects.Verbs;
using Content.Shared.Interfaces;
using Content.Shared.Interfaces.GameObjects.Components;

View File

@@ -6,6 +6,7 @@ using Content.Server.GameObjects.Components.Mobs;
using Content.Server.Interfaces.GameObjects.Components.Items;
using Content.Server.Utility;
using Content.Shared.GameObjects.EntitySystems;
using Content.Shared.GameObjects.EntitySystems.ActionBlocker;
using Content.Shared.GameObjects.Verbs;
using Content.Shared.Interfaces;
using Content.Shared.Interfaces.GameObjects.Components;

View File

@@ -21,6 +21,7 @@ using Robust.Shared.Localization;
using Robust.Shared.Maths;
using Robust.Shared.ViewVariables;
using System;
using Content.Shared.GameObjects.EntitySystems.ActionBlocker;
using static Content.Shared.GameObjects.Components.Disposal.SharedDisposalTaggerComponent;
namespace Content.Server.GameObjects.Components.Disposal

View File

@@ -20,6 +20,7 @@ using Content.Shared.GameObjects.Components.Disposal;
using Content.Shared.GameObjects.Components.Items;
using Content.Shared.GameObjects.Components.Mobs.State;
using Content.Shared.GameObjects.EntitySystems;
using Content.Shared.GameObjects.EntitySystems.ActionBlocker;
using Content.Shared.GameObjects.Verbs;
using Content.Shared.Interfaces;
using Content.Shared.Interfaces.GameObjects.Components;

View File

@@ -1,6 +1,7 @@
using Content.Server.GameObjects.Components.Chemistry;
using Content.Shared.Chemistry;
using Content.Shared.GameObjects.EntitySystems;
using Content.Shared.GameObjects.EntitySystems.ActionBlocker;
using Content.Shared.GameObjects.Verbs;
using Content.Shared.Interfaces;
using Robust.Shared.GameObjects;

View File

@@ -7,6 +7,7 @@ using Content.Shared.GameObjects.Components;
using Content.Shared.GameObjects.Components.Fluids;
using Content.Shared.GameObjects.Components.Items;
using Content.Shared.GameObjects.EntitySystems;
using Content.Shared.GameObjects.EntitySystems.ActionBlocker;
using Content.Shared.Interfaces;
using Content.Shared.Interfaces.GameObjects.Components;
using Robust.Server.GameObjects;

View File

@@ -9,6 +9,7 @@ using Content.Server.Interfaces.GameObjects.Components.Items;
using Content.Shared.GameObjects.Components.Body.Part;
using Content.Shared.GameObjects.Components.Items;
using Content.Shared.GameObjects.EntitySystems;
using Content.Shared.GameObjects.EntitySystems.ActionBlocker;
using Content.Shared.Physics.Pull;
using Robust.Server.GameObjects;
using Robust.Server.GameObjects.Components.Container;
@@ -105,10 +106,9 @@ namespace Content.Server.GameObjects.Components.GUI
return GetHand(handName)?.Entity?.GetComponent<ItemComponent>();
}
public bool TryGetItem(string handName, [MaybeNullWhen(false)] out ItemComponent item)
public bool TryGetItem(string handName, [NotNullWhen(true)] out ItemComponent? item)
{
item = GetItem(handName);
return item != null;
return (item = GetItem(handName)) != null;
}
public ItemComponent? GetActiveHand => ActiveHand == null
@@ -240,7 +240,7 @@ namespace Content.Server.GameObjects.Components.GUI
return true;
}
public bool TryHand(IEntity entity, [MaybeNullWhen(false)] out string handName)
public bool TryHand(IEntity entity, [NotNullWhen(true)] out string? handName)
{
handName = null;

View File

@@ -7,6 +7,8 @@ using Content.Server.GameObjects.EntitySystems.Click;
using Content.Server.Interfaces.GameObjects;
using Content.Shared.GameObjects.Components.Inventory;
using Content.Shared.GameObjects.EntitySystems;
using Content.Shared.GameObjects.EntitySystems.ActionBlocker;
using Content.Shared.GameObjects.EntitySystems.EffectBlocker;
using Content.Shared.Interfaces;
using Robust.Server.GameObjects.Components.Container;
using Robust.Shared.Containers;

View File

@@ -7,6 +7,7 @@ using Content.Server.GameObjects.EntitySystems.DoAfter;
using Content.Server.Utility;
using Content.Shared.GameObjects.Components.GUI;
using Content.Shared.GameObjects.EntitySystems;
using Content.Shared.GameObjects.EntitySystems.ActionBlocker;
using Content.Shared.GameObjects.Verbs;
using Content.Shared.Interfaces;
using Content.Shared.Interfaces.GameObjects.Components;

View File

@@ -7,6 +7,7 @@ using Content.Server.Utility;
using Content.Shared;
using Content.Shared.GameObjects.Components.Instruments;
using Content.Shared.GameObjects.EntitySystems;
using Content.Shared.GameObjects.EntitySystems.ActionBlocker;
using Content.Shared.Interfaces;
using Content.Shared.Interfaces.GameObjects.Components;
using Robust.Server.GameObjects;
@@ -78,8 +79,8 @@ namespace Content.Server.GameObjects.Components.Instruments
private byte _instrumentBank;
private bool _allowPercussion;
private bool _allowProgramChange;
private bool _respectMidiLimits;
[ViewVariables(VVAccess.ReadWrite)]
public override byte InstrumentProgram { get => _instrumentProgram;
set
{
@@ -88,7 +89,6 @@ namespace Content.Server.GameObjects.Components.Instruments
}
}
[ViewVariables(VVAccess.ReadWrite)]
public override byte InstrumentBank { get => _instrumentBank;
set
{
@@ -97,7 +97,6 @@ namespace Content.Server.GameObjects.Components.Instruments
}
}
[ViewVariables(VVAccess.ReadWrite)]
public override bool AllowPercussion { get => _allowPercussion;
set
{
@@ -106,7 +105,6 @@ namespace Content.Server.GameObjects.Components.Instruments
}
}
[ViewVariables(VVAccess.ReadWrite)]
public override bool AllowProgramChange { get => _allowProgramChange;
set
{
@@ -115,6 +113,14 @@ namespace Content.Server.GameObjects.Components.Instruments
}
}
public override bool RespectMidiLimits { get => _respectMidiLimits;
set
{
_respectMidiLimits = value;
Dirty();
}
}
/// <summary>
/// Whether the instrument is an item which can be held or not.
/// </summary>
@@ -181,11 +187,12 @@ namespace Content.Server.GameObjects.Components.Instruments
serializer.DataField(ref _instrumentBank, "bank", (byte) 0);
serializer.DataField(ref _allowPercussion, "allowPercussion", false);
serializer.DataField(ref _allowProgramChange, "allowProgramChange", false);
serializer.DataField(ref _respectMidiLimits, "respectMidiLimits", true);
}
public override ComponentState GetComponentState()
{
return new InstrumentState(Playing, InstrumentProgram, InstrumentBank, AllowPercussion, AllowProgramChange, _lastSequencerTick);
return new InstrumentState(Playing, InstrumentProgram, InstrumentBank, AllowPercussion, AllowProgramChange, RespectMidiLimits, _lastSequencerTick);
}
public override void HandleNetworkMessage(ComponentMessage message, INetChannel channel, ICommonSession? session = null)
@@ -217,14 +224,17 @@ namespace Content.Server.GameObjects.Components.Instruments
_laggedBatches++;
if (_laggedBatches == (int) (maxMidiLaggedBatches * (1 / 3d) + 1))
if (_respectMidiLimits)
{
Owner.PopupMessage(InstrumentPlayer.AttachedEntity,
Loc.GetString("Your fingers are beginning to a cramp a little!"));
} else if (_laggedBatches == (int) (maxMidiLaggedBatches * (2 / 3d) + 1))
{
Owner.PopupMessage(InstrumentPlayer.AttachedEntity,
Loc.GetString("Your fingers are seriously cramping up!"));
if (_laggedBatches == (int) (maxMidiLaggedBatches * (1 / 3d) + 1))
{
Owner.PopupMessage(InstrumentPlayer.AttachedEntity,
Loc.GetString("Your fingers are beginning to a cramp a little!"));
} else if (_laggedBatches == (int) (maxMidiLaggedBatches * (2 / 3d) + 1))
{
Owner.PopupMessage(InstrumentPlayer.AttachedEntity,
Loc.GetString("Your fingers are seriously cramping up!"));
}
}
if (_laggedBatches > maxMidiLaggedBatches)
@@ -250,7 +260,7 @@ namespace Content.Server.GameObjects.Components.Instruments
send = false;
}
if (send)
if (send || !_respectMidiLimits)
{
SendNetworkMessage(midiEventMsg);
}
@@ -367,7 +377,7 @@ namespace Content.Server.GameObjects.Components.Instruments
if ((_batchesDropped >= maxMidiBatchDropped
|| _laggedBatches >= maxMidiLaggedBatches)
&& InstrumentPlayer != null)
&& InstrumentPlayer != null && _respectMidiLimits)
{
var mob = InstrumentPlayer.AttachedEntity;

View File

@@ -4,6 +4,7 @@ using Content.Server.GameObjects.Components.Items.Storage;
using Content.Server.GameObjects.Components.Sound;
using Content.Shared.GameObjects.Components;
using Content.Shared.GameObjects.EntitySystems;
using Content.Shared.GameObjects.EntitySystems.ActionBlocker;
using Content.Shared.GameObjects.Verbs;
using Content.Shared.Interfaces.GameObjects.Components;
using Robust.Server.GameObjects;

View File

@@ -11,6 +11,7 @@ using Content.Server.GameObjects.Components.Weapon.Ranged.Barrels;
using Content.Shared.GameObjects.Components;
using Content.Shared.GameObjects.Components.Mobs;
using Content.Shared.GameObjects.EntitySystems;
using Content.Shared.GameObjects.EntitySystems.ActionBlocker;
using Content.Shared.GameObjects.Verbs;
using Content.Shared.Interfaces;
using Content.Shared.Interfaces.GameObjects.Components;

View File

@@ -5,6 +5,7 @@ using Content.Server.GameObjects.EntitySystems.DoAfter;
using Content.Shared.Audio;
using Content.Shared.GameObjects.Components.Interactable;
using Content.Shared.GameObjects.EntitySystems;
using Content.Shared.GameObjects.EntitySystems.ActionBlocker;
using Robust.Server.GameObjects.EntitySystems;
using Robust.Shared.GameObjects;
using Robust.Shared.GameObjects.Systems;

View File

@@ -9,6 +9,7 @@ using Content.Shared.GameObjects.Components.Body;
using Content.Shared.GameObjects.Components.Interactable;
using Content.Shared.GameObjects.Components.Storage;
using Content.Shared.GameObjects.EntitySystems;
using Content.Shared.GameObjects.EntitySystems.ActionBlocker;
using Content.Shared.GameObjects.Verbs;
using Content.Shared.Interfaces;
using Content.Shared.Interfaces.GameObjects.Components;

View File

@@ -5,6 +5,7 @@ using Content.Shared.GameObjects;
using Content.Shared.GameObjects.Components.Items;
using Content.Shared.GameObjects.Components.Storage;
using Content.Shared.GameObjects.EntitySystems;
using Content.Shared.GameObjects.EntitySystems.ActionBlocker;
using Content.Shared.GameObjects.Verbs;
using Content.Shared.Interfaces.GameObjects.Components;
using Content.Shared.Utility;

View File

@@ -1,6 +1,7 @@
using Content.Server.GameObjects.Components.Access;
using Content.Shared.GameObjects.Components.Storage;
using Content.Shared.GameObjects.EntitySystems;
using Content.Shared.GameObjects.EntitySystems.ActionBlocker;
using Content.Shared.GameObjects.Verbs;
using Content.Shared.Interfaces;
using Content.Shared.Interfaces.GameObjects.Components;

View File

@@ -1,4 +1,5 @@
using Content.Shared.GameObjects.EntitySystems;
using Content.Shared.GameObjects.EntitySystems.ActionBlocker;
using Content.Shared.GameObjects.Verbs;
using Content.Shared.Interfaces;
using Content.Shared.Interfaces.GameObjects.Components;

View File

@@ -4,6 +4,7 @@ using Content.Server.GameObjects.Components.Stack;
using Content.Shared.Damage;
using Content.Shared.GameObjects.Components.Damage;
using Content.Shared.GameObjects.EntitySystems;
using Content.Shared.GameObjects.EntitySystems.ActionBlocker;
using Content.Shared.Interfaces.GameObjects.Components;
using Content.Shared.Utility;
using Robust.Shared.GameObjects;

View File

@@ -13,6 +13,7 @@ using Content.Shared.GameObjects.Components.Damage;
using Content.Shared.GameObjects.Components.Medical;
using Content.Shared.GameObjects.Components.Mobs.State;
using Content.Shared.GameObjects.EntitySystems;
using Content.Shared.GameObjects.EntitySystems.ActionBlocker;
using Content.Shared.GameObjects.Verbs;
using Content.Shared.Interfaces.GameObjects.Components;
using Robust.Server.GameObjects;

View File

@@ -14,6 +14,7 @@ using Content.Shared.GameObjects.Components.Body.Mechanism;
using Content.Shared.GameObjects.Components.Damage;
using Content.Shared.GameObjects.Components.Mobs.State;
using Content.Shared.GameObjects.EntitySystems;
using Content.Shared.GameObjects.EntitySystems.ActionBlocker;
using Content.Shared.Interfaces;
using Content.Shared.Interfaces.Chemistry;
using Robust.Shared.GameObjects;

View File

@@ -3,6 +3,7 @@ using System;
using Content.Shared.Actions;
using Content.Shared.GameObjects.Components.Mobs;
using Content.Shared.GameObjects.EntitySystems;
using Content.Shared.GameObjects.EntitySystems.ActionBlocker;
using Robust.Server.Interfaces.GameObjects;
using Robust.Shared.GameObjects;
using Robust.Shared.Interfaces.GameObjects;

View File

@@ -20,6 +20,7 @@ using Robust.Shared.Localization;
using Robust.Shared.Utility;
using Robust.Shared.ViewVariables;
using System.Threading.Tasks;
using Content.Shared.GameObjects.EntitySystems.ActionBlocker;
namespace Content.Server.GameObjects.Components.Morgue
{

View File

@@ -2,6 +2,7 @@
using Content.Server.GameObjects.Components.Items.Storage;
using Content.Shared.GameObjects.Components.Morgue;
using Content.Shared.GameObjects.EntitySystems;
using Content.Shared.GameObjects.EntitySystems.ActionBlocker;
using Content.Shared.GameObjects.Verbs;
using Content.Shared.Interfaces;
using Content.Shared.Interfaces.GameObjects.Components;

View File

@@ -6,6 +6,7 @@ using Content.Shared.GameObjects.Components.Body;
using Content.Shared.GameObjects.Components.Body.Part;
using Content.Shared.GameObjects.Components.Movement;
using Content.Shared.GameObjects.EntitySystems;
using Content.Shared.GameObjects.EntitySystems.ActionBlocker;
using Content.Shared.GameObjects.Verbs;
using Content.Shared.Interfaces;
using Content.Shared.Interfaces.GameObjects.Components;

View File

@@ -1,4 +1,5 @@
using Content.Shared.GameObjects.EntitySystems;
using Content.Shared.GameObjects.EntitySystems.EffectBlocker;
using Robust.Shared.GameObjects;
namespace Content.Server.GameObjects.Components.Movement

View File

@@ -10,6 +10,7 @@ using Content.Server.GameObjects.Components.VendingMachines;
using Content.Server.Utility;
using Content.Shared.GameObjects.Components;
using Content.Shared.GameObjects.EntitySystems;
using Content.Shared.GameObjects.EntitySystems.ActionBlocker;
using Content.Shared.Interfaces.GameObjects.Components;
using Robust.Server.GameObjects;
using Robust.Server.GameObjects.Components.UserInterface;

View File

@@ -14,6 +14,7 @@ using Content.Server.Interfaces.PDA;
using Content.Server.Utility;
using Content.Shared.GameObjects.Components.PDA;
using Content.Shared.GameObjects.EntitySystems;
using Content.Shared.GameObjects.EntitySystems.ActionBlocker;
using Content.Shared.GameObjects.Verbs;
using Content.Shared.Interfaces;
using Content.Shared.Interfaces.GameObjects.Components;

View File

@@ -11,6 +11,7 @@ using Content.Server.Interfaces.GameObjects.Components.Items;
using Content.Server.Utility;
using Content.Shared.GameObjects.Components.Power.AME;
using Content.Shared.GameObjects.EntitySystems;
using Content.Shared.GameObjects.EntitySystems.ActionBlocker;
using Content.Shared.Interfaces;
using Content.Shared.Interfaces.GameObjects.Components;
using Robust.Server.GameObjects;

View File

@@ -6,6 +6,7 @@ using Content.Server.GameObjects.Components.Items.Storage;
using Content.Server.GameObjects.Components.Weapon.Ranged.Barrels;
using Content.Shared.GameObjects.Components.Power;
using Content.Shared.GameObjects.EntitySystems;
using Content.Shared.GameObjects.EntitySystems.ActionBlocker;
using Content.Shared.GameObjects.Verbs;
using Content.Shared.Interfaces;
using Content.Shared.Interfaces.GameObjects.Components;

View File

@@ -4,6 +4,7 @@ using Content.Server.GameObjects.Components.GUI;
using Content.Server.GameObjects.Components.Items.Storage;
using Content.Shared.Audio;
using Content.Shared.GameObjects.EntitySystems;
using Content.Shared.GameObjects.EntitySystems.ActionBlocker;
using Content.Shared.GameObjects.Verbs;
using Robust.Server.GameObjects.Components.Container;
using Robust.Server.GameObjects.EntitySystems;

View File

@@ -1,4 +1,5 @@
using System.Collections.Generic;
#nullable enable
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using Content.Server.GameObjects.Components.Conveyor;
using Content.Server.GameObjects.Components.Items.Storage;
@@ -40,12 +41,12 @@ namespace Content.Server.GameObjects.Components.Recycling
private int _efficiency; // TODO
private bool Powered =>
!Owner.TryGetComponent(out PowerReceiverComponent receiver) ||
!Owner.TryGetComponent(out PowerReceiverComponent? receiver) ||
receiver.Powered;
private void Bloodstain()
{
if (Owner.TryGetComponent(out AppearanceComponent appearance))
if (Owner.TryGetComponent(out AppearanceComponent? appearance))
{
appearance.SetData(RecyclerVisuals.Bloody, true);
}
@@ -53,7 +54,7 @@ namespace Content.Server.GameObjects.Components.Recycling
private void Clean()
{
if (Owner.TryGetComponent(out AppearanceComponent appearance))
if (Owner.TryGetComponent(out AppearanceComponent? appearance))
{
appearance.SetData(RecyclerVisuals.Bloody, false);
}
@@ -64,7 +65,7 @@ namespace Content.Server.GameObjects.Components.Recycling
return entity.HasComponent<IBody>() && !_safe && Powered;
}
private bool CanRecycle(IEntity entity, [MaybeNullWhen(false)] out ConstructionPrototype prototype)
private bool CanRecycle(IEntity entity, [NotNullWhen(true)] out ConstructionPrototype? prototype)
{
prototype = null;
@@ -100,7 +101,7 @@ namespace Content.Server.GameObjects.Components.Recycling
private bool CanRun()
{
if (Owner.TryGetComponent(out PowerReceiverComponent receiver) &&
if (Owner.TryGetComponent(out PowerReceiverComponent? receiver) &&
!receiver.Powered)
{
return false;
@@ -121,7 +122,7 @@ namespace Content.Server.GameObjects.Components.Recycling
return false;
}
if (!entity.TryGetComponent(out IPhysicsComponent physics) ||
if (!entity.TryGetComponent(out IPhysicsComponent? physics) ||
physics.Anchored)
{
return false;
@@ -165,7 +166,7 @@ namespace Content.Server.GameObjects.Components.Recycling
continue;
}
if (entity.TryGetComponent(out IPhysicsComponent physics))
if (entity.TryGetComponent(out IPhysicsComponent? physics))
{
var controller = physics.EnsureController<ConveyedController>();
controller.Move(direction, frameTime, entity.Transform.WorldPosition - Owner.Transform.WorldPosition);

View File

@@ -1,5 +1,6 @@
#nullable enable
using Content.Shared.GameObjects.EntitySystems;
using Content.Shared.GameObjects.EntitySystems.ActionBlocker;
using Content.Shared.GameObjects.Verbs;
using Content.Shared.Interfaces;
using Robust.Shared.GameObjects;

View File

@@ -1,4 +1,5 @@
using Content.Shared.GameObjects.EntitySystems;
using Content.Shared.GameObjects.EntitySystems.ActionBlocker;
using Content.Shared.GameObjects.Verbs;
using Content.Shared.Interfaces;
using Robust.Shared.GameObjects;

View File

@@ -5,6 +5,7 @@ using Content.Server.GameObjects.Components.Buckle;
using Content.Shared.Alert;
using Content.Shared.GameObjects.Components.Strap;
using Content.Shared.GameObjects.EntitySystems;
using Content.Shared.GameObjects.EntitySystems.ActionBlocker;
using Content.Shared.GameObjects.Verbs;
using Content.Shared.Interfaces.GameObjects.Components;
using Content.Shared.Utility;

View File

@@ -8,6 +8,7 @@ using Content.Server.GameObjects.Components.Power;
using Content.Server.Interfaces.GameObjects.Components.Items;
using Content.Shared.Audio;
using Content.Shared.GameObjects.EntitySystems;
using Content.Shared.GameObjects.EntitySystems.ActionBlocker;
using Content.Shared.GameObjects.Verbs;
using Content.Shared.Interfaces;
using Content.Shared.Interfaces.GameObjects.Components;

View File

@@ -6,6 +6,7 @@ using Content.Server.GameObjects.Components.Items.Storage;
using Content.Server.GameObjects.Components.Weapon.Ranged.Barrels;
using Content.Shared.GameObjects.Components.Weapons.Ranged.Barrels;
using Content.Shared.GameObjects.EntitySystems;
using Content.Shared.GameObjects.EntitySystems.ActionBlocker;
using Content.Shared.GameObjects.Verbs;
using Content.Shared.Interfaces;
using Content.Shared.Interfaces.GameObjects.Components;

View File

@@ -4,6 +4,7 @@ using Content.Server.GameObjects.Components.Weapon.Ranged.Ammunition;
using Content.Shared.GameObjects;
using Content.Shared.GameObjects.Components.Weapons.Ranged.Barrels;
using Content.Shared.GameObjects.EntitySystems;
using Content.Shared.GameObjects.EntitySystems.ActionBlocker;
using Content.Shared.GameObjects.Verbs;
using Content.Shared.Interfaces;
using Content.Shared.Interfaces.GameObjects.Components;

View File

@@ -4,6 +4,7 @@ using Content.Server.GameObjects.Components.Weapon.Ranged.Ammunition;
using Content.Shared.GameObjects;
using Content.Shared.GameObjects.Components.Weapons.Ranged.Barrels;
using Content.Shared.GameObjects.EntitySystems;
using Content.Shared.GameObjects.EntitySystems.ActionBlocker;
using Content.Shared.GameObjects.Verbs;
using Content.Shared.Interfaces;
using Content.Shared.Interfaces.GameObjects.Components;

View File

@@ -9,6 +9,7 @@ using Content.Shared.Damage;
using Content.Shared.GameObjects;
using Content.Shared.GameObjects.Components.Weapons.Ranged.Barrels;
using Content.Shared.GameObjects.EntitySystems;
using Content.Shared.GameObjects.EntitySystems.ActionBlocker;
using Content.Shared.GameObjects.Verbs;
using Content.Shared.Interfaces.GameObjects.Components;
using Robust.Server.GameObjects;

View File

@@ -8,6 +8,7 @@ using Content.Shared.GameObjects;
using Content.Shared.GameObjects.Components.Weapons.Ranged;
using Content.Shared.GameObjects.Components.Weapons.Ranged.Barrels;
using Content.Shared.GameObjects.EntitySystems;
using Content.Shared.GameObjects.EntitySystems.ActionBlocker;
using Content.Shared.GameObjects.Verbs;
using Content.Shared.Interfaces;
using Content.Shared.Interfaces.GameObjects.Components;

View File

@@ -6,6 +6,7 @@ using Content.Shared.Damage;
using Content.Shared.GameObjects.Components.Damage;
using Content.Shared.GameObjects.Components.Weapons.Ranged;
using Content.Shared.GameObjects.EntitySystems;
using Content.Shared.GameObjects.EntitySystems.ActionBlocker;
using Content.Shared.Interfaces;
using Content.Shared.Interfaces.GameObjects.Components;
using Robust.Server.GameObjects.EntitySystems;

View File

@@ -70,7 +70,8 @@ namespace Content.Server.GameObjects.EntitySystems.AI
foreach (var message in _queuedMobStateMessages)
{
if (!message.Entity.TryGetComponent(out AiControllerComponent? controller))
if (message.Entity.Deleted ||
!message.Entity.TryGetComponent(out AiControllerComponent? controller))
{
continue;
}

View File

@@ -8,6 +8,7 @@ using Content.Server.GameObjects.EntitySystems.AI.Pathfinding;
using Content.Server.GameObjects.EntitySystems.AI.Pathfinding.Pathfinders;
using Content.Server.GameObjects.EntitySystems.JobQueues;
using Content.Shared.GameObjects.EntitySystems;
using Content.Shared.GameObjects.EntitySystems.ActionBlocker;
using Content.Shared.Utility;
using Robust.Server.Interfaces.Timing;
using Robust.Shared.GameObjects.Components;

View File

@@ -0,0 +1,65 @@
using System.Collections.Generic;
using Content.Server.GameObjects.Components.Body.Surgery;
using Content.Server.GameObjects.Components.Body.Surgery.Messages;
using Content.Shared.GameObjects.EntitySystems;
using Content.Shared.GameObjects.EntitySystems.ActionBlocker;
using Content.Shared.GameTicking;
using Content.Shared.Utility;
using JetBrains.Annotations;
using Robust.Shared.GameObjects.Systems;
namespace Content.Server.GameObjects.EntitySystems.Body.Surgery
{
[UsedImplicitly]
public class SurgeryToolSystem : EntitySystem, IResettingEntitySystem
{
private readonly HashSet<SurgeryToolComponent> _openSurgeryUIs = new();
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<SurgeryWindowOpenMessage>(OnSurgeryWindowOpen);
SubscribeLocalEvent<SurgeryWindowCloseMessage>(OnSurgeryWindowClose);
}
public void Reset()
{
_openSurgeryUIs.Clear();
}
private void OnSurgeryWindowOpen(SurgeryWindowOpenMessage ev)
{
_openSurgeryUIs.Add(ev.Tool);
}
private void OnSurgeryWindowClose(SurgeryWindowCloseMessage ev)
{
_openSurgeryUIs.Remove(ev.Tool);
}
public override void Update(float frameTime)
{
base.Update(frameTime);
foreach (var tool in _openSurgeryUIs)
{
if (tool.PerformerCache == null)
{
continue;
}
if (tool.BodyCache == null)
{
continue;
}
if (!ActionBlockerSystem.CanInteract(tool.PerformerCache) ||
!tool.PerformerCache.InRangeUnobstructed(tool.BodyCache))
{
tool.CloseAllSurgeryUIs();
}
}
}
}
}

View File

@@ -26,6 +26,14 @@ namespace Content.Server.GameObjects.EntitySystems
SubscribeLocalEvent<EntRemovedFromContainerMessage>(ContainerModified);
}
public override void Update(float frameTime)
{
foreach (var comp in ComponentManager.EntityQuery<BuckleComponent>(false))
{
comp.Update();
}
}
public override void Shutdown()
{
base.Shutdown();

View File

@@ -11,6 +11,7 @@ using Content.Shared.GameObjects.Components.Inventory;
using Content.Shared.GameObjects.Components.Items;
using Content.Shared.GameObjects.EntitySystemMessages;
using Content.Shared.GameObjects.EntitySystems;
using Content.Shared.GameObjects.EntitySystems.ActionBlocker;
using Content.Shared.Input;
using Content.Shared.Interfaces.GameObjects.Components;
using Content.Shared.Utility;

View File

@@ -11,6 +11,7 @@ using Content.Server.GameObjects.EntitySystems.DoAfter;
using Content.Shared.Construction;
using Content.Shared.GameObjects.Components;
using Content.Shared.GameObjects.EntitySystems;
using Content.Shared.GameObjects.EntitySystems.ActionBlocker;
using Content.Shared.Interfaces;
using Content.Shared.Utility;
using JetBrains.Annotations;

View File

@@ -4,6 +4,7 @@ using System.Collections.Generic;
using Content.Server.GameObjects.Components.Pointing;
using Content.Server.Players;
using Content.Shared.GameObjects.EntitySystems;
using Content.Shared.GameObjects.EntitySystems.ActionBlocker;
using Content.Shared.Input;
using Content.Shared.Interfaces;
using Content.Shared.Utility;

View File

@@ -45,7 +45,11 @@ namespace Content.Server.GameTicking
.Where(j =>
{
var (jobId, priority) = j;
var job = _prototypeManager.Index<JobPrototype>(jobId);
if (!_prototypeManager.TryIndex(jobId, out JobPrototype job))
{
// Job doesn't exist, probably old data?
return false;
}
if (job.IsHead != heads)
{
return false;

View File

@@ -5,6 +5,7 @@ using System.Diagnostics.CodeAnalysis;
using Content.Server.GameObjects.Components.Items.Storage;
using Content.Shared.GameObjects.Components.Items;
using Content.Shared.GameObjects.EntitySystems;
using Content.Shared.GameObjects.EntitySystems.ActionBlocker;
using Robust.Server.GameObjects.Components.Container;
using Robust.Server.GameObjects.EntitySystemMessages;
using Robust.Shared.Interfaces.GameObjects;
@@ -47,7 +48,7 @@ namespace Content.Server.Interfaces.GameObjects.Components.Items
/// <param name="handName">The name of the hand to get.</param>
/// <param name="item">The item in the held, null if no item is held</param>
/// <returns>Whether it was holding an item</returns>
bool TryGetItem(string handName, [MaybeNullWhen(false)] out ItemComponent item);
bool TryGetItem(string handName, [NotNullWhen(true)] out ItemComponent? item);
/// <summary>
/// Gets item held by the current active hand
@@ -102,7 +103,7 @@ namespace Content.Server.Interfaces.GameObjects.Components.Items
/// <returns>
/// true if the entity is held, false otherwise
/// </returns>
bool TryHand(IEntity entity, [MaybeNullWhen(false)] out string handName);
bool TryHand(IEntity entity, [NotNullWhen(true)] out string? handName);
/// <summary>
/// Drops the item contained in the slot to the same position as our entity.

View File

@@ -82,6 +82,12 @@ namespace Content.Server
var password = _configurationManager.GetCVar(CCVars.StatusMoMMIPassword);
if (string.IsNullOrEmpty(password))
{
response.StatusCode = (int) HttpStatusCode.Forbidden;
return true;
}
OOCPostMessage message = null;
try
{

View File

@@ -7,6 +7,7 @@ using Content.Server.Interfaces;
using Content.Shared;
using Content.Shared.Network.NetMessages;
using Content.Shared.Preferences;
using Content.Shared.Roles;
using Robust.Server.Interfaces.Player;
using Robust.Shared.Interfaces.Configuration;
using Robust.Shared.Interfaces.Network;
@@ -250,7 +251,36 @@ namespace Content.Server.Preferences
return await _db.InitPrefsAsync(userId, HumanoidCharacterProfile.Default());
}
return prefs;
return SanitizePreferences(prefs);
}
private PlayerPreferences SanitizePreferences(PlayerPreferences prefs)
{
// Clean up preferences in case of changes to the game,
// such as removed jobs still being selected.
return new PlayerPreferences(prefs.Characters.Select(p =>
{
ICharacterProfile newProf;
switch (p.Value)
{
case HumanoidCharacterProfile hp:
{
newProf = hp
.WithJobPriorities(
hp.JobPriorities.Where(job =>
_protos.HasIndex<JobPrototype>(job.Key)))
.WithAntagPreferences(
hp.AntagPreferences.Where(antag =>
_protos.HasIndex<AntagPrototype>(antag)));
break;
}
default:
throw new NotSupportedException();
}
return new KeyValuePair<int, ICharacterProfile>(p.Key, newProf);
}), prefs.SelectedCharacterIndex);
}
public IEnumerable<KeyValuePair<NetUserId, ICharacterProfile>> GetSelectedProfilesForPlayers(

View File

@@ -2,6 +2,7 @@
using Content.Server.GameObjects.Components.Projectiles;
using Content.Shared.GameObjects.Components.Movement;
using Content.Shared.GameObjects.EntitySystems;
using Content.Shared.GameObjects.EntitySystems.ActionBlocker;
using Content.Shared.Physics;
using Robust.Shared.GameObjects.Components;
using Robust.Shared.Interfaces.GameObjects;

View File

@@ -12,10 +12,10 @@ namespace Content.Shared
*/
public static readonly CVarDef<string> StatusMoMMIUrl =
CVarDef.Create<string>("status.mommiurl", null);
CVarDef.Create("status.mommiurl", "", CVar.SERVERONLY);
public static readonly CVarDef<string> StatusMoMMIPassword =
CVarDef.Create<string>("status.mommipassword", null);
CVarDef.Create("status.mommipassword", "", CVar.SERVERONLY);
/*

View File

@@ -2,6 +2,8 @@
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using Content.Shared.GameObjects.EntitySystems;
using Robust.Shared.GameObjects.Systems;
using Robust.Shared.Serialization;
namespace Content.Shared.Damage
@@ -18,27 +20,21 @@ namespace Content.Shared.Damage
public static class DamageClassExtensions
{
// TODO DAMAGE This but not hardcoded
private static readonly ImmutableDictionary<DamageClass, List<DamageType>> ClassToType =
new Dictionary<DamageClass, List<DamageType>>
{
{DamageClass.Brute, new List<DamageType> {DamageType.Blunt, DamageType.Slash, DamageType.Piercing}},
{DamageClass.Burn, new List<DamageType> {DamageType.Heat, DamageType.Shock, DamageType.Cold}},
{DamageClass.Toxin, new List<DamageType> {DamageType.Poison, DamageType.Radiation}},
{DamageClass.Airloss, new List<DamageType> {DamageType.Asphyxiation, DamageType.Bloodloss}},
{DamageClass.Genetic, new List<DamageType> {DamageType.Cellular}}
}.ToImmutableDictionary();
public static List<DamageType> ToTypes(this DamageClass @class)
public static ImmutableList<DamageType> ToTypes(this DamageClass @class)
{
return ClassToType[@class];
return DamageSystem.ClassToType[@class];
}
public static Dictionary<DamageClass, int> ToDictionary()
public static Dictionary<DamageClass, T> ToNewDictionary<T>()
{
return Enum.GetValues(typeof(DamageClass))
.Cast<DamageClass>()
.ToDictionary(@class => @class, type => 0);
.ToDictionary(@class => @class, _ => default(T));
}
public static Dictionary<DamageClass, int> ToNewDictionary()
{
return ToNewDictionary<int>();
}
}
}

View File

@@ -1,7 +1,8 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using Content.Shared.GameObjects.EntitySystems;
using Robust.Shared.GameObjects.Systems;
using Robust.Shared.Serialization;
namespace Content.Shared.Damage
@@ -24,38 +25,26 @@ namespace Content.Shared.Damage
public static class DamageTypeExtensions
{
// TODO: Automatically generate this
private static readonly ImmutableDictionary<DamageType, DamageClass> TypeToClass =
new Dictionary<DamageType, DamageClass>
{
{DamageType.Blunt, DamageClass.Brute},
{DamageType.Slash, DamageClass.Brute},
{DamageType.Piercing, DamageClass.Brute},
{DamageType.Heat, DamageClass.Burn},
{DamageType.Shock, DamageClass.Burn},
{DamageType.Cold, DamageClass.Burn},
{DamageType.Poison, DamageClass.Toxin},
{DamageType.Radiation, DamageClass.Toxin},
{DamageType.Asphyxiation, DamageClass.Airloss},
{DamageType.Bloodloss, DamageClass.Airloss},
{DamageType.Cellular, DamageClass.Genetic}
}.ToImmutableDictionary();
public static DamageClass ToClass(this DamageType type)
{
return TypeToClass[type];
return DamageSystem.TypeToClass[type];
}
public static Dictionary<DamageType, int> ToDictionary()
public static Dictionary<DamageType, T> ToNewDictionary<T>()
{
return Enum.GetValues(typeof(DamageType))
.Cast<DamageType>()
.ToDictionary(type => type, type => 0);
.ToDictionary(type => type, _ => default(T));
}
public static Dictionary<DamageType, int> ToNewDictionary()
{
return ToNewDictionary<int>();
}
public static Dictionary<DamageClass, int> ToClassDictionary(IReadOnlyDictionary<DamageType, int> types)
{
var classes = DamageClassExtensions.ToDictionary();
var classes = DamageClassExtensions.ToNewDictionary();
foreach (var @class in classes.Keys.ToList())
{

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