NanoTask (#34095)
This commit is contained in:
committed by
GitHub
parent
c7022ae7c5
commit
4576555e5b
@@ -0,0 +1,5 @@
|
||||
using Content.Shared.CartridgeLoader.Cartridges;
|
||||
|
||||
namespace Content.Client.CartridgeLoader.Cartridges;
|
||||
|
||||
public sealed class NanoTaskCartridgeSystem : SharedNanoTaskCartridgeSystem;
|
||||
@@ -0,0 +1,32 @@
|
||||
<Control xmlns="https://spacestation14.io" xmlns:system="clr-namespace:System;assembly=System.Runtime">
|
||||
<BoxContainer Name="MainContainer"
|
||||
Orientation="Horizontal"
|
||||
SetWidth="250">
|
||||
<Button Name="MainButton"
|
||||
HorizontalExpand="True"
|
||||
VerticalExpand="True"
|
||||
StyleClasses="ButtonSquare"
|
||||
Margin="-1 0 0 0">
|
||||
<BoxContainer Orientation="Horizontal" HorizontalExpand="True">
|
||||
<BoxContainer Orientation="Vertical"
|
||||
VerticalExpand="True"
|
||||
HorizontalExpand="True"
|
||||
Margin="-5 0 0 0">
|
||||
<Label Name="TaskLabel"
|
||||
StyleClasses="LabelSubText" />
|
||||
<Label Name="TaskForLabel"
|
||||
StyleClasses="LabelSubText"
|
||||
Margin="0 -5 0 0" />
|
||||
</BoxContainer>
|
||||
</BoxContainer>
|
||||
</Button>
|
||||
<Button Name="DoneButton"
|
||||
VerticalExpand="True"
|
||||
Text="{Loc 'nano-task-ui-done'}">
|
||||
<Button.StyleClasses>
|
||||
<system:String>ButtonSmall</system:String>
|
||||
<system:String>OpenLeft</system:String>
|
||||
</Button.StyleClasses>
|
||||
</Button>
|
||||
</BoxContainer>
|
||||
</Control>
|
||||
@@ -0,0 +1,33 @@
|
||||
using Robust.Client.AutoGenerated;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Client.UserInterface;
|
||||
using Robust.Client.UserInterface.XAML;
|
||||
using Robust.Shared.Maths;
|
||||
using Content.Shared.CartridgeLoader.Cartridges;
|
||||
|
||||
namespace Content.Client.CartridgeLoader.Cartridges;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a single control for a single NanoTask item
|
||||
/// </summary>
|
||||
[GenerateTypedNameReferences]
|
||||
public sealed partial class NanoTaskItemControl : Control
|
||||
{
|
||||
public Action<int>? OnMainPressed;
|
||||
public Action<int>? OnDonePressed;
|
||||
|
||||
public NanoTaskItemControl(NanoTaskItemAndId item)
|
||||
{
|
||||
RobustXamlLoader.Load(this);
|
||||
|
||||
TaskLabel.Text = item.Data.Description;
|
||||
TaskLabel.FontColorOverride = Color.White;
|
||||
TaskForLabel.Text = item.Data.TaskIsFor;
|
||||
|
||||
MainButton.OnPressed += _ => OnMainPressed?.Invoke(item.Id);
|
||||
DoneButton.OnPressed += _ => OnDonePressed?.Invoke(item.Id);
|
||||
|
||||
MainButton.Disabled = item.Data.IsTaskDone;
|
||||
DoneButton.Text = item.Data.IsTaskDone ? Loc.GetString("nano-task-ui-revert-done") : Loc.GetString("nano-task-ui-done");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
<DefaultWindow xmlns="https://spacestation14.io"
|
||||
Title="{Loc nano-task-ui-item-title}"
|
||||
MinSize="300 300">
|
||||
<PanelContainer StyleClasses="AngleRect">
|
||||
<BoxContainer Orientation="Vertical" Margin="4">
|
||||
<!-- Task Description Input -->
|
||||
<BoxContainer Orientation="Vertical" Margin="0 4">
|
||||
<Label Text="{Loc nano-task-ui-description-label}"
|
||||
StyleClasses="LabelHeading" />
|
||||
<PanelContainer StyleClasses="ButtonSquare">
|
||||
<LineEdit Name="DescriptionInput"
|
||||
PlaceHolder="{Loc nano-task-ui-description-placeholder}" />
|
||||
</PanelContainer>
|
||||
</BoxContainer>
|
||||
|
||||
<!-- Task Requester Input -->
|
||||
<BoxContainer Orientation="Vertical" Margin="0 4">
|
||||
<Label Text="{Loc nano-task-ui-requester-label}"
|
||||
StyleClasses="LabelHeading" />
|
||||
<PanelContainer StyleClasses="ButtonSquare">
|
||||
<LineEdit Name="RequesterInput"
|
||||
PlaceHolder="{Loc nano-task-ui-requester-placeholder}" />
|
||||
</PanelContainer>
|
||||
</BoxContainer>
|
||||
|
||||
<!-- Severity Buttons -->
|
||||
<BoxContainer Orientation="Horizontal"
|
||||
HorizontalAlignment="Center"
|
||||
Margin="0 8 0 0">
|
||||
<Button Name="LowButton"
|
||||
Text="{Loc nano-task-ui-priority-low}"
|
||||
StyleClasses="OpenRight"
|
||||
MinSize="60 0" />
|
||||
<Button Name="MediumButton"
|
||||
Text="{Loc nano-task-ui-priority-medium}"
|
||||
StyleClasses="ButtonSquare"
|
||||
MinSize="60 0" />
|
||||
<Button Name="HighButton"
|
||||
Text="{Loc nano-task-ui-priority-high}"
|
||||
StyleClasses="OpenLeft"
|
||||
MinSize="60 0" />
|
||||
</BoxContainer>
|
||||
|
||||
<!-- Verb Buttons -->
|
||||
<BoxContainer Orientation="Horizontal"
|
||||
HorizontalAlignment="Right"
|
||||
Margin="0 8 0 0">
|
||||
<Button Name="CancelButton"
|
||||
Text="{Loc nano-task-ui-cancel}"
|
||||
StyleClasses="OpenRight"
|
||||
MinSize="60 0" />
|
||||
<Button Name="DeleteButton"
|
||||
Text="{Loc nano-task-ui-delete}"
|
||||
StyleClasses="ButtonSquare"
|
||||
MinSize="60 0" />
|
||||
<Button Name="PrintButton"
|
||||
Text="{Loc nano-task-ui-print}"
|
||||
StyleClasses="ButtonSquare"
|
||||
MinSize="60 0" />
|
||||
<Button Name="SaveButton"
|
||||
Text="{Loc nano-task-ui-save}"
|
||||
StyleClasses="OpenLeft"
|
||||
MinSize="60 0" />
|
||||
</BoxContainer>
|
||||
</BoxContainer>
|
||||
</PanelContainer>
|
||||
</DefaultWindow>
|
||||
@@ -0,0 +1,109 @@
|
||||
using System.Linq;
|
||||
using Robust.Client.AutoGenerated;
|
||||
using Robust.Client.UserInterface.CustomControls;
|
||||
using Robust.Client.UserInterface.XAML;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
using Content.Shared.CartridgeLoader.Cartridges;
|
||||
|
||||
namespace Content.Client.CartridgeLoader.Cartridges;
|
||||
|
||||
/// <summary>
|
||||
/// Popup displayed to edit a NanoTask item
|
||||
/// </summary>
|
||||
[GenerateTypedNameReferences]
|
||||
public sealed partial class NanoTaskItemPopup : DefaultWindow
|
||||
{
|
||||
private readonly ButtonGroup _priorityGroup = new();
|
||||
private int? _editingTaskId = null;
|
||||
|
||||
public Action<int, NanoTaskItem>? TaskSaved;
|
||||
public Action<int>? TaskDeleted;
|
||||
public Action<NanoTaskItem>? TaskCreated;
|
||||
public Action<NanoTaskItem>? TaskPrinted;
|
||||
|
||||
private NanoTaskItem MakeItem()
|
||||
{
|
||||
return new(
|
||||
description: DescriptionInput.Text,
|
||||
taskIsFor: RequesterInput.Text,
|
||||
isTaskDone: false,
|
||||
priority: _priorityGroup.Pressed switch {
|
||||
var item when item == LowButton => NanoTaskPriority.Low,
|
||||
var item when item == MediumButton => NanoTaskPriority.Medium,
|
||||
var item when item == HighButton => NanoTaskPriority.High,
|
||||
_ => NanoTaskPriority.Medium,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
public NanoTaskItemPopup()
|
||||
{
|
||||
RobustXamlLoader.Load(this);
|
||||
|
||||
LowButton.Group = _priorityGroup;
|
||||
MediumButton.Group = _priorityGroup;
|
||||
HighButton.Group = _priorityGroup;
|
||||
|
||||
CancelButton.OnPressed += _ => Close();
|
||||
DeleteButton.OnPressed += _ =>
|
||||
{
|
||||
if (_editingTaskId is int id)
|
||||
{
|
||||
TaskDeleted?.Invoke(id);
|
||||
}
|
||||
};
|
||||
PrintButton.OnPressed += _ =>
|
||||
{
|
||||
TaskPrinted?.Invoke(MakeItem());
|
||||
};
|
||||
SaveButton.OnPressed += _ =>
|
||||
{
|
||||
if (_editingTaskId is int id)
|
||||
{
|
||||
TaskSaved?.Invoke(id, MakeItem());
|
||||
}
|
||||
else
|
||||
{
|
||||
TaskCreated?.Invoke(MakeItem());
|
||||
}
|
||||
};
|
||||
|
||||
DescriptionInput.OnTextChanged += args =>
|
||||
{
|
||||
if (args.Text.Length > NanoTaskItem.MaximumStringLength)
|
||||
DescriptionInput.Text = args.Text[..NanoTaskItem.MaximumStringLength];
|
||||
};
|
||||
RequesterInput.OnTextChanged += args =>
|
||||
{
|
||||
if (args.Text.Length > NanoTaskItem.MaximumStringLength)
|
||||
RequesterInput.Text = args.Text[..NanoTaskItem.MaximumStringLength];
|
||||
};
|
||||
}
|
||||
|
||||
public void SetEditingTaskId(int? id)
|
||||
{
|
||||
_editingTaskId = id;
|
||||
DeleteButton.Visible = id is not null;
|
||||
}
|
||||
|
||||
public void ResetInputs(NanoTaskItem? item)
|
||||
{
|
||||
if (item is NanoTaskItem task)
|
||||
{
|
||||
var button = task.Priority switch {
|
||||
NanoTaskPriority.High => HighButton,
|
||||
NanoTaskPriority.Medium => MediumButton,
|
||||
NanoTaskPriority.Low => LowButton,
|
||||
};
|
||||
button.Pressed = true;
|
||||
DescriptionInput.Text = task.Description;
|
||||
RequesterInput.Text = task.TaskIsFor;
|
||||
}
|
||||
else
|
||||
{
|
||||
MediumButton.Pressed = true;
|
||||
DescriptionInput.Text = "";
|
||||
RequesterInput.Text = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
82
Content.Client/CartridgeLoader/Cartridges/NanoTaskUi.cs
Normal file
82
Content.Client/CartridgeLoader/Cartridges/NanoTaskUi.cs
Normal file
@@ -0,0 +1,82 @@
|
||||
using System.Linq;
|
||||
using Content.Client.UserInterface.Fragments;
|
||||
using Content.Shared.CartridgeLoader;
|
||||
using Content.Shared.CartridgeLoader.Cartridges;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Client.UserInterface;
|
||||
|
||||
namespace Content.Client.CartridgeLoader.Cartridges;
|
||||
|
||||
/// <summary>
|
||||
/// UI fragment responsible for displaying NanoTask controls in a PDA and coordinating with the NanoTaskCartridgeSystem for state
|
||||
/// </summary>
|
||||
public sealed partial class NanoTaskUi : UIFragment
|
||||
{
|
||||
private NanoTaskUiFragment? _fragment;
|
||||
private NanoTaskItemPopup? _popup;
|
||||
|
||||
public override Control GetUIFragmentRoot()
|
||||
{
|
||||
return _fragment!;
|
||||
}
|
||||
|
||||
public override void Setup(BoundUserInterface userInterface, EntityUid? fragmentOwner)
|
||||
{
|
||||
_fragment = new NanoTaskUiFragment();
|
||||
_popup = new NanoTaskItemPopup();
|
||||
_fragment.NewTask += () =>
|
||||
{
|
||||
_popup.ResetInputs(null);
|
||||
_popup.SetEditingTaskId(null);
|
||||
_popup.OpenCentered();
|
||||
};
|
||||
_fragment.OpenTask += id =>
|
||||
{
|
||||
if (_fragment.Tasks.Find(task => task.Id == id) is not NanoTaskItemAndId task)
|
||||
return;
|
||||
|
||||
_popup.ResetInputs(task.Data);
|
||||
_popup.SetEditingTaskId(task.Id);
|
||||
_popup.OpenCentered();
|
||||
};
|
||||
_fragment.ToggleTaskCompletion += id =>
|
||||
{
|
||||
if (_fragment.Tasks.Find(task => task.Id == id) is not NanoTaskItemAndId task)
|
||||
return;
|
||||
|
||||
userInterface.SendMessage(new CartridgeUiMessage(new NanoTaskUiMessageEvent(new NanoTaskUpdateTask(new(id, new(
|
||||
description: task.Data.Description,
|
||||
taskIsFor: task.Data.TaskIsFor,
|
||||
isTaskDone: !task.Data.IsTaskDone,
|
||||
priority: task.Data.Priority
|
||||
))))));
|
||||
};
|
||||
_popup.TaskSaved += (id, data) =>
|
||||
{
|
||||
userInterface.SendMessage(new CartridgeUiMessage(new NanoTaskUiMessageEvent(new NanoTaskUpdateTask(new(id, data)))));
|
||||
_popup.Close();
|
||||
};
|
||||
_popup.TaskDeleted += id =>
|
||||
{
|
||||
userInterface.SendMessage(new CartridgeUiMessage(new NanoTaskUiMessageEvent(new NanoTaskDeleteTask(id))));
|
||||
_popup.Close();
|
||||
};
|
||||
_popup.TaskCreated += data =>
|
||||
{
|
||||
userInterface.SendMessage(new CartridgeUiMessage(new NanoTaskUiMessageEvent(new NanoTaskAddTask(data))));
|
||||
_popup.Close();
|
||||
};
|
||||
_popup.TaskPrinted += data =>
|
||||
{
|
||||
userInterface.SendMessage(new CartridgeUiMessage(new NanoTaskUiMessageEvent(new NanoTaskPrintTask(data))));
|
||||
};
|
||||
}
|
||||
|
||||
public override void UpdateState(BoundUserInterfaceState state)
|
||||
{
|
||||
if (state is not NanoTaskUiState nanoTaskState)
|
||||
return;
|
||||
|
||||
_fragment?.UpdateState(nanoTaskState.Tasks);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
<cartridges:NanoTaskUiFragment xmlns:cartridges="clr-namespace:Content.Client.CartridgeLoader.Cartridges"
|
||||
xmlns:gfx="clr-namespace:Robust.Client.Graphics;assembly=Robust.Client"
|
||||
xmlns="https://spacestation14.io" Margin="1 0 2 0">
|
||||
|
||||
<PanelContainer StyleClasses="BackgroundDark"></PanelContainer>
|
||||
<BoxContainer Orientation="Vertical" HorizontalExpand="True" VerticalExpand="True">
|
||||
<ScrollContainer HorizontalExpand="True" VerticalExpand="True">
|
||||
<BoxContainer HorizontalExpand="True" VerticalExpand="True" Orientation="Vertical" Margin="8" SeparationOverride="8">
|
||||
<!-- Heading for High Priority Items -->
|
||||
<BoxContainer Orientation="Horizontal">
|
||||
<PanelContainer SetWidth="7" Margin="0 0 8 0">
|
||||
<PanelContainer.PanelOverride>
|
||||
<gfx:StyleBoxFlat BackgroundColor="#e93d58"/>
|
||||
</PanelContainer.PanelOverride>
|
||||
</PanelContainer>
|
||||
<Label Name="HighPriority" StyleClasses="LabelHeading"/>
|
||||
</BoxContainer>
|
||||
<!-- Location for High Priority Items -->
|
||||
<GridContainer Name="HighContainer"
|
||||
HorizontalExpand="True"
|
||||
Access="Public"
|
||||
Columns="2" />
|
||||
|
||||
<!-- Heading for Medium Priority Items -->
|
||||
<BoxContainer Orientation="Horizontal">
|
||||
<PanelContainer SetWidth="7" Margin="0 0 8 0">
|
||||
<PanelContainer.PanelOverride>
|
||||
<gfx:StyleBoxFlat BackgroundColor="#ef973c"/>
|
||||
</PanelContainer.PanelOverride>
|
||||
</PanelContainer>
|
||||
<Label Name="MediumPriority" StyleClasses="LabelHeading"/>
|
||||
</BoxContainer>
|
||||
<!-- Location for Medium Priority Items -->
|
||||
<GridContainer Name="MediumContainer"
|
||||
HorizontalExpand="True"
|
||||
Access="Public"
|
||||
Columns="2" />
|
||||
|
||||
<!-- Location for Low Priority Items -->
|
||||
<BoxContainer Orientation="Horizontal">
|
||||
<PanelContainer SetWidth="7" Margin="0 0 8 0">
|
||||
<PanelContainer.PanelOverride>
|
||||
<gfx:StyleBoxFlat BackgroundColor="#3dd425"/>
|
||||
</PanelContainer.PanelOverride>
|
||||
</PanelContainer>
|
||||
<Label Name="LowPriority" StyleClasses="LabelHeading"/>
|
||||
</BoxContainer>
|
||||
<!-- Location for Low Priority Items -->
|
||||
<GridContainer Name="LowContainer"
|
||||
HorizontalExpand="True"
|
||||
Access="Public"
|
||||
Columns="2" />
|
||||
|
||||
<Button Name="NewTaskButton" Text="{Loc 'nano-task-ui-new-task'}" HorizontalAlignment="Right"/>
|
||||
</BoxContainer>
|
||||
</ScrollContainer>
|
||||
</BoxContainer>
|
||||
</cartridges:NanoTaskUiFragment>
|
||||
@@ -0,0 +1,52 @@
|
||||
using System.Linq;
|
||||
using Robust.Client.AutoGenerated;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
using Robust.Client.UserInterface.XAML;
|
||||
using Content.Shared.CartridgeLoader.Cartridges;
|
||||
|
||||
namespace Content.Client.CartridgeLoader.Cartridges;
|
||||
|
||||
/// <summary>
|
||||
/// Class displaying the main UI of NanoTask
|
||||
/// </summary>
|
||||
[GenerateTypedNameReferences]
|
||||
public sealed partial class NanoTaskUiFragment : BoxContainer
|
||||
{
|
||||
public Action<int>? OpenTask;
|
||||
public Action<int>? ToggleTaskCompletion;
|
||||
public Action? NewTask;
|
||||
public List<NanoTaskItemAndId> Tasks = new();
|
||||
|
||||
public NanoTaskUiFragment()
|
||||
{
|
||||
RobustXamlLoader.Load(this);
|
||||
Orientation = LayoutOrientation.Vertical;
|
||||
HorizontalExpand = true;
|
||||
VerticalExpand = true;
|
||||
NewTaskButton.OnPressed += _ => NewTask?.Invoke();
|
||||
}
|
||||
public void UpdateState(List<NanoTaskItemAndId> tasks)
|
||||
{
|
||||
Tasks = tasks;
|
||||
HighContainer.RemoveAllChildren();
|
||||
MediumContainer.RemoveAllChildren();
|
||||
LowContainer.RemoveAllChildren();
|
||||
|
||||
HighPriority.Text = Loc.GetString("nano-task-ui-heading-high-priority-tasks", ("amount", tasks.Count(task => task.Data.Priority == NanoTaskPriority.High)));
|
||||
MediumPriority.Text = Loc.GetString("nano-task-ui-heading-medium-priority-tasks", ("amount", tasks.Count(task => task.Data.Priority == NanoTaskPriority.Medium)));
|
||||
LowPriority.Text = Loc.GetString("nano-task-ui-heading-low-priority-tasks", ("amount", tasks.Count(task => task.Data.Priority == NanoTaskPriority.Low)));
|
||||
|
||||
foreach (var task in tasks)
|
||||
{
|
||||
var container = task.Data.Priority switch {
|
||||
NanoTaskPriority.High => HighContainer,
|
||||
NanoTaskPriority.Medium => MediumContainer,
|
||||
NanoTaskPriority.Low => LowContainer,
|
||||
};
|
||||
var control = new NanoTaskItemControl(task);
|
||||
container.AddChild(control);
|
||||
control.OnMainPressed += id => OpenTask?.Invoke(id);
|
||||
control.OnDonePressed += id => ToggleTaskCompletion?.Invoke(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,151 @@
|
||||
using Content.Shared.CartridgeLoader.Cartridges;
|
||||
using Content.Shared.CartridgeLoader;
|
||||
using Content.Shared.Hands.EntitySystems;
|
||||
using Content.Shared.Interaction;
|
||||
using Content.Shared.Paper;
|
||||
using Robust.Shared.Audio;
|
||||
using Robust.Shared.Audio.Systems;
|
||||
using Robust.Shared.Timing;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Content.Server.CartridgeLoader.Cartridges;
|
||||
|
||||
/// <summary>
|
||||
/// Server-side class implementing the core UI logic of NanoTask
|
||||
/// </summary>
|
||||
public sealed class NanoTaskCartridgeSystem : SharedNanoTaskCartridgeSystem
|
||||
{
|
||||
[Dependency] private readonly CartridgeLoaderSystem _cartridgeLoader = default!;
|
||||
[Dependency] private readonly IGameTiming _timing = default!;
|
||||
[Dependency] private readonly PaperSystem _paper = default!;
|
||||
[Dependency] private readonly SharedAudioSystem _audio = default!;
|
||||
[Dependency] private readonly SharedHandsSystem _hands = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<NanoTaskCartridgeComponent, CartridgeMessageEvent>(OnUiMessage);
|
||||
SubscribeLocalEvent<NanoTaskCartridgeComponent, CartridgeUiReadyEvent>(OnUiReady);
|
||||
|
||||
SubscribeLocalEvent<NanoTaskCartridgeComponent, CartridgeRemovedEvent>(OnCartridgeRemoved);
|
||||
|
||||
SubscribeLocalEvent<NanoTaskInteractionComponent, InteractUsingEvent>(OnInteractUsing);
|
||||
}
|
||||
|
||||
private void OnCartridgeRemoved(Entity<NanoTaskCartridgeComponent> ent, ref CartridgeRemovedEvent args)
|
||||
{
|
||||
if (!_cartridgeLoader.HasProgram<NanoTaskCartridgeComponent>(args.Loader))
|
||||
{
|
||||
RemComp<NanoTaskInteractionComponent>(args.Loader);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnInteractUsing(Entity<NanoTaskInteractionComponent> ent, ref InteractUsingEvent args)
|
||||
{
|
||||
if (!_cartridgeLoader.TryGetProgram<NanoTaskCartridgeComponent>(ent.Owner, out var uid, out var program))
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (!EntityManager.TryGetComponent<NanoTaskPrintedComponent>(args.Used, out var printed))
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (printed.Task is NanoTaskItem item)
|
||||
{
|
||||
program.Tasks.Add(new(program.Counter++, printed.Task));
|
||||
args.Handled = true;
|
||||
EntityManager.DeleteEntity(args.Used);
|
||||
UpdateUiState(new Entity<NanoTaskCartridgeComponent>(uid.Value, program), ent.Owner);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This gets called when the ui fragment needs to be updated for the first time after activating
|
||||
/// </summary>
|
||||
private void OnUiReady(Entity<NanoTaskCartridgeComponent> ent, ref CartridgeUiReadyEvent args)
|
||||
{
|
||||
UpdateUiState(ent, args.Loader);
|
||||
}
|
||||
|
||||
private void SetupPrintedTask(EntityUid uid, NanoTaskItem item)
|
||||
{
|
||||
PaperComponent? paper = null;
|
||||
NanoTaskPrintedComponent? printed = null;
|
||||
if (!Resolve(uid, ref paper, ref printed))
|
||||
return;
|
||||
|
||||
printed.Task = item;
|
||||
var msg = new FormattedMessage();
|
||||
msg.AddText(Loc.GetString("nano-task-printed-description", ("description", item.Description)));
|
||||
msg.PushNewline();
|
||||
msg.AddText(Loc.GetString("nano-task-printed-requester", ("requester", item.TaskIsFor)));
|
||||
msg.PushNewline();
|
||||
msg.AddText(item.Priority switch {
|
||||
NanoTaskPriority.High => Loc.GetString("nano-task-printed-high-priority"),
|
||||
NanoTaskPriority.Medium => Loc.GetString("nano-task-printed-medium-priority"),
|
||||
NanoTaskPriority.Low => Loc.GetString("nano-task-printed-low-priority"),
|
||||
_ => "",
|
||||
});
|
||||
|
||||
_paper.SetContent((uid, paper), msg.ToMarkup());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The ui messages received here get wrapped by a CartridgeMessageEvent and are relayed from the <see cref="CartridgeLoaderSystem"/>
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The cartridge specific ui message event needs to inherit from the CartridgeMessageEvent
|
||||
/// </remarks>
|
||||
private void OnUiMessage(Entity<NanoTaskCartridgeComponent> ent, ref CartridgeMessageEvent args)
|
||||
{
|
||||
if (args is not NanoTaskUiMessageEvent message)
|
||||
return;
|
||||
|
||||
switch (message.Payload)
|
||||
{
|
||||
case NanoTaskAddTask task:
|
||||
if (!task.Item.Validate())
|
||||
return;
|
||||
|
||||
ent.Comp.Tasks.Add(new(ent.Comp.Counter++, task.Item));
|
||||
break;
|
||||
case NanoTaskUpdateTask task:
|
||||
{
|
||||
if (!task.Item.Data.Validate())
|
||||
return;
|
||||
|
||||
var idx = ent.Comp.Tasks.FindIndex(t => t.Id == task.Item.Id);
|
||||
if (idx != -1)
|
||||
ent.Comp.Tasks[idx] = task.Item;
|
||||
break;
|
||||
}
|
||||
case NanoTaskDeleteTask task:
|
||||
ent.Comp.Tasks.RemoveAll(t => t.Id == task.Id);
|
||||
break;
|
||||
case NanoTaskPrintTask task:
|
||||
{
|
||||
if (!task.Item.Validate())
|
||||
return;
|
||||
if (_timing.CurTime < ent.Comp.NextPrintAllowedAfter)
|
||||
return;
|
||||
|
||||
ent.Comp.NextPrintAllowedAfter = _timing.CurTime + ent.Comp.PrintDelay;
|
||||
var printed = Spawn("PaperNanoTaskItem", Transform(message.Actor).Coordinates);
|
||||
_hands.PickupOrDrop(message.Actor, printed);
|
||||
_audio.PlayPvs(new SoundPathSpecifier("/Audio/Machines/printer.ogg"), ent.Owner);
|
||||
SetupPrintedTask(printed, task.Item);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
UpdateUiState(ent, GetEntity(args.LoaderUid));
|
||||
}
|
||||
|
||||
|
||||
private void UpdateUiState(Entity<NanoTaskCartridgeComponent> ent, EntityUid loaderUid)
|
||||
{
|
||||
var state = new NanoTaskUiState(ent.Comp.Tasks);
|
||||
_cartridgeLoader.UpdateCartridgeUiState(loaderUid, state);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
using Content.Shared.CartridgeLoader.Cartridges;
|
||||
|
||||
namespace Content.Shared.CartridgeLoader.Cartridges;
|
||||
|
||||
/// <summary>
|
||||
/// Component that indicates a PDA cartridge as containing the NanoTask program
|
||||
/// </summary>
|
||||
[RegisterComponent, AutoGenerateComponentPause]
|
||||
public sealed partial class NanoTaskCartridgeComponent : Component
|
||||
{
|
||||
/// <summary>
|
||||
/// The list of tasks
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public List<NanoTaskItemAndId> Tasks = new();
|
||||
|
||||
/// <summary>
|
||||
/// counter for generating task IDs
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public int Counter = 1;
|
||||
|
||||
/// <summary>
|
||||
/// When the user can print again
|
||||
/// </summary>
|
||||
[DataField, AutoPausedField]
|
||||
public TimeSpan NextPrintAllowedAfter = TimeSpan.Zero;
|
||||
|
||||
/// <summary>
|
||||
/// How long in between each time the user can print out a task
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public TimeSpan PrintDelay = TimeSpan.FromSeconds(5);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Component attached to the PDA a NanoTask cartridge is inserted into for interaction handling
|
||||
/// </summary>
|
||||
[RegisterComponent]
|
||||
public sealed partial class NanoTaskInteractionComponent : Component
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
using Content.Shared.CartridgeLoader.Cartridges;
|
||||
|
||||
namespace Content.Shared.CartridgeLoader.Cartridges;
|
||||
|
||||
/// <summary>
|
||||
/// Component attached to a piece of paper to indicate that it was printed from NanoTask and can be inserted back into it
|
||||
/// </summary>
|
||||
[RegisterComponent]
|
||||
public sealed partial class NanoTaskPrintedComponent : Component
|
||||
{
|
||||
/// <summary>
|
||||
/// The task that this item holds
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public NanoTaskItem? Task;
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
using Robust.Shared.Serialization;
|
||||
|
||||
namespace Content.Shared.CartridgeLoader.Cartridges;
|
||||
|
||||
/// <summary>
|
||||
/// Base UI message for NanoTask interactions
|
||||
/// </summary>
|
||||
public interface INanoTaskUiMessagePayload
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Dispatched when a new task is created
|
||||
/// </summary>
|
||||
[Serializable, NetSerializable, DataRecord]
|
||||
public sealed class NanoTaskAddTask : INanoTaskUiMessagePayload
|
||||
{
|
||||
/// <summary>
|
||||
/// The newly created task
|
||||
/// </summary>
|
||||
public readonly NanoTaskItem Item;
|
||||
|
||||
public NanoTaskAddTask(NanoTaskItem item)
|
||||
{
|
||||
Item = item;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Dispatched when an existing task is modified
|
||||
/// </summary>
|
||||
[Serializable, NetSerializable, DataRecord]
|
||||
public sealed class NanoTaskUpdateTask : INanoTaskUiMessagePayload
|
||||
{
|
||||
/// <summary>
|
||||
/// The task that was updated and its ID
|
||||
/// </summary>
|
||||
public readonly NanoTaskItemAndId Item;
|
||||
|
||||
public NanoTaskUpdateTask(NanoTaskItemAndId item)
|
||||
{
|
||||
Item = item;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Dispatched when an existing task is deleted
|
||||
/// </summary>
|
||||
[Serializable, NetSerializable, DataRecord]
|
||||
public sealed class NanoTaskDeleteTask : INanoTaskUiMessagePayload
|
||||
{
|
||||
/// <summary>
|
||||
/// The ID of the task to delete
|
||||
/// </summary>
|
||||
public readonly int Id;
|
||||
|
||||
public NanoTaskDeleteTask(int id)
|
||||
{
|
||||
Id = id;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Dispatched when a task is requested to be printed
|
||||
/// </summary>
|
||||
[Serializable, NetSerializable, DataRecord]
|
||||
public sealed class NanoTaskPrintTask : INanoTaskUiMessagePayload
|
||||
{
|
||||
/// <summary>
|
||||
/// The NanoTask to print
|
||||
/// </summary>
|
||||
public readonly NanoTaskItem Item;
|
||||
|
||||
public NanoTaskPrintTask(NanoTaskItem item)
|
||||
{
|
||||
Item = item;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Cartridge message event carrying the NanoTask UI messages
|
||||
/// </summary>
|
||||
[Serializable, NetSerializable]
|
||||
public sealed class NanoTaskUiMessageEvent : CartridgeMessageEvent
|
||||
{
|
||||
public readonly INanoTaskUiMessagePayload Payload;
|
||||
public NanoTaskUiMessageEvent(INanoTaskUiMessagePayload payload)
|
||||
{
|
||||
Payload = payload;
|
||||
}
|
||||
}
|
||||
88
Content.Shared/CartridgeLoader/Cartridges/NanoTaskUiState.cs
Normal file
88
Content.Shared/CartridgeLoader/Cartridges/NanoTaskUiState.cs
Normal file
@@ -0,0 +1,88 @@
|
||||
using Robust.Shared.Serialization;
|
||||
|
||||
namespace Content.Shared.CartridgeLoader.Cartridges;
|
||||
|
||||
/// <summary>
|
||||
/// The priority assigned to a NanoTask item
|
||||
/// </summary>
|
||||
[Serializable, NetSerializable]
|
||||
public enum NanoTaskPriority : byte
|
||||
{
|
||||
High,
|
||||
Medium,
|
||||
Low,
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// The data relating to a single NanoTask item, but not its identifier
|
||||
/// </summary>
|
||||
[Serializable, NetSerializable, DataRecord]
|
||||
public sealed class NanoTaskItem
|
||||
{
|
||||
/// <summary>
|
||||
/// The maximum length of the Description and TaskIsFor fields
|
||||
/// </summary>
|
||||
public static int MaximumStringLength = 30;
|
||||
|
||||
/// <summary>
|
||||
/// The task description, i.e. "Bake a cake"
|
||||
/// </summary>
|
||||
public readonly string Description;
|
||||
|
||||
/// <summary>
|
||||
/// Who the task is for, i.e. "Cargo"
|
||||
/// </summary>
|
||||
public readonly string TaskIsFor;
|
||||
|
||||
/// <summary>
|
||||
/// If the task is marked as done or not
|
||||
/// </summary>
|
||||
public readonly bool IsTaskDone;
|
||||
|
||||
/// <summary>
|
||||
/// The task's marked priority
|
||||
/// </summary>
|
||||
public readonly NanoTaskPriority Priority;
|
||||
|
||||
public NanoTaskItem(string description, string taskIsFor, bool isTaskDone, NanoTaskPriority priority)
|
||||
{
|
||||
Description = description;
|
||||
TaskIsFor = taskIsFor;
|
||||
IsTaskDone = isTaskDone;
|
||||
Priority = priority;
|
||||
}
|
||||
public bool Validate()
|
||||
{
|
||||
return Description.Length <= MaximumStringLength && TaskIsFor.Length <= MaximumStringLength;
|
||||
}
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Pairs a NanoTask item and its identifier
|
||||
/// </summary>
|
||||
[Serializable, NetSerializable, DataRecord]
|
||||
public sealed class NanoTaskItemAndId
|
||||
{
|
||||
public readonly int Id;
|
||||
public readonly NanoTaskItem Data;
|
||||
|
||||
public NanoTaskItemAndId(int id, NanoTaskItem data)
|
||||
{
|
||||
Id = id;
|
||||
Data = data;
|
||||
}
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// The UI state of the NanoTask
|
||||
/// </summary>
|
||||
[Serializable, NetSerializable]
|
||||
public sealed class NanoTaskUiState : BoundUserInterfaceState
|
||||
{
|
||||
public List<NanoTaskItemAndId> Tasks;
|
||||
|
||||
public NanoTaskUiState(List<NanoTaskItemAndId> tasks)
|
||||
{
|
||||
Tasks = tasks;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
using Content.Shared.CartridgeLoader;
|
||||
using Content.Shared.CartridgeLoader.Cartridges;
|
||||
|
||||
namespace Content.Shared.CartridgeLoader.Cartridges;
|
||||
|
||||
public abstract class SharedNanoTaskCartridgeSystem : EntitySystem
|
||||
{
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<NanoTaskCartridgeComponent, CartridgeAddedEvent>(OnCartridgeAdded);
|
||||
}
|
||||
|
||||
private void OnCartridgeAdded(Entity<NanoTaskCartridgeComponent> ent, ref CartridgeAddedEvent args)
|
||||
{
|
||||
EnsureComp<NanoTaskInteractionComponent>(args.Loader);
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@ device-pda-slot-component-slot-name-cartridge = Cartridge
|
||||
|
||||
default-program-name = Program
|
||||
notekeeper-program-name = Notekeeper
|
||||
nano-task-program-name = NanoTask
|
||||
news-read-program-name = Station news
|
||||
|
||||
crew-manifest-program-name = Crew manifest
|
||||
@@ -28,6 +29,47 @@ astro-nav-program-name = AstroNav
|
||||
|
||||
med-tek-program-name = MedTek
|
||||
|
||||
# NanoTask cartridge
|
||||
|
||||
nano-task-ui-heading-high-priority-tasks =
|
||||
{ $amount ->
|
||||
[zero] No High Priority Tasks
|
||||
[one] 1 High Priority Task
|
||||
*[other] {$amount} High Priority Tasks
|
||||
}
|
||||
nano-task-ui-heading-medium-priority-tasks =
|
||||
{ $amount ->
|
||||
[zero] No Medium Priority Tasks
|
||||
[one] 1 Medium Priority Task
|
||||
*[other] {$amount} Medium Priority Tasks
|
||||
}
|
||||
nano-task-ui-heading-low-priority-tasks =
|
||||
{ $amount ->
|
||||
[zero] No Low Priority Tasks
|
||||
[one] 1 Low Priority Task
|
||||
*[other] {$amount} Low Priority Tasks
|
||||
}
|
||||
nano-task-ui-done = Done
|
||||
nano-task-ui-revert-done = Undo
|
||||
nano-task-ui-priority-low = Low
|
||||
nano-task-ui-priority-medium = Medium
|
||||
nano-task-ui-priority-high = High
|
||||
nano-task-ui-cancel = Cancel
|
||||
nano-task-ui-print = Print
|
||||
nano-task-ui-delete = Delete
|
||||
nano-task-ui-save = Save
|
||||
nano-task-ui-new-task = New Task
|
||||
nano-task-ui-description-label = Description:
|
||||
nano-task-ui-description-placeholder = Get something important
|
||||
nano-task-ui-requester-label = Requester:
|
||||
nano-task-ui-requester-placeholder = John Nanotrasen
|
||||
nano-task-ui-item-title = Edit Task
|
||||
nano-task-printed-description = Description: {$description}
|
||||
nano-task-printed-requester = Requester: {$requester}
|
||||
nano-task-printed-high-priority = Priority: High
|
||||
nano-task-printed-medium-priority = Priority: Medium
|
||||
nano-task-printed-low-priority = Priority: Low
|
||||
|
||||
# Wanted list cartridge
|
||||
wanted-list-program-name = Wanted list
|
||||
wanted-list-label-no-records = It's all right, cowboy
|
||||
|
||||
@@ -16,6 +16,25 @@
|
||||
state: book_icon
|
||||
- type: NotekeeperCartridge
|
||||
|
||||
|
||||
- type: entity
|
||||
parent: BaseItem
|
||||
id: NanoTaskCartridge
|
||||
name: NanoTask cartridge
|
||||
description: A program that allows you to keep a list of tasks to do.
|
||||
components:
|
||||
- type: Sprite
|
||||
sprite: Objects/Devices/cartridge.rsi
|
||||
state: cart-nav
|
||||
- type: Cartridge
|
||||
programName: nano-task-program-name
|
||||
icon:
|
||||
sprite: Interface/Misc/program_icons.rsi
|
||||
state: nano_task
|
||||
- type: UIFragment
|
||||
ui: !type:NanoTaskUi
|
||||
- type: NanoTaskCartridge
|
||||
|
||||
- type: entity
|
||||
parent: BaseItem
|
||||
id: NewsReaderCartridge
|
||||
|
||||
@@ -80,6 +80,7 @@
|
||||
preinstalled:
|
||||
- CrewManifestCartridge
|
||||
- NotekeeperCartridge
|
||||
- NanoTaskCartridge
|
||||
- NewsReaderCartridge
|
||||
cartridgeSlot:
|
||||
priority: -1
|
||||
@@ -130,6 +131,7 @@
|
||||
preinstalled:
|
||||
- CrewManifestCartridge
|
||||
- NotekeeperCartridge
|
||||
- NanoTaskCartridge
|
||||
- NewsReaderCartridge
|
||||
- WantedListCartridge
|
||||
|
||||
@@ -143,6 +145,7 @@
|
||||
preinstalled:
|
||||
- CrewManifestCartridge
|
||||
- NotekeeperCartridge
|
||||
- NanoTaskCartridge
|
||||
- NewsReaderCartridge
|
||||
- MedTekCartridge
|
||||
|
||||
@@ -492,6 +495,7 @@
|
||||
preinstalled:
|
||||
- CrewManifestCartridge
|
||||
- NotekeeperCartridge
|
||||
- NanoTaskCartridge
|
||||
- NewsReaderCartridge
|
||||
- AstroNavCartridge
|
||||
|
||||
@@ -840,6 +844,7 @@
|
||||
preinstalled:
|
||||
- CrewManifestCartridge
|
||||
- NotekeeperCartridge
|
||||
- NanoTaskCartridge
|
||||
- NewsReaderCartridge
|
||||
- WantedListCartridge
|
||||
- LogProbeCartridge
|
||||
@@ -908,6 +913,7 @@
|
||||
preinstalled:
|
||||
- CrewManifestCartridge
|
||||
- NotekeeperCartridge
|
||||
- NanoTaskCartridge
|
||||
- NewsReaderCartridge
|
||||
- MedTekCartridge
|
||||
- WantedListCartridge
|
||||
@@ -932,6 +938,7 @@
|
||||
preinstalled:
|
||||
- CrewManifestCartridge
|
||||
- NotekeeperCartridge
|
||||
- NanoTaskCartridge
|
||||
- NewsReaderCartridge
|
||||
- LogProbeCartridge
|
||||
- WantedListCartridge
|
||||
@@ -1054,6 +1061,7 @@
|
||||
uiKey: enum.PdaUiKey.Key
|
||||
preinstalled:
|
||||
- NotekeeperCartridge
|
||||
- NanoTaskCartridge
|
||||
|
||||
- type: entity
|
||||
parent: BaseSecurityPDA
|
||||
@@ -1080,6 +1088,7 @@
|
||||
preinstalled:
|
||||
- CrewManifestCartridge
|
||||
- NotekeeperCartridge
|
||||
- NanoTaskCartridge
|
||||
- NewsReaderCartridge
|
||||
- MedTekCartridge
|
||||
- WantedListCartridge
|
||||
@@ -1250,6 +1259,7 @@
|
||||
preinstalled:
|
||||
- CrewManifestCartridge
|
||||
- NotekeeperCartridge
|
||||
- NanoTaskCartridge
|
||||
- NewsReaderCartridge
|
||||
- WantedListCartridge
|
||||
- LogProbeCartridge
|
||||
@@ -1277,6 +1287,7 @@
|
||||
preinstalled:
|
||||
- CrewManifestCartridge
|
||||
- NotekeeperCartridge
|
||||
- NanoTaskCartridge
|
||||
- NewsReaderCartridge
|
||||
- WantedListCartridge
|
||||
- MedTekCartridge
|
||||
@@ -1423,6 +1434,7 @@
|
||||
uiKey: enum.PdaUiKey.Key
|
||||
preinstalled:
|
||||
- NotekeeperCartridge
|
||||
- NanoTaskCartridge
|
||||
- MedTekCartridge
|
||||
|
||||
- type: entity
|
||||
|
||||
@@ -196,6 +196,21 @@
|
||||
headerImagePath: "/Textures/Interface/Paper/paper_heading_cargo_invoice.svg.96dpi.png"
|
||||
headerMargin: 0.0, 12.0, 0.0, 0.0
|
||||
|
||||
- type: entity
|
||||
id: PaperNanoTaskItem
|
||||
parent: Paper
|
||||
name: NanoTask item
|
||||
description: A printed NanoTask item. Can be inserted into your PDA to add it to your tasks.
|
||||
components:
|
||||
- type: Tag
|
||||
tags:
|
||||
- Document
|
||||
- Trash
|
||||
- Paper
|
||||
- type: StaticPrice
|
||||
price: 0
|
||||
- type: NanoTaskPrinted
|
||||
|
||||
- type: entity
|
||||
id: PaperCargoBountyManifest
|
||||
parent: PaperCargoInvoice
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"version": 1,
|
||||
"license": "CC-BY-SA-3.0",
|
||||
"copyright": "news_read by Misha_Unity, crew_manifest by Phill101",
|
||||
"copyright": "news_read by Misha_Unity, crew_manifest by Phill101, nano_task by Janet Blackquill <uhhadd@gmail.com>",
|
||||
"size": {
|
||||
"x": 32,
|
||||
"y": 32
|
||||
@@ -12,6 +12,9 @@
|
||||
},
|
||||
{
|
||||
"name": "crew_manifest"
|
||||
},
|
||||
{
|
||||
"name": "nano_task"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 324 B |
Reference in New Issue
Block a user