mirror of
https://gitlab.acidiclight.dev/sociallydistant/sociallydistant.git
synced 2025-01-22 17:41:49 -05:00
Implement skeletal crafting UI
Signed-off-by: Ritchie Frodomar <alkalinethunder@gmail.com>
This commit is contained in:
parent
935007c3f5
commit
0809f86ca9
20 changed files with 700 additions and 8 deletions
|
@ -8,6 +8,7 @@ namespace AcidicGUI.VisualStyles;
|
||||||
|
|
||||||
internal sealed class FallbackVisualStyle : IVisualStyle
|
internal sealed class FallbackVisualStyle : IVisualStyle
|
||||||
{
|
{
|
||||||
|
public int ProgressBarHeight => 6;
|
||||||
public int SliderThickness => 12;
|
public int SliderThickness => 12;
|
||||||
public Point ToggleSize => new Point(18, 18);
|
public Point ToggleSize => new Point(18, 18);
|
||||||
public Point SwitchSize => ToggleSize;
|
public Point SwitchSize => ToggleSize;
|
||||||
|
@ -54,6 +55,14 @@ internal sealed class FallbackVisualStyle : IVisualStyle
|
||||||
geometry.AddQuad(new LayoutRect(scrollBarArea.Left, scrollBarArea.Top + barOffset, scrollBarArea.Width, barHeight), Color.White);
|
geometry.AddQuad(new LayoutRect(scrollBarArea.Left, scrollBarArea.Top + barOffset, scrollBarArea.Width, barHeight), Color.White);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void DrawProgressBar(Widget widget, GeometryHelper geometry, float fillPercentage)
|
||||||
|
{
|
||||||
|
geometry.AddQuad(widget.ContentArea, Color.DimGray);
|
||||||
|
|
||||||
|
var fillWidth = (int)MathHelper.Lerp(0, widget.ContentArea.Width, fillPercentage);
|
||||||
|
geometry.AddQuad(new LayoutRect(widget.ContentArea.Left, widget.ContentArea.Top, fillWidth, widget.ContentArea.Height), Color.Red);
|
||||||
|
}
|
||||||
|
|
||||||
public void DrawToggle(
|
public void DrawToggle(
|
||||||
Toggle toggle,
|
Toggle toggle,
|
||||||
GeometryHelper geometry,
|
GeometryHelper geometry,
|
||||||
|
|
|
@ -8,6 +8,7 @@ namespace AcidicGUI.VisualStyles;
|
||||||
|
|
||||||
public interface IVisualStyle : IFontFamilyProvider
|
public interface IVisualStyle : IFontFamilyProvider
|
||||||
{
|
{
|
||||||
|
int ProgressBarHeight { get; }
|
||||||
int SliderThickness { get; }
|
int SliderThickness { get; }
|
||||||
Point ToggleSize { get; }
|
Point ToggleSize { get; }
|
||||||
Point SwitchSize { get; }
|
Point SwitchSize { get; }
|
||||||
|
@ -41,6 +42,8 @@ public interface IVisualStyle : IFontFamilyProvider
|
||||||
bool isChecked
|
bool isChecked
|
||||||
);
|
);
|
||||||
|
|
||||||
|
void DrawProgressBar(Widget widget, GeometryHelper geometry, float fillPercentage);
|
||||||
|
|
||||||
void DrawToggleSwitch(
|
void DrawToggleSwitch(
|
||||||
Toggle toggle,
|
Toggle toggle,
|
||||||
GeometryHelper geometry,
|
GeometryHelper geometry,
|
||||||
|
|
29
src/AcidicGUI/Widgets/ProgressBar.cs
Normal file
29
src/AcidicGUI/Widgets/ProgressBar.cs
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
using AcidicGUI.Rendering;
|
||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
|
||||||
|
namespace AcidicGUI.Widgets;
|
||||||
|
|
||||||
|
public sealed class ProgressBar : Widget
|
||||||
|
{
|
||||||
|
private float fillPercentage = 0;
|
||||||
|
|
||||||
|
public float Value
|
||||||
|
{
|
||||||
|
get => fillPercentage;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
fillPercentage = MathHelper.Clamp(value, 0, 1);
|
||||||
|
InvalidateGeometry();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override Point GetContentSize(Point availableSize)
|
||||||
|
{
|
||||||
|
return new Point(availableSize.X, GetVisualStyle().ProgressBarHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void RebuildGeometry(GeometryHelper geometry)
|
||||||
|
{
|
||||||
|
GetVisualStyle().DrawProgressBar(this, geometry, fillPercentage);
|
||||||
|
}
|
||||||
|
}
|
128
src/AcidicGUI/Widgets/TablePanel.cs
Normal file
128
src/AcidicGUI/Widgets/TablePanel.cs
Normal file
|
@ -0,0 +1,128 @@
|
||||||
|
using AcidicGUI.Layout;
|
||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
|
||||||
|
namespace AcidicGUI.Widgets;
|
||||||
|
|
||||||
|
public sealed class TablePanel : ContainerWidget
|
||||||
|
{
|
||||||
|
private int columnCount = 3;
|
||||||
|
private int rowSpacing = 0;
|
||||||
|
private int columnSpacing = 0;
|
||||||
|
private int[] columnSizesCache = Array.Empty<int>();
|
||||||
|
|
||||||
|
public int ColumnCount
|
||||||
|
{
|
||||||
|
get => columnCount;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value < 1)
|
||||||
|
throw new InvalidOperationException("A table must have at least one column.");
|
||||||
|
|
||||||
|
columnCount = value;
|
||||||
|
InvalidateLayout();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int ColumnSpacing
|
||||||
|
{
|
||||||
|
get => columnSpacing;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
columnSpacing = value;
|
||||||
|
InvalidateLayout();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int RowSpacing
|
||||||
|
{
|
||||||
|
get => rowSpacing;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
rowSpacing = value;
|
||||||
|
InvalidateLayout();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override unsafe Point GetContentSize(Point availableSize)
|
||||||
|
{
|
||||||
|
if (Children.Count == 0)
|
||||||
|
return Point.Zero;
|
||||||
|
|
||||||
|
Span<int> columnSizes = stackalloc int[columnCount];
|
||||||
|
int maxColumnSize = availableSize.X - (columnSpacing * columnCount - 1) / columnCount;
|
||||||
|
int height = 0;
|
||||||
|
int rowHeight = 0;
|
||||||
|
int lastRow = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < Children.Count; i++)
|
||||||
|
{
|
||||||
|
var columnIndex = i % columnCount;
|
||||||
|
var row = i / columnCount;
|
||||||
|
var child = Children[i];
|
||||||
|
|
||||||
|
if (row != lastRow)
|
||||||
|
{
|
||||||
|
lastRow = row;
|
||||||
|
height += rowHeight;
|
||||||
|
rowHeight = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int availableHeight = availableSize.Y - height;
|
||||||
|
|
||||||
|
var widgetSize = child.GetCachedContentSize(new Point(maxColumnSize, availableHeight));
|
||||||
|
|
||||||
|
columnSizes[columnIndex] = Math.Max(columnSizes[columnIndex], widgetSize.X);
|
||||||
|
rowHeight = Math.Max(rowHeight, widgetSize.Y);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rowHeight > 0)
|
||||||
|
{
|
||||||
|
height += rowHeight;
|
||||||
|
rowHeight = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
var columnsWidth = columnSpacing * (columnCount - 1);
|
||||||
|
for (var i = 0; i < columnCount; i++)
|
||||||
|
{
|
||||||
|
columnsWidth += columnSizes[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
columnSizesCache = columnSizes.ToArray();
|
||||||
|
return new Point(columnsWidth, height + rowSpacing * lastRow);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void ArrangeChildren(IGuiContext context, LayoutRect availableSpace)
|
||||||
|
{
|
||||||
|
if (Children.Count == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var rowCount = Math.Max(1, Children.Count / columnCount);
|
||||||
|
var rowSpace = (availableSpace.Height - rowSpacing * (rowCount - 1)) / rowCount;
|
||||||
|
int yStart = availableSpace.Top;
|
||||||
|
int xStart = availableSpace.Left;
|
||||||
|
int lastRow = 0;
|
||||||
|
int rowHeight = 0;
|
||||||
|
|
||||||
|
for (var i = 0; i < Children.Count; i++)
|
||||||
|
{
|
||||||
|
var columnIndex = i % columnCount;
|
||||||
|
var rowIndex = i / columnCount;
|
||||||
|
var child = Children[i];
|
||||||
|
|
||||||
|
if (rowIndex != lastRow)
|
||||||
|
{
|
||||||
|
lastRow = rowIndex;
|
||||||
|
yStart += rowHeight + rowSpacing;
|
||||||
|
xStart = availableSpace.Left;
|
||||||
|
rowHeight = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
var childSize = child.GetCachedContentSize(new Point(columnSizesCache[columnIndex], rowSpace));
|
||||||
|
|
||||||
|
child.UpdateLayout(context, new LayoutRect(xStart, yStart, childSize.X, rowSpace));
|
||||||
|
|
||||||
|
rowHeight = Math.Max(rowHeight, childSize.Y);
|
||||||
|
xStart += columnSizesCache[columnIndex] + columnSpacing;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -8,9 +8,22 @@ namespace SociallyDistant.Core.Core
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public enum RecipeCategory
|
||||||
|
{
|
||||||
|
Components,
|
||||||
|
Exploits,
|
||||||
|
Payloads,
|
||||||
|
Attacks,
|
||||||
|
Daemons,
|
||||||
|
ShellExtensions
|
||||||
|
}
|
||||||
|
|
||||||
public abstract class CraftingRecipe : IGameContent
|
public abstract class CraftingRecipe : IGameContent
|
||||||
{
|
{
|
||||||
|
public abstract RecipeCategory Category { get; }
|
||||||
public abstract string Id { get; }
|
public abstract string Id { get; }
|
||||||
|
public abstract string Description { get; }
|
||||||
|
public abstract string Title { get; }
|
||||||
|
|
||||||
public abstract IEnumerable<IngredientRequirement> RequiredIngredients { get; }
|
public abstract IEnumerable<IngredientRequirement> RequiredIngredients { get; }
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,7 @@ namespace SociallyDistant.Core.Core
|
||||||
INarrativeObjectTable<WorldComputerData> Computers { get; }
|
INarrativeObjectTable<WorldComputerData> Computers { get; }
|
||||||
INarrativeObjectTable<WorldInternetServiceProviderData> InternetProviders { get; }
|
INarrativeObjectTable<WorldInternetServiceProviderData> InternetProviders { get; }
|
||||||
INarrativeObjectTable<WorldLocalNetworkData> LocalAreaNetworks { get; }
|
INarrativeObjectTable<WorldLocalNetworkData> LocalAreaNetworks { get; }
|
||||||
|
IWorldTable<WorldInventoryItem> Inventory { get; }
|
||||||
IWorldTable<WorldNetworkConnection> NetworkConnections { get; }
|
IWorldTable<WorldNetworkConnection> NetworkConnections { get; }
|
||||||
IWorldTable<WorldPortForwardingRule> PortForwardingRules { get; }
|
IWorldTable<WorldPortForwardingRule> PortForwardingRules { get; }
|
||||||
IWorldTable<WorldCraftedExploitData> CraftedExploits { get; }
|
IWorldTable<WorldCraftedExploitData> CraftedExploits { get; }
|
||||||
|
|
|
@ -0,0 +1,43 @@
|
||||||
|
using SociallyDistant.Core.Core.Serialization;
|
||||||
|
|
||||||
|
namespace SociallyDistant.Core.Core.WorldData.Data;
|
||||||
|
|
||||||
|
public struct WorldInventoryItem : IWorldData, IDataWithId
|
||||||
|
{
|
||||||
|
private ObjectId id;
|
||||||
|
private ObjectId userId;
|
||||||
|
private string recipeId;
|
||||||
|
private int quantity;
|
||||||
|
|
||||||
|
public ObjectId InstanceId
|
||||||
|
{
|
||||||
|
get => id;
|
||||||
|
set => id = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ObjectId Owner
|
||||||
|
{
|
||||||
|
get => userId;
|
||||||
|
set => userId = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string RecipeId
|
||||||
|
{
|
||||||
|
get => recipeId;
|
||||||
|
set => recipeId = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Quantity
|
||||||
|
{
|
||||||
|
get => quantity;
|
||||||
|
set => quantity = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Serialize(IWorldSerializer serializer)
|
||||||
|
{
|
||||||
|
SerializationUtility.SerializeAtRevision(ref id, serializer, WorldRevision.Inventory, default);
|
||||||
|
SerializationUtility.SerializeAtRevision(ref userId, serializer, WorldRevision.Inventory, default);
|
||||||
|
SerializationUtility.SerializeAtRevision(ref recipeId, serializer, WorldRevision.Inventory, string.Empty);
|
||||||
|
SerializationUtility.SerializeAtRevision(ref quantity, serializer, WorldRevision.Inventory, default);
|
||||||
|
}
|
||||||
|
}
|
|
@ -33,6 +33,7 @@
|
||||||
SubDocuments = 28,
|
SubDocuments = 28,
|
||||||
Checkpoints = 29,
|
Checkpoints = 29,
|
||||||
IngredientLedger = 30,
|
IngredientLedger = 30,
|
||||||
|
Inventory=31,
|
||||||
|
|
||||||
Latest
|
Latest
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,8 @@ public sealed class CommandAttribute : Attribute
|
||||||
|
|
||||||
public string Name => name;
|
public string Name => name;
|
||||||
|
|
||||||
|
public bool Cheat { get; set; }
|
||||||
|
|
||||||
public CommandAttribute(string name)
|
public CommandAttribute(string name)
|
||||||
{
|
{
|
||||||
this.name = name;
|
this.name = name;
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
using AcidicGUI.CustomProperties;
|
||||||
using AcidicGUI.Layout;
|
using AcidicGUI.Layout;
|
||||||
using AcidicGUI.ListAdapters;
|
using AcidicGUI.ListAdapters;
|
||||||
using AcidicGUI.Widgets;
|
using AcidicGUI.Widgets;
|
||||||
|
@ -7,12 +9,13 @@ namespace SociallyDistant.Core.UI.Recycling;
|
||||||
|
|
||||||
public sealed class TwoLineListItemWithIcon : Widget
|
public sealed class TwoLineListItemWithIcon : Widget
|
||||||
{
|
{
|
||||||
private readonly ListItem root = new();
|
private readonly ListItem root = new();
|
||||||
private readonly StackPanel stack = new();
|
private readonly FlexPanel stack = new();
|
||||||
private readonly Box icon = new();
|
private readonly Box icon = new();
|
||||||
private readonly StackPanel lines = new();
|
private readonly StackPanel lines = new();
|
||||||
private readonly TextWidget line1 = new();
|
private readonly TextWidget line1 = new();
|
||||||
private readonly TextWidget line2 = new();
|
private readonly TextWidget line2 = new();
|
||||||
|
private readonly Emblem emblem = new();
|
||||||
|
|
||||||
public string Line1
|
public string Line1
|
||||||
{
|
{
|
||||||
|
@ -40,8 +43,32 @@ public sealed class TwoLineListItemWithIcon : Widget
|
||||||
set => root.ClickCallback = value;
|
set => root.ClickCallback = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool ShowEmblem
|
||||||
|
{
|
||||||
|
get => emblem.Visibility == Visibility.Visible;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value)
|
||||||
|
emblem.Visibility = Visibility.Visible;
|
||||||
|
else
|
||||||
|
emblem.Visibility = Visibility.Collapsed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string EmblemText
|
||||||
|
{
|
||||||
|
get => emblem.Text;
|
||||||
|
set => emblem.Text = value;
|
||||||
|
}
|
||||||
|
|
||||||
public TwoLineListItemWithIcon()
|
public TwoLineListItemWithIcon()
|
||||||
{
|
{
|
||||||
|
emblem.Visibility = Visibility.Collapsed;
|
||||||
|
|
||||||
|
lines.GetCustomProperties<FlexPanelProperties>().Mode = FlexMode.Proportional;
|
||||||
|
|
||||||
|
emblem.VerticalAlignment = VerticalAlignment.Middle;
|
||||||
|
|
||||||
line1.WordWrapping = true;
|
line1.WordWrapping = true;
|
||||||
line2.WordWrapping = true;
|
line2.WordWrapping = true;
|
||||||
line1.UseMarkup = true;
|
line1.UseMarkup = true;
|
||||||
|
@ -57,6 +84,7 @@ public sealed class TwoLineListItemWithIcon : Widget
|
||||||
stack.ChildWidgets.Add(lines);
|
stack.ChildWidgets.Add(lines);
|
||||||
lines.ChildWidgets.Add(line1);
|
lines.ChildWidgets.Add(line1);
|
||||||
lines.ChildWidgets.Add(line2);
|
lines.ChildWidgets.Add(line2);
|
||||||
|
stack.ChildWidgets.Add(emblem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,17 @@ public sealed class ListItemWidgetController<T> : RecyclableWidgetController
|
||||||
{
|
{
|
||||||
listItem = GetWidget<TwoLineListItemWithIcon>();
|
listItem = GetWidget<TwoLineListItemWithIcon>();
|
||||||
|
|
||||||
|
if (typeof(T) == typeof(int))
|
||||||
|
{
|
||||||
|
listItem.ShowEmblem = true;
|
||||||
|
listItem.EmblemText = Data!.ToString() ?? "0";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
listItem.ShowEmblem = false;
|
||||||
|
listItem.EmblemText = string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
if (Image != null)
|
if (Image != null)
|
||||||
{
|
{
|
||||||
Image.Build(listItem.Icon);
|
Image.Build(listItem.Icon);
|
||||||
|
|
|
@ -53,6 +53,7 @@ public class SociallyDistantVisualStyle : IVisualStyle
|
||||||
private IFontFamily monospace = null!;
|
private IFontFamily monospace = null!;
|
||||||
private Texture2D? checkboxEmblem;
|
private Texture2D? checkboxEmblem;
|
||||||
|
|
||||||
|
public int ProgressBarHeight => 6;
|
||||||
public int SliderThickness => 18;
|
public int SliderThickness => 18;
|
||||||
public Point ToggleSize => new Point(20, 20);
|
public Point ToggleSize => new Point(20, 20);
|
||||||
public Point SwitchSize => new Point(40, 22);
|
public Point SwitchSize => new Point(40, 22);
|
||||||
|
@ -485,6 +486,14 @@ public class SociallyDistantVisualStyle : IVisualStyle
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void DrawProgressBar(Widget widget, GeometryHelper geometry, float fillPercentage)
|
||||||
|
{
|
||||||
|
geometry.AddRoundedRectangleOutline(widget.ContentArea, 1, 6, accentCyberspace);
|
||||||
|
|
||||||
|
var fillWidth = (int)MathHelper.Lerp(0, widget.ContentArea.Width, fillPercentage);
|
||||||
|
geometry.AddRoundedRectangle(new LayoutRect(widget.ContentArea.Left, widget.ContentArea.Top, fillWidth, widget.ContentArea.Height), 6, accentCyberspace * 0.5f);
|
||||||
|
}
|
||||||
|
|
||||||
public void DrawToggleSwitch(
|
public void DrawToggleSwitch(
|
||||||
Toggle toggle,
|
Toggle toggle,
|
||||||
GeometryHelper geometry,
|
GeometryHelper geometry,
|
||||||
|
|
|
@ -13,6 +13,8 @@ internal sealed class CommandAsset :
|
||||||
private readonly CommandAttribute attribute;
|
private readonly CommandAttribute attribute;
|
||||||
private readonly Func<IGameContext, ICommandTask> constructor;
|
private readonly Func<IGameContext, ICommandTask> constructor;
|
||||||
|
|
||||||
|
public bool IsCheat => attribute.Cheat;
|
||||||
|
|
||||||
public string Name => attribute.Name;
|
public string Name => attribute.Name;
|
||||||
|
|
||||||
public CommandAsset(IGameContext context, CommandAttribute attribute, Func<IGameContext, ICommandTask> constructor)
|
public CommandAsset(IGameContext context, CommandAttribute attribute, Func<IGameContext, ICommandTask> constructor)
|
||||||
|
|
27
src/SociallyDistant/Commands/Cheats/CodingInTheNameOf.cs
Normal file
27
src/SociallyDistant/Commands/Cheats/CodingInTheNameOf.cs
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
using SociallyDistant.Architecture;
|
||||||
|
using SociallyDistant.Core;
|
||||||
|
using SociallyDistant.Core.Core;
|
||||||
|
using SociallyDistant.Core.Modules;
|
||||||
|
using SociallyDistant.Core.OS.Tasks;
|
||||||
|
using SociallyDistant.Core.WorldData;
|
||||||
|
|
||||||
|
namespace SociallyDistant.Commands.Cheats;
|
||||||
|
|
||||||
|
[Command("codinginthenameof", Cheat = true)]
|
||||||
|
public class CodingInTheNameOf : ScriptableCommand
|
||||||
|
{
|
||||||
|
public CodingInTheNameOf(IGameContext gameContext) : base(gameContext)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override Task OnExecute()
|
||||||
|
{
|
||||||
|
var ledger = WorldManager.Instance.World.Ledger;
|
||||||
|
if (ledger is not IngredientLedger ledgerInternal)
|
||||||
|
return Task.CompletedTask;
|
||||||
|
|
||||||
|
ledgerInternal.Deposit(CraftingIngredient.CodeFragments, 50);
|
||||||
|
Console.WriteLine("Fuck you, I won't code what you tell me!");
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
}
|
27
src/SociallyDistant/Commands/Cheats/KnowledgeIsPower.cs
Normal file
27
src/SociallyDistant/Commands/Cheats/KnowledgeIsPower.cs
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
using SociallyDistant.Architecture;
|
||||||
|
using SociallyDistant.Core;
|
||||||
|
using SociallyDistant.Core.Core;
|
||||||
|
using SociallyDistant.Core.Modules;
|
||||||
|
using SociallyDistant.Core.OS.Tasks;
|
||||||
|
using SociallyDistant.Core.WorldData;
|
||||||
|
|
||||||
|
namespace SociallyDistant.Commands.Cheats;
|
||||||
|
|
||||||
|
[Command("knowledgeispower", Cheat = true)]
|
||||||
|
public class KnowledgeIsPower : ScriptableCommand
|
||||||
|
{
|
||||||
|
public KnowledgeIsPower(IGameContext gameContext) : base(gameContext)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override Task OnExecute()
|
||||||
|
{
|
||||||
|
var ledger = WorldManager.Instance.World.Ledger;
|
||||||
|
if (ledger is not IngredientLedger ledgerInternal)
|
||||||
|
return Task.CompletedTask;
|
||||||
|
|
||||||
|
ledgerInternal.Deposit(CraftingIngredient.DataFragments, 50);
|
||||||
|
Console.WriteLine("Knowledge is power, Noah...");
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
using SociallyDistant.Core.Core;
|
using SociallyDistant.Core.Core;
|
||||||
using SociallyDistant.Core.Core.Serialization;
|
using SociallyDistant.Core.Core.Serialization;
|
||||||
|
using YamlDotNet.Core.Tokens;
|
||||||
|
|
||||||
namespace SociallyDistant.Core.WorldData;
|
namespace SociallyDistant.Core.WorldData;
|
||||||
|
|
||||||
|
|
|
@ -35,6 +35,7 @@ namespace SociallyDistant.Core.WorldData
|
||||||
private readonly WorldDataTable<WorldWitnessedObjectData> witnessedObjects;
|
private readonly WorldDataTable<WorldWitnessedObjectData> witnessedObjects;
|
||||||
private readonly WorldDataTable<WorldNotificationData> notifications;
|
private readonly WorldDataTable<WorldNotificationData> notifications;
|
||||||
private readonly NarrativeObjectTable<WorldNewsData> newsArticles;
|
private readonly NarrativeObjectTable<WorldNewsData> newsArticles;
|
||||||
|
private readonly WorldDataTable<WorldInventoryItem> inventory;
|
||||||
|
|
||||||
|
|
||||||
internal IWorldDataObject<ProtectedWorldState> ProtectedWorldData => protectedWorldState;
|
internal IWorldDataObject<ProtectedWorldState> ProtectedWorldData => protectedWorldState;
|
||||||
|
@ -44,6 +45,9 @@ namespace SociallyDistant.Core.WorldData
|
||||||
|
|
||||||
public ILedger Ledger => ledger;
|
public ILedger Ledger => ledger;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public IWorldTable<WorldInventoryItem> Inventory => inventory;
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public IWorldDataObject<GlobalWorldData> GlobalWorldState => globalWorldState;
|
public IWorldDataObject<GlobalWorldData> GlobalWorldState => globalWorldState;
|
||||||
|
|
||||||
|
@ -160,7 +164,7 @@ namespace SociallyDistant.Core.WorldData
|
||||||
witnessedObjects = new WorldDataTable<WorldWitnessedObjectData>(instanceIdGenerator, eventDispatcher);
|
witnessedObjects = new WorldDataTable<WorldWitnessedObjectData>(instanceIdGenerator, eventDispatcher);
|
||||||
notifications = new WorldDataTable<WorldNotificationData>(instanceIdGenerator, eventDispatcher);
|
notifications = new WorldDataTable<WorldNotificationData>(instanceIdGenerator, eventDispatcher);
|
||||||
newsArticles = new NarrativeObjectTable<WorldNewsData>(instanceIdGenerator, eventDispatcher);
|
newsArticles = new NarrativeObjectTable<WorldNewsData>(instanceIdGenerator, eventDispatcher);
|
||||||
|
inventory = new WorldDataTable<WorldInventoryItem>(instanceIdGenerator, eventDispatcher);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Serialize(IWorldSerializer serializer)
|
public void Serialize(IWorldSerializer serializer)
|
||||||
|
@ -196,6 +200,7 @@ namespace SociallyDistant.Core.WorldData
|
||||||
witnessedObjects.Serialize(serializer, WorldRevision.MissionFailures);
|
witnessedObjects.Serialize(serializer, WorldRevision.MissionFailures);
|
||||||
notifications.Serialize(serializer, WorldRevision.Notifications);
|
notifications.Serialize(serializer, WorldRevision.Notifications);
|
||||||
newsArticles.Serialize(serializer, WorldRevision.Articles);
|
newsArticles.Serialize(serializer, WorldRevision.Articles);
|
||||||
|
inventory.Serialize(serializer, WorldRevision.Inventory);
|
||||||
|
|
||||||
eventDispatcher.PauseEvents = false;
|
eventDispatcher.PauseEvents = false;
|
||||||
}
|
}
|
||||||
|
@ -204,6 +209,7 @@ namespace SociallyDistant.Core.WorldData
|
||||||
{
|
{
|
||||||
// You must wipe the world in reverse order of how you would create or serialize it.
|
// You must wipe the world in reverse order of how you would create or serialize it.
|
||||||
// This ensures proper handling of deleting objects that depend on other objects.
|
// This ensures proper handling of deleting objects that depend on other objects.
|
||||||
|
inventory.Clear();
|
||||||
newsArticles.Clear();
|
newsArticles.Clear();
|
||||||
notifications.Clear();
|
notifications.Clear();
|
||||||
witnessedObjects.Clear();
|
witnessedObjects.Clear();
|
||||||
|
|
28
src/SociallyDistant/Recipes/DataScraper.cs
Normal file
28
src/SociallyDistant/Recipes/DataScraper.cs
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
using SociallyDistant.Core.Core;
|
||||||
|
using SociallyDistant.Core.Modules;
|
||||||
|
|
||||||
|
namespace SociallyDistant.Recipes;
|
||||||
|
|
||||||
|
public sealed class DataScraper : CraftingRecipe
|
||||||
|
{
|
||||||
|
public override RecipeCategory Category => RecipeCategory.ShellExtensions;
|
||||||
|
|
||||||
|
public override string Description =>
|
||||||
|
"""
|
||||||
|
Scrapes <b>Data Fragments</b> from the remote system, adding them to the Inventory. Has a small chance of locating useful information in home directories but does not download it.
|
||||||
|
""";
|
||||||
|
public override string Id => "data_scraper";
|
||||||
|
public override string Title => "Data Scraper";
|
||||||
|
|
||||||
|
public override IEnumerable<IngredientRequirement> RequiredIngredients
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
yield return new IngredientRequirement(CraftingIngredient.DataFragments, 250);
|
||||||
|
yield return new IngredientRequirement(CraftingIngredient.CodeFragments, 100);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
protected override void OnCraft(IGameContext game)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,15 +1,338 @@
|
||||||
|
using AcidicGUI.CustomProperties;
|
||||||
|
using AcidicGUI.Layout;
|
||||||
|
using AcidicGUI.ListAdapters;
|
||||||
|
using AcidicGUI.TextRendering;
|
||||||
|
using AcidicGUI.Widgets;
|
||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
using SociallyDistant.Core;
|
||||||
|
using SociallyDistant.Core.Core;
|
||||||
using SociallyDistant.Core.Programs;
|
using SociallyDistant.Core.Programs;
|
||||||
|
using SociallyDistant.Core.Shell;
|
||||||
|
using SociallyDistant.Core.UI.Common;
|
||||||
|
using SociallyDistant.Core.UI.Recycling;
|
||||||
|
using SociallyDistant.Core.UI.VisualStyles;
|
||||||
|
using SociallyDistant.UI.FloatingTools.FileManager;
|
||||||
|
|
||||||
namespace SociallyDistant.UI.Tools.Crafting;
|
namespace SociallyDistant.UI.Tools.Crafting;
|
||||||
|
|
||||||
public sealed class CraftingProgramController : ProgramController
|
public sealed class CraftingProgramController : ProgramController
|
||||||
{
|
{
|
||||||
|
private readonly string ghost = """
|
||||||
|
______ __ __ _____ __ _ __
|
||||||
|
/ ____// /_ ____ _____ / /_/ ___/ ____ / /____ (_)/ /_
|
||||||
|
/ / __ / __ \ / __ \ / ___// __/\__ \ / __ \ / // __ \ / // __/
|
||||||
|
/ /_/ // / / // /_/ /(__ )/ /_ ___/ // /_/ // // /_/ // // /_
|
||||||
|
\____//_/ /_/ \____//____/ \__//____// .___//_/ \____//_/ \__/
|
||||||
|
/_/
|
||||||
|
""";
|
||||||
|
|
||||||
|
private readonly FlexPanel root = new();
|
||||||
|
private readonly FlexPanel header = new();
|
||||||
|
private readonly StackPanel headerInfo = new();
|
||||||
|
private readonly TablePanel resourcesTable = new();
|
||||||
|
private readonly TextWidget headerTitle = new();
|
||||||
|
private readonly TextWidget logo = new();
|
||||||
|
private readonly FlexPanel bodyArea = new();
|
||||||
|
private readonly RecyclableWidgetList<ScrollView> componentsAndCategories = new();
|
||||||
|
private readonly FlexPanel inventoryRoot = new();
|
||||||
|
private readonly FlexPanel specsRoot = new();
|
||||||
|
private readonly FlexPanel currentItemRoot = new();
|
||||||
|
private readonly TextWidget storageLabel = new();
|
||||||
|
private readonly ProgressBar storageProgress = new();
|
||||||
|
private readonly TextWidget storageValue = new();
|
||||||
|
private readonly TextWidget skillLabel = new();
|
||||||
|
private readonly ProgressBar skillProgress = new();
|
||||||
|
private readonly TextWidget skillValue = new();
|
||||||
|
private readonly List<CraftingRecipe> recipes = new();
|
||||||
|
private readonly TextWidget inventoryTitle = new();
|
||||||
|
private readonly ScrollView inventoryView = new();
|
||||||
|
private readonly FileGrid inventoryGrid = new();
|
||||||
|
private readonly TextWidget recipesTitle = new();
|
||||||
|
private readonly ScrollView recipesView = new();
|
||||||
|
private readonly FileGrid recipesGrid = new();
|
||||||
|
private readonly List<InventoryItemModel> inventoryItems = new();
|
||||||
|
private readonly List<int> filteredRecipeMap = new();
|
||||||
|
private readonly TextWidget currentItemHeader = new();
|
||||||
|
private readonly ScrollView itemInfoScroller = new();
|
||||||
|
private readonly FlexPanel itemBanner = new();
|
||||||
|
private readonly CompositeIconWidget itemBannerIcon = new();
|
||||||
|
private readonly TextWidget itemBannerText = new();
|
||||||
|
private readonly TextWidget itemDescription = new();
|
||||||
|
private readonly FlexPanel interactionPanel = new();
|
||||||
|
private readonly TextWidget interactionLabel = new();
|
||||||
|
private readonly ProgressBar interactionProgress = new();
|
||||||
|
private readonly TextWidget interactionPercentage = new();
|
||||||
|
private readonly OverlayWidget interactionOverlay = new();
|
||||||
|
private readonly TextButton interactionButton = new();
|
||||||
|
private readonly TextWidget interactionError = new();
|
||||||
|
private readonly StackPanel interactionsArea = new();
|
||||||
|
private InventoryItemModel? currentItem;
|
||||||
|
private RecipeCategory inventoryFilter;
|
||||||
|
private CraftingRecipe? currentRecipe;
|
||||||
|
|
||||||
protected CraftingProgramController(ProgramContext context) : base(context)
|
protected CraftingProgramController(ProgramContext context) : base(context)
|
||||||
{
|
{
|
||||||
|
context.Window.Content = root;
|
||||||
|
|
||||||
|
skillLabel.Text = "Skill:";
|
||||||
|
storageLabel.Text = "Storage:";
|
||||||
|
storageValue.Text = "0 / 0 MiB";
|
||||||
|
skillValue.Text = "0 / 0 XP";
|
||||||
|
|
||||||
|
headerTitle.Text = "CRAFTING";
|
||||||
|
|
||||||
|
resourcesTable.ColumnCount = 3;
|
||||||
|
resourcesTable.ColumnSpacing = 3;
|
||||||
|
resourcesTable.RowSpacing = 3;
|
||||||
|
root.Padding = 12;
|
||||||
|
root.Spacing = 12;
|
||||||
|
bodyArea.Spacing = 12;
|
||||||
|
logo.Text = ghost;
|
||||||
|
headerTitle.FontWeight = FontWeight.Bold;
|
||||||
|
headerInfo.Spacing = 3;
|
||||||
|
headerInfo.VerticalAlignment = VerticalAlignment.Middle;
|
||||||
|
logo.VerticalAlignment = VerticalAlignment.Middle;
|
||||||
|
logo.HorizontalAlignment = HorizontalAlignment.Right;
|
||||||
|
inventoryTitle.Text = "Inventory";
|
||||||
|
inventoryTitle.FontWeight = FontWeight.Bold;
|
||||||
|
recipesTitle.FontWeight = FontWeight.Bold;
|
||||||
|
itemBannerText.UseMarkup = true;
|
||||||
|
|
||||||
|
headerTitle.FontSize = 22;
|
||||||
|
logo.FontSize = 8;
|
||||||
|
logo.Font = PresetFontFamily.Monospace;
|
||||||
|
skillProgress.VerticalAlignment = VerticalAlignment.Middle;
|
||||||
|
storageProgress.VerticalAlignment = VerticalAlignment.Middle;
|
||||||
|
currentItemHeader.FontWeight = FontWeight.Bold;
|
||||||
|
|
||||||
|
bodyArea.GetCustomProperties<FlexPanelProperties>().Mode = FlexMode.Proportional;
|
||||||
|
logo.GetCustomProperties<FlexPanelProperties>().Mode = FlexMode.Proportional;
|
||||||
|
headerInfo.GetCustomProperties<FlexPanelProperties>().Mode = FlexMode.Proportional;
|
||||||
|
inventoryRoot.GetCustomProperties<FlexPanelProperties>().Mode = FlexMode.Proportional;
|
||||||
|
specsRoot.GetCustomProperties<FlexPanelProperties>().Mode = FlexMode.Proportional;
|
||||||
|
itemInfoScroller.GetCustomProperties<FlexPanelProperties>().Mode = FlexMode.Proportional;
|
||||||
|
inventoryView.GetCustomProperties<FlexPanelProperties>().Mode = FlexMode.Proportional;
|
||||||
|
recipesView.GetCustomProperties<FlexPanelProperties>().Mode = FlexMode.Proportional;
|
||||||
|
itemBannerText.GetCustomProperties<FlexPanelProperties>().Mode = FlexMode.Proportional;
|
||||||
|
interactionProgress.GetCustomProperties<FlexPanelProperties>().Mode = FlexMode.Proportional;
|
||||||
|
|
||||||
|
interactionPanel.Direction = Direction.Horizontal;
|
||||||
|
interactionsArea.Padding = new Padding(48, 6);
|
||||||
|
interactionsArea.Spacing = 3;
|
||||||
|
interactionPanel.Spacing = 3;
|
||||||
|
interactionProgress.VerticalAlignment = VerticalAlignment.Middle;
|
||||||
|
interactionLabel.VerticalAlignment = VerticalAlignment.Middle;
|
||||||
|
interactionPercentage.VerticalAlignment = VerticalAlignment.Middle;
|
||||||
|
interactionButton.VerticalAlignment = VerticalAlignment.Middle;
|
||||||
|
interactionError.VerticalAlignment = VerticalAlignment.Middle;
|
||||||
|
interactionError.HorizontalAlignment = HorizontalAlignment.Center;
|
||||||
|
interactionButton.HorizontalAlignment = HorizontalAlignment.Center;
|
||||||
|
|
||||||
|
itemBannerIcon.IconSize = 56;
|
||||||
|
|
||||||
|
itemBannerIcon.VerticalAlignment = VerticalAlignment.Middle;
|
||||||
|
itemBannerText.VerticalAlignment = VerticalAlignment.Middle;
|
||||||
|
itemBanner.Spacing = 6;
|
||||||
|
|
||||||
|
itemDescription.UseMarkup = true;
|
||||||
|
itemDescription.WordWrapping = true;
|
||||||
|
|
||||||
|
header.Direction = Direction.Horizontal;
|
||||||
|
bodyArea.Direction = Direction.Horizontal;
|
||||||
|
|
||||||
|
currentItemRoot.MinimumSize = new Point(391, 0);
|
||||||
|
currentItemRoot.MaximumSize = new Point(391, 0);
|
||||||
|
|
||||||
|
itemInfoScroller.Spacing = 12;
|
||||||
|
|
||||||
|
itemBanner.Direction = Direction.Horizontal;
|
||||||
|
|
||||||
|
itemInfoScroller.Padding = 24;
|
||||||
|
|
||||||
|
interactionError.FontWeight = FontWeight.SemiBold;
|
||||||
|
interactionError.SetCustomProperty(WidgetForegrounds.Common);
|
||||||
|
interactionError.SetCustomProperty(CommonColor.Red);
|
||||||
|
interactionPanel.Visibility = Visibility.Hidden;
|
||||||
|
|
||||||
|
root.ChildWidgets.Add(header);
|
||||||
|
root.ChildWidgets.Add(bodyArea);
|
||||||
|
header.ChildWidgets.Add(headerInfo);
|
||||||
|
header.ChildWidgets.Add(logo);
|
||||||
|
headerInfo.ChildWidgets.Add(headerTitle);
|
||||||
|
headerInfo.ChildWidgets.Add(resourcesTable);
|
||||||
|
bodyArea.ChildWidgets.Add(componentsAndCategories);
|
||||||
|
bodyArea.ChildWidgets.Add(inventoryRoot);
|
||||||
|
bodyArea.ChildWidgets.Add(specsRoot);
|
||||||
|
bodyArea.ChildWidgets.Add(currentItemRoot);
|
||||||
|
resourcesTable.ChildWidgets.Add(storageLabel);
|
||||||
|
resourcesTable.ChildWidgets.Add(storageProgress);
|
||||||
|
resourcesTable.ChildWidgets.Add(storageValue);
|
||||||
|
resourcesTable.ChildWidgets.Add(skillLabel);
|
||||||
|
resourcesTable.ChildWidgets.Add(skillProgress);
|
||||||
|
resourcesTable.ChildWidgets.Add(skillValue);
|
||||||
|
inventoryRoot.ChildWidgets.Add(inventoryTitle);
|
||||||
|
inventoryRoot.ChildWidgets.Add(inventoryView);
|
||||||
|
inventoryView.ChildWidgets.Add(inventoryGrid);
|
||||||
|
specsRoot.ChildWidgets.Add(recipesTitle);
|
||||||
|
specsRoot.ChildWidgets.Add(recipesView);
|
||||||
|
recipesView.ChildWidgets.Add(recipesGrid);
|
||||||
|
currentItemRoot.ChildWidgets.Add(currentItemHeader);
|
||||||
|
currentItemRoot.ChildWidgets.Add(itemInfoScroller);
|
||||||
|
itemInfoScroller.ChildWidgets.Add(itemBanner);
|
||||||
|
itemBanner.ChildWidgets.Add(itemBannerIcon);
|
||||||
|
itemBanner.ChildWidgets.Add(itemBannerText);
|
||||||
|
itemInfoScroller.ChildWidgets.Add(itemDescription);
|
||||||
|
currentItemRoot.ChildWidgets.Add(interactionsArea);
|
||||||
|
interactionsArea.ChildWidgets.Add(interactionPanel);
|
||||||
|
interactionsArea.ChildWidgets.Add(interactionOverlay);
|
||||||
|
interactionOverlay.ChildWidgets.Add(interactionError);
|
||||||
|
interactionOverlay.ChildWidgets.Add(interactionButton);
|
||||||
|
interactionPanel.ChildWidgets.Add(interactionLabel);
|
||||||
|
interactionPanel.ChildWidgets.Add(interactionProgress);
|
||||||
|
interactionPanel.ChildWidgets.Add(interactionPercentage);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void Main()
|
protected override void Main()
|
||||||
{
|
{
|
||||||
|
recipes.Clear();
|
||||||
|
recipes.AddRange(SociallyDistantGame.Instance.ContentManager.GetContentOfType<CraftingRecipe>());
|
||||||
|
|
||||||
|
RefreshInterface();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void RefreshInterface()
|
||||||
|
{
|
||||||
|
filteredRecipeMap.Clear();
|
||||||
|
for (var i = 0; i < recipes.Count; i++)
|
||||||
|
{
|
||||||
|
var recipe = recipes[i];
|
||||||
|
if (recipe.Category != inventoryFilter)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
filteredRecipeMap.Add(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.inventoryItems.Clear();
|
||||||
|
this.inventoryItems.AddRange(WorldManager.Instance.World.Inventory.Where(x => x.Owner == 0).Select(item => new InventoryItemModel { WorldItem = item.InstanceId, Recipe = filteredRecipeMap.Select(i=>recipes[i]).FirstOrDefault(y => y.Id == item.RecipeId)! }).Where(x => x.Recipe != null!).ToArray());
|
||||||
|
|
||||||
|
var codeFragmentCount = WorldManager.Instance.World.Ledger.GetItemCount(CraftingIngredient.CodeFragments);
|
||||||
|
var dataFragmentCount = WorldManager.Instance.World.Ledger.GetItemCount(CraftingIngredient.DataFragments);
|
||||||
|
|
||||||
|
RefreshSidebar(codeFragmentCount, dataFragmentCount);
|
||||||
|
RefreshInventory();
|
||||||
|
RefreshRecipes();
|
||||||
|
|
||||||
|
if (currentItem != null)
|
||||||
|
{
|
||||||
|
currentItemRoot.Visibility = Visibility.Visible;
|
||||||
|
currentItemHeader.Text = "Inventory Item";
|
||||||
|
|
||||||
|
SetItemInfo(currentItem.Value.Recipe);
|
||||||
|
|
||||||
|
interactionError.Visibility = Visibility.Collapsed;
|
||||||
|
interactionButton.Visibility = Visibility.Visible;
|
||||||
|
interactionButton.Text = "Disassemble";
|
||||||
|
interactionLabel.Text = "Disassembling:";
|
||||||
|
}
|
||||||
|
else if (currentRecipe != null)
|
||||||
|
{
|
||||||
|
currentItemRoot.Visibility = Visibility.Visible;
|
||||||
|
currentItemHeader.Text = "Crafting Spec";
|
||||||
|
|
||||||
|
SetItemInfo(currentRecipe);
|
||||||
|
|
||||||
|
interactionError.Visibility = Visibility.Collapsed;
|
||||||
|
interactionButton.Visibility = Visibility.Visible;
|
||||||
|
interactionButton.Text = "Craft";
|
||||||
|
interactionLabel.Text = "Crafting:";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
currentItemRoot.Visibility = Visibility.Hidden;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetItemInfo(CraftingRecipe data)
|
||||||
|
{
|
||||||
|
itemBannerIcon.Icon = MaterialIcons.Star;
|
||||||
|
itemBannerText.Text = $"<b><size=32>{data.Title.ToUpper()}</size></b>{Environment.NewLine}{data.Category}";
|
||||||
|
itemDescription.Text = data.Description;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RefreshRecipes()
|
||||||
|
{
|
||||||
|
recipesTitle.Text = inventoryFilter.ToString();
|
||||||
|
var models = new List<FileIconModel>();
|
||||||
|
|
||||||
|
for (int i = 0; i < filteredRecipeMap.Count; i++)
|
||||||
|
{
|
||||||
|
var recipe = recipes[filteredRecipeMap[i]];
|
||||||
|
|
||||||
|
models.Add(new FileIconModel
|
||||||
|
{
|
||||||
|
Title = recipe.Title,
|
||||||
|
Id = i,
|
||||||
|
OpenHandler = SelectRecipe
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
recipesGrid.SetFiles(models);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RefreshInventory()
|
||||||
|
{
|
||||||
|
inventoryGrid.SetFiles(inventoryItems.Select(x => new FileIconModel
|
||||||
|
{
|
||||||
|
Title = x.Recipe.Title,
|
||||||
|
Id = x.WorldItem.Id,
|
||||||
|
Selected = currentItem?.WorldItem == x.WorldItem,
|
||||||
|
OpenHandler = SelectItem
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SelectRecipe(int id)
|
||||||
|
{
|
||||||
|
currentItem = null;
|
||||||
|
currentRecipe = recipes[filteredRecipeMap[id]];
|
||||||
|
RefreshInterface();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SelectItem(int id)
|
||||||
|
{
|
||||||
|
currentRecipe = null;
|
||||||
|
currentItem = inventoryItems.First(x => x.WorldItem == id);
|
||||||
|
RefreshInterface();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RefreshSidebar(int codeFragments, int dataFragments)
|
||||||
|
{
|
||||||
|
var builder = new WidgetBuilder();
|
||||||
|
builder.Begin();
|
||||||
|
|
||||||
|
builder.AddSection("Crafting Components", out SectionWidget components);
|
||||||
|
|
||||||
|
builder.AddWidget(new ListItemWidget<int> { Title = "Data Fragments", Data = dataFragments }, components);
|
||||||
|
builder.AddWidget(new ListItemWidget<int> { Title = "Code Fragments", Data = codeFragments }, components);
|
||||||
|
|
||||||
|
builder.AddSection("Craftables", out SectionWidget craftables);
|
||||||
|
|
||||||
|
foreach (RecipeCategory category in Enum.GetValues<RecipeCategory>())
|
||||||
|
{
|
||||||
|
builder.AddWidget(new ListItemWidget<RecipeCategory>() { Title = category.ToString(), Data = category, Callback = SetFilter, Selected = category == inventoryFilter }, craftables);
|
||||||
|
}
|
||||||
|
|
||||||
|
componentsAndCategories.SetWidgets(builder.Build());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetFilter(RecipeCategory category)
|
||||||
|
{
|
||||||
|
inventoryFilter = category;
|
||||||
|
RefreshInterface();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct InventoryItemModel
|
||||||
|
{
|
||||||
|
public CraftingRecipe Recipe;
|
||||||
|
public ObjectId WorldItem;
|
||||||
}
|
}
|
|
@ -1,3 +1,4 @@
|
||||||
|
using AcidicGUI.Widgets;
|
||||||
using SociallyDistant.Core.Shell;
|
using SociallyDistant.Core.Shell;
|
||||||
|
|
||||||
namespace SociallyDistant.UI.Tools.Crafting;
|
namespace SociallyDistant.UI.Tools.Crafting;
|
||||||
|
|
Loading…
Reference in a new issue