Skip to content
This repository was archived by the owner on Aug 22, 2025. It is now read-only.
49 changes: 49 additions & 0 deletions Content.Client/_White/DNAConsole/DNAConsoleBoundInterface.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
using Content.Shared.DNAConsole;
using JetBrains.Annotations;

namespace Content.Client.DNAConsole.UI
{
[UsedImplicitly]
public sealed class DNAConsoleBoundUserInterface : BoundUserInterface
{
[ViewVariables]
private DNAConsoleWindow? _window;

public DNAConsoleBoundUserInterface(EntityUid owner, Enum uiKey) : base(owner, uiKey)
{
}

protected override void Open()
{
base.Open();
_window = new DNAConsoleWindow
{
Title = "DNAConsole"
};
_window.OnClose += Close;
// _window.ModifierButton.OnPressed += _ => SendMessage(new UiButtonPressedMessage(UiButton.Clone));
_window.OpenCentered();
}

protected override void UpdateState(BoundUserInterfaceState state)
{
base.UpdateState(state);

_window?.Populate((DNAConsoleBoundUserInterfaceState) state);
}

protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (!disposing)
return;

if (_window != null)
{
_window.OnClose -= Close;
//_window.DNAButton.OnPressed -= _ => SendMessage(new UiButtonPressedMessage(UiButton.Clone));
}
_window?.Dispose();
}
}
}
26 changes: 26 additions & 0 deletions Content.Client/_White/DNAConsole/DNAConsoleWindow.xaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<DefaultWindow xmlns="https://spacestation14.io"
Title="{Loc 'comp-pda-ui-menu-title'}"
SetSize="400 400"
MinSize="400 400">
<TabContainer Name="MasterTabContainer">
<BoxContainer Name="DNA"
Orientation="Vertical"
VerticalExpand="True"
HorizontalExpand="True"
MinSize="100 150">
<BoxContainer Name="DNAConsoleContent" Margin="5 5 5 5" Orientation="Vertical" VerticalExpand="True" HorizontalExpand="True">
<RichTextLabel Name="ModifierInfoLabel" Access="Public" HorizontalExpand="True" />
<Label HorizontalAlignment="Center" Name="ModifierActivity" Access="Public" HorizontalExpand="True" />
<BoxContainer Name="DNAModifierMissing" Margin="5 5 5 5" Orientation="Vertical" VerticalExpand="True" HorizontalExpand="True">
<Label HorizontalAlignment="Center" VerticalAlignment="Center" Text="{Loc 'DNAModifier missing!'}" />
</BoxContainer>
<BoxContainer Name="DNAModifierFar" Margin="5 5 5 5" Orientation="Vertical" VerticalExpand="True" HorizontalExpand="True">
<Label HorizontalAlignment="Center" VerticalAlignment="Center" Text="{Loc 'DNAModifier is far!'}" />
</BoxContainer>

<Label HorizontalAlignment="Center" Text="all is ok." Name="DNATest" />

</BoxContainer>
</BoxContainer>
</TabContainer>
</DefaultWindow>
86 changes: 86 additions & 0 deletions Content.Client/_White/DNAConsole/DNAConsoleWindow.xaml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
using Content.Client.Message;
using Content.Shared.DNAConsole;
using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.CustomControls;
using Robust.Client.UserInterface.XAML;

namespace Content.Client.DNAConsole;

[GenerateTypedNameReferences]
public sealed partial class DNAConsoleWindow : DefaultWindow
{

public DNAConsoleWindow()
{
RobustXamlLoader.Load(this);
}

private DNAConsoleBoundUserInterfaceState? _lastUpdate;

public void Populate(DNAConsoleBoundUserInterfaceState state)
{
_lastUpdate = state;
// BUILD SCANNER UI
if (state.ModifierConnected)
{
if (!state.ModifierInRange)
{
DNAModifierFar.Visible = true;
DNAConsoleContent.Visible = false;
DNAModifierMissing.Visible = false;
return;
}

DNAConsoleContent.Visible = true;
DNAModifierFar.Visible = false;
DNAModifierMissing.Visible = false;

switch (state.ModifierStatus)
{
case ModifierStatus.Ready:
ModifierActivity.Text = (Loc.GetString("dna-console-component-msg-ready"));
break;
case ModifierStatus.ModifierOccupied:
ModifierActivity.Text = (Loc.GetString("dna-console-component-msg-occupied"));
break;
case ModifierStatus.ModifierEmpty:
ModifierActivity.Text = (Loc.GetString("dna-console-component-msg-empty"));
break;
case ModifierStatus.OccupantMetaphyiscal:
ModifierActivity.Text = (Loc.GetString("dna-console-component-msg-already-alive"));
break;
}
// Set label depending on if scanner is occupied or not.
ModifierInfoLabel.SetMarkup(state.ModifierBodyInfo != null ?
Loc.GetString("dna-console-window-scanner-id", ("modifierOccupantName", state.ModifierBodyInfo)) :
Loc.GetString("dna-console-window-id-blank"));
}
else
{
// Scanner is missing, set error message visible
DNAConsoleContent.Visible = false;
DNAModifierFar.Visible = false;
DNAModifierMissing.Visible = true;
}

// BUILD ClONER UI
if (state.ModifierConnected)
{
if (!state.ModifierInRange)
{
DNATest.Visible = false;
return;
}

DNATest.Visible = true;
}
else
{
// Clone pod is missing, set error message visible
DNATest.Visible = false;
}
}

}

8 changes: 8 additions & 0 deletions Content.Client/_White/DNAModifier/DNAModifierComponent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
using Content.Shared.DNAModifier;

namespace Content.Client.DNAModifier;

[RegisterComponent]
public sealed partial class DNAModifierComponent : SharedDNAModifierComponent
{
}
26 changes: 26 additions & 0 deletions Content.Client/_White/Genetics/DNAScannerBoundUserInterface.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
namespace Content.Client._White.Genetics
{
[UserImplicitly]
public sealed class DNAScannerBoundUserInterface : BoundUserInterface
{
[ViewVariables]
private DNAScannerWindow? _window;

public DNAScannerBoundUserInterface(EntityUid owner, Enum uiKey) : base(owner, uiKey)
{
}

protected override void Open()
{
base.Open();
_window = new DNAScannerWindow
{
Title = EntMan.GetComponent<MetaDataComponent>(Owner).EntityName,
};
_window.OnClose += Close;
_window.OpenCentered();
}
Comment on lines +13 to +22
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Enhance error handling and resource management.

  1. Consider handling potential exceptions when retrieving the MetaDataComponent. This can prevent runtime errors if the component is missing.
  2. Ensure that the _window resource is properly disposed of when it's no longer needed to prevent memory leaks.
protected override void Open()
{
    base.Open();
    try
    {
        var metaData = EntMan.GetComponent<MetaDataComponent>(Owner);
        _window = new DNAScannerWindow
        {
            Title = metaData.EntityName,
        };
    }
    catch (Exception ex)
    {
        Logger.Error($"Failed to open DNA scanner window: {ex.Message}");
        return;
    }
    _window.OnClose += Close;
    _window.OpenCentered();
}

protected override void Dispose(bool disposing)
{
    if (disposing)
    {
        _window?.Dispose();
    }
    base.Dispose(disposing);
}


}

}
5 changes: 5 additions & 0 deletions Content.Client/_White/Genetics/DNAScannerWindow.xaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<controls:DNAScannerWindow
xmlns="https://spacestation14.io"
xmlns:controls="clr-namespace:Content.Client._White.Genetics">

</controls:DNAScannerWindow>
15 changes: 15 additions & 0 deletions Content.Client/_White/Genetics/DNAScannerWindow.xaml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.XAML;

namespace Content.Client._White.Genetics;

[GenerateTypedNameReferences]
public sealed partial class DNAScannerWindow : Control
{
public DNAScannerWindow()
{
RobustXamlLoader.Load(this);
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace Content.Server._White.Genetics.Components;

/// <summary>
/// Shrimply a tracking component for pods that are cloning.
/// </summary>
[RegisterComponent]
public sealed partial class ActiveModifierComponent : Component
{
}
17 changes: 17 additions & 0 deletions Content.Server/_White/Genetics/Components/DNAConsoleComponent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
namespace Content.Server._White.Genetics.Components
{
[RegisterComponent]
public sealed partial class DNAConsoleComponent : Component
{
public const string ScannerPort = "DNAModifierSender";

[ViewVariables]
public EntityUid? Modifier = null;

/// Maximum distance between console and one if its machines
[DataField("maxDistance")]
public float MaxDistance = 4f;

public bool ModifierInRange = true;
}
}
16 changes: 16 additions & 0 deletions Content.Server/_White/Genetics/Components/DNAModifierComponent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using Content.Shared.DNAModifier;
using Robust.Shared.Containers;

namespace Content.Server._White.Genetics.Components
{
[RegisterComponent]
public sealed partial class DNAModifierComponent : SharedDNAModifierComponent
{
public const string ScannerPort = "DNAModifierReceiver";
public ContainerSlot BodyContainer = default!;
public EntityUid? ConnectedConsole;

[DataField, ViewVariables(VVAccess.ReadWrite)]
public float CloningFailChanceMultiplier = 1f;
}
}
39 changes: 39 additions & 0 deletions Content.Server/_White/Genetics/Components/DNAScannerComponent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
using Robust.Shared.Audio;

namespace Content.Server._White.Genetics.Components;

/// <summary>
///
/// </summary>
public sealed partial class DNAScannerComponent : Component
{
/// <summary>
/// How long it takes to scan someone.
/// </summary>
[DataField("UseDelay")]
public TimeSpan ScanDelay = TimeSpan.FromSeconds(0.8);

/// <summary>
/// The maximum range in tiles at which the analyzer can receive continuous updates
/// </summary>
[DataField]
public float MaxScanRange = 2.5f;

/// <summary>
/// Sound played on scanning begin
/// </summary>
[DataField]
public SoundSpecifier? ScanningBeginSound;

/// <summary>
/// Sound played on scanning end
/// </summary>
[DataField]
public SoundSpecifier? ScanningEndSound;

/// <summary>
/// Genome that was scanned.
/// </summary>
[DataField]
public GenomeComponent? ScannedGenome;
}
66 changes: 66 additions & 0 deletions Content.Server/_White/Genetics/Components/GenomeComponent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
using Content.Shared._White.Genetics;
using Robust.Shared.Prototypes;

namespace Content.Server._White.Genetics.Components;

/// <summary>
/// Gives this entity a genome for traits to be passed on and potentially mutated.
/// Both of those must be handled by other systems, on its own it has no functionality.
/// TODO: комплиментарные последовательности
/// </summary>
[RegisterComponent]
public sealed partial class GenomeComponent : Component
{
/// <summary>
/// Name of the <see cref="GenomePrototype"/> to create on init.
/// </summary>
[DataField(required: true)]
public ProtoId<GenomePrototype> GenomeId = string.Empty;

/// <summary>
/// Genome layout to use for this round and genome type.
/// Stored in <see cref="GeneticsSystem"/>.
/// </summary>
[ViewVariables]
public GenomeLayout Layout = new();

/// <summary>
/// Activated mutations. Acquired through activators or radiation.
/// </summary>
[ViewVariables]
public List<string> ActivatedMutations = new List<string>();

/// <summary>
/// Mutations that were acquired via mutators.
/// </summary>
[DataField]
public List<string> MutatedMutations = new List<string>();

/// <summary>
/// TODO: wtf is this
/// </summary>
[DataField("humanGenes")]
public bool HumanGenes = false;

/// <summary>
/// Key is the name of the region in GenomeLayout, value is the name of corresponding mutation.
/// </summary>
[DataField]
public Dictionary<string, string> MutationRegions = new Dictionary<string, string>();

/// <summary>
/// Genome bits themselves.
/// Data can be retrieved with <c>comp.Layout.GetInt(comp.Genome, "name")</c>, etc.
/// </summary>
/// <remarks>
/// Completely empty by default, another system must use <see cref="GenomeSystem"/> to load genes or copy from a parent.
/// </remarks>
[DataField]
public Genome Genome = new();

/// <summary>
/// It is changed when a mutation through mutator is applied.
/// </summary>
[DataField]
public int Instability = 0;
}
Loading