Adds Gas Analyzer (#1591)

* -Started Gas Analyzer
-TemperatureHelpers

* Formatting

* Adds PopupTooltip to NotifyManager

* Revert Tooltip fuckery

* Gas Analyzer gives proper error messages

* Localization

* Added a very wip gas analyzer ui

* UI works, doesn't look good but hey

* Safety checks

* Fancy WIP gas mix bar

* Gas Color

* Gas Amount shows only 2 decimal places

* -Made bar full width
-Moved gas list into a table
-Some gas bar things

* IDropped something

* Description

* -Percentage
-Padding

* ItemStatus

* -Proper Danger Warnings
-Added Warning danger state

* Pressure unit

Co-authored-by: Víctor Aguilera Puerto <6766154+Zumorica@users.noreply.github.com>
This commit is contained in:
Exp
2020-08-08 18:24:41 +02:00
committed by GitHub
parent 5b3b2e3207
commit cc9f16e738
14 changed files with 750 additions and 13 deletions

View File

@@ -1,39 +1,190 @@
#nullable enable
using Content.Server.GameObjects.EntitySystems;
using Content.Server.Interfaces;
using Content.Server.Interfaces.GameObjects.Components.Items;
using Content.Shared.Atmos;
using Content.Shared.GameObjects.Components;
using Content.Shared.GameObjects.EntitySystems;
using Content.Shared.Interfaces;
using Content.Shared.Interfaces.GameObjects.Components;
using Content.Shared.Utility;
using Robust.Server.GameObjects.Components.UserInterface;
using Robust.Server.Interfaces.GameObjects;
using Robust.Server.Interfaces.Player;
using Robust.Shared.GameObjects;
using Robust.Shared.GameObjects.Systems;
using Robust.Shared.IoC;
using Robust.Shared.Localization;
using Robust.Shared.Map;
using Robust.Shared.Utility;
using System;
using System.Collections.Generic;
namespace Content.Server.GameObjects.Components.Atmos
{
[RegisterComponent]
public class GasAnalyzerComponent : Component, IExamine
public class GasAnalyzerComponent : SharedGasAnalyzerComponent, IAfterInteract, IDropped
{
public override string Name => "GasAnalyzer";
public void Examine(FormattedMessage message, bool inDetailsRange)
{
if (!inDetailsRange) return;
#pragma warning disable 649
[Dependency] private IServerNotifyManager _notifyManager = default!;
#pragma warning restore 649
private BoundUserInterface _userInterface = default!;
private GasAnalyzerDanger _pressureDanger;
private float _timeSinceSync;
private const float TimeBetweenSyncs = 10f;
public override void Initialize()
{
base.Initialize();
_userInterface = Owner.GetComponent<ServerUserInterfaceComponent>()
.GetBoundUserInterface(GasAnalyzerUiKey.Key);
_userInterface.OnReceiveMessage += UserInterfaceOnReceiveMessage;
}
public override ComponentState GetComponentState()
{
return new GasAnalyzerComponentState(_pressureDanger);
}
/// <summary>
/// Call this from other components to open the gas analyzer UI.
/// </summary>
public void OpenInterface(IPlayerSession session)
{
_userInterface.Open(session);
UpdateUserInterface();
Resync();
}
public void CloseInterface(IPlayerSession session)
{
_userInterface.Close(session);
Resync();
}
public void Update(float frameTime)
{
_timeSinceSync += frameTime;
if (_timeSinceSync > TimeBetweenSyncs)
{
Resync();
}
}
private void Resync()
{
// 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.GridPosition).Air;
if (tile != null)
{
pressure = tile.Pressure;
}
if (pressure >= Atmospherics.HazardHighPressure || pressure <= Atmospherics.HazardLowPressure)
{
_pressureDanger = GasAnalyzerDanger.Hazard;
}
else if (pressure >= Atmospherics.WarningHighPressure || pressure <= Atmospherics.WarningLowPressure)
{
_pressureDanger = GasAnalyzerDanger.Warning;
}
else
{
_pressureDanger = GasAnalyzerDanger.Nominal;
}
Dirty();
_timeSinceSync = 0f;
}
private void UpdateUserInterface()
{
string? error = null;
var gam = EntitySystem.Get<AtmosphereSystem>().GetGridAtmosphere(Owner.Transform.GridID);
var tile = gam?.GetTile(Owner.Transform.GridPosition).Air;
if (tile == null)
{
error = "No Atmosphere!";
_userInterface.SetState(
new GasAnalyzerBoundUserInterfaceState(
0,
0,
null,
error));
return;
}
if (tile == null) return;
message.AddText($"Pressure: {tile.Pressure}\n");
message.AddText($"Temperature: {tile.Temperature}\n");
var gases = new List<GasEntry>();
for (int i = 0; i < Atmospherics.TotalNumberOfGases; i++)
{
var gas = Atmospherics.GetGas(i);
if (tile.Gases[i] <= Atmospherics.GasMinMoles) continue;
message.AddText(gas.Name);
message.AddText($"\n Moles: {tile.Gases[i]}\n");
gases.Add(new GasEntry(gas.Name, tile.Gases[i], gas.Color));
}
_userInterface.SetState(
new GasAnalyzerBoundUserInterfaceState(
tile.Pressure,
tile.Temperature,
gases.ToArray(),
error));
}
private void UserInterfaceOnReceiveMessage(ServerBoundUserInterfaceMessage serverMsg)
{
var message = serverMsg.Message;
switch (message)
{
case GasAnalyzerRefreshMessage msg:
var player = serverMsg.Session.AttachedEntity;
if (player == null)
{
return;
}
if (!player.TryGetComponent(out IHandsComponent handsComponent))
{
_notifyManager.PopupMessage(Owner.Transform.GridPosition, player,
Loc.GetString("You have no hands."));
return;
}
var activeHandEntity = handsComponent.GetActiveHand?.Owner;
if (activeHandEntity == null || !activeHandEntity.TryGetComponent(out GasAnalyzerComponent gasAnalyzer))
{
_notifyManager.PopupMessage(serverMsg.Session.AttachedEntity,
serverMsg.Session.AttachedEntity,
Loc.GetString("You need a Gas Analyzer in your hand!"));
return;
}
UpdateUserInterface();
Resync();
break;
}
}
void IAfterInteract.AfterInteract(AfterInteractEventArgs eventArgs)
{
if (eventArgs.User.TryGetComponent(out IActorComponent actor))
{
OpenInterface(actor.playerSession);
//TODO: show other sprite when ui open?
}
}
void IDropped.Dropped(DroppedEventArgs eventArgs)
{
if (eventArgs.User.TryGetComponent(out IActorComponent actor))
{
CloseInterface(actor.playerSession);
//TODO: if other sprite is shown, change again
}
}
}