Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Jabak
2024-07-28 15:08:05 +03:00
91 changed files with 1040 additions and 267 deletions

View File

@@ -3,7 +3,7 @@ namespace Content.Client.SurveillanceCamera;
[RegisterComponent]
public sealed partial class ActiveSurveillanceCameraMonitorVisualsComponent : Component
{
public float TimeLeft = 10f;
public float TimeLeft = 0.5f;
public Action? OnFinish;
}

View File

@@ -14,18 +14,30 @@ public sealed class SurveillanceCameraMonitorBoundUserInterface : BoundUserInter
[ViewVariables]
private EntityUid? _currentCamera;
private readonly IEntityManager _entManager;
public SurveillanceCameraMonitorBoundUserInterface(EntityUid owner, Enum uiKey) : base(owner, uiKey)
{
_eyeLerpingSystem = EntMan.System<EyeLerpingSystem>();
_surveillanceCameraMonitorSystem = EntMan.System<SurveillanceCameraMonitorSystem>();
IoCManager.InjectDependencies(this);
_entManager = IoCManager.Resolve<IEntityManager>();
}
protected override void Open()
{
base.Open();
_window = new SurveillanceCameraMonitorWindow();
// Sunrise-start
EntityUid? gridUid = null;
if (_entManager.TryGetComponent<TransformComponent>(Owner, out var xform))
{
gridUid = xform.GridUid;
}
_window = new SurveillanceCameraMonitorWindow(gridUid);
// Sunrise-end
if (State != null)
{
@@ -35,7 +47,6 @@ public sealed class SurveillanceCameraMonitorBoundUserInterface : BoundUserInter
_window.OpenCentered();
_window.CameraSelected += OnCameraSelected;
_window.SubnetOpened += OnSubnetRequest;
_window.CameraRefresh += OnCameraRefresh;
_window.SubnetRefresh += OnSubnetRefresh;
_window.OnClose += Close;
@@ -43,14 +54,9 @@ public sealed class SurveillanceCameraMonitorBoundUserInterface : BoundUserInter
_window.CameraDisconnect += OnCameraDisconnect;
}
private void OnCameraSelected(string address)
private void OnCameraSelected(NetEntity camera)
{
SendMessage(new SurveillanceCameraMonitorSwitchMessage(address));
}
private void OnSubnetRequest(string subnet)
{
SendMessage(new SurveillanceCameraMonitorSubnetRequestMessage(subnet));
SendMessage(new SurveillanceCameraMonitorSwitchMessage(camera));
}
private void OnCameraSwitchTimer()
@@ -82,9 +88,11 @@ public sealed class SurveillanceCameraMonitorBoundUserInterface : BoundUserInter
var active = EntMan.GetEntity(cast.ActiveCamera);
_entManager.TryGetComponent<TransformComponent>(Owner, out var xform);
if (active == null)
{
_window.UpdateState(null, cast.Subnets, cast.ActiveAddress, cast.ActiveSubnet, cast.Cameras);
_window.UpdateState(null, cast.ActiveAddress, cast.ActiveCamera);
if (_currentCamera != null)
{
@@ -109,9 +117,11 @@ public sealed class SurveillanceCameraMonitorBoundUserInterface : BoundUserInter
if (EntMan.TryGetComponent<EyeComponent>(active, out var eye))
{
_window.UpdateState(eye.Eye, cast.Subnets, cast.ActiveAddress, cast.ActiveSubnet, cast.Cameras);
_window.UpdateState(eye.Eye, cast.ActiveAddress, cast.ActiveCamera);
}
}
_window.ShowCameras(cast.Cameras, xform?.Coordinates);
}
protected override void Dispose(bool disposing)

View File

@@ -1,25 +1,41 @@
<DefaultWindow xmlns="https://spacestation14.io"
xmlns:viewport="clr-namespace:Content.Client.Viewport"
Title="{Loc 'surveillance-camera-monitor-ui-window'}">
<BoxContainer Orientation="Horizontal">
<BoxContainer Orientation="Vertical" MinWidth="350" VerticalExpand="True">
<!-- lazy -->
<OptionButton Name="SubnetSelector" />
<Button Name="SubnetRefreshButton" Text="{Loc 'surveillance-camera-monitor-ui-refresh-subnets'}" />
<ScrollContainer VerticalExpand="True">
<ItemList Name="SubnetList" />
</ScrollContainer>
<Button Name="CameraRefreshButton" Text="{Loc 'surveillance-camera-monitor-ui-refresh-cameras'}" />
<Button Name="CameraDisconnectButton" Text="{Loc 'surveillance-camera-monitor-ui-disconnect'}" />
<Label Name="CameraStatus" />
<controls:FancyWindow xmlns="https://spacestation14.io"
xmlns:viewport="clr-namespace:Content.Client.Viewport"
xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls"
xmlns:ui="clr-namespace:Content.Client.SurveillanceCamera.UI"
xmlns:customControls="clr-namespace:Content.Client.Administration.UI.CustomControls"
Title="{Loc 'surveillance-camera-monitor-ui-window'}"
Resizable="False"
MinSize="1300 750">
<BoxContainer Orientation="Vertical">
<BoxContainer Orientation="Horizontal" VerticalExpand="True" HorizontalExpand="True">
<ui:SurveillanceCameraNavMapControl Name="NavMap" HorizontalExpand="True" VerticalExpand="True" MinSize="600 700" VerticalAlignment="Top"/>
<customControls:VSeparator/>
<BoxContainer Orientation="Vertical">
<Control VerticalExpand="True" HorizontalExpand="True" Margin="5 5 5 5" Name="CameraViewBox">
<viewport:ScalingViewport Name="CameraView"
VerticalExpand="True"
HorizontalExpand="True"
MinSize="700 700"
MouseFilter="Ignore" />
<TextureRect VerticalExpand="True" HorizontalExpand="True" MinSize="700 700" Name="CameraViewBackground" />
</Control>
<BoxContainer Orientation="Vertical">
<Button Name="SubnetRefreshButton" Text="{Loc 'surveillance-camera-monitor-ui-refresh-subnets'}" />
<Button Name="CameraRefreshButton" Text="{Loc 'surveillance-camera-monitor-ui-refresh-cameras'}" />
<Button Name="CameraDisconnectButton" Text="{Loc 'surveillance-camera-monitor-ui-disconnect'}" />
<Label Name="CameraStatus" />
</BoxContainer>
</BoxContainer>
</BoxContainer>
<BoxContainer Orientation="Vertical">
<PanelContainer StyleClasses="LowDivider" />
<BoxContainer Orientation="Horizontal" Margin="10 2 5 0" VerticalAlignment="Bottom">
<Label Text="{Loc 'surveillance-camera-monitor-ui-flavor-left'}" StyleClasses="WindowFooterText" />
<Label Text="{Loc 'surveillance-camera-monitor-ui-flavor-right'}" StyleClasses="WindowFooterText"
HorizontalAlignment="Right" HorizontalExpand="True" Margin="0 0 5 0" />
<TextureRect StyleClasses="NTLogoDark" Stretch="KeepAspectCentered"
VerticalAlignment="Center" HorizontalAlignment="Right" SetSize="19 19"/>
</BoxContainer>
</BoxContainer>
<Control VerticalExpand="True" HorizontalExpand="True" Margin="5 5 5 5" Name="CameraViewBox">
<viewport:ScalingViewport Name="CameraView"
VerticalExpand="True"
HorizontalExpand="True"
MinSize="500 500"
MouseFilter="Ignore" />
<TextureRect VerticalExpand="True" HorizontalExpand="True" MinSize="500 500" Name="CameraViewBackground" />
</Control>
</BoxContainer>
</DefaultWindow>
</controls:FancyWindow>

View File

@@ -1,27 +1,28 @@
using System.Linq;
using Content.Client.Pinpointer.UI;
using Content.Client.Resources;
using Content.Client.Viewport;
using Content.Shared.DeviceNetwork;
using Content.Client.Stylesheets;
using Content.Client.UserInterface.Controls;
using Content.Shared.SurveillanceCamera;
using Robust.Client.AutoGenerated;
using Robust.Client.GameObjects;
using Robust.Client.Graphics;
using Robust.Client.ResourceManagement;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.CustomControls;
using Robust.Client.UserInterface.XAML;
using Robust.Shared.Graphics;
using Robust.Shared.Map;
using Robust.Shared.Prototypes;
using Robust.Shared.Utility;
namespace Content.Client.SurveillanceCamera.UI;
[GenerateTypedNameReferences]
public sealed partial class SurveillanceCameraMonitorWindow : DefaultWindow
public sealed partial class SurveillanceCameraMonitorWindow : FancyWindow
{
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
[Dependency] private readonly IResourceCache _resourceCache = default!;
private readonly IPrototypeManager _prototypeManager;
private readonly IEntityManager _entManager;
public event Action<string>? CameraSelected;
public event Action<string>? SubnetOpened;
public event Action<NetEntity>? CameraSelected;
public event Action? CameraRefresh;
public event Action? SubnetRefresh;
public event Action? CameraSwitchTimer;
@@ -30,110 +31,96 @@ public sealed partial class SurveillanceCameraMonitorWindow : DefaultWindow
private string _currentAddress = string.Empty;
private bool _isSwitching;
private readonly FixedEye _defaultEye = new();
private readonly Dictionary<string, int> _subnetMap = new();
private Dictionary<NetEntity, CameraData> _cameras = new();
private Texture? _blipTexture;
private NetEntity? _trackedEntity;
private string? SelectedSubnet
{
get
{
if (SubnetSelector.ItemCount == 0
|| SubnetSelector.SelectedMetadata == null)
{
return null;
}
return (string) SubnetSelector.SelectedMetadata;
}
}
public SurveillanceCameraMonitorWindow()
public SurveillanceCameraMonitorWindow(EntityUid? mapUid)
{
RobustXamlLoader.Load(this);
IoCManager.InjectDependencies(this);
_prototypeManager = IoCManager.Resolve<IPrototypeManager>();
var resourceCache = IoCManager.Resolve<IResourceCache>();
_entManager = IoCManager.Resolve<IEntityManager>();
var spriteSystem = _entManager.System<SpriteSystem>();
// This could be done better. I don't want to deal with stylesheets at the moment.
var texture = _resourceCache.GetTexture("/Textures/Interface/Nano/square_black.png");
var texture = resourceCache.GetTexture("/Textures/Interface/Nano/square_black.png");
var shader = _prototypeManager.Index<ShaderPrototype>("CameraStatic").Instance().Duplicate();
_blipTexture = spriteSystem.Frame0(new SpriteSpecifier.Texture(new ResPath("/Textures/Interface/NavMap/beveled_circle.png")));
CameraView.ViewportSize = new Vector2i(500, 500);
CameraView.Eye = _defaultEye; // sure
CameraViewBackground.Stretch = TextureRect.StretchMode.Scale;
CameraViewBackground.Texture = texture;
CameraViewBackground.ShaderOverride = shader;
SubnetList.OnItemSelected += OnSubnetListSelect;
SubnetSelector.OnItemSelected += args =>
{
// piss
SubnetOpened!((string) args.Button.GetItemMetadata(args.Id)!);
};
SubnetRefreshButton.OnPressed += _ => SubnetRefresh!();
CameraRefreshButton.OnPressed += _ => CameraRefresh!();
CameraDisconnectButton.OnPressed += _ => CameraDisconnect!();
NavMap.TrackedEntitySelectedAction += SetTrackedEntityFromNavMap;
_entManager = IoCManager.Resolve<IEntityManager>();
if (_entManager.TryGetComponent<TransformComponent>(mapUid, out var xform))
NavMap.MapUid = xform.GridUid;
else
NavMap.Visible = false;
}
// Sunrise-start
private void SetTrackedEntityFromNavMap(NetEntity? netEntity)
{
NavMap.Focus = _trackedEntity;
if (netEntity != null)
{
CameraSelected!(netEntity.Value);
}
}
public void ShowCameras(Dictionary<NetEntity, CameraData> cameras, EntityCoordinates? monitorCoords)
{
ClearAllCamerasPoint();
_cameras = cameras;
foreach (var camera in cameras)
{
NavMap.LocalizedNames.TryAdd(camera.Key, camera.Value.Name);
var coordinates = _entManager.GetCoordinates(camera.Value.Coordinates);
if (NavMap.Visible && _blipTexture != null)
{
NavMap.TrackedEntities.TryAdd(camera.Key,
new NavMapBlip(coordinates,
_blipTexture,
camera.Key == _trackedEntity ? Color.LimeGreen : camera.Value.SubnetColor,
camera.Key == _trackedEntity));
NavMap.Focus = _trackedEntity;
}
}
// Show monitor point
if (monitorCoords != null)
NavMap.TrackedCoordinates.Add(monitorCoords.Value, (true, StyleNano.PointMagenta));
}
// Sunrise-end
// The UI class should get the eye from the entity, and then
// pass it here so that the UI can change its view.
public void UpdateState(IEye? eye, HashSet<string> subnets, string activeAddress, string activeSubnet, Dictionary<string, string> cameras)
public void UpdateState(IEye? eye, string activeAddress, NetEntity? activeCamera)
{
_currentAddress = activeAddress;
_trackedEntity = activeCamera;
SetCameraView(eye);
if (subnets.Count == 0)
{
SubnetSelector.AddItem(Loc.GetString("surveillance-camera-monitor-ui-no-subnets"));
SubnetSelector.Disabled = true;
return;
}
if (SubnetSelector.Disabled && subnets.Count != 0)
{
SubnetSelector.Clear();
SubnetSelector.Disabled = false;
}
// That way, we have *a* subnet selected if this is ever opened.
if (string.IsNullOrEmpty(activeSubnet))
{
SubnetOpened!(subnets.First());
return;
}
// if the subnet count is unequal, that means
// we have to rebuild the subnet selector
if (SubnetSelector.ItemCount != subnets.Count)
{
SubnetSelector.Clear();
_subnetMap.Clear();
foreach (var subnet in subnets)
{
var id = AddSubnet(subnet);
_subnetMap.Add(subnet, id);
}
}
if (_subnetMap.TryGetValue(activeSubnet, out var subnetId))
{
SubnetSelector.Select(subnetId);
}
PopulateCameraList(cameras);
}
private void PopulateCameraList(Dictionary<string, string> cameras)
{
SubnetList.Clear();
foreach (var (address, name) in cameras)
{
AddCameraToList(name, address);
}
SubnetList.SortItemsByText();
}
private void SetCameraView(IEye? eye)
{
@@ -173,28 +160,9 @@ public sealed partial class SurveillanceCameraMonitorWindow : DefaultWindow
("address", _currentAddress));
}
private int AddSubnet(string subnet)
private void ClearAllCamerasPoint()
{
var name = subnet;
if (_prototypeManager.TryIndex<DeviceFrequencyPrototype>(subnet, out var frequency))
{
name = Loc.GetString(frequency.Name ?? subnet);
}
SubnetSelector.AddItem(name);
SubnetSelector.SetItemMetadata(SubnetSelector.ItemCount - 1, subnet);
return SubnetSelector.ItemCount - 1;
}
private void AddCameraToList(string name, string address)
{
var item = SubnetList.AddItem($"{name}: {address}");
item.Metadata = address;
}
private void OnSubnetListSelect(ItemList.ItemListSelectedEventArgs args)
{
CameraSelected!((string) SubnetList[args.ItemIndex].Metadata!);
NavMap.TrackedCoordinates.Clear();
NavMap.TrackedEntities.Clear();
}
}

View File

@@ -0,0 +1,80 @@
using Content.Client.Pinpointer.UI;
using Robust.Client.Graphics;
using Robust.Client.UserInterface.Controls;
namespace Content.Client.SurveillanceCamera.UI;
public sealed partial class SurveillanceCameraNavMapControl : NavMapControl
{
public NetEntity? Focus;
public Dictionary<NetEntity, string> LocalizedNames = new();
private Label _trackedEntityLabel;
private PanelContainer _trackedEntityPanel;
public SurveillanceCameraNavMapControl()
{
WallColor = new Color(192, 122, 196);
TileColor = new(71, 42, 72);
BackgroundColor = Color.FromSrgb(TileColor.WithAlpha(BackgroundOpacity));
_trackedEntityLabel = new Label
{
Margin = new Thickness(10f, 8f),
HorizontalAlignment = HAlignment.Center,
VerticalAlignment = VAlignment.Center,
Modulate = Color.White,
};
_trackedEntityPanel = new PanelContainer
{
PanelOverride = new StyleBoxFlat
{
BackgroundColor = BackgroundColor,
},
Margin = new Thickness(5f, 45f),
HorizontalAlignment = HAlignment.Left,
VerticalAlignment = VAlignment.Bottom,
Visible = false,
};
_trackedEntityPanel.AddChild(_trackedEntityLabel);
AddChild(_trackedEntityPanel);
VerticalExpand = true;
VerticalAlignment = VAlignment.Stretch;
}
protected override void Draw(DrawingHandleScreen handle)
{
base.Draw(handle);
if (Focus == null)
{
_trackedEntityLabel.Text = string.Empty;
_trackedEntityPanel.Visible = false;
return;
}
foreach ((var netEntity, var blip) in TrackedEntities)
{
if (netEntity != Focus)
continue;
if (!LocalizedNames.TryGetValue(netEntity, out var name))
name = "Unknown";
var message = name + "\nLocation: [x = " + MathF.Round(blip.Coordinates.X) + ", y = " + MathF.Round(blip.Coordinates.Y) + "]";
_trackedEntityLabel.Text = message;
_trackedEntityPanel.Visible = true;
return;
}
_trackedEntityLabel.Text = string.Empty;
_trackedEntityPanel.Visible = false;
}
}

View File

@@ -2,6 +2,7 @@ using Content.Server.Explosion.EntitySystems;
using Content.Server.Power.EntitySystems;
using Content.Server.Radio;
using Content.Server.SurveillanceCamera;
using Content.Server.SurveillanceCamera.Systems;
using Content.Shared.Emp;
using Content.Shared.Examine;
using Robust.Shared.Map;

View File

@@ -1,8 +1,9 @@
using Content.Server._White.SurveillanceCamera;
using Content.Server.SurveillanceCamera.Systems;
using Content.Shared.DeviceNetwork;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List;
namespace Content.Server.SurveillanceCamera;
namespace Content.Server.SurveillanceCamera.Components;
[RegisterComponent]
[Access(typeof(SurveillanceCameraSystem), typeof(SurveillanceBodyCameraSystem))]

View File

@@ -1,4 +1,7 @@
namespace Content.Server.SurveillanceCamera;
using Content.Server.SurveillanceCamera.Systems;
using Content.Shared.SurveillanceCamera;
namespace Content.Server.SurveillanceCamera.Components;
[RegisterComponent]
[Access(typeof(SurveillanceCameraMonitorSystem))]
@@ -29,14 +32,10 @@ public sealed partial class SurveillanceCameraMonitorComponent : Component
// Set of viewers currently looking at this monitor.
public HashSet<EntityUid> Viewers { get; } = new();
// Current active subnet.
[ViewVariables]
public string ActiveSubnet { get; set; } = default!;
// Known cameras in this subnet by address with name values.
// This is cleared when the subnet is changed.
[ViewVariables]
public Dictionary<string, string> KnownCameras { get; } = new();
public Dictionary<NetEntity, CameraData> KnownCameras { get; } = new();
[ViewVariables]
// The subnets known by this camera monitor.

View File

@@ -28,4 +28,9 @@ public sealed partial class SurveillanceCameraRouterComponent : Component
[DataField("setupAvailableNetworks", customTypeSerializer:typeof(PrototypeIdListSerializer<DeviceFrequencyPrototype>))]
public List<string> AvailableNetworks { get; private set; } = new();
// Sunrise-start
[DataField("subnetColor")]
public Color SubnetColor;
// Sunrise-end
}

View File

@@ -1,10 +1,11 @@
using Content.Server.Chat.Systems;
using Content.Server.Speech;
using Content.Server.Speech.Components;
using Content.Server.SurveillanceCamera.Components;
using Robust.Shared.Player;
using static Content.Server.Chat.Systems.ChatSystem;
namespace Content.Server.SurveillanceCamera;
namespace Content.Server.SurveillanceCamera.Systems;
public sealed class SurveillanceCameraMicrophoneSystem : EntitySystem
{

View File

@@ -2,13 +2,16 @@ using System.Linq;
using Content.Server.DeviceNetwork;
using Content.Server.DeviceNetwork.Systems;
using Content.Server.Power.Components;
using Content.Server.SurveillanceCamera.Components;
using Content.Server.SurveillanceCamera.Systems;
using Content.Shared.DeviceNetwork;
using Content.Shared.UserInterface;
using Content.Shared.SurveillanceCamera;
using Robust.Server.GameObjects;
using Robust.Shared.Player;
using Robust.Shared.Map;
namespace Content.Server.SurveillanceCamera;
namespace Content.Server.SurveillanceCamera.Systems;
public sealed class SurveillanceCameraMonitorSystem : EntitySystem
{
@@ -28,7 +31,6 @@ public sealed class SurveillanceCameraMonitorSystem : EntitySystem
subs.Event<SurveillanceCameraRefreshCamerasMessage>(OnRefreshCamerasMessage);
subs.Event<SurveillanceCameraRefreshSubnetsMessage>(OnRefreshSubnetsMessage);
subs.Event<SurveillanceCameraDisconnectMessage>(OnDisconnectMessage);
subs.Event<SurveillanceCameraMonitorSubnetRequestMessage>(OnSubnetRequest);
subs.Event<SurveillanceCameraMonitorSwitchMessage>(OnSwitchMessage);
subs.Event<BoundUIClosedEvent>(OnBoundUiClose);
});
@@ -87,15 +89,6 @@ public sealed class SurveillanceCameraMonitorSystem : EntitySystem
RefreshSubnets(uid, component);
}
private void OnSubnetRequest(EntityUid uid, SurveillanceCameraMonitorComponent component,
SurveillanceCameraMonitorSubnetRequestMessage args)
{
if (args.Session.AttachedEntity != null)
{
SetActiveSubnet(uid, args.Subnet, component);
}
}
private void OnPacketReceived(EntityUid uid, SurveillanceCameraMonitorComponent component,
DeviceNetworkPacketEvent args)
{
@@ -127,28 +120,48 @@ public sealed class SurveillanceCameraMonitorSystem : EntitySystem
case SurveillanceCameraSystem.CameraDataMessage:
if (!args.Data.TryGetValue(SurveillanceCameraSystem.CameraNameData, out string? name)
|| !args.Data.TryGetValue(SurveillanceCameraSystem.CameraSubnetData, out string? subnetData)
|| !args.Data.TryGetValue(SurveillanceCameraSystem.CameraAddressData, out string? address))
|| !args.Data.TryGetValue(SurveillanceCameraSystem.CameraAddressData, out string? address)
|| !args.Data.TryGetValue(SurveillanceCameraSystem.CameraUid, out EntityUid cameraUid)
|| !args.Data.TryGetValue(SurveillanceCameraSystem.CameraSubnetColor, out Color color))
{
return;
}
if (component.ActiveSubnet != subnetData)
if (!component.KnownSubnets.TryGetValue(subnetData, out var subnetAddress))
{
DisconnectFromSubnet(uid, subnetData);
return;
}
if (!component.KnownCameras.ContainsKey(address))
var netEntCamera = GetNetEntity(cameraUid);
if (!component.KnownCameras.ContainsKey(netEntCamera))
{
component.KnownCameras.Add(address, name);
var coordinates = EntityCoordinates.Invalid;
if (TryComp<TransformComponent>(cameraUid, out var transform))
{
if (transform.GridUid != null)
{
coordinates = transform.Coordinates;
}
}
component.KnownCameras.Add(netEntCamera,
new CameraData {
Name = name,
CameraAddress = address,
SubnetAddress = subnetAddress,
SubnetColor = color,
Coordinates = GetNetCoordinates(coordinates)
});
}
UpdateUserInterface(uid, component);
break;
case SurveillanceCameraSystem.CameraSubnetData:
if (args.Data.TryGetValue(SurveillanceCameraSystem.CameraSubnetData, out string? subnet)
&& !component.KnownSubnets.ContainsKey(subnet))
if (args.Data.TryGetValue(SurveillanceCameraSystem.CameraSubnetData, out string? subnet))
{
component.KnownSubnets.Add(subnet, args.SenderAddress);
component.KnownSubnets.TryAdd(subnet, args.SenderAddress);
}
UpdateUserInterface(uid, component);
@@ -161,13 +174,30 @@ public sealed class SurveillanceCameraMonitorSystem : EntitySystem
SurveillanceCameraDisconnectMessage message)
{
DisconnectCamera(uid, true, component);
// Sunrise-start
foreach (var subnet in component.KnownSubnets)
{
DisconnectFromSubnet(uid, subnet.Key);
component.KnownCameras.Clear();
UpdateUserInterface(uid, component);
ConnectToSubnet(uid, subnet.Key);
}
// Sunrise-end
}
private void OnRefreshCamerasMessage(EntityUid uid, SurveillanceCameraMonitorComponent component,
SurveillanceCameraRefreshCamerasMessage message)
{
component.KnownCameras.Clear();
RequestActiveSubnetInfo(uid, component);
// Sunrise-start
foreach (var subnet in component.KnownSubnets)
{
DisconnectFromSubnet(uid, subnet.Key);
DisconnectCamera(uid, true, component);
component.KnownCameras.Clear();
UpdateUserInterface(uid, component);
ConnectToSubnet(uid, subnet.Key);
}
// Sunrise-end
}
private void OnRefreshSubnetsMessage(EntityUid uid, SurveillanceCameraMonitorComponent component,
@@ -181,7 +211,7 @@ public sealed class SurveillanceCameraMonitorSystem : EntitySystem
// there would be a null check here, but honestly
// whichever one is the "latest" switch message gets to
// do the switch
TrySwitchCameraByAddress(uid, message.Address, component);
TrySwitchCameraByUid(uid, GetEntity(message.CameraNetEntity), component);
}
private void OnPowerChanged(EntityUid uid, SurveillanceCameraMonitorComponent component, ref PowerChangedEvent args)
@@ -190,7 +220,6 @@ public sealed class SurveillanceCameraMonitorSystem : EntitySystem
{
RemoveActiveCamera(uid, component);
component.NextCameraAddress = null;
component.ActiveSubnet = string.Empty;
}
}
@@ -208,20 +237,17 @@ public sealed class SurveillanceCameraMonitorSystem : EntitySystem
private void OnBoundUiClose(EntityUid uid, SurveillanceCameraMonitorComponent component, BoundUIClosedEvent args)
{
if (args.Session.AttachedEntity == null)
{
return;
}
RemoveViewer(uid, args.Session.AttachedEntity.Value, component);
RemoveViewer(uid, args.Entity, component);
}
#endregion
private void SendHeartbeat(EntityUid uid, SurveillanceCameraMonitorComponent? monitor = null)
{
if (!Resolve(uid, ref monitor)
|| monitor.LastHeartbeatSent < _heartbeatDelay
|| !monitor.KnownSubnets.TryGetValue(monitor.ActiveSubnet, out var subnetAddress))
|| monitor.ActiveCamera == null
|| !monitor.KnownCameras.TryGetValue(GetNetEntity(monitor.ActiveCamera.Value), out var cameraData))
{
return;
}
@@ -232,7 +258,7 @@ public sealed class SurveillanceCameraMonitorSystem : EntitySystem
{ SurveillanceCameraSystem.CameraAddressData, monitor.ActiveCameraAddress }
};
_deviceNetworkSystem.QueuePacket(uid, subnetAddress, payload);
_deviceNetworkSystem.QueuePacket(uid, cameraData.SubnetAddress, payload);
}
private void DisconnectCamera(EntityUid uid, bool removeViewers, SurveillanceCameraMonitorComponent? monitor = null)
@@ -278,28 +304,10 @@ public sealed class SurveillanceCameraMonitorSystem : EntitySystem
_deviceNetworkSystem.QueuePacket(uid, null, payload);
}
private void SetActiveSubnet(EntityUid uid, string subnet,
SurveillanceCameraMonitorComponent? monitor = null)
private void RequestSubnetInfo(EntityUid uid, string subnet, SurveillanceCameraMonitorComponent? monitor = null)
{
if (!Resolve(uid, ref monitor)
|| !monitor.KnownSubnets.ContainsKey(subnet))
{
return;
}
DisconnectFromSubnet(uid, monitor.ActiveSubnet);
DisconnectCamera(uid, true, monitor);
monitor.ActiveSubnet = subnet;
monitor.KnownCameras.Clear();
UpdateUserInterface(uid, monitor);
ConnectToSubnet(uid, subnet);
}
private void RequestActiveSubnetInfo(EntityUid uid, SurveillanceCameraMonitorComponent? monitor = null)
{
if (!Resolve(uid, ref monitor)
|| !monitor.KnownSubnets.TryGetValue(monitor.ActiveSubnet, out var address))
|| !monitor.KnownSubnets.TryGetValue(subnet, out var address))
{
return;
}
@@ -325,7 +333,7 @@ public sealed class SurveillanceCameraMonitorSystem : EntitySystem
};
_deviceNetworkSystem.QueuePacket(uid, address, payload);
RequestActiveSubnetInfo(uid);
RequestSubnetInfo(uid, subnet, monitor);
}
private void DisconnectFromSubnet(EntityUid uid, string subnet, SurveillanceCameraMonitorComponent? monitor = null)
@@ -415,11 +423,12 @@ public sealed class SurveillanceCameraMonitorSystem : EntitySystem
UpdateUserInterface(uid, monitor);
}
private void TrySwitchCameraByAddress(EntityUid uid, string address,
private void TrySwitchCameraByAddress(EntityUid uid,
string camera,
string subnet,
SurveillanceCameraMonitorComponent? monitor = null)
{
if (!Resolve(uid, ref monitor)
|| !monitor.KnownSubnets.TryGetValue(monitor.ActiveSubnet, out var subnetAddress))
if (!Resolve(uid, ref monitor))
{
return;
}
@@ -427,11 +436,11 @@ public sealed class SurveillanceCameraMonitorSystem : EntitySystem
var payload = new NetworkPayload()
{
{DeviceNetworkConstants.Command, SurveillanceCameraSystem.CameraConnectMessage},
{SurveillanceCameraSystem.CameraAddressData, address}
{SurveillanceCameraSystem.CameraAddressData, camera}
};
monitor.NextCameraAddress = address;
_deviceNetworkSystem.QueuePacket(uid, subnetAddress, payload);
monitor.NextCameraAddress = camera;
_deviceNetworkSystem.QueuePacket(uid, subnet, payload);
}
// Attempts to switch over the current viewed camera on this monitor
@@ -486,7 +495,7 @@ public sealed class SurveillanceCameraMonitorSystem : EntitySystem
return;
}
var state = new SurveillanceCameraMonitorUiState(GetNetEntity(monitor.ActiveCamera), monitor.KnownSubnets.Keys.ToHashSet(), monitor.ActiveCameraAddress, monitor.ActiveSubnet, monitor.KnownCameras);
var state = new SurveillanceCameraMonitorUiState(GetNetEntity(monitor.ActiveCamera), monitor.KnownSubnets.Keys.ToHashSet(), monitor.ActiveCameraAddress, monitor.KnownCameras);
_userInterface.TrySetUiState(uid, SurveillanceCameraMonitorUiKey.Key, state);
}
}

View File

@@ -2,6 +2,8 @@ using Content.Server.DeviceNetwork;
using Content.Server.DeviceNetwork.Components;
using Content.Server.DeviceNetwork.Systems;
using Content.Server.Power.Components;
using Content.Server.SurveillanceCamera;
using Content.Server.SurveillanceCamera.Systems;
using Content.Shared.ActionBlocker;
using Content.Shared.DeviceNetwork;
using Content.Shared.SurveillanceCamera;
@@ -10,7 +12,7 @@ using Robust.Server.GameObjects;
using Robust.Shared.Player;
using Robust.Shared.Prototypes;
namespace Content.Server.SurveillanceCamera;
namespace Content.Server.SurveillanceCamera.Systems;
public sealed class SurveillanceCameraRouterSystem : EntitySystem
{
@@ -244,7 +246,8 @@ public sealed class SurveillanceCameraRouterSystem : EntitySystem
var payload = new NetworkPayload()
{
{ DeviceNetworkConstants.Command, SurveillanceCameraSystem.CameraPingMessage },
{ SurveillanceCameraSystem.CameraSubnetData, router.SubnetName }
{ SurveillanceCameraSystem.CameraSubnetData, router.SubnetName },
{ SurveillanceCameraSystem.CameraSubnetColor, router.SubnetColor}
};
_deviceNetworkSystem.QueuePacket(uid, null, payload, router.SubnetFrequency);
@@ -257,6 +260,10 @@ public sealed class SurveillanceCameraRouterSystem : EntitySystem
{
return;
}
payload[SurveillanceCameraSystem.CameraSubnetData] = router.SubnetFrequencyId;
payload[SurveillanceCameraSystem.CameraSubnetColor] = router.SubnetColor;
payload[SurveillanceCameraSystem.CameraSubnetData] = router.SubnetFrequencyId;
foreach (var address in router.MonitorRoutes)
{

View File

@@ -4,7 +4,7 @@ using Content.Shared.Speech;
using Robust.Shared.Audio.Systems;
using Robust.Shared.Timing;
namespace Content.Server.SurveillanceCamera;
namespace Content.Server.SurveillanceCamera.Systems;
/// <summary>
/// This handles speech for surveillance camera monitors.

View File

@@ -4,6 +4,7 @@ using Content.Server.DeviceNetwork.Components;
using Content.Server.DeviceNetwork.Systems;
using Content.Server.Emp;
using Content.Server.Power.Components;
using Content.Server.SurveillanceCamera.Components;
using Content.Shared.ActionBlocker;
using Content.Shared.DeviceNetwork;
using Content.Shared.SurveillanceCamera;
@@ -12,7 +13,7 @@ using Robust.Server.GameObjects;
using Robust.Shared.Player;
using Robust.Shared.Prototypes;
namespace Content.Server.SurveillanceCamera;
namespace Content.Server.SurveillanceCamera.Systems;
public sealed class SurveillanceCameraSystem : EntitySystem
{
@@ -47,8 +48,10 @@ public sealed class SurveillanceCameraSystem : EntitySystem
public const string CameraSubnetDisconnectMessage = "surveillance_camera_subnet_disconnect";
public const string CameraAddressData = "surveillance_camera_data_origin";
public const string CameraUid = "surveillance_camera_data_uid";
public const string CameraNameData = "surveillance_camera_data_name";
public const string CameraSubnetData = "surveillance_camera_data_subnet";
public const string CameraSubnetColor = "surveillance_camera_color_subnet";
public const int CameraNameLimit = 32;
@@ -84,7 +87,9 @@ public sealed class SurveillanceCameraSystem : EntitySystem
{ DeviceNetworkConstants.Command, string.Empty },
{ CameraAddressData, deviceNet.Address },
{ CameraNameData, component.CameraId },
{ CameraSubnetData, string.Empty }
{ CameraSubnetData, string.Empty },
{ CameraSubnetColor, new Color() },
{ CameraUid, uid }
};
var dest = string.Empty;
@@ -92,60 +97,50 @@ public sealed class SurveillanceCameraSystem : EntitySystem
switch (command)
{
case CameraConnectMessage:
if (!args.Data.TryGetValue(CameraAddressData, out dest)
|| string.IsNullOrEmpty(args.Address))
{
if (!args.Data.TryGetValue(CameraAddressData, out dest) || string.IsNullOrEmpty(args.Address))
return;
}
payload[DeviceNetworkConstants.Command] = CameraConnectMessage;
break;
case CameraHeartbeatMessage:
if (!args.Data.TryGetValue(CameraAddressData, out dest)
|| string.IsNullOrEmpty(args.Address))
{
if (!args.Data.TryGetValue(CameraAddressData, out dest) || string.IsNullOrEmpty(args.Address))
return;
}
payload[DeviceNetworkConstants.Command] = CameraHeartbeatMessage;
break;
case CameraPingMessage:
if (!args.Data.TryGetValue(CameraSubnetData, out string? subnet))
{
return;
}
if (!args.Data.TryGetValue(CameraSubnetColor, out Color color))
return;
dest = args.SenderAddress;
payload[CameraSubnetData] = subnet;
payload[CameraSubnetColor] = color;
payload[CameraUid] = uid;
payload[DeviceNetworkConstants.Command] = CameraDataMessage;
break;
}
_deviceNetworkSystem.QueuePacket(
uid,
dest,
payload);
_deviceNetworkSystem.QueuePacket(uid, dest, payload);
}
}
private void AddVerbs(EntityUid uid, SurveillanceCameraComponent component, GetVerbsEvent<AlternativeVerb> verbs)
{
if (!_actionBlocker.CanInteract(verbs.User, uid))
{
return;
}
if (TryComp<SurveillanceBodyCameraComponent>(uid, out _)) // WD EDIT
{
if (HasComp<SurveillanceBodyCameraComponent>(uid)) // WD EDIT
return;
}
if (component.NameSet && component.NetworkSet)
{
return;
}
AlternativeVerb verb = new();
var verb = new AlternativeVerb();
verb.Text = Loc.GetString("surveillance-camera-setup");
verb.Act = () => OpenSetupInterface(uid, verbs.User, component);
verbs.Verbs.Add(verb);
@@ -181,21 +176,14 @@ public sealed class SurveillanceCameraSystem : EntitySystem
private void OnSetNetwork(EntityUid uid, SurveillanceCameraComponent component,
SurveillanceCameraSetupSetNetwork args)
{
if (args.UiKey is not SurveillanceCameraSetupUiKey key
|| key != SurveillanceCameraSetupUiKey.Camera)
{
if (args.UiKey is not SurveillanceCameraSetupUiKey key || key != SurveillanceCameraSetupUiKey.Camera)
return;
}
if (args.Network < 0 || args.Network >= component.AvailableNetworks.Count)
{
return;
}
if (!_prototypeManager.TryIndex<DeviceFrequencyPrototype>(component.AvailableNetworks[args.Network],
out var frequency))
{
if (args.Network < 0 || args.Network >= component.AvailableNetworks.Count)
return;
if (!_prototypeManager.TryIndex<DeviceFrequencyPrototype>(component.AvailableNetworks[args.Network], out var frequency))
return;
}
_deviceNetworkSystem.SetReceiveFrequency(uid, frequency.Frequency);
component.NetworkSet = true;
@@ -206,6 +194,7 @@ public sealed class SurveillanceCameraSystem : EntitySystem
{
if (!Resolve(uid, ref camera) || !Resolve(player, ref actor))
return;
if (!_userInterface.TryGetUi(uid, SurveillanceCameraSetupUiKey.Camera, out var bui))
return;
@@ -216,9 +205,7 @@ public sealed class SurveillanceCameraSystem : EntitySystem
public void UpdateSetupInterface(EntityUid uid, SurveillanceCameraComponent? camera = null, DeviceNetworkComponent? deviceNet = null)
{
if (!Resolve(uid, ref camera, ref deviceNet))
{
return;
}
if (camera.NameSet && camera.NetworkSet && !TryComp<SurveillanceBodyCameraComponent>(uid, out _)) // WD EDIT
{
@@ -249,9 +236,7 @@ public sealed class SurveillanceCameraSystem : EntitySystem
private void Deactivate(EntityUid camera, SurveillanceCameraComponent? component = null)
{
if (!Resolve(camera, ref component))
{
return;
}
var ev = new SurveillanceCameraDeactivateEvent(camera);

View File

@@ -2,6 +2,8 @@
using Content.Server.Power.EntitySystems;
using Content.Server.PowerCell;
using Content.Server.SurveillanceCamera;
using Content.Server.SurveillanceCamera.Components;
using Content.Server.SurveillanceCamera.Systems;
using Content.Shared.Examine;
using Content.Shared.Clothing.EntitySystems;
using Content.Shared.Item;

View File

@@ -1047,21 +1047,21 @@ namespace Content.Shared.CCVar
/// Divisor from maxForce (pressureDifference * 2.25f) to force applied on objects.
/// </summary>
public static readonly CVarDef<float> SpaceWindPressureForceDivisorPush =
CVarDef.Create("atmos.space_wind_pressure_force_divisor_push", 2500f, CVar.SERVERONLY);
CVarDef.Create("atmos.space_wind_pressure_force_divisor_push", 1700f, CVar.SERVERONLY);
/// <summary>
/// The maximum velocity (not force) that may be applied to an object by atmospheric pressure differences.
/// Useful to prevent clipping through objects.
/// </summary>
public static readonly CVarDef<float> SpaceWindMaxVelocity =
CVarDef.Create("atmos.space_wind_max_velocity", 15f, CVar.SERVERONLY);
CVarDef.Create("atmos.space_wind_max_velocity", 7f, CVar.SERVERONLY);
/// <summary>
/// The maximum force that may be applied to an object by pushing (i.e. not throwing) atmospheric pressure differences.
/// A "throwing" atmospheric pressure difference ignores this limit, but not the max. velocity limit.
/// </summary>
public static readonly CVarDef<float> SpaceWindMaxPushForce =
CVarDef.Create("atmos.space_wind_max_push_force", 20f, CVar.SERVERONLY);
CVarDef.Create("atmos.space_wind_max_push_force", 17f, CVar.SERVERONLY);
/// <summary>
/// If an object's mass is below this number, then this number is used in place of mass to determine whether air pressure can throw an object.
@@ -1079,7 +1079,7 @@ namespace Content.Shared.CCVar
/// If an object's inverse mass is lower than this, it is capped at this. Basically, an upper limit to how heavy an object can be before it stops resisting space wind more.
/// </summary>
public static readonly CVarDef<float> SpaceWindMaximumCalculatedInverseMass =
CVarDef.Create("atmos.space_wind_maximum_calculated_inverse_mass", 0.04f, CVar.SERVERONLY);
CVarDef.Create("atmos.space_wind_maximum_calculated_inverse_mass", 0.08f, CVar.SERVERONLY);
/// <summary>
/// Whether monstermos tile equalization is enabled.

View File

@@ -1,3 +1,4 @@
using Robust.Shared.Map;
using Robust.Shared.Serialization;
namespace Content.Shared.SurveillanceCamera;
@@ -17,30 +18,39 @@ public sealed class SurveillanceCameraMonitorUiState : BoundUserInterfaceState
public string ActiveAddress;
// Currently active subnet.
public string ActiveSubnet { get; }
// Known cameras, by address and name.
public Dictionary<string, string> Cameras { get; }
public Dictionary<NetEntity, CameraData> Cameras { get; }
public SurveillanceCameraMonitorUiState(NetEntity? activeCamera, HashSet<string> subnets, string activeAddress, string activeSubnet, Dictionary<string, string> cameras)
public SurveillanceCameraMonitorUiState(NetEntity? activeCamera, HashSet<string> subnets, string activeAddress, Dictionary<NetEntity, CameraData> cameras)
{
ActiveCamera = activeCamera;
Subnets = subnets;
ActiveAddress = activeAddress;
ActiveSubnet = activeSubnet;
Cameras = cameras;
}
}
// Sunrise-start
[Serializable, NetSerializable]
[DataDefinition]
public partial class CameraData
{
public string CameraAddress { get; set; }
public string SubnetAddress { get; set; }
public string Name { get; set; }
public NetCoordinates Coordinates { get; set; }
public Color SubnetColor { get; set; }
}
// Sunrise-end
[Serializable, NetSerializable]
public sealed class SurveillanceCameraMonitorSwitchMessage : BoundUserInterfaceMessage
{
public string Address { get; }
public NetEntity CameraNetEntity { get; }
public SurveillanceCameraMonitorSwitchMessage(string address)
public SurveillanceCameraMonitorSwitchMessage(NetEntity camera)
{
Address = address;
CameraNetEntity = camera;
}
}

View File

View File

@@ -6785,3 +6785,32 @@
id: 419
time: '2024-07-26T13:53:25.0000000+00:00'
url: https://api.github.com/repos/frosty-dev/ss14-core/pulls/499
- author: Warete
changes:
- message: "\u041A\u0430\u043C\u0435\u0440\u044B \u0441\u0442\u0430\u043B\u0438\
\ \u0431\u043E\u043B\u0435\u0435 \u043F\u0440\u0438\u044F\u0442\u043D\u044B\u043C\
\u0438 \u0432 \u0438\u0441\u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u043D\
\u0438\u0438"
type: Tweak
id: 420
time: '2024-07-27T15:47:27.0000000+00:00'
url: https://api.github.com/repos/frosty-dev/ss14-core/pulls/501
- author: PuroSlavKing
changes:
- message: "\u0414\u043E\u0431\u0430\u0432\u043B\u0435\u043D\u044B \u0441\u0442\u0435\
\u043A\u043B\u044F\u043D\u043D\u044B\u0435 \u0448\u043B\u044E\u0437\u044B \u0440\
\u0430\u0437\u043C\u0435\u0440\u0430\u043C\u0438 \u0432 2\u04451 \u0438 3\u0445\
1 \u0442\u0430\u0439\u043B\u0430."
type: Add
id: 421
time: '2024-07-27T15:46:53.0000000+00:00'
url: https://api.github.com/repos/frosty-dev/ss14-core/pulls/504
- author: ThereDrD
changes:
- message: "\u0420\u0430\u0437\u0433\u0435\u0440\u043C\u044B \u0441\u0442\u0430\u043B\
\u0438 \u044D\u0444\u0444\u0435\u043A\u0442\u043D\u0435\u0435 \u0438 \u0441\u043C\
\u0435\u0448\u043D\u0435\u0435"
type: Tweak
id: 422
time: '2024-07-27T15:48:25.0000000+00:00'
url: https://api.github.com/repos/frosty-dev/ss14-core/pulls/492

View File

@@ -0,0 +1,7 @@
ent-DoubleGlassAirlock = двойной стеклянный шлюз
.desc = { ent-AirlockGlass.desc }
.suffix = 2x1
ent-ThreepleGlassAirlock = тройной стеклянный шлюз
.desc = { ent-AirlockGlass.desc }
.suffix = 3x1

View File

@@ -11,3 +11,6 @@ surveillance-camera-setup = Настроить
surveillance-camera-setup-ui-set = Установить
surveillance-body-camera-on = { $item } начинает мигать
surveillance-body-camera-off = { $item } перестает мигать
surveillance-camera-monitor-ui-flavor-left = Большой брат смотрит.
surveillance-camera-monitor-ui-flavor-right = v1.984

View File

@@ -38,6 +38,7 @@
- SurveillanceCameraGeneral
- SurveillanceCameraMedical
- SurveillanceCameraCommand
subnetColor: "#088743"
- type: entity
parent: SurveillanceCameraRouterBase
@@ -46,6 +47,7 @@
components:
- type: SurveillanceCameraRouter
subnetFrequency: SurveillanceCameraEngineering
subnetColor: "#EFB341"
- type: entity
parent: SurveillanceCameraRouterBase
@@ -54,6 +56,7 @@
components:
- type: SurveillanceCameraRouter
subnetFrequency: SurveillanceCameraSecurity
subnetColor: "#DE3A3A"
- type: entity
parent: SurveillanceCameraRouterBase
@@ -62,6 +65,7 @@
components:
- type: SurveillanceCameraRouter
subnetFrequency: SurveillanceCameraScience
subnetColor: "#D381C9"
- type: entity
parent: SurveillanceCameraRouterBase
@@ -70,6 +74,7 @@
components:
- type: SurveillanceCameraRouter
subnetFrequency: SurveillanceCameraSupply
subnetColor: "#A46106"
- type: entity
parent: SurveillanceCameraRouterBase
@@ -78,6 +83,7 @@
components:
- type: SurveillanceCameraRouter
subnetFrequency: SurveillanceCameraCommand
subnetColor: "#052EED"
- type: entity
parent: SurveillanceCameraRouterBase
@@ -86,6 +92,7 @@
components:
- type: SurveillanceCameraRouter
subnetFrequency: SurveillanceCameraService
subnetColor: "#9FED58"
- type: entity
parent: SurveillanceCameraRouterBase
@@ -94,6 +101,7 @@
components:
- type: SurveillanceCameraRouter
subnetFrequency: SurveillanceCameraMedical
subnetColor: "#52B4E9"
- type: entity
parent: SurveillanceCameraRouterBase
@@ -102,6 +110,7 @@
components:
- type: SurveillanceCameraRouter
subnetFrequency: SurveillanceCameraGeneral
subnetColor: "#088743"
- type: entity
parent: [ BaseMachinePowered, ConstructibleMachine ]
@@ -136,6 +145,7 @@
setupAvailableNetworks:
- SurveillanceCameraEntertainment
- SurveillanceCameraSecurity
subnetColor: "#088743"
- type: entity
parent: SurveillanceCameraWirelessRouterBase
@@ -144,6 +154,7 @@
components:
- type: SurveillanceCameraRouter
subnetFrequency: SurveillanceCameraEntertainment
subnetColor: "#088743"
# Body Camera Separate Router
- type: entity

View File

@@ -0,0 +1,44 @@
- type: entity
parent: Airlock
id: DoubleGlassAirlock
components:
- type: MeleeSound
soundGroups:
Brute:
collection: GlassSmack
- type: Door
occludes: false
- type: Occluder
enabled: false
- type: Sprite
sprite: White/Structures/Doors/Airlocks/Glass/Wide/glass_2x1.rsi
snapCardinals: false
offset: 0.5,0
- type: AnimationPlayer
- type: Fixtures
fixtures:
fix1:
shape:
!type:PhysShapeAabb
bounds: "-0.49,-0.49,1.49,0.49" # 2x1
density: 100
mask:
- FullTileMask
layer:
- GlassAirlockLayer
- type: LayerChangeOnWeld
unWeldedLayer: GlassAirlockLayer
weldedLayer: GlassLayer
- type: Rotatable
rotateWhileAnchored: true
- type: Transform
noRot: false
- type: Construction
graph: Airlock
node: glassAirlock
- type: PaintableAirlock
group: Glass
department: null
- type: Tag
tags:
- GlassAirlock

View File

@@ -0,0 +1,43 @@
- type: entity
parent: Airlock
id: ThreepleGlassAirlock
components:
- type: MeleeSound
soundGroups:
Brute:
collection: GlassSmack
- type: Door
occludes: false
- type: Occluder
enabled: false
- type: Sprite # TODO: NORMAL 3x1 AIRLOCK SPRITE
sprite: White/Structures/Doors/Airlocks/Glass/Wide/glass_3x1.rsi
snapCardinals: false
- type: AnimationPlayer
- type: Fixtures
fixtures:
fix1:
shape:
!type:PhysShapeAabb
bounds: "-1.5,-0.49,1.5,0.49" # 3x1
density: 100
mask:
- FullTileMask
layer:
- GlassAirlockLayer
- type: LayerChangeOnWeld
unWeldedLayer: GlassAirlockLayer
weldedLayer: GlassLayer
- type: Rotatable
rotateWhileAnchored: true
- type: Transform
noRot: false
- type: Construction
graph: Airlock
node: glassAirlock
- type: PaintableAirlock
group: Glass
department: null
- type: Tag
tags:
- GlassAirlock

Binary file not shown.

After

Width:  |  Height:  |  Size: 312 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 267 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 267 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 293 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 264 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 849 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 475 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 625 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 272 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 272 B

View File

@@ -0,0 +1,264 @@
{
"version": 1,
"license": "CC-BY-SA-3.0",
"copyright": "Taken from IDINa_Huy.dmi | Edited by PuroSlavKing (Github)",
"size": {
"x": 64,
"y": 32
},
"states": [
{
"name": "assembly"
},
{
"name": "assembly-fill"
},
{
"name": "assembly-glass"
},
{
"name": "bolted_unlit"
},
{
"name": "bolted_open_unlit"
},
{
"name": "closed"
},
{
"name": "closed_unlit"
},
{
"name": "closed-fill"
},
{
"name": "closed-glass"
},
{
"name": "panel_closed"
},
{
"name": "closing",
"delays": [
[
0.2,
0.2,
0.2,
0.2,
0.2,
0.2,
0.2,
0.2,
0.2
]
]
},
{
"name": "closing_unlit",
"delays": [
[
0.1,
0.1,
0.07,
0.07,
0.07,
0.2
]
]
},
{
"name": "closing-fill",
"delays": [
[
0.1,
0.1,
0.07,
0.07,
0.07,
0.2
]
]
},
{
"name": "closing-glass",
"delays": [
[
0.1,
0.1,
0.07,
0.07,
0.07,
0.2
]
]
},
{
"name": "closing-panel",
"delays": [
[
0.1,
0.1,
0.07,
0.07,
0.07,
0.2
]
]
},
{
"name": "deny_unlit",
"delays": [
[
0.1,
0.1,
0.1
]
]
},
{
"name": "open"
},
{
"name": "open_unlit"
},
{
"name": "panel_open"
},
{
"name": "opening",
"delays": [
[
0.2,
0.2,
0.2,
0.2,
0.2,
0.2,
0.2,
0.2,
0.2
]
]
},
{
"name": "opening_unlit",
"delays": [
[
0.1,
0.1,
0.07,
0.07,
0.07,
0.2
]
]
},
{
"name": "opening-fill",
"delays": [
[
0.1,
0.1,
0.07,
0.07,
0.07,
0.2
]
]
},
{
"name": "opening-glass",
"delays": [
[
0.1,
0.1,
0.07,
0.07,
0.07,
0.2
]
]
},
{
"name": "opening-panel",
"delays": [
[
0.1,
0.1,
0.07,
0.07,
0.07,
0.2
]
]
},
{
"name": "sparks",
"delays": [
[
0.1,
0.1,
0.1,
0.1,
0.1,
0.1
]
]
},
{
"name": "sparks_broken",
"delays": [
[
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
1.7
]
]
},
{
"name": "sparks_damaged",
"delays": [
[
0.1,
0.1,
0.1,
0.1,
0.1,
0.1
]
]
},
{
"name": "sparks_open",
"delays": [
[
0.1,
0.1,
0.1,
0.1,
0.1,
0.1
]
]
},
{
"name": "welded"
},
{
"name": "emergency_unlit",
"delays": [
[
1.2,
1.2
]
]
},
{
"name": "emergency_open_unlit"
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 453 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 264 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 870 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 467 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1009 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 100 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 374 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 315 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 288 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 140 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 403 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 704 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 704 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 687 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 680 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 680 B

View File

@@ -0,0 +1,264 @@
{
"version": 1,
"license": "CC-BY-SA-3.0",
"copyright": "Taken from IDINa_Huy.dmi | Edited by PuroSlavKing (Github)",
"size": {
"x": 96,
"y": 32
},
"states": [
{
"name": "assembly"
},
{
"name": "assembly-fill"
},
{
"name": "assembly-glass"
},
{
"name": "bolted_unlit"
},
{
"name": "bolted_open_unlit"
},
{
"name": "closed"
},
{
"name": "closed_unlit"
},
{
"name": "closed-fill"
},
{
"name": "closed-glass"
},
{
"name": "panel_closed"
},
{
"name": "closing",
"delays": [
[
0.2,
0.2,
0.2,
0.2,
0.2,
0.2,
0.2,
0.2,
0.2
]
]
},
{
"name": "closing_unlit",
"delays": [
[
0.1,
0.1,
0.07,
0.07,
0.07,
0.2
]
]
},
{
"name": "closing-fill",
"delays": [
[
0.1,
0.1,
0.07,
0.07,
0.07,
0.2
]
]
},
{
"name": "closing-glass",
"delays": [
[
0.1,
0.1,
0.07,
0.07,
0.07,
0.2
]
]
},
{
"name": "closing-panel",
"delays": [
[
0.1,
0.1,
0.07,
0.07,
0.07,
0.2
]
]
},
{
"name": "deny_unlit",
"delays": [
[
0.1,
0.1,
0.1
]
]
},
{
"name": "open"
},
{
"name": "open_unlit"
},
{
"name": "panel_open"
},
{
"name": "opening",
"delays": [
[
0.2,
0.2,
0.2,
0.2,
0.2,
0.2,
0.2,
0.2,
0.2
]
]
},
{
"name": "opening_unlit",
"delays": [
[
0.1,
0.1,
0.07,
0.07,
0.07,
0.2
]
]
},
{
"name": "opening-fill",
"delays": [
[
0.1,
0.1,
0.07,
0.07,
0.07,
0.2
]
]
},
{
"name": "opening-glass",
"delays": [
[
0.1,
0.1,
0.07,
0.07,
0.07,
0.2
]
]
},
{
"name": "opening-panel",
"delays": [
[
0.1,
0.1,
0.07,
0.07,
0.07,
0.2
]
]
},
{
"name": "sparks",
"delays": [
[
0.1,
0.1,
0.1,
0.1,
0.1,
0.1
]
]
},
{
"name": "sparks_broken",
"delays": [
[
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
1.7
]
]
},
{
"name": "sparks_damaged",
"delays": [
[
0.1,
0.1,
0.1,
0.1,
0.1,
0.1
]
]
},
{
"name": "sparks_open",
"delays": [
[
0.1,
0.1,
0.1,
0.1,
0.1,
0.1
]
]
},
{
"name": "welded"
},
{
"name": "emergency_unlit",
"delays": [
[
1.2,
1.2
]
]
},
{
"name": "emergency_open_unlit"
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 837 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 687 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 105 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 744 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 164 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 701 B

View File

@@ -0,0 +1,14 @@
{
"version": 1,
"size": {
"x": 32,
"y": 32
},
"license": "CC-BY-SA-3.0",
"copyright": "",
"states": [
{
"name": "icon"
}
]
}