convert News read tab to PDA Cartridge (#18368)

* Add Console, PDA news tab, and ringstone popup

* Add English localization

* Add mass-media console board to Advanced Entertainment resrarch

* Fix misprint

* Deleting unused libraries

* Fix round restart problem

* Fixing restart problem

* Just another fix

* Сode optimization

* Code optimization

* Convert News read tab to cartridge

Convert the News read tab into a cartridge, and fix a couple of bugs

* Just another fix

* Some updates

* More fixing!!

Fix cooldown, add author label to read menu

* Again, fix cooldown bug

* Some minor changes

* Revert "Some minor changes"

This reverts commit 470c8d727629ac79994f70e56162adae8659e944.

* Some minor updates
This commit is contained in:
MishaUnity
2023-07-28 22:59:03 +03:00
committed by GitHub
parent 70ceba5fbc
commit e4dcdc0c6e
32 changed files with 395 additions and 363 deletions

View File

@@ -0,0 +1,50 @@
using Content.Client.UserInterface.Fragments;
using Content.Shared.CartridgeLoader.Cartridges;
using Content.Shared.CartridgeLoader;
using Robust.Client.GameObjects;
using Robust.Client.UserInterface;
namespace Content.Client.CartridgeLoader.Cartridges;
public sealed class NewsReadUi : UIFragment
{
private NewsReadUiFragment? _fragment;
public override Control GetUIFragmentRoot()
{
return _fragment!;
}
public override void Setup(BoundUserInterface userInterface, EntityUid? fragmentOwner)
{
_fragment = new NewsReadUiFragment();
_fragment.OnNextButtonPressed += () =>
{
SendNewsReadMessage(NewsReadUiAction.Next, userInterface);
};
_fragment.OnPrevButtonPressed += () =>
{
SendNewsReadMessage(NewsReadUiAction.Prev, userInterface);
};
_fragment.OnNotificationSwithPressed += () =>
{
SendNewsReadMessage(NewsReadUiAction.NotificationSwith, userInterface);
};
}
public override void UpdateState(BoundUserInterfaceState state)
{
if (state is NewsReadBoundUserInterfaceState cast)
_fragment?.UpdateState(cast.Article, cast.TargetNum, cast.TotalNum, cast.NotificationOn);
else if (state is NewsReadEmptyBoundUserInterfaceState empty)
_fragment?.UpdateEmptyState(empty.NotificationOn);
}
private void SendNewsReadMessage(NewsReadUiAction action, BoundUserInterface userInterface)
{
var newsMessage = new NewsReadUiMessageEvent(action);
var message = new CartridgeUiMessage(newsMessage);
userInterface.SendMessage(message);
}
}

View File

@@ -0,0 +1,54 @@
<cartridges:NewsReadUiFragment xmlns:cartridges="clr-namespace:Content.Client.CartridgeLoader.Cartridges"
xmlns:gfx="clr-namespace:Robust.Client.Graphics;assembly=Robust.Client"
xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls"
xmlns="https://spacestation14.io" Margin="1 0 2 0">
<PanelContainer StyleClasses="BackgroundDark"></PanelContainer>
<BoxContainer Orientation="Horizontal" HorizontalExpand="True" Margin="5,5,5,5">
<Button
Name="Prev"
MinWidth="64"
HorizontalAlignment="Left"
Text="{Loc 'news-read-ui-past-text'}"
Access="Public"
HorizontalExpand="True"/>
<Button
Name="Next"
MinWidth="64"
HorizontalAlignment="Right"
Text="{Loc 'news-read-ui-next-text'}" />
</BoxContainer>
<controls:StripeBack Name="АrticleNameContainer">
<PanelContainer>
<Label Name="PageNum" VerticalAlignment="Center" HorizontalAlignment="Left" Margin="4,0,0,0"/>
<Label Name="PageName" Align="Center"/>
</PanelContainer>
</controls:StripeBack>
<PanelContainer VerticalExpand="True">
<PanelContainer.PanelOverride>
<gfx:StyleBoxFlat BackgroundColor="#80808005" />
</PanelContainer.PanelOverride>
<ScrollContainer
Name="PageTextScroll"
HScrollEnabled="False"
HorizontalExpand="True"
MinSize="0 0"
SizeFlagsStretchRatio="2"
VerticalExpand="True">
<BoxContainer
Name="PageTextContainer"
MinSize="0 0"
Orientation="Vertical"
SizeFlagsStretchRatio="2"
VerticalExpand="True">
</BoxContainer>
<RichTextLabel Margin="8,8,8,8" Name="PageText" VerticalAlignment="Top"/>
</ScrollContainer>
</PanelContainer>
<BoxContainer Orientation="Horizontal" HorizontalExpand="True" Margin="5,5,5,5">
<Button
Name="NotificationSwith"
MinWidth="20"/>
<RichTextLabel Margin="5,2,2,2" Name="ShareTime" VerticalAlignment="Top"/>
<RichTextLabel Margin="5,2,2,2" Name="Author" VerticalAlignment="Top" HorizontalAlignment="Right"/>
</BoxContainer>
</cartridges:NewsReadUiFragment>

View File

@@ -0,0 +1,60 @@
using Content.Client.Message;
using Content.Shared.MassMedia.Systems;
using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.XAML;
namespace Content.Client.CartridgeLoader.Cartridges;
[GenerateTypedNameReferences]
public sealed partial class NewsReadUiFragment : BoxContainer
{
public event Action? OnNextButtonPressed;
public event Action? OnPrevButtonPressed;
public event Action? OnNotificationSwithPressed;
public NewsReadUiFragment()
{
RobustXamlLoader.Load(this);
Orientation = LayoutOrientation.Vertical;
HorizontalExpand = true;
VerticalExpand = true;
Next.OnPressed += _ => OnNextButtonPressed?.Invoke();
Prev.OnPressed += _ => OnPrevButtonPressed?.Invoke();
NotificationSwith.OnPressed += _ => OnNotificationSwithPressed?.Invoke();
}
public void UpdateState(NewsArticle article, int targetNum, int totalNum, bool notificationOn)
{
PageNum.Visible = true;
PageText.Visible = true;
ShareTime.Visible = true;
Author.Visible = true;
PageName.Text = article.Name;
PageText.SetMarkup(article.Content);
PageNum.Text = $"{targetNum}/{totalNum}";
NotificationSwith.Text = Loc.GetString(notificationOn ? "news-read-ui-notification-on" : "news-read-ui-notification-off");
string shareTime = article.ShareTime.ToString("hh\\:mm\\:ss");
ShareTime.SetMarkup(Loc.GetString("news-read-ui-time-prefix-text") + " " + shareTime);
Author.SetMarkup(Loc.GetString("news-read-ui-author-prefix") + " " + (article.Author != null ? article.Author : Loc.GetString("news-read-ui-no-author")));
}
public void UpdateEmptyState(bool notificationOn)
{
PageNum.Visible = false;
PageText.Visible = false;
ShareTime.Visible = false;
Author.Visible = false;
PageName.Text = Loc.GetString("news-read-ui-not-found-text");
NotificationSwith.Text = Loc.GetString(notificationOn ? "news-read-ui-notification-on" : "news-read-ui-notification-off");
}
}

View File

@@ -1,4 +1,4 @@
<cartridges:NotekeeperUiFragment xmlns:cartridges="clr-namespace:Content.Client.CartridgeLoader.Cartridges" <cartridges:NotekeeperUiFragment xmlns:cartridges="clr-namespace:Content.Client.CartridgeLoader.Cartridges"
xmlns="https://spacestation14.io" Margin="1 0 2 0"> xmlns="https://spacestation14.io" Margin="1 0 2 0">
<PanelContainer StyleClasses="BackgroundDark"></PanelContainer> <PanelContainer StyleClasses="BackgroundDark"></PanelContainer>
<BoxContainer Orientation="Vertical" HorizontalExpand="True" VerticalExpand="True"> <BoxContainer Orientation="Vertical" HorizontalExpand="True" VerticalExpand="True">

View File

@@ -1,58 +0,0 @@
using JetBrains.Annotations;
using Robust.Client.GameObjects;
using Content.Shared.MassMedia.Components;
using Robust.Shared.Timing;
namespace Content.Client.MassMedia.Ui
{
[UsedImplicitly]
public sealed class NewsReadBoundUserInterface : BoundUserInterface
{
[Dependency] private readonly IGameTiming _gameTiming = default!;
[ViewVariables]
private NewsReadMenu? _menu;
[ViewVariables]
private string _windowName = Loc.GetString("news-read-ui-default-title");
public NewsReadBoundUserInterface(EntityUid owner, Enum uiKey) : base(owner, uiKey)
{
}
protected override void Open()
{
_menu = new NewsReadMenu(_windowName);
_menu.OpenCentered();
_menu.OnClose += Close;
_menu.NextButtonPressed += () => SendMessage(new NewsReadNextMessage());
_menu.PastButtonPressed += () => SendMessage(new NewsReadPrevMessage());
SendMessage(new NewsReadArticleRequestMessage());
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (!disposing)
return;
_menu?.Close();
_menu?.Dispose();
}
protected override void UpdateState(BoundUserInterfaceState state)
{
base.UpdateState(state);
if (_menu == null)
return;
if (state is NewsReadBoundUserInterfaceState cast)
_menu.UpdateUI(cast.Article, cast.TargetNum, cast.TotalNum);
if (state is NewsReadEmptyBoundUserInterfaceState)
_menu.UpdateEmptyUI();
}
}
}

View File

@@ -1,52 +0,0 @@
<DefaultWindow
xmlns="https://spacestation14.io"
xmlns:gfx="clr-namespace:Robust.Client.Graphics;assembly=Robust.Client"
xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls"
Title="{Loc 'news-read-ui-default-title'}"
MinSize="512 512"
SetSize="512 512">
<BoxContainer Orientation="Vertical">
<BoxContainer Margin="4,4,4,4" Orientation="Horizontal">
<Button
Name="Past"
MinWidth="64"
HorizontalAlignment="Left"
Text="{Loc 'news-read-ui-past-text'}"
Access="Public"
HorizontalExpand="True" />
<Button
Name="Next"
MinWidth="64"
HorizontalAlignment="Right"
Text="{Loc 'news-read-ui-next-text'}" />
</BoxContainer>
<controls:StripeBack Name="АrticleNameContainer">
<PanelContainer>
<Label Name="PageNum" VerticalAlignment="Center" HorizontalAlignment="Left" Margin="10,0,0,0"/>
<Label Name="PageName" Align="Center"/>
</PanelContainer>
</controls:StripeBack>
<PanelContainer VerticalExpand="True">
<PanelContainer.PanelOverride>
<gfx:StyleBoxFlat BackgroundColor="#80808005" />
</PanelContainer.PanelOverride>
<ScrollContainer
Name="PageTextScroll"
HScrollEnabled="False"
HorizontalExpand="True"
MinSize="100 256"
SizeFlagsStretchRatio="2"
VerticalExpand="True">
<BoxContainer
Name="PageTextContainer"
MinSize="100 256"
Orientation="Vertical"
SizeFlagsStretchRatio="2"
VerticalExpand="True">
</BoxContainer>
<RichTextLabel Margin="8,8,8,8" Name="PageText" VerticalAlignment="Top"/>
</ScrollContainer>
</PanelContainer>
<RichTextLabel Margin="8,8,8,8" Name="ShareTime" VerticalAlignment="Top"/>
</BoxContainer>
</DefaultWindow>

View File

@@ -1,50 +0,0 @@
using Content.Client.Message;
using Content.Shared.MassMedia.Systems;
using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface.CustomControls;
using Robust.Client.UserInterface.XAML;
namespace Content.Client.MassMedia.Ui;
[GenerateTypedNameReferences]
public sealed partial class NewsReadMenu : DefaultWindow
{
public event Action? NextButtonPressed;
public event Action? PastButtonPressed;
public NewsReadMenu(string name)
{
RobustXamlLoader.Load(this);
IoCManager.InjectDependencies(this);
if (Window != null)
Window.Title = name;
Next.OnPressed += _ => NextButtonPressed?.Invoke();
Past.OnPressed += _ => PastButtonPressed?.Invoke();
}
public void UpdateUI(NewsArticle article, int targetNum, int totalNum)
{
PageNum.Visible = true;
PageText.Visible = true;
ShareTime.Visible = true;
PageName.Text = $"{article.Name} by {article.Author ?? Loc.GetString("news-read-ui-no-author")}";
PageText.SetMarkup(article.Content);
PageNum.Text = $"{targetNum}/{totalNum}";
string shareTime = article.ShareTime.ToString("hh\\:mm\\:ss");
ShareTime.SetMarkup($"{Loc.GetString("news-read-ui-time-prefix-text")} {shareTime}");
}
public void UpdateEmptyUI()
{
PageName.Text = Loc.GetString("news-read-ui-not-found-text");
PageNum.Visible = false;
PageText.Visible = false;
ShareTime.Visible = false;
}
}

View File

@@ -57,7 +57,7 @@ namespace Content.Client.MassMedia.Ui
if (_menu == null || state is not NewsWriteBoundUserInterfaceState cast) if (_menu == null || state is not NewsWriteBoundUserInterfaceState cast)
return; return;
_menu.UpdateUI(cast.Articles); _menu.UpdateUI(cast.Articles, cast.ShareAvalible);
} }
private void OnShareButtonPressed() private void OnShareButtonPressed()
@@ -71,10 +71,15 @@ namespace Content.Client.MassMedia.Ui
if (_gameTicker == null) return; if (_gameTicker == null) return;
NewsArticle article = new NewsArticle(); NewsArticle article = new NewsArticle();
article.Name = _menu.NameInput.Text; var stringName = _menu.NameInput.Text;
var name = (stringName.Length <= 25 ? stringName.Trim() : $"{stringName.Trim().Substring(0, 25)}...");
article.Name = name;
article.Content = stringContent; article.Content = stringContent;
article.ShareTime = _gameTiming.CurTime.Subtract(_gameTicker.RoundStartTimeSpan); article.ShareTime = _gameTiming.CurTime.Subtract(_gameTicker.RoundStartTimeSpan);
_menu.ContentInput.TextRope = new Rope.Leaf(string.Empty);
_menu.NameInput.Text = string.Empty;
SendMessage(new NewsWriteShareMessage(article)); SendMessage(new NewsWriteShareMessage(article));
} }

View File

@@ -26,7 +26,7 @@ public sealed partial class NewsWriteMenu : DefaultWindow
Share.OnPressed += _ => ShareButtonPressed?.Invoke(); Share.OnPressed += _ => ShareButtonPressed?.Invoke();
} }
public void UpdateUI(NewsArticle[] articles) public void UpdateUI(NewsArticle[] articles, bool shareAvalible)
{ {
ArticleCardsContainer.Children.Clear(); ArticleCardsContainer.Children.Clear();
@@ -38,5 +38,7 @@ public sealed partial class NewsWriteMenu : DefaultWindow
ArticleCardsContainer.AddChild(mini); ArticleCardsContainer.AddChild(mini);
} }
Share.Disabled = !shareAvalible;
} }
} }

View File

@@ -73,12 +73,6 @@ namespace Content.Client.PDA
SendMessage(new PdaLockUplinkMessage()); SendMessage(new PdaLockUplinkMessage());
}; };
_menu.NewsReadButton.OnPressed += _ =>
{
SendMessage(new PdaOpenNewsMessage());
};
_menu.OnProgramItemPressed += ActivateCartridge; _menu.OnProgramItemPressed += ActivateCartridge;
_menu.OnInstallButtonPressed += InstallCartridge; _menu.OnInstallButtonPressed += InstallCartridge;
_menu.OnUninstallButtonPressed += UninstallCartridge; _menu.OnUninstallButtonPressed += UninstallCartridge;

View File

@@ -65,10 +65,6 @@
Text="{Loc 'crew-manifest-button-label'}" Text="{Loc 'crew-manifest-button-label'}"
Description="{Loc 'crew-manifest-button-description'}" Description="{Loc 'crew-manifest-button-description'}"
Visible="False" /> Visible="False" />
<pda:PdaSettingsButton Name="NewsReadButton"
Access="Public"
Text="{Loc 'pda-news-button-label'}"
Description="{Loc 'pda-news-button-description'}"/>
<pda:PdaSettingsButton Name="ActivateMusicButton" <pda:PdaSettingsButton Name="ActivateMusicButton"
Access="Public" Access="Public"
Text="{Loc 'pda-bound-user-interface-music-button'}" Text="{Loc 'pda-bound-user-interface-music-button'}"

View File

@@ -0,0 +1,11 @@
namespace Content.Server.CartridgeLoader.Cartridges;
[RegisterComponent]
public sealed class NewsReadCartridgeComponent : Component
{
[ViewVariables(VVAccess.ReadWrite)]
public int ArticleNum;
[ViewVariables(VVAccess.ReadWrite)]
public bool NotificationOn = true;
}

View File

@@ -1,4 +1,4 @@
namespace Content.Server.CartridgeLoader.Cartridges; namespace Content.Server.CartridgeLoader.Cartridges;
[RegisterComponent] [RegisterComponent]
public sealed class NotekeeperCartridgeComponent : Component public sealed class NotekeeperCartridgeComponent : Component

View File

@@ -1,4 +1,4 @@
using Content.Shared.CartridgeLoader; using Content.Shared.CartridgeLoader;
using Content.Shared.CartridgeLoader.Cartridges; using Content.Shared.CartridgeLoader.Cartridges;
namespace Content.Server.CartridgeLoader.Cartridges; namespace Content.Server.CartridgeLoader.Cartridges;

View File

@@ -1,9 +0,0 @@
namespace Content.Server.MassMedia.Components
{
[RegisterComponent]
public sealed class NewsReadComponent : Component
{
[ViewVariables(VVAccess.ReadWrite)]
public int ArticleNum;
}
}

View File

@@ -1,8 +1,17 @@
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
namespace Content.Server.MassMedia.Components namespace Content.Server.MassMedia.Components
{ {
[RegisterComponent] [RegisterComponent]
public sealed class NewsWriteComponent : Component public sealed class NewsWriteComponent : Component
{ {
[ViewVariables(VVAccess.ReadWrite)]
public bool ShareAvalible = false;
[ViewVariables(VVAccess.ReadWrite), DataField("nextShare", customTypeSerializer: typeof(TimeOffsetSerializer))]
public TimeSpan NextShare;
[ViewVariables(VVAccess.ReadWrite), DataField("shareCooldown")]
public float ShareCooldown = 60f;
} }
} }

View File

@@ -8,28 +8,37 @@ using Content.Shared.MassMedia.Systems;
using Content.Shared.PDA; using Content.Shared.PDA;
using Robust.Server.GameObjects; using Robust.Server.GameObjects;
using System.Linq; using System.Linq;
using Content.Server.CartridgeLoader.Cartridges;
using Content.Shared.CartridgeLoader;
using Content.Shared.CartridgeLoader.Cartridges;
using Content.Server.CartridgeLoader;
using Robust.Shared.Timing;
using TerraFX.Interop.Windows; using TerraFX.Interop.Windows;
namespace Content.Server.MassMedia.Systems; namespace Content.Server.MassMedia.Systems;
public sealed class NewsSystem : EntitySystem public sealed class NewsSystem : EntitySystem
{ {
[Dependency] private readonly IGameTiming _timing = default!;
[Dependency] private readonly UserInterfaceSystem _ui = default!; [Dependency] private readonly UserInterfaceSystem _ui = default!;
[Dependency] private readonly RingerSystem _ringer = default!; [Dependency] private readonly RingerSystem _ringer = default!;
[Dependency] private readonly CartridgeLoaderSystem? _cartridgeLoaderSystem = default!;
[Dependency] private readonly AccessReaderSystem _accessReader = default!; [Dependency] private readonly AccessReaderSystem _accessReader = default!;
private readonly List<NewsArticle> _articles = new List<NewsArticle>(); private readonly List<NewsArticle> _articles = new List<NewsArticle>();
public override void Initialize() public override void Initialize()
{ {
base.Initialize(); base.Initialize();
SubscribeLocalEvent<NewsWriteComponent, NewsWriteShareMessage>(OnWriteUiMessage); SubscribeLocalEvent<NewsWriteComponent, NewsWriteShareMessage>(OnWriteUiShareMessage);
SubscribeLocalEvent<NewsWriteComponent, NewsWriteDeleteMessage>(OnDeleteUiMessage); SubscribeLocalEvent<NewsWriteComponent, NewsWriteDeleteMessage>(OnWriteUiDeleteMessage);
SubscribeLocalEvent<NewsWriteComponent, NewsWriteArticlesRequestMessage>(OnRequestUiMessage); SubscribeLocalEvent<NewsWriteComponent, NewsWriteArticlesRequestMessage>(OnRequestWriteUiMessage);
SubscribeLocalEvent<NewsReadComponent, NewsReadNextMessage>(OnNextArticleUiMessage);
SubscribeLocalEvent<NewsReadComponent, NewsReadPrevMessage>(OnPrevArticleUiMessage); SubscribeLocalEvent<NewsReadCartridgeComponent, CartridgeUiReadyEvent>(OnReadUiReady);
SubscribeLocalEvent<NewsReadComponent, NewsReadArticleRequestMessage>(OnReadUiMessage); SubscribeLocalEvent<NewsReadCartridgeComponent, CartridgeMessageEvent>(OnReadUiMessage);
SubscribeLocalEvent<RoundRestartCleanupEvent>(OnRoundRestart); SubscribeLocalEvent<RoundRestartCleanupEvent>(OnRoundRestart);
} }
@@ -39,17 +48,6 @@ public sealed class NewsSystem : EntitySystem
_articles?.Clear(); _articles?.Clear();
} }
public void ToggleUi(EntityUid user, EntityUid deviceEnt, NewsReadComponent? component)
{
if (!Resolve(deviceEnt, ref component))
return;
if (!TryComp<ActorComponent>(user, out var actor))
return;
_ui.TryToggleUi(deviceEnt, NewsReadUiKey.Key, actor.PlayerSession);
}
public void ToggleUi(EntityUid user, EntityUid deviceEnt, NewsWriteComponent? component) public void ToggleUi(EntityUid user, EntityUid deviceEnt, NewsWriteComponent? component)
{ {
if (!Resolve(deviceEnt, ref component)) if (!Resolve(deviceEnt, ref component))
@@ -61,41 +59,49 @@ public sealed class NewsSystem : EntitySystem
_ui.TryToggleUi(deviceEnt, NewsWriteUiKey.Key, actor.PlayerSession); _ui.TryToggleUi(deviceEnt, NewsWriteUiKey.Key, actor.PlayerSession);
} }
public void UpdateWriteUi(EntityUid uid) public void OnReadUiReady(EntityUid uid, NewsReadCartridgeComponent component, CartridgeUiReadyEvent args)
{
UpdateReadUi(uid, args.Loader, component);
}
public void UpdateWriteUi(EntityUid uid, NewsWriteComponent component)
{ {
if (!_ui.TryGetUi(uid, NewsWriteUiKey.Key, out _)) if (!_ui.TryGetUi(uid, NewsWriteUiKey.Key, out _))
return; return;
var state = new NewsWriteBoundUserInterfaceState(_articles.ToArray()); var state = new NewsWriteBoundUserInterfaceState(_articles.ToArray(), component.ShareAvalible);
_ui.TrySetUiState(uid, NewsWriteUiKey.Key, state); _ui.TrySetUiState(uid, NewsWriteUiKey.Key, state);
} }
public void UpdateReadUi(EntityUid uid, NewsReadComponent component) public void UpdateReadUi(EntityUid uid, EntityUid loaderUid, NewsReadCartridgeComponent? component)
{ {
if (!_ui.TryGetUi(uid, NewsReadUiKey.Key, out _)) if (!Resolve(uid, ref component))
return; return;
if (component.ArticleNum < 0) NewsReadLeafArticle(component, 0);
{
NewsReadPreviousArticle(component);
}
if (_articles.Any()) if (_articles.Any())
{ _cartridgeLoaderSystem?.UpdateCartridgeUiState(loaderUid, new NewsReadBoundUserInterfaceState(_articles[component.ArticleNum], component.ArticleNum + 1, _articles.Count, component.NotificationOn));
if (component.ArticleNum >= _articles.Count)
{
component.ArticleNum = _articles.Count - 1;
}
_ui.TrySetUiState(uid, NewsReadUiKey.Key, new NewsReadBoundUserInterfaceState(_articles[component.ArticleNum], component.ArticleNum + 1, _articles.Count));
}
else else
{ _cartridgeLoaderSystem?.UpdateCartridgeUiState(loaderUid, new NewsReadEmptyBoundUserInterfaceState(component.NotificationOn));
_ui.TrySetUiState(uid, NewsReadUiKey.Key, new NewsReadEmptyBoundUserInterfaceState());
}
} }
public void OnWriteUiMessage(EntityUid uid, NewsWriteComponent component, NewsWriteShareMessage msg) private void OnReadUiMessage(EntityUid uid, NewsReadCartridgeComponent component, CartridgeMessageEvent args)
{
if (args is not NewsReadUiMessageEvent message)
return;
if (message.Action == NewsReadUiAction.Next)
NewsReadLeafArticle(component, 1);
if (message.Action == NewsReadUiAction.Prev)
NewsReadLeafArticle(component, -1);
if (message.Action == NewsReadUiAction.NotificationSwith)
component.NotificationOn = !component.NotificationOn;
UpdateReadUi(uid, args.LoaderUid, component);
}
public void OnWriteUiShareMessage(EntityUid uid, NewsWriteComponent component, NewsWriteShareMessage msg)
{ {
var article = msg.Article; var article = msg.Article;
@@ -127,12 +133,15 @@ public sealed class NewsSystem : EntitySystem
_articles.Add(article); _articles.Add(article);
component.ShareAvalible = false;
component.NextShare = _timing.CurTime + TimeSpan.FromSeconds(component.ShareCooldown);
UpdateReadDevices(); UpdateReadDevices();
UpdateWriteDevices(); UpdateWriteDevices();
TryNotify(); TryNotify();
} }
public void OnDeleteUiMessage(EntityUid uid, NewsWriteComponent component, NewsWriteDeleteMessage msg) public void OnWriteUiDeleteMessage(EntityUid uid, NewsWriteComponent component, NewsWriteDeleteMessage msg)
{ {
if (msg.ArticleNum > _articles.Count) if (msg.ArticleNum > _articles.Count)
return; return;
@@ -157,67 +166,44 @@ public sealed class NewsSystem : EntitySystem
UpdateWriteDevices(); UpdateWriteDevices();
} }
public void OnRequestUiMessage(EntityUid uid, NewsWriteComponent component, NewsWriteArticlesRequestMessage msg) public void OnRequestWriteUiMessage(EntityUid uid, NewsWriteComponent component, NewsWriteArticlesRequestMessage msg)
{ {
UpdateWriteUi(uid); UpdateWriteUi(uid, component);
} }
public void OnNextArticleUiMessage(EntityUid uid, NewsReadComponent component, NewsReadNextMessage msg) private void NewsReadLeafArticle(NewsReadCartridgeComponent component, int leafDir)
{ {
NewsReadNextArticle(component); component.ArticleNum += leafDir;
UpdateReadUi(uid, component); if (component.ArticleNum >= _articles.Count) component.ArticleNum = 0;
} if (component.ArticleNum < 0) component.ArticleNum = _articles.Count - 1;
public void OnPrevArticleUiMessage(EntityUid uid, NewsReadComponent component, NewsReadPrevMessage msg)
{
NewsReadPreviousArticle(component);
UpdateReadUi(uid, component);
}
public void OnReadUiMessage(EntityUid uid, NewsReadComponent component, NewsReadArticleRequestMessage msg)
{
UpdateReadUi(uid, component);
}
private void NewsReadNextArticle(NewsReadComponent component)
{
if (!_articles.Any())
{
return;
}
component.ArticleNum = (component.ArticleNum + 1) % _articles.Count;
}
private void NewsReadPreviousArticle(NewsReadComponent component)
{
if (!_articles.Any())
{
return;
}
component.ArticleNum = (component.ArticleNum - 1 + _articles.Count) % _articles.Count;
} }
private void TryNotify() private void TryNotify()
{ {
var query = EntityQueryEnumerator<NewsReadComponent, RingerComponent>(); var query = EntityQueryEnumerator<CartridgeLoaderComponent, RingerComponent>();
while (query.MoveNext(out var owner, out var _, out var ringer)) while (query.MoveNext(out var owner, out var comp, out var ringer))
{ {
_ringer.RingerPlayRingtone(owner, ringer); foreach (var app in comp.InstalledPrograms)
{
if (EntityManager.TryGetComponent<NewsReadCartridgeComponent>(app, out var cartridge) && cartridge.NotificationOn)
{
_ringer.RingerPlayRingtone(owner, ringer);
break;
}
}
} }
} }
private void UpdateReadDevices() private void UpdateReadDevices()
{ {
var query = EntityQueryEnumerator<NewsReadComponent>(); var query = EntityQueryEnumerator<CartridgeLoaderComponent>();
while (query.MoveNext(out var owner, out var comp)) while (query.MoveNext(out var owner, out var comp))
{ {
UpdateReadUi(owner, comp); if (EntityManager.TryGetComponent<NewsReadCartridgeComponent>(comp.ActiveProgram, out var cartridge))
UpdateReadUi(cartridge.Owner, comp.Owner, cartridge);
} }
} }
@@ -225,9 +211,25 @@ public sealed class NewsSystem : EntitySystem
{ {
var query = EntityQueryEnumerator<NewsWriteComponent>(); var query = EntityQueryEnumerator<NewsWriteComponent>();
while (query.MoveNext(out var owner, out var _)) while (query.MoveNext(out var owner, out var comp))
{ {
UpdateWriteUi(owner); UpdateWriteUi(owner, comp);
}
}
public override void Update(float frameTime)
{
base.Update(frameTime);
var query = EntityQueryEnumerator<NewsWriteComponent>();
while (query.MoveNext(out var comp))
{
if (comp.ShareAvalible || _timing.CurTime < comp.NextShare)
continue;
comp.ShareAvalible = true;
UpdateWriteUi(comp.Owner, comp);
} }
} }
} }

View File

@@ -44,7 +44,6 @@ namespace Content.Server.PDA
SubscribeLocalEvent<PdaComponent, PdaShowMusicMessage>(OnUiMessage); SubscribeLocalEvent<PdaComponent, PdaShowMusicMessage>(OnUiMessage);
SubscribeLocalEvent<PdaComponent, PdaShowUplinkMessage>(OnUiMessage); SubscribeLocalEvent<PdaComponent, PdaShowUplinkMessage>(OnUiMessage);
SubscribeLocalEvent<PdaComponent, PdaLockUplinkMessage>(OnUiMessage); SubscribeLocalEvent<PdaComponent, PdaLockUplinkMessage>(OnUiMessage);
SubscribeLocalEvent<PdaComponent, PdaOpenNewsMessage>(OnUiMessage);
SubscribeLocalEvent<StationRenamedEvent>(OnStationRenamed); SubscribeLocalEvent<StationRenamedEvent>(OnStationRenamed);
SubscribeLocalEvent<AlertLevelChangedEvent>(OnAlertLevelChanged); SubscribeLocalEvent<AlertLevelChangedEvent>(OnAlertLevelChanged);
@@ -115,7 +114,6 @@ namespace Content.Server.PDA
var address = GetDeviceNetAddress(uid); var address = GetDeviceNetAddress(uid);
var hasInstrument = HasComp<InstrumentComponent>(uid); var hasInstrument = HasComp<InstrumentComponent>(uid);
var showUplink = HasComp<StoreComponent>(uid) && IsUnlocked(uid); var showUplink = HasComp<StoreComponent>(uid) && IsUnlocked(uid);
var showNews = HasComp<NewsReadComponent>(uid);
UpdateStationName(uid, pda); UpdateStationName(uid, pda);
UpdateAlertLevel(uid, pda); UpdateAlertLevel(uid, pda);
@@ -137,7 +135,6 @@ namespace Content.Server.PDA
pda.StationName, pda.StationName,
showUplink, showUplink,
hasInstrument, hasInstrument,
showNews,
address); address);
_cartridgeLoader?.UpdateUiState(uid, state); _cartridgeLoader?.UpdateUiState(uid, state);
@@ -200,18 +197,6 @@ namespace Content.Server.PDA
} }
} }
private void OnUiMessage(EntityUid uid, PdaComponent pda, PdaOpenNewsMessage msg)
{
if (!PdaUiKey.Key.Equals(msg.UiKey))
return;
if (TryComp<NewsReadComponent>(uid, out var news))
{
_news.ToggleUi(msg.Session.AttachedEntity!.Value, uid, news);
UpdatePdaUi(uid, pda);
}
}
private bool IsUnlocked(EntityUid uid) private bool IsUnlocked(EntityUid uid)
{ {
return !TryComp<RingerUplinkComponent>(uid, out var uplink) || uplink.Unlocked; return !TryComp<RingerUplinkComponent>(uid, out var uplink) || uplink.Unlocked;

View File

@@ -0,0 +1,22 @@
using Robust.Shared.Serialization;
namespace Content.Shared.CartridgeLoader.Cartridges;
[Serializable, NetSerializable]
public sealed class NewsReadUiMessageEvent : CartridgeMessageEvent
{
public readonly NewsReadUiAction Action;
public NewsReadUiMessageEvent(NewsReadUiAction action)
{
Action = action;
}
}
[Serializable, NetSerializable]
public enum NewsReadUiAction
{
Next,
Prev,
NotificationSwith
}

View File

@@ -0,0 +1,32 @@
using Robust.Shared.Serialization;
using Content.Shared.MassMedia.Systems;
namespace Content.Shared.CartridgeLoader.Cartridges;
[Serializable, NetSerializable]
public sealed class NewsReadBoundUserInterfaceState : BoundUserInterfaceState
{
public NewsArticle Article;
public int TargetNum;
public int TotalNum;
public bool NotificationOn;
public NewsReadBoundUserInterfaceState(NewsArticle article, int targetNum, int totalNum, bool notificationOn)
{
Article = article;
TargetNum = targetNum;
TotalNum = totalNum;
NotificationOn = notificationOn;
}
}
[Serializable, NetSerializable]
public sealed class NewsReadEmptyBoundUserInterfaceState : BoundUserInterfaceState
{
public bool NotificationOn;
public NewsReadEmptyBoundUserInterfaceState(bool notificationOn)
{
NotificationOn = notificationOn;
}
}

View File

@@ -1,4 +1,4 @@
using Robust.Shared.Serialization; using Robust.Shared.Serialization;
namespace Content.Shared.CartridgeLoader.Cartridges; namespace Content.Shared.CartridgeLoader.Cartridges;

View File

@@ -1,57 +0,0 @@
using Robust.Shared.Serialization;
using Content.Shared.MassMedia.Systems;
namespace Content.Shared.MassMedia.Components;
[Serializable, NetSerializable]
public enum NewsReadUiKey : byte
{
Key
}
[Serializable, NetSerializable]
public sealed class NewsReadBoundUserInterfaceState : BoundUserInterfaceState
{
public NewsArticle Article;
public int TargetNum;
public int TotalNum;
public NewsReadBoundUserInterfaceState(NewsArticle article, int targetNum, int totalNum)
{
Article = article;
TargetNum = targetNum;
TotalNum = totalNum;
}
}
[Serializable, NetSerializable]
public sealed class NewsReadEmptyBoundUserInterfaceState : BoundUserInterfaceState
{
public NewsReadEmptyBoundUserInterfaceState()
{
}
}
[Serializable, NetSerializable]
public sealed class NewsReadNextMessage : BoundUserInterfaceMessage
{
public NewsReadNextMessage()
{
}
}
[Serializable, NetSerializable]
public sealed class NewsReadPrevMessage : BoundUserInterfaceMessage
{
public NewsReadPrevMessage()
{
}
}
[Serializable, NetSerializable]
public sealed class NewsReadArticleRequestMessage : BoundUserInterfaceMessage
{
public NewsReadArticleRequestMessage()
{
}
}

View File

@@ -13,10 +13,12 @@ public enum NewsWriteUiKey : byte
public sealed class NewsWriteBoundUserInterfaceState : BoundUserInterfaceState public sealed class NewsWriteBoundUserInterfaceState : BoundUserInterfaceState
{ {
public NewsArticle[] Articles; public NewsArticle[] Articles;
public bool ShareAvalible;
public NewsWriteBoundUserInterfaceState(NewsArticle[] articles) public NewsWriteBoundUserInterfaceState(NewsArticle[] articles, bool shareAvalible)
{ {
Articles = articles; Articles = articles;
ShareAvalible = shareAvalible;
} }
} }

View File

@@ -32,12 +32,6 @@ public sealed class PdaShowMusicMessage : BoundUserInterfaceMessage
public PdaShowMusicMessage() { } public PdaShowMusicMessage() { }
} }
[Serializable, NetSerializable]
public sealed class PdaOpenNewsMessage : BoundUserInterfaceMessage
{
public PdaOpenNewsMessage() { }
}
[Serializable, NetSerializable] [Serializable, NetSerializable]
public sealed class PdaRequestUpdateInterfaceMessage : BoundUserInterfaceMessage public sealed class PdaRequestUpdateInterfaceMessage : BoundUserInterfaceMessage
{ {

View File

@@ -12,24 +12,17 @@ namespace Content.Shared.PDA
public string? StationName; public string? StationName;
public bool HasUplink; public bool HasUplink;
public bool CanPlayMusic; public bool CanPlayMusic;
public bool HasNewsTab;
public string? Address; public string? Address;
public PdaUpdateState(bool flashlightEnabled, public PdaUpdateState(bool flashlightEnabled, bool hasPen, PdaIdInfoText pdaOwnerInfo,
bool hasPen, string? stationName, bool hasUplink = false,
PdaIdInfoText pdaOwnerInfo, bool canPlayMusic = false, string? address = null)
string? stationName,
bool hasUplink = false,
bool canPlayMusic = false,
bool hasNewsTab = false,
string? address = null)
{ {
FlashlightEnabled = flashlightEnabled; FlashlightEnabled = flashlightEnabled;
HasPen = hasPen; HasPen = hasPen;
PdaOwnerInfo = pdaOwnerInfo; PdaOwnerInfo = pdaOwnerInfo;
HasUplink = hasUplink; HasUplink = hasUplink;
CanPlayMusic = canPlayMusic; CanPlayMusic = canPlayMusic;
HasNewsTab = hasNewsTab;
StationName = stationName; StationName = stationName;
Address = address; Address = address;
} }

View File

@@ -1,5 +1,6 @@
default-program-name = Program default-program-name = Program
notekeeper-program-name = Notekeeper notekeeper-program-name = Notekeeper
news-read-program-name = Station news
net-probe-program-name = NetProbe net-probe-program-name = NetProbe
net-probe-scan = Scanned {$device}! net-probe-scan = Scanned {$device}!

View File

@@ -1,11 +1,12 @@
pda-news-button-label = News
pda-news-button-description = View station news
news-read-ui-next-text = Next news-read-ui-next-text = Next
news-read-ui-past-text = Past news-read-ui-past-text = Past
news-read-ui-default-title = Station News news-read-ui-default-title = Station News
news-read-ui-not-found-text = No articles found news-read-ui-not-found-text = No articles found
news-read-ui-time-prefix-text = Publication time: news-read-ui-time-prefix-text = Publication time:
news-read-ui-notification-off = ̶♫̶
news-read-ui-notification-on = ♫
news-read-ui-no-author = Anonymous news-read-ui-no-author = Anonymous
news-read-ui-author-prefix = Author:
news-write-ui-default-title = Mass-media Management news-write-ui-default-title = Mass-media Management
news-write-ui-articles-label = Articles: news-write-ui-articles-label = Articles:
news-write-ui-delete-text = Delete news-write-ui-delete-text = Delete

View File

@@ -369,7 +369,7 @@
- type: entity - type: entity
parent: BaseComputerCircuitboard parent: BaseComputerCircuitboard
id: ComputerMassMediaCircuitboard id: ComputerMassMediaCircuitboard
name: mass media console board name: mass-media console board
description: Write your message to the world! description: Write your message to the world!
components: components:
- type: Sprite - type: Sprite

View File

@@ -19,6 +19,27 @@
state: book6 state: book6
- type: NotekeeperCartridge - type: NotekeeperCartridge
- type: entity
parent: BaseItem
id: NewsReadCartridge
name: News Cartridge
description: A program for reading news
components:
- type: Sprite
sprite: Objects/Devices/cartridge.rsi
state: cart-y
- type: Icon
sprite: Objects/Devices/cartridge.rsi
state: cart-y
- type: UIFragment
ui: !type:NewsReadUi
- type: Cartridge
programName: news-read-program-name
icon:
sprite: Interface/Misc/program_icons.rsi
state: news_read
- type: NewsReadCartridge
- type: entity - type: entity
parent: BaseItem parent: BaseItem
id: NetProbeCartridge id: NetProbeCartridge

View File

@@ -73,6 +73,7 @@
uiKey: enum.PdaUiKey.Key uiKey: enum.PdaUiKey.Key
preinstalled: preinstalled:
- NotekeeperCartridge - NotekeeperCartridge
- NewsReadCartridge
cartridgeSlot: cartridgeSlot:
priority: -1 priority: -1
name: Cartridge name: Cartridge
@@ -97,11 +98,8 @@
type: InstrumentBoundUserInterface type: InstrumentBoundUserInterface
- key: enum.HealthAnalyzerUiKey.Key - key: enum.HealthAnalyzerUiKey.Key
type: HealthAnalyzerBoundUserInterface type: HealthAnalyzerBoundUserInterface
- key: enum.NewsReadUiKey.Key
type: NewsReadBoundUserInterface
- type: CrewManifestViewer - type: CrewManifestViewer
unsecure: true unsecure: true
- type: NewsRead
- type: Tag - type: Tag
tags: tags:
- DoorBumpOpener - DoorBumpOpener
@@ -733,6 +731,18 @@
borderColor: "#891417" borderColor: "#891417"
- type: Icon - type: Icon
state: pda-syndi state: pda-syndi
- type: CartridgeLoader
uiKey: enum.PdaUiKey.Key
preinstalled:
- NotekeeperCartridge
cartridgeSlot:
priority: -1
name: Cartridge
ejectSound: /Audio/Machines/id_swipe.ogg
insertSound: /Audio/Weapons/Guns/MagIn/batrifle_magin.ogg
whitelist:
components:
- Cartridge
- type: entity - type: entity
parent: BasePDA parent: BasePDA

View File

@@ -0,0 +1,14 @@
{
"version": 1,
"license": "CC-BY-SA-3.0",
"copyright": "Made with love, by Misha_Unity",
"size": {
"x": 32,
"y": 32
},
"states": [
{
"name": "news_read"
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 417 B