diff --git a/.editorconfig b/.editorconfig
index a87e5e0651..fa740a7511 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -351,7 +351,7 @@ resharper_csharp_qualified_using_at_nested_scope = false
resharper_csharp_prefer_qualified_reference = false
resharper_csharp_allow_alias = false
-[*.{csproj,xml,yml,yaml,dll.config,msbuildproj,targets,props}]
+[*.{csproj,xml,yml,yaml,dll.config,msbuildproj,targets,props,slnx}]
indent_size = 2
[nuget.config]
diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
index 18a499cb62..c938f7106e 100644
--- a/.github/PULL_REQUEST_TEMPLATE.md
+++ b/.github/PULL_REQUEST_TEMPLATE.md
@@ -1,4 +1,5 @@
-
+
+
## Кратное описание
diff --git a/.github/workflows/build-docfx.yml b/.github/workflows/build-docfx.yml
index 1f010b7291..dee31e9b31 100644
--- a/.github/workflows/build-docfx.yml
+++ b/.github/workflows/build-docfx.yml
@@ -21,7 +21,7 @@ jobs:
- name: Setup .NET Core
uses: actions/setup-dotnet@v4.1.0
with:
- dotnet-version: 9.0.x
+ dotnet-version: 10.0.x
- name: Install dependencies
run: dotnet restore
diff --git a/.github/workflows/build-map-renderer.yml b/.github/workflows/build-map-renderer.yml
index 852888cc6c..5f6abb9ca9 100644
--- a/.github/workflows/build-map-renderer.yml
+++ b/.github/workflows/build-map-renderer.yml
@@ -36,7 +36,7 @@ jobs:
- name: Setup .NET Core
uses: actions/setup-dotnet@v4.1.0
with:
- dotnet-version: 9.0.x
+ dotnet-version: 10.0.x
- name: Install dependencies
run: dotnet restore
diff --git a/.github/workflows/build-test-debug.yml b/.github/workflows/build-test-debug.yml
index 43d621cdf7..52b3fffbd8 100644
--- a/.github/workflows/build-test-debug.yml
+++ b/.github/workflows/build-test-debug.yml
@@ -36,7 +36,7 @@ jobs:
- name: Setup .NET Core
uses: actions/setup-dotnet@v4.1.0
with:
- dotnet-version: 9.0.x
+ dotnet-version: 10.0.x
- name: Install dependencies
run: dotnet restore
diff --git a/.github/workflows/publish-test.yml b/.github/workflows/publish-test.yml
index 48ee9761bc..7b7a576bf7 100644
--- a/.github/workflows/publish-test.yml
+++ b/.github/workflows/publish-test.yml
@@ -39,7 +39,7 @@ jobs:
- name: Setup .NET Core
uses: actions/setup-dotnet@v4.1.0
with:
- dotnet-version: 9.0.x
+ dotnet-version: 10.0.x
- name: Get Engine Tag
run: |
diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml
index 11bea90946..148bcc247a 100644
--- a/.github/workflows/publish.yml
+++ b/.github/workflows/publish.yml
@@ -33,7 +33,7 @@ jobs:
- name: Setup .NET Core
uses: actions/setup-dotnet@v4.1.0
with:
- dotnet-version: 9.0.x
+ dotnet-version: 10.0.x
- name: Get Engine Tag
run: |
diff --git a/.github/workflows/test-packaging.yml b/.github/workflows/test-packaging.yml
index 308871a1b2..5f6578e6b9 100644
--- a/.github/workflows/test-packaging.yml
+++ b/.github/workflows/test-packaging.yml
@@ -51,7 +51,7 @@ jobs:
- name: Setup .NET Core
uses: actions/setup-dotnet@v4.1.0
with:
- dotnet-version: 9.0.x
+ dotnet-version: 10.0.x
- name: Install dependencies
run: dotnet restore
diff --git a/.github/workflows/yaml-linter.yml b/.github/workflows/yaml-linter.yml
index 91e1d57d08..d5e4913f3a 100644
--- a/.github/workflows/yaml-linter.yml
+++ b/.github/workflows/yaml-linter.yml
@@ -26,7 +26,7 @@ jobs:
- name: Setup .NET Core
uses: actions/setup-dotnet@v4.1.0
with:
- dotnet-version: 9.0.x
+ dotnet-version: 10.0.x
- name: Install dependencies
run: dotnet restore
- name: Build
diff --git a/.gitignore b/.gitignore
index 2dd5912047..76f5837d75 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,6 @@
+# MSbuild binlog files
+*.binlog
+
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
diff --git a/BuildChecker/git_helper.py b/BuildChecker/git_helper.py
index bd6603bd34..4e42b1e70e 100644
--- a/BuildChecker/git_helper.py
+++ b/BuildChecker/git_helper.py
@@ -11,7 +11,7 @@ import time
from pathlib import Path
from typing import List
-SOLUTION_PATH = Path("..") / "SpaceStation14.sln"
+SOLUTION_PATH = Path("..") / "SpaceStation14.slnx"
# If this doesn't match the saved version we overwrite them all.
CURRENT_HOOKS_VERSION = "4"
QUIET = len(sys.argv) == 2 and sys.argv[1] == "--quiet"
diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md
index b2aeb6197a..f8f22fb3f8 100644
--- a/CODE_OF_CONDUCT.md
+++ b/CODE_OF_CONDUCT.md
@@ -8,7 +8,7 @@ This isn’t an exhaustive list of things that you can’t do. Rather, take it i
This code of conduct applies specifically to the Github repositories and its spaces managed by the Space Station 14 project or Space Wizards Federation. Some spaces, such as the Space Station 14 Discord or the official Wizard's Den game servers, have their own rules but are in spirit equal to what may be found in here.
-If you believe someone is violating the code of conduct, we ask that you report it by contacting a Maintainer, Project Manager or Wizard staff member through [Discord](https://discord.ss14.io/), [the forums](https://forum.spacestation14.com/), or emailing [telecommunications@spacestation14.com](mailto:telecommunications@spacestation14.com).
+If you believe someone is violating the code of conduct, we ask that you report it by contacting a Maintainer, Project Manager or Wizard staff member through [Discord](https://discord.ss14.io/), [the forums](https://forum.spacestation14.com/), or emailing [support@spacestation14.com](mailto:support@spacestation14.com).
- **Be friendly and patient.**
- **Be welcoming.** We strive to be a community that welcomes and supports people of all backgrounds and identities. This includes, but is not limited to members of any race, ethnicity, culture, national origin, colour, immigration status, social and economic class, educational level, sex, sexual orientation, gender identity and expression, age, size, family status, political belief, religion, and mental and physical ability.
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 0000000000..da081074c4
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,11 @@
+# Space Station 14 Contributing Guidelines
+
+Thanks for contributing to Space Station 14.
+When contributing, be sure to follow our [codebase conventions](https://docs.spacestation14.com/en/general-development/codebase-info/codebase-organization.html) and [PR guidelines](https://docs.spacestation14.com/en/general-development/codebase-info/pull-request-guidelines.html).
+
+Following these guidelines helps us increase review turnaround time, so be sure to review the linked documents in full.
+
+The last major guidelines update was on **December 6th, 2025**.
+
+### Why is this here?
+We put this here so that GitHub will notify you when submitting a pull request that the PR guidelines have changed, if you haven't read the latest version.
diff --git a/Content.Benchmarks/Content.Benchmarks.csproj b/Content.Benchmarks/Content.Benchmarks.csproj
index c3b60a1c69..8d4dfa31bd 100644
--- a/Content.Benchmarks/Content.Benchmarks.csproj
+++ b/Content.Benchmarks/Content.Benchmarks.csproj
@@ -1,17 +1,20 @@
-
- $(TargetFramework)
..\bin\Content.Benchmarks\
- false
false
Exe
true
- 12
+ false
+ disable
+
+
+
+
+
@@ -19,10 +22,12 @@
-
-
-
-
-
+
+
+
+
+
+
+
diff --git a/Content.Benchmarks/DestructibleBenchmark.cs b/Content.Benchmarks/DestructibleBenchmark.cs
new file mode 100644
index 0000000000..aa759c35fc
--- /dev/null
+++ b/Content.Benchmarks/DestructibleBenchmark.cs
@@ -0,0 +1,191 @@
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using BenchmarkDotNet.Attributes;
+using Content.IntegrationTests;
+using Content.IntegrationTests.Pair;
+using Content.Server.Destructible;
+using Content.Shared.Damage;
+using Content.Shared.Damage.Components;
+using Content.Shared.Damage.Prototypes;
+using Content.Shared.Damage.Systems;
+using Content.Shared.FixedPoint;
+using Content.Shared.Maps;
+using Robust.Shared;
+using Robust.Shared.Analyzers;
+using Robust.Shared.GameObjects;
+using Robust.Shared.Map;
+using Robust.Shared.Maths;
+using Robust.Shared.Prototypes;
+using Robust.Shared.Random;
+
+namespace Content.Benchmarks;
+
+[Virtual]
+[GcServer(true)]
+[MemoryDiagnoser]
+public class DestructibleBenchmark
+{
+ ///
+ /// Number of destructible entities per prototype to spawn with a .
+ ///
+ [Params(1, 10, 100, 1000, 5000)]
+ public int EntityCount;
+
+ ///
+ /// Amount of blunt damage we do to each entity.
+ ///
+ [Params(10000)]
+ public FixedPoint2 DamageAmount;
+
+ [Params("Blunt")]
+ public ProtoId DamageType;
+
+ private static readonly EntProtoId WindowProtoId = "Window";
+ private static readonly EntProtoId WallProtoId = "WallReinforced";
+ private static readonly EntProtoId HumanProtoId = "MobHuman";
+
+ private static readonly ProtoId TileRef = "Plating";
+
+ private readonly EntProtoId[] _prototypes = [WindowProtoId, WallProtoId, HumanProtoId];
+
+ private readonly List> _damageables = new();
+ private readonly List> _destructbiles = new();
+
+ private TestMapData _currentMapData = default!;
+
+ private DamageSpecifier _damage;
+
+ private TestPair _pair = default!;
+ private IEntityManager _entMan = default!;
+ private IPrototypeManager _protoMan = default!;
+ private IRobustRandom _random = default!;
+ private ITileDefinitionManager _tileDefMan = default!;
+ private DamageableSystem _damageable = default!;
+ private DestructibleSystem _destructible = default!;
+ private SharedMapSystem _map = default!;
+
+ [GlobalSetup]
+ public async Task SetupAsync()
+ {
+ ProgramShared.PathOffset = "../../../../";
+ PoolManager.Startup();
+ _pair = await PoolManager.GetServerClient();
+ var server = _pair.Server;
+
+ _entMan = server.ResolveDependency();
+ _protoMan = server.ResolveDependency();
+ _random = server.ResolveDependency();
+ _tileDefMan = server.ResolveDependency();
+ _damageable = _entMan.System();
+ _destructible = _entMan.System();
+ _map = _entMan.System();
+
+ if (!_protoMan.Resolve(DamageType, out var type))
+ return;
+
+ _damage = new DamageSpecifier(type, DamageAmount);
+
+ _random.SetSeed(69420); // Randomness needs to be deterministic for benchmarking.
+ }
+
+ [IterationSetup]
+ public void IterationSetup()
+ {
+ var plating = _tileDefMan[TileRef].TileId;
+ var server = _pair.Server;
+ _currentMapData = _pair.CreateTestMap().GetAwaiter().GetResult();
+
+ // We make a rectangular grid of destructible entities, and then damage them all simultaneously to stress test the system.
+ // Needed for managing the performance of destructive effects and damage application.
+ server.WaitPost(() =>
+ {
+ // Set up a thin line of tiles to place our objects on. They should be anchored for a "realistic" scenario...
+ for (var x = 0; x < EntityCount; x++)
+ {
+ for (var y = 0; y < _prototypes.Length; y++)
+ {
+ _map.SetTile(_currentMapData.Grid, _currentMapData.Grid, new Vector2i(x, y), new Tile(plating));
+ }
+ }
+
+ for (var x = 0; x < EntityCount; x++)
+ {
+ var y = 0;
+ foreach (var protoId in _prototypes)
+ {
+ var coords = new EntityCoordinates(_currentMapData.Grid, x + 0.5f, y + 0.5f);
+ _entMan.SpawnEntity(protoId, coords);
+ y++;
+ }
+ }
+
+ var query = _entMan.EntityQueryEnumerator();
+
+ _destructbiles.EnsureCapacity(EntityCount);
+ _damageables.EnsureCapacity(EntityCount);
+
+ while (query.MoveNext(out var uid, out var damageable, out var destructible))
+ {
+ _damageables.Add((uid, damageable));
+ _destructbiles.Add((uid, damageable, destructible));
+ }
+ })
+ .GetAwaiter()
+ .GetResult();
+ }
+
+ [Benchmark]
+ public async Task PerformDealDamage()
+ {
+ await _pair.Server.WaitPost(() =>
+ {
+ _damageable.ApplyDamageToAllEntities(_damageables, _damage);
+ });
+ }
+
+ [Benchmark]
+ public async Task PerformTestTriggers()
+ {
+ await _pair.Server.WaitPost(() =>
+ {
+ _destructible.TestAllTriggers(_destructbiles);
+ });
+ }
+
+ [Benchmark]
+ public async Task PerformTestBehaviors()
+ {
+ await _pair.Server.WaitPost(() =>
+ {
+ _destructible.TestAllBehaviors(_destructbiles);
+ });
+ }
+
+ [IterationCleanup]
+ public void IterationCleanupAsync()
+ {
+ // We need to nuke the entire map and respawn everything as some destructible effects
+ // spawn entities and whatnot.
+ _pair.Server.WaitPost(() =>
+ {
+ _map.QueueDeleteMap(_currentMapData.MapId);
+ })
+ .Wait();
+
+ // Deletion of entities is often queued (QueueDel) which must be processed by running ticks
+ // or else it will grow infinitely and leak memory.
+ _pair.Server.WaitRunTicks(2)
+ .GetAwaiter()
+ .GetResult();
+
+ _destructbiles.Clear();
+ _damageables.Clear();
+ }
+
+ [GlobalCleanup]
+ public async Task CleanupAsync()
+ {
+ await _pair.DisposeAsync();
+ PoolManager.Shutdown();
+ }
+}
diff --git a/Content.Benchmarks/GasReactionBenchmark.cs b/Content.Benchmarks/GasReactionBenchmark.cs
new file mode 100644
index 0000000000..9ed30373d1
--- /dev/null
+++ b/Content.Benchmarks/GasReactionBenchmark.cs
@@ -0,0 +1,253 @@
+using System.Threading.Tasks;
+using BenchmarkDotNet.Attributes;
+using Content.IntegrationTests;
+using Content.IntegrationTests.Pair;
+using Content.Server.Atmos;
+using Content.Server.Atmos.EntitySystems;
+using Content.Server.Atmos.Reactions;
+using Content.Shared.Atmos;
+using Robust.Shared;
+using Robust.Shared.Analyzers;
+using Robust.Shared.GameObjects;
+using Robust.Shared.Maths;
+
+namespace Content.Benchmarks;
+
+///
+/// Benchmarks the performance of different gas reactions.
+/// Tests each reaction type with realistic gas mixtures to measure computational cost.
+///
+[Virtual]
+[GcServer(true)]
+[MemoryDiagnoser]
+public class GasReactionBenchmark
+{
+ private const int Iterations = 1000;
+ private TestPair _pair = default!;
+ private AtmosphereSystem _atmosphereSystem = default!;
+
+ // Grid and tile for reactions that need a holder
+ private EntityUid _testGrid = default!;
+ private TileAtmosphere _testTile = default!;
+ // Reaction instances
+ private PlasmaFireReaction _plasmaFireReaction = default!;
+ private TritiumFireReaction _tritiumFireReaction = default!;
+ private FrezonProductionReaction _frezonProductionReaction = default!;
+ private FrezonCoolantReaction _frezonCoolantReaction = default!;
+ private AmmoniaOxygenReaction _ammoniaOxygenReaction = default!;
+ private N2ODecompositionReaction _n2oDecompositionReaction = default!;
+ private WaterVaporReaction _waterVaporReaction = default!;
+ // Gas mixtures for each reaction type
+ private GasMixture _plasmaFireMixture = default!;
+ private GasMixture _tritiumFireMixture = default!;
+ private GasMixture _frezonProductionMixture = default!;
+ private GasMixture _frezonCoolantMixture = default!;
+ private GasMixture _ammoniaOxygenMixture = default!;
+ private GasMixture _n2oDecompositionMixture = default!;
+ private GasMixture _waterVaporMixture = default!;
+
+ [GlobalSetup]
+ public async Task SetupAsync()
+ {
+ ProgramShared.PathOffset = "../../../../";
+ PoolManager.Startup();
+ _pair = await PoolManager.GetServerClient();
+ var server = _pair.Server;
+
+ // Create test map and grid
+ var mapData = await _pair.CreateTestMap();
+ _testGrid = mapData.Grid;
+
+ await server.WaitPost(() =>
+ {
+ var entMan = server.ResolveDependency();
+ _atmosphereSystem = entMan.System();
+
+ _plasmaFireReaction = new PlasmaFireReaction();
+ _tritiumFireReaction = new TritiumFireReaction();
+ _frezonProductionReaction = new FrezonProductionReaction();
+ _frezonCoolantReaction = new FrezonCoolantReaction();
+ _ammoniaOxygenReaction = new AmmoniaOxygenReaction();
+ _n2oDecompositionReaction = new N2ODecompositionReaction();
+ _waterVaporReaction = new WaterVaporReaction();
+
+ SetupGasMixtures();
+ SetupTile();
+ });
+ }
+
+ private void SetupGasMixtures()
+ {
+ // Plasma Fire: Plasma + Oxygen at high temperature
+ // Temperature must be > PlasmaMinimumBurnTemperature for reaction to occur
+ _plasmaFireMixture = new GasMixture(Atmospherics.CellVolume)
+ {
+ Temperature = Atmospherics.PlasmaMinimumBurnTemperature + 100f // ~673K
+ };
+ _plasmaFireMixture.AdjustMoles(Gas.Plasma, 20f);
+ _plasmaFireMixture.AdjustMoles(Gas.Oxygen, 100f);
+
+ // Tritium Fire: Tritium + Oxygen at high temperature
+ // Temperature must be > FireMinimumTemperatureToExist for reaction to occur
+ _tritiumFireMixture = new GasMixture(Atmospherics.CellVolume)
+ {
+ Temperature = Atmospherics.FireMinimumTemperatureToExist + 100f // ~473K
+ };
+ _tritiumFireMixture.AdjustMoles(Gas.Tritium, 20f);
+ _tritiumFireMixture.AdjustMoles(Gas.Oxygen, 100f);
+
+ // Frezon Production: Oxygen + Tritium + Nitrogen catalyst
+ // Optimal temperature for efficiency (80% of max efficiency temp)
+ _frezonProductionMixture = new GasMixture(Atmospherics.CellVolume)
+ {
+ Temperature = Atmospherics.FrezonProductionMaxEfficiencyTemperature * 0.8f // ~48K
+ };
+ _frezonProductionMixture.AdjustMoles(Gas.Oxygen, 50f);
+ _frezonProductionMixture.AdjustMoles(Gas.Tritium, 50f);
+ _frezonProductionMixture.AdjustMoles(Gas.Nitrogen, 10f);
+
+ // Frezon Coolant: Frezon + Nitrogen
+ // Temperature must be > FrezonCoolLowerTemperature (23.15K) for reaction to occur
+ _frezonCoolantMixture = new GasMixture(Atmospherics.CellVolume)
+ {
+ Temperature = Atmospherics.T20C + 50f // ~343K
+ };
+ _frezonCoolantMixture.AdjustMoles(Gas.Frezon, 30f);
+ _frezonCoolantMixture.AdjustMoles(Gas.Nitrogen, 100f);
+
+ // Ammonia + Oxygen reaction (concentration-dependent, no temp requirement)
+ _ammoniaOxygenMixture = new GasMixture(Atmospherics.CellVolume)
+ {
+ Temperature = Atmospherics.T20C + 100f // ~393K
+ };
+ _ammoniaOxygenMixture.AdjustMoles(Gas.Ammonia, 40f);
+ _ammoniaOxygenMixture.AdjustMoles(Gas.Oxygen, 40f);
+
+ // N2O Decomposition (no temperature requirement, just needs N2O moles)
+ _n2oDecompositionMixture = new GasMixture(Atmospherics.CellVolume)
+ {
+ Temperature = Atmospherics.T20C + 100f // ~393K
+ };
+ _n2oDecompositionMixture.AdjustMoles(Gas.NitrousOxide, 100f);
+
+ // Water Vapor - needs water vapor to condense
+ _waterVaporMixture = new GasMixture(Atmospherics.CellVolume)
+ {
+ Temperature = Atmospherics.T20C
+ };
+ _waterVaporMixture.AdjustMoles(Gas.WaterVapor, 50f);
+ }
+
+ private void SetupTile()
+ {
+ // Create a tile atmosphere to use as holder for all reactions
+ var testIndices = new Vector2i(0, 0);
+ _testTile = new TileAtmosphere(_testGrid, testIndices, new GasMixture(Atmospherics.CellVolume)
+ {
+ Temperature = Atmospherics.T20C
+ });
+ }
+
+ private static GasMixture CloneMixture(GasMixture original)
+ {
+ return new GasMixture(original);
+ }
+
+ [Benchmark]
+ public async Task PlasmaFireReaction()
+ {
+ await _pair.Server.WaitPost(() =>
+ {
+ for (var i = 0; i < Iterations; i++)
+ {
+ var mixture = CloneMixture(_plasmaFireMixture);
+ _plasmaFireReaction.React(mixture, _testTile, _atmosphereSystem, 1f);
+ }
+ });
+ }
+
+ [Benchmark]
+ public async Task TritiumFireReaction()
+ {
+ await _pair.Server.WaitPost(() =>
+ {
+ for (var i = 0; i < Iterations; i++)
+ {
+ var mixture = CloneMixture(_tritiumFireMixture);
+ _tritiumFireReaction.React(mixture, _testTile, _atmosphereSystem, 1f);
+ }
+ });
+ }
+
+ [Benchmark]
+ public async Task FrezonProductionReaction()
+ {
+ await _pair.Server.WaitPost(() =>
+ {
+ for (var i = 0; i < Iterations; i++)
+ {
+ var mixture = CloneMixture(_frezonProductionMixture);
+ _frezonProductionReaction.React(mixture, _testTile, _atmosphereSystem, 1f);
+ }
+ });
+ }
+
+ [Benchmark]
+ public async Task FrezonCoolantReaction()
+ {
+ await _pair.Server.WaitPost(() =>
+ {
+ for (var i = 0; i < Iterations; i++)
+ {
+ var mixture = CloneMixture(_frezonCoolantMixture);
+ _frezonCoolantReaction.React(mixture, _testTile, _atmosphereSystem, 1f);
+ }
+ });
+ }
+
+ [Benchmark]
+ public async Task AmmoniaOxygenReaction()
+ {
+ await _pair.Server.WaitPost(() =>
+ {
+ for (var i = 0; i < Iterations; i++)
+ {
+ var mixture = CloneMixture(_ammoniaOxygenMixture);
+ _ammoniaOxygenReaction.React(mixture, _testTile, _atmosphereSystem, 1f);
+ }
+ });
+ }
+
+ [Benchmark]
+ public async Task N2ODecompositionReaction()
+ {
+ await _pair.Server.WaitPost(() =>
+ {
+ for (var i = 0; i < Iterations; i++)
+ {
+ var mixture = CloneMixture(_n2oDecompositionMixture);
+ _n2oDecompositionReaction.React(mixture, _testTile, _atmosphereSystem, 1f);
+ }
+ });
+ }
+
+ [Benchmark]
+ public async Task WaterVaporReaction()
+ {
+ await _pair.Server.WaitPost(() =>
+ {
+ for (var i = 0; i < Iterations; i++)
+ {
+ var mixture = CloneMixture(_waterVaporMixture);
+ _waterVaporReaction.React(mixture, _testTile, _atmosphereSystem, 1f);
+ }
+ });
+ }
+
+ [GlobalCleanup]
+ public async Task CleanupAsync()
+ {
+ await _pair.DisposeAsync();
+ PoolManager.Shutdown();
+ }
+}
diff --git a/Content.Benchmarks/MapLoadBenchmark.cs b/Content.Benchmarks/MapLoadBenchmark.cs
index 3d527953b8..261d408aac 100644
--- a/Content.Benchmarks/MapLoadBenchmark.cs
+++ b/Content.Benchmarks/MapLoadBenchmark.cs
@@ -5,7 +5,7 @@ using System.Threading.Tasks;
using BenchmarkDotNet.Attributes;
using Content.IntegrationTests;
using Content.IntegrationTests.Pair;
-using Content.Server.Maps;
+using Content.Shared.Maps;
using Robust.Shared;
using Robust.Shared.Analyzers;
using Robust.Shared.EntitySerialization.Systems;
diff --git a/Content.Benchmarks/RaiseEventBenchmark.cs b/Content.Benchmarks/RaiseEventBenchmark.cs
index 4c4e0d9125..e3d377ccb3 100644
--- a/Content.Benchmarks/RaiseEventBenchmark.cs
+++ b/Content.Benchmarks/RaiseEventBenchmark.cs
@@ -23,6 +23,8 @@ public class RaiseEventBenchmark
PoolManager.Startup(typeof(BenchSystem).Assembly);
_pair = PoolManager.GetServerClient().GetAwaiter().GetResult();
var entMan = _pair.Server.EntMan;
+ var fact = _pair.Server.ResolveDependency();
+ var bus = (EntityEventBus)entMan.EventBus;
_sys = entMan.System();
_pair.Server.WaitPost(() =>
@@ -30,6 +32,8 @@ public class RaiseEventBenchmark
var uid = entMan.Spawn();
_sys.Ent = new(uid, entMan.GetComponent(uid));
_sys.Ent2 = new(_sys.Ent.Owner, _sys.Ent.Comp);
+ _sys.NetId = fact.GetRegistration().NetID!.Value;
+ _sys.EvSubs = bus.GetNetCompEventHandlers();
})
.GetAwaiter()
.GetResult();
@@ -60,6 +64,12 @@ public class RaiseEventBenchmark
return _sys.RaiseICompEvent();
}
+ [Benchmark]
+ public int RaiseNetEvent()
+ {
+ return _sys.RaiseNetIdEvent();
+ }
+
[Benchmark]
public int RaiseCSharpEvent()
{
@@ -74,6 +84,8 @@ public class RaiseEventBenchmark
public delegate void EntityEventHandler(EntityUid uid, TransformComponent comp, ref BenchEv ev);
public event EntityEventHandler? OnCSharpEvent;
+ public ushort NetId;
+ internal EntityEventBus.DirectedEventHandler?[] EvSubs = default!;
public override void Initialize()
{
@@ -92,7 +104,7 @@ public class RaiseEventBenchmark
public int RaiseCompEvent()
{
var ev = new BenchEv();
- EntityManager.EventBus.RaiseComponentEvent(Ent.Owner, Ent.Comp, ref ev);
+ RaiseComponentEvent(Ent.Owner, Ent.Comp, ref ev);
return ev.N;
}
@@ -100,7 +112,16 @@ public class RaiseEventBenchmark
{
// Raise with an IComponent instead of concrete type
var ev = new BenchEv();
- EntityManager.EventBus.RaiseComponentEvent(Ent2.Owner, Ent2.Comp, ref ev);
+ RaiseComponentEvent(Ent2.Owner, Ent2.Comp, ref ev);
+ return ev.N;
+ }
+
+ public int RaiseNetIdEvent()
+ {
+ // Raise a "IComponent" event using a net-id index delegate array (for PVS & client game-state events)
+ var ev = new BenchEv();
+ ref var unitEv = ref Unsafe.As(ref ev);
+ EvSubs[NetId]?.Invoke(Ent2.Owner, Ent2.Comp, ref unitEv);
return ev.N;
}
@@ -118,6 +139,7 @@ public class RaiseEventBenchmark
}
[ByRefEvent]
+ [ComponentEvent(Exclusive = false)]
public struct BenchEv
{
public int N;
diff --git a/Content.Client/Access/UI/AccessLevelControl.xaml b/Content.Client/Access/UI/AccessLevelControl.xaml
index 56968d8983..6a3155effa 100644
--- a/Content.Client/Access/UI/AccessLevelControl.xaml
+++ b/Content.Client/Access/UI/AccessLevelControl.xaml
@@ -1,4 +1,4 @@
diff --git a/Content.Client/Access/UI/AccessOverriderWindow.xaml b/Content.Client/Access/UI/AccessOverriderWindow.xaml
index ae482140bc..545ebec494 100644
--- a/Content.Client/Access/UI/AccessOverriderWindow.xaml
+++ b/Content.Client/Access/UI/AccessOverriderWindow.xaml
@@ -2,7 +2,7 @@
MinSize="650 290">
-
+
diff --git a/Content.Client/Access/UI/AccessOverriderWindow.xaml.cs b/Content.Client/Access/UI/AccessOverriderWindow.xaml.cs
index a783dd368f..d0d15d2bd5 100644
--- a/Content.Client/Access/UI/AccessOverriderWindow.xaml.cs
+++ b/Content.Client/Access/UI/AccessOverriderWindow.xaml.cs
@@ -53,6 +53,8 @@ namespace Content.Client.Access.UI
public void UpdateState(IPrototypeManager protoManager, AccessOverriderBoundUserInterfaceState state)
{
+ PrivilegedIdGrid.Visible = state.ShowPrivilegedIdGrid;
+
PrivilegedIdLabel.Text = state.PrivilegedIdName;
PrivilegedIdButton.Text = state.IsPrivilegedIdPresent
? Loc.GetString("access-overrider-window-eject-button")
@@ -77,7 +79,9 @@ namespace Content.Client.Access.UI
missingPrivileges.Add(privilege);
}
- MissingPrivilegesLabel.Text = Loc.GetString("access-overrider-window-missing-privileges");
+ MissingPrivilegesLabel.Text = state.ShowPrivilegedIdGrid ?
+ Loc.GetString("access-overrider-window-missing-privileges") :
+ Loc.GetString("access-overrider-window-missing-privileges-no-id");
MissingPrivilegesText.Text = string.Join(", ", missingPrivileges);
}
diff --git a/Content.Client/Access/UI/AgentIDCardWindow.xaml.cs b/Content.Client/Access/UI/AgentIDCardWindow.xaml.cs
index 209c58c950..2b8ebf53b7 100644
--- a/Content.Client/Access/UI/AgentIDCardWindow.xaml.cs
+++ b/Content.Client/Access/UI/AgentIDCardWindow.xaml.cs
@@ -49,12 +49,12 @@ namespace Content.Client.Access.UI
icons.Sort((x, y) => string.Compare(x.LocalizedJobName, y.LocalizedJobName, StringComparison.CurrentCulture));
foreach (var jobIcon in icons)
{
- String styleBase = StyleBase.ButtonOpenBoth;
+ String styleBase = StyleClass.ButtonOpenBoth;
var modulo = i % JobIconColumnCount;
if (modulo == 0)
- styleBase = StyleBase.ButtonOpenRight;
+ styleBase = StyleClass.ButtonOpenRight;
else if (modulo == JobIconColumnCount - 1)
- styleBase = StyleBase.ButtonOpenLeft;
+ styleBase = StyleClass.ButtonOpenLeft;
// Generate buttons
var jobIconButton = new Button
diff --git a/Content.Client/Access/UI/GroupedAccessLevelChecklist.xaml.cs b/Content.Client/Access/UI/GroupedAccessLevelChecklist.xaml.cs
index 7af78d9e5f..2a85530c48 100644
--- a/Content.Client/Access/UI/GroupedAccessLevelChecklist.xaml.cs
+++ b/Content.Client/Access/UI/GroupedAccessLevelChecklist.xaml.cs
@@ -119,11 +119,11 @@ public sealed partial class GroupedAccessLevelChecklist : BoxContainer
if (_groupedAccessLevels.Count > 1)
{
if (AccessGroupList.ChildCount == 0)
- accessGroupButton.AddStyleClass(StyleBase.ButtonOpenLeft);
+ accessGroupButton.AddStyleClass(StyleClass.ButtonOpenLeft);
else if (_groupedAccessLevels.Count > 1 && AccessGroupList.ChildCount == (_groupedAccessLevels.Count - 1))
- accessGroupButton.AddStyleClass(StyleBase.ButtonOpenRight);
+ accessGroupButton.AddStyleClass(StyleClass.ButtonOpenRight);
else
- accessGroupButton.AddStyleClass(StyleBase.ButtonOpenBoth);
+ accessGroupButton.AddStyleClass(StyleClass.ButtonOpenBoth);
}
accessGroupButton.Pressed = _accessGroupTabIndex == orderedAccessGroups.IndexOf(accessGroup);
diff --git a/Content.Client/Actions/UI/ActionAlertTooltip.cs b/Content.Client/Actions/UI/ActionAlertTooltip.cs
index 664a67b406..065c16d61b 100644
--- a/Content.Client/Actions/UI/ActionAlertTooltip.cs
+++ b/Content.Client/Actions/UI/ActionAlertTooltip.cs
@@ -23,9 +23,10 @@ namespace Content.Client.Actions.UI
public ActionAlertTooltip(FormattedMessage name, FormattedMessage? desc, string? requires = null)
{
+ Stylesheet = IoCManager.Resolve().SheetSystem;
_gameTiming = IoCManager.Resolve();
- SetOnlyStyleClass(StyleNano.StyleClassTooltipPanel);
+ SetOnlyStyleClass(StyleClass.TooltipPanel);
BoxContainer vbox;
AddChild(vbox = new BoxContainer
@@ -36,7 +37,7 @@ namespace Content.Client.Actions.UI
var nameLabel = new RichTextLabel
{
MaxWidth = TooltipTextMaxWidth,
- StyleClasses = {StyleNano.StyleClassTooltipActionTitle}
+ StyleClasses = { StyleClass.TooltipTitle }
};
nameLabel.SetMessage(name);
vbox.AddChild(nameLabel);
@@ -46,7 +47,7 @@ namespace Content.Client.Actions.UI
var description = new RichTextLabel
{
MaxWidth = TooltipTextMaxWidth,
- StyleClasses = {StyleNano.StyleClassTooltipActionDescription}
+ StyleClasses = { StyleClass.TooltipDesc }
};
description.SetMessage(desc);
vbox.AddChild(description);
@@ -55,7 +56,7 @@ namespace Content.Client.Actions.UI
vbox.AddChild(_cooldownLabel = new RichTextLabel
{
MaxWidth = TooltipTextMaxWidth,
- StyleClasses = {StyleNano.StyleClassTooltipActionCooldown},
+ StyleClasses = { StyleClass.TooltipDesc },
Visible = false
});
@@ -64,7 +65,7 @@ namespace Content.Client.Actions.UI
var requiresLabel = new RichTextLabel
{
MaxWidth = TooltipTextMaxWidth,
- StyleClasses = {StyleNano.StyleClassTooltipActionRequirements}
+ StyleClasses = { StyleClass.TooltipDesc }
};
if (!FormattedMessage.TryFromMarkup("[color=#635c5c]" + requires + "[/color]", out var markup))
diff --git a/Content.Client/Administration/Components/KillSignComponent.cs b/Content.Client/Administration/Components/KillSignComponent.cs
deleted file mode 100644
index 91c44ef3f2..0000000000
--- a/Content.Client/Administration/Components/KillSignComponent.cs
+++ /dev/null
@@ -1,7 +0,0 @@
-using Content.Shared.Administration.Components;
-using Robust.Shared.GameStates;
-
-namespace Content.Client.Administration.Components;
-
-[RegisterComponent]
-public sealed partial class KillSignComponent : SharedKillSignComponent;
diff --git a/Content.Client/Administration/Systems/BufferingSystem.cs b/Content.Client/Administration/Systems/BufferingSystem.cs
new file mode 100644
index 0000000000..e511bbff36
--- /dev/null
+++ b/Content.Client/Administration/Systems/BufferingSystem.cs
@@ -0,0 +1,7 @@
+using Content.Shared.Administration.Systems;
+
+namespace Content.Client.Administration.Systems;
+
+public sealed class BufferingSystem : SharedBufferingSystem
+{
+}
diff --git a/Content.Client/Administration/Systems/KillSignSystem.cs b/Content.Client/Administration/Systems/KillSignSystem.cs
index c12f65f1f0..f17c384c1e 100644
--- a/Content.Client/Administration/Systems/KillSignSystem.cs
+++ b/Content.Client/Administration/Systems/KillSignSystem.cs
@@ -1,46 +1,77 @@
using System.Numerics;
-using Content.Client.Administration.Components;
+using Content.Shared.Administration.Components;
using Robust.Client.GameObjects;
-using Robust.Shared.Utility;
+using Robust.Client.Player;
namespace Content.Client.Administration.Systems;
public sealed class KillSignSystem : EntitySystem
{
[Dependency] private readonly SpriteSystem _sprite = default!;
+ [Dependency] private readonly IPlayerManager _player = default!;
public override void Initialize()
{
SubscribeLocalEvent(KillSignAdded);
SubscribeLocalEvent(KillSignRemoved);
+ SubscribeLocalEvent(AfterAutoHandleState);
}
- private void KillSignRemoved(EntityUid uid, KillSignComponent component, ComponentShutdown args)
+ private void KillSignRemoved(Entity ent, ref ComponentShutdown args)
{
- if (!TryComp(uid, out var sprite))
- return;
-
- if (!_sprite.LayerMapTryGet((uid, sprite), KillSignKey.Key, out var layer, false))
- return;
-
- _sprite.RemoveLayer((uid, sprite), layer);
+ RemoveKillsign(ent);
}
- private void KillSignAdded(EntityUid uid, KillSignComponent component, ComponentStartup args)
+ private void KillSignAdded(Entity ent, ref ComponentStartup args)
{
- if (!TryComp(uid, out var sprite))
+ AddKillsign(ent);
+ }
+
+ private void AfterAutoHandleState(Entity ent, ref AfterAutoHandleStateEvent args)
+ {
+ // After receiving a new state for the component, we remove the old killsign and build a new one.
+ // This is so changes to the sprite can be displayed live and allowing them to be edited via ViewVariables.
+ // This could just update an existing sprite, but this is both easier and runs rarely anyway.
+ RemoveKillsign(ent);
+ AddKillsign(ent);
+ }
+
+ private void AddKillsign(Entity ent)
+ {
+ // If we hide from owner and we ARE the owner, don't add a killsign.
+ // This could use session specific networking to FULLY hide it, but I am too lazy right now.
+ if (ent.Comp.HideFromOwner && _player.LocalEntity == ent)
return;
- if (_sprite.LayerMapTryGet((uid, sprite), KillSignKey.Key, out var _, false))
+ if (!TryComp(ent, out var sprite))
return;
- var adj = _sprite.GetLocalBounds((uid, sprite)).Height / 2 + ((1.0f / 32) * 6.0f);
+ if (_sprite.LayerMapTryGet((ent, sprite), KillSignKey.Key, out var _, false))
+ return;
- var layer = _sprite.AddLayer((uid, sprite), new SpriteSpecifier.Rsi(new ResPath("Objects/Misc/killsign.rsi"), "sign"));
- _sprite.LayerMapSet((uid, sprite), KillSignKey.Key, layer);
+ if (ent.Comp.Sprite == null)
+ return;
- _sprite.LayerSetOffset((uid, sprite), layer, new Vector2(0.0f, adj));
- sprite.LayerSetShader(layer, "unshaded");
+ var adj = _sprite.GetLocalBounds((ent, sprite)).Height / 2 + ((1.0f / 32) * 6.0f);
+
+ var layer = _sprite.AddLayer((ent, sprite), ent.Comp.Sprite);
+ _sprite.LayerMapSet((ent, sprite), KillSignKey.Key, layer);
+ _sprite.LayerSetScale((ent, sprite), layer, ent.Comp.Scale);
+ _sprite.LayerSetOffset((ent, sprite), layer, ent.Comp.DoOffset ? new Vector2(0.0f, adj) : new Vector2(0.0f, 0.0f));
+
+ if (ent.Comp.ForceUnshaded)
+ sprite.LayerSetShader(layer, "unshaded");
+ }
+
+ private void RemoveKillsign(Entity ent)
+ {
+ if (!TryComp(ent, out var sprite))
+ return;
+
+ if (!_sprite.LayerMapTryGet((ent, sprite), KillSignKey.Key, out var layer, false))
+ return;
+
+ _sprite.RemoveLayer((ent, sprite), layer);
}
private enum KillSignKey
diff --git a/Content.Client/Administration/UI/AdminRemarks/AdminMessagePopupWindow.xaml b/Content.Client/Administration/UI/AdminRemarks/AdminMessagePopupWindow.xaml
index cc5207bb3a..bfe6b31c28 100644
--- a/Content.Client/Administration/UI/AdminRemarks/AdminMessagePopupWindow.xaml
+++ b/Content.Client/Administration/UI/AdminRemarks/AdminMessagePopupWindow.xaml
@@ -7,7 +7,7 @@
-
+
diff --git a/Content.Client/Administration/UI/AdminRemarks/AdminMessagePopupWindow.xaml.cs b/Content.Client/Administration/UI/AdminRemarks/AdminMessagePopupWindow.xaml.cs
index 148cbf4e18..7870dae7b2 100644
--- a/Content.Client/Administration/UI/AdminRemarks/AdminMessagePopupWindow.xaml.cs
+++ b/Content.Client/Administration/UI/AdminRemarks/AdminMessagePopupWindow.xaml.cs
@@ -12,17 +12,19 @@ namespace Content.Client.Administration.UI.AdminRemarks;
[GenerateTypedNameReferences]
public sealed partial class AdminMessagePopupWindow : Control
{
+ [Dependency] private readonly IStylesheetManager _styleMan = default!;
+
private float _timer = float.MaxValue;
public event Action? OnDismissPressed;
-
public event Action? OnAcceptPressed;
public AdminMessagePopupWindow()
{
RobustXamlLoader.Load(this);
+ IoCManager.InjectDependencies(this);
- Stylesheet = IoCManager.Resolve().SheetSpace;
+ Stylesheet = _styleMan.SheetSystem;
AcceptButton.OnPressed += OnAcceptButtonPressed;
DismissButton.OnPressed += OnDismissButtonPressed;
@@ -49,7 +51,8 @@ public sealed partial class AdminMessagePopupWindow : Control
MessageContainer.AddChild(new AdminMessagePopupMessage(message));
}
- Description.SetMessage(FormattedMessage.FromMarkupOrThrow(Loc.GetString("admin-notes-message-desc", ("count", state.Messages.Length))));
+ Description.SetMessage(
+ FormattedMessage.FromMarkup(Loc.GetString("admin-notes-message-desc", ("count", state.Messages.Length))));
}
private void OnDismissButtonPressed(BaseButton.ButtonEventArgs obj)
diff --git a/Content.Client/Administration/UI/BanPanel/BanPanel.xaml.cs b/Content.Client/Administration/UI/BanPanel/BanPanel.xaml.cs
index d6a67af955..9b1278f187 100644
--- a/Content.Client/Administration/UI/BanPanel/BanPanel.xaml.cs
+++ b/Content.Client/Administration/UI/BanPanel/BanPanel.xaml.cs
@@ -299,19 +299,19 @@ public sealed partial class BanPanel : DefaultWindow
}
///
- /// Adds a check button specifically for one "role" in a "group"
+ /// Adds a toggle button specifically for one "role" in a "group"
/// E.g. it would add the Chief Medical Officer "role" into the "Medical" group.
///
private void AddRoleCheckbox(string group, string role, GridContainer roleGroupInnerContainer, Button roleGroupCheckbox)
{
var roleCheckboxContainer = new BoxContainer();
- var roleCheckButton = new Button
+ var roleToggleButton = new Button
{
Name = role,
Text = role,
ToggleMode = true,
};
- roleCheckButton.OnToggled += args =>
+ roleToggleButton.OnToggled += args =>
{
// Checks the role group checkbox if all the children are pressed
if (args.Pressed && _roleCheckboxes[group].All(e => e.Item1.Pressed))
@@ -348,12 +348,12 @@ public sealed partial class BanPanel : DefaultWindow
roleCheckboxContainer.AddChild(jobIconTexture);
}
- roleCheckboxContainer.AddChild(roleCheckButton);
+ roleCheckboxContainer.AddChild(roleToggleButton);
roleGroupInnerContainer.AddChild(roleCheckboxContainer);
_roleCheckboxes.TryAdd(group, []);
- _roleCheckboxes[group].Add((roleCheckButton, rolePrototype));
+ _roleCheckboxes[group].Add((roleToggleButton, rolePrototype));
}
public void UpdateBanFlag(bool newFlag)
diff --git a/Content.Client/Administration/UI/CustomControls/AdminLogLabel.cs b/Content.Client/Administration/UI/CustomControls/AdminLogLabel.cs
index 0de38ce234..eb2281cf7b 100644
--- a/Content.Client/Administration/UI/CustomControls/AdminLogLabel.cs
+++ b/Content.Client/Administration/UI/CustomControls/AdminLogLabel.cs
@@ -15,7 +15,7 @@ public sealed class AdminLogLabel : RichTextLabel
OnVisibilityChanged += VisibilityChanged;
}
- public SharedAdminLog Log { get; }
+ public new SharedAdminLog Log { get; }
public HSeparator Separator { get; }
diff --git a/Content.Client/Administration/UI/CustomControls/PlayerListEntry.xaml.cs b/Content.Client/Administration/UI/CustomControls/PlayerListEntry.xaml.cs
index cd6a56ea71..cf2e776ea8 100644
--- a/Content.Client/Administration/UI/CustomControls/PlayerListEntry.xaml.cs
+++ b/Content.Client/Administration/UI/CustomControls/PlayerListEntry.xaml.cs
@@ -11,6 +11,9 @@ namespace Content.Client.Administration.UI.CustomControls;
[GenerateTypedNameReferences]
public sealed partial class PlayerListEntry : BoxContainer
{
+ private readonly ResPath _pinnedResPath = new("/Textures/Interface/Bwoink/pinned.png");
+ private readonly ResPath _unPinnedResPath = new("/Textures/Interface/Bwoink/un_pinned.png");
+
public PlayerListEntry()
{
RobustXamlLoader.Load(this);
@@ -44,15 +47,6 @@ public sealed partial class PlayerListEntry : BoxContainer
private void UpdatePinButtonTexture(bool isPinned)
{
- if (isPinned)
- {
- PlayerEntryPinButton?.RemoveStyleClass(StyleNano.StyleClassPinButtonUnpinned);
- PlayerEntryPinButton?.AddStyleClass(StyleNano.StyleClassPinButtonPinned);
- }
- else
- {
- PlayerEntryPinButton?.RemoveStyleClass(StyleNano.StyleClassPinButtonPinned);
- PlayerEntryPinButton?.AddStyleClass(StyleNano.StyleClassPinButtonUnpinned);
- }
+ PlayerEntryPinButton.TexturePath = isPinned ? _pinnedResPath.CanonPath : _unPinnedResPath.CanonPath;
}
}
diff --git a/Content.Client/Administration/UI/PermissionsEui.cs b/Content.Client/Administration/UI/PermissionsEui.cs
index fe1237d4c9..96b53babb5 100644
--- a/Content.Client/Administration/UI/PermissionsEui.cs
+++ b/Content.Client/Administration/UI/PermissionsEui.cs
@@ -27,7 +27,7 @@ namespace Content.Client.Administration.UI
[Dependency] private readonly IClientAdminManager _adminManager = default!;
private readonly Menu _menu;
- private readonly List _subWindows = new();
+ private readonly List _subWindows = new();
private Dictionary _ranks =
new();
@@ -216,7 +216,7 @@ namespace Content.Client.Administration.UI
var titleControl = new Label { Text = admin.Title ?? Loc.GetString("permissions-eui-edit-admin-title-control-text").ToLowerInvariant() };
if (admin.Title == null) // none
{
- titleControl.StyleClasses.Add(StyleBase.StyleClassItalic);
+ titleControl.StyleClasses.Add(StyleClass.Italic);
}
al.AddChild(titleControl);
@@ -240,7 +240,7 @@ namespace Content.Client.Administration.UI
var rankControl = new Label { Text = rank };
if (italic)
{
- rankControl.StyleClasses.Add(StyleBase.StyleClassItalic);
+ rankControl.StyleClasses.Add(StyleClass.Italic);
}
al.AddChild(rankControl);
@@ -340,10 +340,9 @@ namespace Content.Client.Administration.UI
tab.AddChild(adminVBox);
tab.AddChild(rankVBox);
- Contents.AddChild(tab);
+ ContentsContainer.AddChild(tab);
+ ContentsContainer.MinSize = new(600, 400);
}
-
- protected override Vector2 ContentsMinimumSize => new Vector2(600, 400);
}
private sealed class EditAdminWindow : DefaultWindow
@@ -419,21 +418,21 @@ namespace Content.Client.Administration.UI
var inherit = new Button
{
Text = "I",
- StyleClasses = { StyleBase.ButtonOpenRight },
+ StyleClasses = { StyleClass.ButtonOpenRight },
Disabled = disable,
Group = group,
};
var sub = new Button
{
Text = "-",
- StyleClasses = { StyleBase.ButtonOpenBoth },
+ StyleClasses = { StyleClass.ButtonOpenBoth },
Disabled = disable,
Group = group
};
var plus = new Button
{
Text = "+",
- StyleClasses = { StyleBase.ButtonOpenLeft },
+ StyleClasses = { StyleClass.ButtonOpenLeft },
Disabled = disable,
Group = group
};
@@ -479,7 +478,7 @@ namespace Content.Client.Administration.UI
bottomButtons.AddChild(SaveButton);
- Contents.AddChild(new BoxContainer
+ ContentsContainer.AddChild(new BoxContainer
{
Orientation = LayoutOrientation.Vertical,
Children =
@@ -605,7 +604,7 @@ namespace Content.Client.Administration.UI
bottomButtons.AddChild(SaveButton);
- Contents.AddChild(new BoxContainer
+ ContentsContainer.AddChild(new BoxContainer
{
Orientation = LayoutOrientation.Vertical,
Children =
diff --git a/Content.Client/Anomaly/Ui/AnomalyGeneratorWindow.xaml b/Content.Client/Anomaly/Ui/AnomalyGeneratorWindow.xaml
index 9784b34557..88df194ecb 100644
--- a/Content.Client/Anomaly/Ui/AnomalyGeneratorWindow.xaml
+++ b/Content.Client/Anomaly/Ui/AnomalyGeneratorWindow.xaml
@@ -14,7 +14,7 @@
VerticalExpand="True"
Margin="0 0 0 0"
VerticalAlignment="Center">
-
+
-
-
+
+
OnPlayerAction?.Invoke(SharedSpaceVillainArcadeComponent.PlayerAction.NewGame);
grid.AddChild(newGame);
- Contents.AddChild(grid);
+ ContentsContainer.AddChild(grid);
}
private void UpdateMetadata(SharedSpaceVillainArcadeComponent.SpaceVillainArcadeMetaDataUpdateMessage message)
diff --git a/Content.Client/Atmos/EntitySystems/DeltaPressureSystem.cs b/Content.Client/Atmos/EntitySystems/DeltaPressureSystem.cs
new file mode 100644
index 0000000000..3d9893ac62
--- /dev/null
+++ b/Content.Client/Atmos/EntitySystems/DeltaPressureSystem.cs
@@ -0,0 +1,5 @@
+using Content.Shared.Atmos.EntitySystems;
+
+namespace Content.Client.Atmos.EntitySystems;
+
+public sealed class DeltaPressureSystem : SharedDeltaPressureSystem;
diff --git a/Content.Client/Atmos/Monitor/UI/AirAlarmWindow.xaml.cs b/Content.Client/Atmos/Monitor/UI/AirAlarmWindow.xaml.cs
index 64680b5321..60e06e98ce 100644
--- a/Content.Client/Atmos/Monitor/UI/AirAlarmWindow.xaml.cs
+++ b/Content.Client/Atmos/Monitor/UI/AirAlarmWindow.xaml.cs
@@ -1,6 +1,6 @@
using Content.Client.Atmos.Monitor.UI.Widgets;
using Content.Client.Message;
-using Content.Client.Stylesheets;
+using Content.Client.Stylesheets.Palette;
using Content.Client.UserInterface.Controls;
using Content.Shared.Atmos;
using Content.Shared.Atmos.Monitor;
@@ -17,7 +17,7 @@ namespace Content.Client.Atmos.Monitor.UI;
public sealed partial class AirAlarmWindow : FancyWindow
{
public event Action? AtmosDeviceDataChanged;
- public event Action? AtmosDeviceDataCopied;
+ public event Action? AtmosDeviceDataCopied;
public event Action? AtmosAlarmThresholdChanged;
public event Action? AirAlarmModeChanged;
public event Action? AutoModeChanged;
@@ -131,7 +131,7 @@ public sealed partial class AirAlarmWindow : FancyWindow
case GasVentPumpData pump:
if (!_pumps.TryGetValue(addr, out var pumpControl))
{
- var control= new PumpControl(pump, addr);
+ var control = new PumpControl(pump, addr);
control.PumpDataChanged += AtmosDeviceDataChanged;
control.PumpDataCopied += AtmosDeviceDataCopied;
_pumps.Add(addr, control);
@@ -186,11 +186,9 @@ public sealed partial class AirAlarmWindow : FancyWindow
{
return curAlarm switch
{
- AtmosAlarmType.Danger => StyleNano.DangerousRedFore,
- AtmosAlarmType.Warning => StyleNano.ConcerningOrangeFore,
- _ => StyleNano.GoodGreenFore,
+ AtmosAlarmType.Danger => Palettes.Status.Critical,
+ AtmosAlarmType.Warning => Palettes.Status.Warning,
+ _ => Palettes.Status.Good,
};
}
-
-
}
diff --git a/Content.Client/Atmos/Monitor/UI/Widgets/ThresholdBoundControl.xaml.cs b/Content.Client/Atmos/Monitor/UI/Widgets/ThresholdBoundControl.xaml.cs
index 38c631e630..f4b31fd95b 100644
--- a/Content.Client/Atmos/Monitor/UI/Widgets/ThresholdBoundControl.xaml.cs
+++ b/Content.Client/Atmos/Monitor/UI/Widgets/ThresholdBoundControl.xaml.cs
@@ -1,3 +1,4 @@
+using Content.Client.Stylesheets;
using Content.Shared.Atmos.Monitor;
using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface.Controls;
@@ -42,11 +43,11 @@ public sealed partial class ThresholdBoundControl : BoxContainer
if (enabled)
{
- CBoundLabel.RemoveStyleClass("Disabled");
+ CBoundLabel.RemoveStyleClass(StyleClass.LabelWeak);
}
else
{
- CBoundLabel.SetOnlyStyleClass("Disabled");
+ CBoundLabel.SetOnlyStyleClass(StyleClass.LabelWeak);
}
}
diff --git a/Content.Client/Atmos/Overlays/GasTileOverlay.cs b/Content.Client/Atmos/Overlays/GasTileOverlay.cs
index d91cc29e4c..eeb10b54d0 100644
--- a/Content.Client/Atmos/Overlays/GasTileOverlay.cs
+++ b/Content.Client/Atmos/Overlays/GasTileOverlay.cs
@@ -3,6 +3,7 @@ using Content.Client.Atmos.Components;
using Content.Client.Atmos.EntitySystems;
using Content.Shared.Atmos;
using Content.Shared.Atmos.Components;
+using Content.Shared.Atmos.EntitySystems;
using Content.Shared.Atmos.Prototypes;
using Robust.Client.GameObjects;
using Robust.Client.Graphics;
@@ -23,6 +24,7 @@ namespace Content.Client.Atmos.Overlays
private readonly IEntityManager _entManager;
private readonly IMapManager _mapManager;
+ private readonly SharedAtmosphereSystem _atmosphereSystem;
private readonly SharedMapSystem _mapSystem;
private readonly SharedTransformSystem _xformSys;
@@ -54,6 +56,7 @@ namespace Content.Client.Atmos.Overlays
{
_entManager = entManager;
_mapManager = IoCManager.Resolve();
+ _atmosphereSystem = entManager.System();
_mapSystem = entManager.System();
_xformSys = xformSys;
_shader = protoMan.Index(UnshadedShader).Instance();
@@ -67,7 +70,7 @@ namespace Content.Client.Atmos.Overlays
for (var i = 0; i < _gasCount; i++)
{
- var gasPrototype = protoMan.Index(system.VisibleGasId[i].ToString());
+ var gasPrototype = _atmosphereSystem.GetGas(system.VisibleGasId[i]);
SpriteSpecifier overlay;
diff --git a/Content.Client/Atmos/UI/GasCanisterWindow.xaml b/Content.Client/Atmos/UI/GasCanisterWindow.xaml
index f76e32a31d..3c7647385a 100644
--- a/Content.Client/Atmos/UI/GasCanisterWindow.xaml
+++ b/Content.Client/Atmos/UI/GasCanisterWindow.xaml
@@ -4,7 +4,7 @@
MinSize="480 400" Title="Canister">
-
+
@@ -16,7 +16,7 @@
-
+
@@ -29,7 +29,7 @@
-
+
diff --git a/Content.Client/Atmos/UI/GasFilterBoundUserInterface.cs b/Content.Client/Atmos/UI/GasFilterBoundUserInterface.cs
index 2b8020924c..ecaaca3005 100644
--- a/Content.Client/Atmos/UI/GasFilterBoundUserInterface.cs
+++ b/Content.Client/Atmos/UI/GasFilterBoundUserInterface.cs
@@ -52,14 +52,18 @@ namespace Content.Client.Atmos.UI
private void OnSelectGasPressed()
{
- if (_window is null) return;
+ if (_window is null)
+ return;
+
if (_window.SelectedGas is null)
{
SendMessage(new GasFilterSelectGasMessage(null));
}
else
{
- if (!int.TryParse(_window.SelectedGas, out var gas)) return;
+ if (!Enum.TryParse(_window.SelectedGas, out var gas))
+ return;
+
SendMessage(new GasFilterSelectGasMessage(gas));
}
}
diff --git a/Content.Client/Bed/BedSystem.cs b/Content.Client/Bed/BedSystem.cs
deleted file mode 100644
index 9c6f28290f..0000000000
--- a/Content.Client/Bed/BedSystem.cs
+++ /dev/null
@@ -1,8 +0,0 @@
-using Content.Shared.Bed;
-
-namespace Content.Client.Bed;
-
-public sealed class BedSystem : SharedBedSystem
-{
-
-}
diff --git a/Content.Client/Bed/Cryostorage/CryostorageEntryControl.xaml b/Content.Client/Bed/Cryostorage/CryostorageEntryControl.xaml
index 5acb142a60..3378dc7797 100644
--- a/Content.Client/Bed/Cryostorage/CryostorageEntryControl.xaml
+++ b/Content.Client/Bed/Cryostorage/CryostorageEntryControl.xaml
@@ -7,10 +7,7 @@
Orientation="Vertical"
HorizontalExpand="True"
Margin="0 0 0 5">
-
-
-
-
+
diff --git a/Content.Client/Bed/Cryostorage/CryostorageMenu.xaml b/Content.Client/Bed/Cryostorage/CryostorageMenu.xaml
index 5360cdb38e..b0f8d5cb0a 100644
--- a/Content.Client/Bed/Cryostorage/CryostorageMenu.xaml
+++ b/Content.Client/Bed/Cryostorage/CryostorageMenu.xaml
@@ -14,10 +14,8 @@
-
-
-
+ Margin="15"
+ StyleClasses="PanelDark">
diff --git a/Content.Client/Bql/ToolshedVisualizeWindow.xaml b/Content.Client/Bql/ToolshedVisualizeWindow.xaml
index 9affbf2181..b20d05b4f3 100644
--- a/Content.Client/Bql/ToolshedVisualizeWindow.xaml
+++ b/Content.Client/Bql/ToolshedVisualizeWindow.xaml
@@ -1,7 +1,7 @@
-
+
diff --git a/Content.Client/Bql/ToolshedVisualizeWindow.xaml.cs b/Content.Client/Bql/ToolshedVisualizeWindow.xaml.cs
index 55ee029a91..35a7524a6f 100644
--- a/Content.Client/Bql/ToolshedVisualizeWindow.xaml.cs
+++ b/Content.Client/Bql/ToolshedVisualizeWindow.xaml.cs
@@ -21,8 +21,6 @@ internal sealed partial class ToolshedVisualizeWindow : DefaultWindow
RobustXamlLoader.Load(this);
}
- protected override Vector2 ContentsMinimumSize => new(500, 700);
-
public void Update((string name, NetEntity entity)[] entities)
{
StatusLabel.Text = _loc.GetString("ui-bql-results-status", ("count", entities.Length));
diff --git a/Content.Client/Cargo/UI/BountyEntry.xaml b/Content.Client/Cargo/UI/BountyEntry.xaml
index 7c61323bd5..99874cf1a5 100644
--- a/Content.Client/Cargo/UI/BountyEntry.xaml
+++ b/Content.Client/Cargo/UI/BountyEntry.xaml
@@ -3,7 +3,7 @@
Margin="10 10 10 0"
HorizontalExpand="True"
Visible="True">
-
+
diff --git a/Content.Client/Cargo/UI/BountyEntry.xaml.cs b/Content.Client/Cargo/UI/BountyEntry.xaml.cs
index d813f70ff4..bac7d84bf7 100644
--- a/Content.Client/Cargo/UI/BountyEntry.xaml.cs
+++ b/Content.Client/Cargo/UI/BountyEntry.xaml.cs
@@ -7,7 +7,6 @@ using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.XAML;
using Robust.Shared.Prototypes;
using Robust.Shared.Timing;
-using Serilog;
namespace Content.Client.Cargo.UI;
diff --git a/Content.Client/CartridgeLoader/Cartridges/NewsReaderUiFragment.xaml.cs b/Content.Client/CartridgeLoader/Cartridges/NewsReaderUiFragment.xaml.cs
index 2d4d192ea8..f76adfb866 100644
--- a/Content.Client/CartridgeLoader/Cartridges/NewsReaderUiFragment.xaml.cs
+++ b/Content.Client/CartridgeLoader/Cartridges/NewsReaderUiFragment.xaml.cs
@@ -1,8 +1,12 @@
using Content.Client.Message;
+using Content.Client.RichText;
+using Content.Client.UserInterface.RichText;
using Content.Shared.MassMedia.Systems;
using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface.Controls;
+using Robust.Client.UserInterface.RichText;
using Robust.Client.UserInterface.XAML;
+using Robust.Shared.Utility;
namespace Content.Client.CartridgeLoader.Cartridges;
@@ -31,16 +35,17 @@ public sealed partial class NewsReaderUiFragment : BoxContainer
Author.Visible = true;
PageName.Text = article.Title;
- PageText.SetMarkupPermissive(article.Content);
+ PageText.SetMessage(FormattedMessage.FromMarkupPermissive(article.Content), UserFormattableTags.BaseAllowedTags);
PageNum.Text = $"{targetNum}/{totalNum}";
NotificationSwitch.Text = Loc.GetString(notificationOn ? "news-read-ui-notification-on" : "news-read-ui-notification-off");
- string shareTime = article.ShareTime.ToString(@"hh\:mm\:ss");
+ var 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")));
+ var author = Loc.GetString("news-read-ui-author-prefix") + " " + (article.Author ?? Loc.GetString("news-read-ui-no-author"));
+ Author.SetMessage(FormattedMessage.FromMarkupPermissive(author), UserFormattableTags.BaseAllowedTags);
Prev.Disabled = targetNum <= 1;
Next.Disabled = targetNum >= totalNum;
diff --git a/Content.Client/Changeling/UI/ChangelingTransformBoundUserInterface.cs b/Content.Client/Changeling/UI/ChangelingTransformBoundUserInterface.cs
index 97c07dd8c9..64d809c0c5 100644
--- a/Content.Client/Changeling/UI/ChangelingTransformBoundUserInterface.cs
+++ b/Content.Client/Changeling/UI/ChangelingTransformBoundUserInterface.cs
@@ -1,4 +1,4 @@
-using Content.Client.Stylesheets;
+using Content.Client.Stylesheets.Palette;
using Content.Client.UserInterface.Controls;
using Content.Shared.Changeling.Components;
using Content.Shared.Changeling.Systems;
@@ -11,8 +11,8 @@ namespace Content.Client.Changeling.UI;
public sealed partial class ChangelingTransformBoundUserInterface(EntityUid owner, Enum uiKey) : BoundUserInterface(owner, uiKey)
{
private SimpleRadialMenu? _menu;
- private static readonly Color SelectedOptionBackground = StyleNano.ButtonColorGoodDefault.WithAlpha(128);
- private static readonly Color SelectedOptionHoverBackground = StyleNano.ButtonColorGoodHovered.WithAlpha(128);
+ private static readonly Color SelectedOptionBackground = Palettes.Green.Element.WithAlpha(128);
+ private static readonly Color SelectedOptionHoverBackground = Palettes.Green.HoveredElement.WithAlpha(128);
protected override void Open()
{
diff --git a/Content.Client/Changelog/ChangelogButton.cs b/Content.Client/Changelog/ChangelogButton.cs
index 6e8862492c..8611866b0d 100644
--- a/Content.Client/Changelog/ChangelogButton.cs
+++ b/Content.Client/Changelog/ChangelogButton.cs
@@ -36,12 +36,12 @@ namespace Content.Client.Changelog
if (_changelogManager.NewChangelogEntries)
{
Text = Loc.GetString("changelog-button-new-entries");
- StyleClasses.Add(StyleBase.ButtonCaution);
+ StyleClasses.Add(StyleClass.Negative);
}
else
{
Text = Loc.GetString("changelog-button");
- StyleClasses.Remove(StyleBase.ButtonCaution);
+ StyleClasses.Remove(StyleClass.Negative);
}
}
}
diff --git a/Content.Client/Changelog/ChangelogManager.cs b/Content.Client/Changelog/ChangelogManager.cs
index f17e84168f..1b1d01a464 100644
--- a/Content.Client/Changelog/ChangelogManager.cs
+++ b/Content.Client/Changelog/ChangelogManager.cs
@@ -52,6 +52,7 @@ namespace Content.Client.Changelog
// Open changelog purely to compare to the last viewed date.
var changelogs = await LoadChangelog();
UpdateChangelogs(changelogs);
+ _configManager.OnValueChanged(CCVars.ServerId, OnServerIdCVarChanged);
}
private void UpdateChangelogs(List changelogs)
@@ -81,6 +82,11 @@ namespace Content.Client.Changelog
MaxId = changelog.Entries.Max(c => c.Id);
+ CheckLastSeenEntry();
+ }
+
+ private void CheckLastSeenEntry()
+ {
var path = new ResPath($"/changelog_last_seen_{_configManager.GetCVar(CCVars.ServerId)}");
if (_resource.UserData.TryReadAllText(path, out var lastReadIdText))
{
@@ -92,6 +98,11 @@ namespace Content.Client.Changelog
NewChangelogEntriesChanged?.Invoke();
}
+ private void OnServerIdCVarChanged(string newValue)
+ {
+ CheckLastSeenEntry();
+ }
+
public Task> LoadChangelog()
{
return Task.Run(() =>
diff --git a/Content.Client/Changelog/ChangelogTab.xaml.cs b/Content.Client/Changelog/ChangelogTab.xaml.cs
index 83df0bbdfc..8565d83264 100644
--- a/Content.Client/Changelog/ChangelogTab.xaml.cs
+++ b/Content.Client/Changelog/ChangelogTab.xaml.cs
@@ -66,12 +66,12 @@ public sealed partial class ChangelogTab : Control
else
dayNice = day.ToShortDateString();
- ChangelogBody.AddChild(new Label
- {
- Text = dayNice,
- StyleClasses = { StyleBase.StyleClassLabelHeading },
- Margin = new Thickness(4, 6, 0, 0)
- });
+ ChangelogBody.AddChild(new Label
+ {
+ Text = dayNice,
+ StyleClasses = { StyleClass.LabelHeading },
+ Margin = new Thickness(4, 6, 0, 0)
+ });
var first = true;
@@ -127,9 +127,9 @@ public sealed partial class ChangelogTab : Control
}
};
- readDivider.AddChild(hBox);
- readDivider.AddChild(new PanelContainer { StyleClasses = { StyleBase.ClassLowDivider } });
- ChangelogBody.AddChild(readDivider);
+ readDivider.AddChild(hBox);
+ readDivider.AddChild(new PanelContainer { StyleClasses = { StyleClass.LowDivider } });
+ ChangelogBody.AddChild(readDivider);
if (first)
readDivider.SetPositionInParent(ChangelogBody.ChildCount - 2);
diff --git a/Content.Client/Changelog/ChangelogWindow.xaml b/Content.Client/Changelog/ChangelogWindow.xaml
index 355452dbfa..8325de02b5 100644
--- a/Content.Client/Changelog/ChangelogWindow.xaml
+++ b/Content.Client/Changelog/ChangelogWindow.xaml
@@ -2,8 +2,9 @@
xmlns:ui="clr-namespace:Content.Client.Changelog"
Title="{Loc 'changelog-window-title'}"
MinSize="500 400"
- SetSize="500 400">
-
+ SetSize="500 400"
+ Stylesheet="Interface">
+
diff --git a/Content.Client/Changelog/ChangelogWindow.xaml.cs b/Content.Client/Changelog/ChangelogWindow.xaml.cs
index d8f560f151..801d0859c3 100644
--- a/Content.Client/Changelog/ChangelogWindow.xaml.cs
+++ b/Content.Client/Changelog/ChangelogWindow.xaml.cs
@@ -21,8 +21,7 @@ namespace Content.Client.Changelog
public ChangelogWindow()
{
RobustXamlLoader.Load(this);
- WindowTitle.AddStyleClass(StyleBase.StyleClassLabelHeading);
- Stylesheet = IoCManager.Resolve().SheetSpace;
+ WindowTitle.AddStyleClass(StyleClass.LabelHeading);
}
protected override void Opened()
diff --git a/Content.Client/Chat/Managers/ChatManager.cs b/Content.Client/Chat/Managers/ChatManager.cs
index 8acb480e83..ec42213bd4 100644
--- a/Content.Client/Chat/Managers/ChatManager.cs
+++ b/Content.Client/Chat/Managers/ChatManager.cs
@@ -32,6 +32,11 @@ internal sealed class ChatManager : IChatManager
// See server-side manager. This just exists for shared code.
}
+ public void SendAdminAlertNoFormatOrEscape(string message)
+ {
+ // See server-side manager. This just exists for shared code.
+ }
+
public void SendMessage(string text, ChatSelectChannel channel)
{
var str = text.ToString();
diff --git a/Content.Client/Chemistry/EntitySystems/HyposprayStatusControlSystem.cs b/Content.Client/Chemistry/EntitySystems/HyposprayStatusControlSystem.cs
deleted file mode 100644
index 4dfc8506d2..0000000000
--- a/Content.Client/Chemistry/EntitySystems/HyposprayStatusControlSystem.cs
+++ /dev/null
@@ -1,16 +0,0 @@
-using Content.Client.Chemistry.UI;
-using Content.Client.Items;
-using Content.Shared.Chemistry.Components;
-using Content.Shared.Chemistry.EntitySystems;
-
-namespace Content.Client.Chemistry.EntitySystems;
-
-public sealed class HyposprayStatusControlSystem : EntitySystem
-{
- [Dependency] private readonly SharedSolutionContainerSystem _solutionContainers = default!;
- public override void Initialize()
- {
- base.Initialize();
- Subs.ItemStatus(ent => new HyposprayStatusControl(ent, _solutionContainers));
- }
-}
diff --git a/Content.Client/Chemistry/EntitySystems/InjectorStatusControlSystem.cs b/Content.Client/Chemistry/EntitySystems/InjectorStatusControlSystem.cs
new file mode 100644
index 0000000000..ca8685eb3e
--- /dev/null
+++ b/Content.Client/Chemistry/EntitySystems/InjectorStatusControlSystem.cs
@@ -0,0 +1,20 @@
+using Content.Client.Chemistry.UI;
+using Content.Client.Items;
+using Content.Shared.Chemistry.Components;
+using Content.Shared.Chemistry.EntitySystems;
+using Robust.Shared.Prototypes;
+
+namespace Content.Client.Chemistry.EntitySystems;
+
+public sealed class InjectorStatusControlSystem : EntitySystem
+{
+ [Dependency] private readonly SharedSolutionContainerSystem _solutionContainers = default!;
+ [Dependency] private readonly IPrototypeManager _prototypeManager = default!;
+
+
+ public override void Initialize()
+ {
+ base.Initialize();
+ Subs.ItemStatus(injector => new InjectorStatusControl(injector, _solutionContainers, _prototypeManager));
+ }
+}
diff --git a/Content.Client/Chemistry/EntitySystems/InjectorSystem.cs b/Content.Client/Chemistry/EntitySystems/InjectorSystem.cs
deleted file mode 100644
index 58cb5330a2..0000000000
--- a/Content.Client/Chemistry/EntitySystems/InjectorSystem.cs
+++ /dev/null
@@ -1,16 +0,0 @@
-using Content.Client.Chemistry.UI;
-using Content.Client.Items;
-using Content.Shared.Chemistry.Components;
-using Content.Shared.Chemistry.EntitySystems;
-
-namespace Content.Client.Chemistry.EntitySystems;
-
-public sealed class InjectorSystem : SharedInjectorSystem
-{
- public override void Initialize()
- {
- base.Initialize();
-
- Subs.ItemStatus(ent => new InjectorStatusControl(ent, SolutionContainer));
- }
-}
diff --git a/Content.Client/Chemistry/UI/ChemMasterWindow.xaml b/Content.Client/Chemistry/UI/ChemMasterWindow.xaml
index db9991622a..710cdb33d4 100644
--- a/Content.Client/Chemistry/UI/ChemMasterWindow.xaml
+++ b/Content.Client/Chemistry/UI/ChemMasterWindow.xaml
@@ -33,8 +33,8 @@
+
-
@@ -82,7 +82,7 @@
-
+
@@ -112,9 +112,9 @@
-
+
-
+
@@ -134,7 +134,7 @@
-
+
diff --git a/Content.Client/Chemistry/UI/ChemMasterWindow.xaml.cs b/Content.Client/Chemistry/UI/ChemMasterWindow.xaml.cs
index 5137eb6f33..619c9687ff 100644
--- a/Content.Client/Chemistry/UI/ChemMasterWindow.xaml.cs
+++ b/Content.Client/Chemistry/UI/ChemMasterWindow.xaml.cs
@@ -53,14 +53,14 @@ namespace Content.Client.Chemistry.UI
{
// For every button decide which stylebase to have
// Every row has 10 buttons
- String styleBase = StyleBase.ButtonOpenBoth;
+ String styleBase = StyleClass.ButtonOpenBoth;
uint modulo = i % 10;
if (i > 0 && modulo == 0)
- styleBase = StyleBase.ButtonOpenRight;
+ styleBase = StyleClass.ButtonOpenRight;
else if (i > 0 && modulo == 9)
- styleBase = StyleBase.ButtonOpenLeft;
+ styleBase = StyleClass.ButtonOpenLeft;
else if (i == 0)
- styleBase = StyleBase.ButtonOpenRight;
+ styleBase = StyleClass.ButtonOpenRight;
// Generate buttons
PillTypeButtons[i] = new Button
@@ -117,16 +117,16 @@ namespace Content.Client.Chemistry.UI
var buttonConfigs = new (string text, ChemMasterReagentAmount amount, string styleClass)[]
{
- ("1", ChemMasterReagentAmount.U1, StyleBase.ButtonOpenBoth),
- ("5", ChemMasterReagentAmount.U5, StyleBase.ButtonOpenBoth),
- ("10", ChemMasterReagentAmount.U10, StyleBase.ButtonOpenBoth),
- ("15", ChemMasterReagentAmount.U15, StyleBase.ButtonOpenBoth),
- ("20", ChemMasterReagentAmount.U20, StyleBase.ButtonOpenBoth),
- ("25", ChemMasterReagentAmount.U25, StyleBase.ButtonOpenBoth),
- ("30", ChemMasterReagentAmount.U30, StyleBase.ButtonOpenBoth),
- ("50", ChemMasterReagentAmount.U50, StyleBase.ButtonOpenBoth),
- ("100", ChemMasterReagentAmount.U100, StyleBase.ButtonOpenBoth),
- (Loc.GetString("chem-master-window-buffer-all-amount"), ChemMasterReagentAmount.All, StyleBase.ButtonOpenLeft),
+ ("1", ChemMasterReagentAmount.U1, StyleClass.ButtonOpenBoth),
+ ("5", ChemMasterReagentAmount.U5, StyleClass.ButtonOpenBoth),
+ ("10", ChemMasterReagentAmount.U10, StyleClass.ButtonOpenBoth),
+ ("15", ChemMasterReagentAmount.U15, StyleClass.ButtonOpenBoth),
+ ("20", ChemMasterReagentAmount.U20, StyleClass.ButtonOpenBoth),
+ ("25", ChemMasterReagentAmount.U25, StyleClass.ButtonOpenBoth),
+ ("30", ChemMasterReagentAmount.U30, StyleClass.ButtonOpenBoth),
+ ("50", ChemMasterReagentAmount.U50, StyleClass.ButtonOpenBoth),
+ ("100", ChemMasterReagentAmount.U100, StyleClass.ButtonOpenBoth),
+ (Loc.GetString("chem-master-window-buffer-all-amount"), ChemMasterReagentAmount.All, StyleClass.ButtonOpenLeft),
};
var buttons = new List();
@@ -280,7 +280,7 @@ namespace Content.Client.Chemistry.UI
var bufferVol = new Label
{
Text = $"{state.BufferCurrentVolume}u",
- StyleClasses = { StyleNano.StyleClassLabelSecondaryColor }
+ StyleClasses = { StyleClass.LabelWeak }
};
bufferHBox.AddChild(bufferVol);
@@ -349,7 +349,7 @@ namespace Content.Client.Chemistry.UI
new Label
{
Text = $"{info.CurrentVolume}/{info.MaxVolume}",
- StyleClasses = { StyleNano.StyleClassLabelSecondaryColor }
+ StyleClasses = { StyleClass.LabelWeak }
}
}
});
@@ -404,7 +404,7 @@ namespace Content.Client.Chemistry.UI
new Label
{
Text = $"{quantity}u",
- StyleClasses = { StyleNano.StyleClassLabelSecondaryColor }
+ StyleClasses = { StyleClass.LabelWeak }
},
// Padding
diff --git a/Content.Client/Chemistry/UI/HyposprayStatusControl.cs b/Content.Client/Chemistry/UI/HyposprayStatusControl.cs
deleted file mode 100644
index 37b6fb5ed8..0000000000
--- a/Content.Client/Chemistry/UI/HyposprayStatusControl.cs
+++ /dev/null
@@ -1,58 +0,0 @@
-using Content.Client.Message;
-using Content.Client.Stylesheets;
-using Content.Shared.Chemistry.Components;
-using Content.Shared.Chemistry.EntitySystems;
-using Content.Shared.FixedPoint;
-using Robust.Client.UserInterface;
-using Robust.Client.UserInterface.Controls;
-using Robust.Shared.Timing;
-
-namespace Content.Client.Chemistry.UI;
-
-public sealed class HyposprayStatusControl : Control
-{
- private readonly Entity _parent;
- private readonly RichTextLabel _label;
- private readonly SharedSolutionContainerSystem _solutionContainers;
-
- private FixedPoint2 PrevVolume;
- private FixedPoint2 PrevMaxVolume;
- private bool PrevOnlyAffectsMobs;
-
- public HyposprayStatusControl(Entity parent, SharedSolutionContainerSystem solutionContainers)
- {
- _parent = parent;
- _solutionContainers = solutionContainers;
- _label = new RichTextLabel { StyleClasses = { StyleNano.StyleClassItemStatus } };
- AddChild(_label);
- }
-
- protected override void FrameUpdate(FrameEventArgs args)
- {
- base.FrameUpdate(args);
-
- if (!_solutionContainers.TryGetSolution(_parent.Owner, _parent.Comp.SolutionName, out _, out var solution))
- return;
-
- // only updates the UI if any of the details are different than they previously were
- if (PrevVolume == solution.Volume
- && PrevMaxVolume == solution.MaxVolume
- && PrevOnlyAffectsMobs == _parent.Comp.OnlyAffectsMobs)
- return;
-
- PrevVolume = solution.Volume;
- PrevMaxVolume = solution.MaxVolume;
- PrevOnlyAffectsMobs = _parent.Comp.OnlyAffectsMobs;
-
- var modeStringLocalized = Loc.GetString((_parent.Comp.OnlyAffectsMobs && _parent.Comp.CanContainerDraw) switch
- {
- false => "hypospray-all-mode-text",
- true => "hypospray-mobs-only-mode-text",
- });
-
- _label.SetMarkup(Loc.GetString("hypospray-volume-label",
- ("currentVolume", solution.Volume),
- ("totalVolume", solution.MaxVolume),
- ("modeString", modeStringLocalized)));
- }
-}
diff --git a/Content.Client/Chemistry/UI/InjectorStatusControl.cs b/Content.Client/Chemistry/UI/InjectorStatusControl.cs
index 0358876b76..0c57da7813 100644
--- a/Content.Client/Chemistry/UI/InjectorStatusControl.cs
+++ b/Content.Client/Chemistry/UI/InjectorStatusControl.cs
@@ -2,29 +2,35 @@ using Content.Client.Message;
using Content.Client.Stylesheets;
using Content.Shared.Chemistry.Components;
using Content.Shared.Chemistry.EntitySystems;
+using Content.Shared.Chemistry.Prototypes;
using Content.Shared.FixedPoint;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls;
+using Robust.Shared.Prototypes;
using Robust.Shared.Timing;
namespace Content.Client.Chemistry.UI;
public sealed class InjectorStatusControl : Control
{
+ private readonly IPrototypeManager _prototypeManager;
+
private readonly Entity _parent;
private readonly SharedSolutionContainerSystem _solutionContainers;
private readonly RichTextLabel _label;
- private FixedPoint2 PrevVolume;
- private FixedPoint2 PrevMaxVolume;
- private FixedPoint2 PrevTransferAmount;
- private InjectorToggleMode PrevToggleState;
+ private FixedPoint2 _prevVolume;
+ private FixedPoint2 _prevMaxVolume;
+ private FixedPoint2? _prevTransferAmount;
+ private InjectorBehavior _prevBehavior;
- public InjectorStatusControl(Entity parent, SharedSolutionContainerSystem solutionContainers)
+ public InjectorStatusControl(Entity parent, SharedSolutionContainerSystem solutionContainers, IPrototypeManager prototypeManager)
{
+ _prototypeManager = prototypeManager;
+
_parent = parent;
_solutionContainers = solutionContainers;
- _label = new RichTextLabel { StyleClasses = { StyleNano.StyleClassItemStatus } };
+ _label = new RichTextLabel { StyleClasses = { StyleClass.ItemStatus } };
AddChild(_label);
}
@@ -32,33 +38,38 @@ public sealed class InjectorStatusControl : Control
{
base.FrameUpdate(args);
- if (!_solutionContainers.TryGetSolution(_parent.Owner, _parent.Comp.SolutionName, out _, out var solution))
+ if (!_solutionContainers.TryGetSolution(_parent.Owner, _parent.Comp.SolutionName, out _, out var solution)
+ || !_prototypeManager.Resolve(_parent.Comp.ActiveModeProtoId, out var activeMode))
return;
// only updates the UI if any of the details are different than they previously were
- if (PrevVolume == solution.Volume
- && PrevMaxVolume == solution.MaxVolume
- && PrevTransferAmount == _parent.Comp.CurrentTransferAmount
- && PrevToggleState == _parent.Comp.ToggleState)
+ if (_prevVolume == solution.Volume
+ && _prevMaxVolume == solution.MaxVolume
+ && _prevTransferAmount == _parent.Comp.CurrentTransferAmount
+ && _prevBehavior == activeMode.Behavior)
return;
- PrevVolume = solution.Volume;
- PrevMaxVolume = solution.MaxVolume;
- PrevTransferAmount = _parent.Comp.CurrentTransferAmount;
- PrevToggleState = _parent.Comp.ToggleState;
+ _prevVolume = solution.Volume;
+ _prevMaxVolume = solution.MaxVolume;
+ _prevTransferAmount = _parent.Comp.CurrentTransferAmount;
+ _prevBehavior = activeMode.Behavior;
// Update current volume and injector state
- var modeStringLocalized = Loc.GetString(_parent.Comp.ToggleState switch
+ // Seeing transfer volume is only important for injectors that can change it.
+ if (activeMode.TransferAmounts.Count > 1 && _parent.Comp.CurrentTransferAmount.HasValue)
{
- InjectorToggleMode.Draw => "injector-draw-text",
- InjectorToggleMode.Inject => "injector-inject-text",
- _ => "injector-invalid-injector-toggle-mode"
- });
-
- _label.SetMarkup(Loc.GetString("injector-volume-label",
- ("currentVolume", solution.Volume),
- ("totalVolume", solution.MaxVolume),
- ("modeString", modeStringLocalized),
- ("transferVolume", _parent.Comp.CurrentTransferAmount)));
+ _label.SetMarkup(Loc.GetString("injector-volume-transfer-label",
+ ("currentVolume", solution.Volume),
+ ("totalVolume", solution.MaxVolume),
+ ("modeString", Loc.GetString(activeMode.Name)),
+ ("transferVolume", _parent.Comp.CurrentTransferAmount.Value)));
+ }
+ else
+ {
+ _label.SetMarkup(Loc.GetString("injector-volume-label",
+ ("currentVolume", solution.Volume),
+ ("totalVolume", solution.MaxVolume),
+ ("modeString", Loc.GetString(activeMode.Name))));
+ }
}
}
diff --git a/Content.Client/Chemistry/UI/ReagentDispenserWindow.xaml.cs b/Content.Client/Chemistry/UI/ReagentDispenserWindow.xaml.cs
index 2b64eed570..1b56a1b4ec 100644
--- a/Content.Client/Chemistry/UI/ReagentDispenserWindow.xaml.cs
+++ b/Content.Client/Chemistry/UI/ReagentDispenserWindow.xaml.cs
@@ -107,7 +107,7 @@ namespace Content.Client.Chemistry.UI
var quantityLabel = new Label
{
Text = Loc.GetString("reagent-dispenser-window-quantity-label-text", ("quantity", quantity)),
- StyleClasses = { StyleNano.StyleClassLabelSecondaryColor },
+ StyleClasses = { StyleClass.LabelWeak },
};
ContainerInfo.Children.Add(new BoxContainer
diff --git a/Content.Client/Chemistry/UI/SolutionStatusControl.cs b/Content.Client/Chemistry/UI/SolutionStatusControl.cs
index 1a33ffb0e1..8a551a262c 100644
--- a/Content.Client/Chemistry/UI/SolutionStatusControl.cs
+++ b/Content.Client/Chemistry/UI/SolutionStatusControl.cs
@@ -29,7 +29,7 @@ public sealed class SolutionStatusControl : PollingItemStatusControl
+/// Sets the a CVar to the name of a component, which allows the client to quickly open a VV window for that component
+/// by using the Alt+C or Alt+B hotkeys.
+///
+public sealed class QuickInspectCommand : LocalizedEntityCommands
+{
+ [Dependency] private readonly IConfigurationManager _configurationManager = default!;
+ [Dependency] private readonly IInputManager _inputManager = default!;
+
+ public override string Command => "quickinspect";
+
+ public override void Execute(IConsoleShell shell, string argStr, string[] args)
+ {
+ if (args.Length != 1)
+ {
+ shell.WriteLine(Loc.GetString("shell-wrong-arguments-number"));
+ return;
+ }
+
+ _configurationManager.SetCVar(CCVars.DebugQuickInspect, args[0]);
+
+ var serverKey = _inputManager.GetKeyFunctionButtonString(ContentKeyFunctions.InspectServerComponent);
+ var clientKey = _inputManager.GetKeyFunctionButtonString(ContentKeyFunctions.InspectClientComponent);
+ shell.WriteLine(Loc.GetString($"cmd-quickinspect-success", ("component", args[0]), ("serverKeybind", serverKey), ("clientKeybind", clientKey)));
+ }
+
+ public override CompletionResult GetCompletion(IConsoleShell shell, string[] args)
+ {
+ if (args.Length == 1)
+ {
+ // Not ideal since it only shows client-side components, but you can still type in any name you want.
+ // If you know how to get server component names on the client then please fix this.
+ var options = EntityManager.ComponentFactory.AllRegisteredTypes
+ .Select(p => new CompletionOption(
+ EntityManager.ComponentFactory.GetComponentName(p)
+ ));
+
+ return CompletionResult.FromOptions(options);
+ }
+
+ return CompletionResult.Empty;
+ }
+}
diff --git a/Content.Client/Commands/ShowWallmountsCommand.cs b/Content.Client/Commands/ShowWallmountsCommand.cs
new file mode 100644
index 0000000000..d44c13911b
--- /dev/null
+++ b/Content.Client/Commands/ShowWallmountsCommand.cs
@@ -0,0 +1,24 @@
+using Content.Client.Wall;
+using Robust.Client.Graphics;
+using Robust.Shared.Console;
+
+namespace Content.Client.Commands;
+
+///
+/// Shows the area in which entities with can be interacted from.
+///
+public sealed class ShowWallmountsCommand : LocalizedCommands
+{
+ [Dependency] private readonly IOverlayManager _overlay = default!;
+
+ public override string Command => "showwallmounts";
+
+ public override void Execute(IConsoleShell shell, string argStr, string[] args)
+ {
+ var existing = _overlay.RemoveOverlay();
+ if (!existing)
+ _overlay.AddOverlay(new WallmountDebugOverlay());
+
+ shell.WriteLine(Loc.GetString("cmd-showwallmounts-status", ("status", !existing)));
+ }
+}
diff --git a/Content.Client/Configurable/UI/ConfigurationMenu.cs b/Content.Client/Configurable/UI/ConfigurationMenu.cs
index 4ca68c5fa0..845c72f954 100644
--- a/Content.Client/Configurable/UI/ConfigurationMenu.cs
+++ b/Content.Client/Configurable/UI/ConfigurationMenu.cs
@@ -68,7 +68,7 @@ namespace Content.Client.Configurable.UI
outerColumn.AddChild(Column);
baseContainer.AddChild(outerColumn);
baseContainer.AddChild(confirmButton);
- Contents.AddChild(baseContainer);
+ ContentsContainer.AddChild(baseContainer);
}
private void OnConfirm(ButtonEventArgs args)
diff --git a/Content.Client/Content.Client.csproj b/Content.Client/Content.Client.csproj
index 9fed9e73e2..aaf1f7a0ca 100644
--- a/Content.Client/Content.Client.csproj
+++ b/Content.Client/Content.Client.csproj
@@ -1,26 +1,24 @@
-
- $(TargetFramework)
- 12
- false
false
..\bin\Content.Client\
Exe
RA0032;nullable
- enable
- Debug;Release;Tools;DebugOpt
- AnyCPU
+
+
+
+
+
+
+
+
+
-
-
-
-
diff --git a/Content.Client/ContextMenu/UI/ContextMenuElement.xaml b/Content.Client/ContextMenu/UI/ContextMenuElement.xaml
index d0e39865b8..271b6b1bff 100644
--- a/Content.Client/ContextMenu/UI/ContextMenuElement.xaml
+++ b/Content.Client/ContextMenu/UI/ContextMenuElement.xaml
@@ -13,7 +13,8 @@
Name="IconLabel"
HorizontalAlignment="Right"
VerticalAlignment="Bottom"
- StyleClasses="contextMenuIconLabel"
+ StyleClasses="LabelSubText"
+ Align="Right"
Visible="false"/>
(_crayon.Owner).MaxCharges;
- _label = new RichTextLabel { StyleClasses = { StyleNano.StyleClassItemStatus } };
+ _label = new RichTextLabel { StyleClasses = { StyleClass.ItemStatus } };
AddChild(_label);
}
diff --git a/Content.Client/Crayon/UI/CrayonWindow.xaml.cs b/Content.Client/Crayon/UI/CrayonWindow.xaml.cs
index f1ac5a79cb..166ba01832 100644
--- a/Content.Client/Crayon/UI/CrayonWindow.xaml.cs
+++ b/Content.Client/Crayon/UI/CrayonWindow.xaml.cs
@@ -137,7 +137,8 @@ namespace Content.Client.Crayon.UI
private void ButtonOnPressed(ButtonEventArgs obj)
{
- if (obj.Button.Name == null) return;
+ if (obj.Button.Name == null)
+ return;
_selected = obj.Button.Name;
_autoSelected = null;
diff --git a/Content.Client/Credits/CreditsWindow.xaml.cs b/Content.Client/Credits/CreditsWindow.xaml.cs
index 6035bcc2bd..c068eb5a8c 100644
--- a/Content.Client/Credits/CreditsWindow.xaml.cs
+++ b/Content.Client/Credits/CreditsWindow.xaml.cs
@@ -258,7 +258,7 @@ public sealed partial class CreditsWindow : DefaultWindow
foreach (var entry in CreditsManager.GetLicenses(_resourceManager).OrderBy(p => p.Name))
{
licensesContainer.AddChild(new Label
- { StyleClasses = { StyleBase.StyleClassLabelHeading }, Text = entry.Name });
+ { StyleClasses = { StyleClass.LabelHeading }, Text = entry.Name });
// We split these line by line because otherwise
// the LGPL causes Clyde to go out of bounds in the rendering code.
@@ -299,7 +299,7 @@ public sealed partial class CreditsWindow : DefaultWindow
first = false;
patronsContainer.AddChild(new Label
- { StyleClasses = { StyleBase.StyleClassLabelHeading }, Text = $"{tier.Key}" });
+ { StyleClasses = { StyleClass.LabelHeading }, Text = $"{tier.Key}" });
var msg = string.Join(", ", tier.OrderBy(p => p.Name).Select(p => p.Name));
@@ -347,7 +347,7 @@ public sealed partial class CreditsWindow : DefaultWindow
first = false;
ss14ContributorsContainer.AddChild(new Label
- { StyleClasses = { StyleBase.StyleClassLabelHeading }, Text = title });
+ { StyleClasses = { StyleClass.LabelHeading }, Text = title });
var label = new RichTextLabel();
var text = _resourceManager.ContentFileReadAllText($"/Credits/{path}");
diff --git a/Content.Client/CriminalRecords/CriminalRecordsConsoleWindow.xaml.cs b/Content.Client/CriminalRecords/CriminalRecordsConsoleWindow.xaml.cs
index 33b4fbc335..dcae68fa7e 100644
--- a/Content.Client/CriminalRecords/CriminalRecordsConsoleWindow.xaml.cs
+++ b/Content.Client/CriminalRecords/CriminalRecordsConsoleWindow.xaml.cs
@@ -276,7 +276,7 @@ public sealed partial class CriminalRecordsConsoleWindow : FancyWindow
private void SetStatus(SecurityStatus status)
{
- if (status == SecurityStatus.Wanted || status == SecurityStatus.Suspected)
+ if (status == SecurityStatus.Wanted || status == SecurityStatus.Suspected || status == SecurityStatus.Hostile)
{
GetReason(status);
return;
@@ -322,6 +322,8 @@ public sealed partial class CriminalRecordsConsoleWindow : FancyWindow
SecurityStatus.Detained => "hud_incarcerated",
SecurityStatus.Discharged => "hud_discharged",
SecurityStatus.Suspected => "hud_suspected",
+ SecurityStatus.Hostile => "hud_hostile",
+ SecurityStatus.Eliminated => "hud_eliminated",
_ => "SecurityIconNone"
};
}
diff --git a/Content.Client/Damage/DamageVisualsSystem.cs b/Content.Client/Damage/DamageVisualsSystem.cs
index 065bf628bc..ac3ff819aa 100644
--- a/Content.Client/Damage/DamageVisualsSystem.cs
+++ b/Content.Client/Damage/DamageVisualsSystem.cs
@@ -1,5 +1,6 @@
using System.Linq;
using Content.Shared.Damage;
+using Content.Shared.Damage.Components;
using Content.Shared.Damage.Prototypes;
using Content.Shared.FixedPoint;
using Robust.Client.GameObjects;
diff --git a/Content.Client/Decals/UI/DecalPlacerWindow.xaml.cs b/Content.Client/Decals/UI/DecalPlacerWindow.xaml.cs
index adeb451a07..873fb851b7 100644
--- a/Content.Client/Decals/UI/DecalPlacerWindow.xaml.cs
+++ b/Content.Client/Decals/UI/DecalPlacerWindow.xaml.cs
@@ -157,15 +157,12 @@ public sealed partial class DecalPlacerWindow : DefaultWindow
{
var panelContainer = new PanelContainer
{
- PanelOverride = new StyleBoxFlat
- {
- BackgroundColor = StyleNano.ButtonColorDefault
- },
Children =
{
button
}
};
+ panelContainer.SetOnlyStyleClass(StyleClass.PanelLight);
Grid.AddChild(panelContainer);
}
else
diff --git a/Content.Client/DeviceLinking/Systems/RandomGateSystem.cs b/Content.Client/DeviceLinking/Systems/RandomGateSystem.cs
new file mode 100644
index 0000000000..db0d956c72
--- /dev/null
+++ b/Content.Client/DeviceLinking/Systems/RandomGateSystem.cs
@@ -0,0 +1,5 @@
+using Content.Shared.DeviceLinking.Systems;
+
+namespace Content.Client.DeviceLinking.Systems;
+
+public sealed class RandomGateSystem : SharedRandomGateSystem;
diff --git a/Content.Client/DeviceLinking/UI/RandomGateBoundUserInterface.cs b/Content.Client/DeviceLinking/UI/RandomGateBoundUserInterface.cs
new file mode 100644
index 0000000000..c8c97b84c6
--- /dev/null
+++ b/Content.Client/DeviceLinking/UI/RandomGateBoundUserInterface.cs
@@ -0,0 +1,37 @@
+using Content.Shared.DeviceLinking;
+using JetBrains.Annotations;
+using Robust.Client.UserInterface;
+
+namespace Content.Client.DeviceLinking.UI;
+
+[UsedImplicitly]
+public sealed class RandomGateBoundUserInterface : BoundUserInterface
+{
+ private RandomGateSetupWindow? _window;
+
+ public RandomGateBoundUserInterface(EntityUid owner, Enum uiKey) : base(owner, uiKey) { }
+
+ protected override void Open()
+ {
+ base.Open();
+ _window = this.CreateWindow();
+ _window.OnApplyPressed += OnProbabilityChanged;
+ }
+
+ private void OnProbabilityChanged(string value)
+ {
+ if (!float.TryParse(value, out var probability))
+ return;
+
+ SendPredictedMessage(new RandomGateProbabilityChangedMessage(probability));
+ }
+
+ protected override void UpdateState(BoundUserInterfaceState state)
+ {
+ base.UpdateState(state);
+ if (state is not RandomGateBoundUserInterfaceState castState || _window == null)
+ return;
+
+ _window.SetProbability(castState.SuccessProbability * 100);
+ }
+}
diff --git a/Content.Client/DeviceLinking/UI/RandomGateSetupWindow.xaml b/Content.Client/DeviceLinking/UI/RandomGateSetupWindow.xaml
new file mode 100644
index 0000000000..d9273c9110
--- /dev/null
+++ b/Content.Client/DeviceLinking/UI/RandomGateSetupWindow.xaml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Content.Client/DeviceLinking/UI/RandomGateSetupWindow.xaml.cs b/Content.Client/DeviceLinking/UI/RandomGateSetupWindow.xaml.cs
new file mode 100644
index 0000000000..64e0690072
--- /dev/null
+++ b/Content.Client/DeviceLinking/UI/RandomGateSetupWindow.xaml.cs
@@ -0,0 +1,28 @@
+using Content.Client.UserInterface.Controls;
+using Robust.Client.AutoGenerated;
+using Robust.Client.UserInterface.XAML;
+
+namespace Content.Client.DeviceLinking.UI;
+
+///
+/// Window for setting up the random gate probability.
+///
+[GenerateTypedNameReferences]
+public sealed partial class RandomGateSetupWindow : FancyWindow
+{
+ ///
+ /// Event triggered when the "Apply" button is pressed.
+ ///
+ public event Action? OnApplyPressed;
+
+ public RandomGateSetupWindow()
+ {
+ RobustXamlLoader.Load(this);
+ ApplyButton.OnPressed += _ => OnApplyPressed?.Invoke(ProbabilityInput.Text);
+ }
+
+ public void SetProbability(float probability)
+ {
+ ProbabilityInput.Text = probability.ToString("0.00");
+ }
+}
diff --git a/Content.Client/Disposal/Mailing/MailingUnitWindow.xaml b/Content.Client/Disposal/Mailing/MailingUnitWindow.xaml
index 0acd300895..ab910d2db4 100644
--- a/Content.Client/Disposal/Mailing/MailingUnitWindow.xaml
+++ b/Content.Client/Disposal/Mailing/MailingUnitWindow.xaml
@@ -47,7 +47,7 @@
Access="Public"
Text="{Loc 'ui-disposal-unit-button-eject'}"
StyleClasses="OpenBoth" />
-
diff --git a/Content.Client/Disposal/Unit/DisposalUnitWindow.xaml b/Content.Client/Disposal/Unit/DisposalUnitWindow.xaml
index 60ca7ba0db..312f80c176 100644
--- a/Content.Client/Disposal/Unit/DisposalUnitWindow.xaml
+++ b/Content.Client/Disposal/Unit/DisposalUnitWindow.xaml
@@ -34,7 +34,7 @@
Access="Public"
Text="{Loc 'ui-disposal-unit-button-eject'}"
StyleClasses="OpenBoth" />
-
diff --git a/Content.Client/Drunk/DrunkOverlay.cs b/Content.Client/Drunk/DrunkOverlay.cs
index c806cdad66..692232776a 100644
--- a/Content.Client/Drunk/DrunkOverlay.cs
+++ b/Content.Client/Drunk/DrunkOverlay.cs
@@ -27,6 +27,15 @@ public sealed class DrunkOverlay : Overlay
private const float VisualThreshold = 10.0f;
private const float PowerDivisor = 250.0f;
+ ///
+ /// This is a magic number based on my person preference of how quickly the bloodloss effect should kick in.
+ /// It is entirely arbitrary, and you should change it if it sucks.
+ /// Honestly should be refactored to be based on amount of blood lost but that's out of scope for what I'm doing atm.
+ /// Also caps all booze visual effects to a max intensity of 100 seconds or 100 booze power.
+ ///
+ private const float MaxBoozePower = 100f;
+
+ private const float BoozePowerScale = 8f;
private float _visualScale = 0;
@@ -50,15 +59,9 @@ public sealed class DrunkOverlay : Overlay
var time = status.Item2;
- var power = SharedDrunkSystem.MagicNumber;
+ var power = time == null ? MaxBoozePower : (float) Math.Min((time - _timing.CurTime).Value.TotalSeconds, MaxBoozePower);
- if (time != null)
- {
- var curTime = _timing.CurTime;
- power = (float) (time - curTime).Value.TotalSeconds;
- }
-
- CurrentBoozePower += 8f * (power * 0.5f - CurrentBoozePower) * args.DeltaSeconds / (power+1);
+ CurrentBoozePower += BoozePowerScale * (power - CurrentBoozePower) * args.DeltaSeconds / (power+1);
}
protected override bool BeforeDraw(in OverlayDrawArgs args)
diff --git a/Content.Client/Entry/EntryPoint.cs b/Content.Client/Entry/EntryPoint.cs
index 15928fd282..71f6ea2fe7 100644
--- a/Content.Client/Entry/EntryPoint.cs
+++ b/Content.Client/Entry/EntryPoint.cs
@@ -110,7 +110,6 @@ namespace Content.Client.Entry
_componentFactory.IgnoreMissingComponents();
// Do not add to these, they are legacy.
- _componentFactory.RegisterClass();
_componentFactory.RegisterClass();
// Do not add to the above, they are legacy
@@ -125,8 +124,6 @@ namespace Content.Client.Entry
_prototypeManager.RegisterIgnore("htnPrimitive");
_prototypeManager.RegisterIgnore("gameMap");
_prototypeManager.RegisterIgnore("gameMapPool");
- // Sunrise-Edit
- // _prototypeManager.RegisterIgnore("lobbyBackground");
_prototypeManager.RegisterIgnore("gamePreset");
_prototypeManager.RegisterIgnore("noiseChannel");
_prototypeManager.RegisterIgnore("playerConnectionWhitelist");
diff --git a/Content.Client/Fax/UI/FaxWindow.xaml b/Content.Client/Fax/UI/FaxWindow.xaml
index d78686ff70..01bdaa99c7 100644
--- a/Content.Client/Fax/UI/FaxWindow.xaml
+++ b/Content.Client/Fax/UI/FaxWindow.xaml
@@ -56,7 +56,7 @@
HorizontalAlignment="Center"
VerticalAlignment="Center"
Scale="0.9 0.9"
- StyleClasses="Refresh" />
+ StyleClasses="RefreshButton" />
diff --git a/Content.Client/Fluids/PuddleSystem.cs b/Content.Client/Fluids/PuddleSystem.cs
index 1ab1ded3e8..ab96d24d85 100644
--- a/Content.Client/Fluids/PuddleSystem.cs
+++ b/Content.Client/Fluids/PuddleSystem.cs
@@ -73,7 +73,19 @@ public sealed class PuddleSystem : SharedPuddleSystem
// Maybe someday we'll have clientside prediction for entity spawning, but not today.
// Until then, these methods do nothing on the client.
///
- public override bool TrySplashSpillAt(EntityUid uid, EntityCoordinates coordinates, Solution solution, out EntityUid puddleUid, bool sound = true, EntityUid? user = null)
+ public override bool TrySplashSpillAt(Entity entity, EntityCoordinates coordinates, out EntityUid puddleUid, out Solution solution, bool sound = true, EntityUid? user = null)
+ {
+ puddleUid = EntityUid.Invalid;
+ solution = new Solution();
+ return false;
+ }
+
+ public override bool TrySplashSpillAt(EntityUid entity,
+ EntityCoordinates coordinates,
+ Solution spilled,
+ out EntityUid puddleUid,
+ bool sound = true,
+ EntityUid? user = null)
{
puddleUid = EntityUid.Invalid;
return false;
diff --git a/Content.Client/Fluids/SpraySystem.cs b/Content.Client/Fluids/SpraySystem.cs
new file mode 100644
index 0000000000..877a2a0592
--- /dev/null
+++ b/Content.Client/Fluids/SpraySystem.cs
@@ -0,0 +1,7 @@
+using Content.Shared.Fluids.Components;
+using Content.Shared.Fluids.EntitySystems;
+using Robust.Shared.Map;
+
+namespace Content.Client.Fluids;
+
+public sealed class SpraySystem : SharedSpraySystem;
diff --git a/Content.Client/GPS/UI/HandheldGpsStatusControl.cs b/Content.Client/GPS/UI/HandheldGpsStatusControl.cs
index 57645e386e..2feca1f176 100644
--- a/Content.Client/GPS/UI/HandheldGpsStatusControl.cs
+++ b/Content.Client/GPS/UI/HandheldGpsStatusControl.cs
@@ -21,7 +21,7 @@ public sealed class HandheldGpsStatusControl : Control
_parent = parent;
_entMan = IoCManager.Resolve();
_transform = _entMan.System();
- _label = new RichTextLabel { StyleClasses = { StyleNano.StyleClassItemStatus } };
+ _label = new RichTextLabel { StyleClasses = { StyleClass.ItemStatus } };
AddChild(_label);
UpdateGpsDetails();
}
diff --git a/Content.Client/GameTicking/Managers/ClientGameTicker.cs b/Content.Client/GameTicking/Managers/ClientGameTicker.cs
index 0d523327d1..b5d265ad33 100644
--- a/Content.Client/GameTicking/Managers/ClientGameTicker.cs
+++ b/Content.Client/GameTicking/Managers/ClientGameTicker.cs
@@ -11,6 +11,7 @@ using Robust.Client.State;
using Robust.Client.UserInterface;
using Robust.Shared.Prototypes;
using Robust.Shared.Audio;
+using Content.Shared.GameTicking.Prototypes;
namespace Content.Client.GameTicking.Managers
{
@@ -31,7 +32,7 @@ namespace Content.Client.GameTicking.Managers
// Sunrise-Start
[ViewVariables] public string? LobbyType { get; private set; }
[ViewVariables] public string? LobbyParallax { get; private set; }
- [ViewVariables] public string? LobbyAnimation { get; private set; }
+ [ViewVariables] public ProtoId? LobbyAnimation { get; private set; }
[ViewVariables] public string? LobbyArt { get; private set; }
// Sunrise-End
[ViewVariables] public bool DisallowedLateJoin { get; private set; }
diff --git a/Content.Client/Gameplay/GameplayStateBase.cs b/Content.Client/Gameplay/GameplayStateBase.cs
index 69e6e0b58b..c2b10fd01a 100644
--- a/Content.Client/Gameplay/GameplayStateBase.cs
+++ b/Content.Client/Gameplay/GameplayStateBase.cs
@@ -3,6 +3,7 @@ using System.Numerics;
using Content.Client.Clickable;
using Content.Client.UserInterface;
using Content.Client.Viewport;
+using Content.Shared.CCVar;
using Content.Shared.Input;
using Robust.Client.ComponentTrees;
using Robust.Client.GameObjects;
@@ -13,6 +14,7 @@ using Robust.Client.State;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.CustomControls;
+using Robust.Shared.Configuration;
using Robust.Shared.Console;
using Robust.Shared.Graphics;
using Robust.Shared.Input;
@@ -40,6 +42,7 @@ namespace Content.Client.Gameplay
[Dependency] private readonly IEntityManager _entityManager = default!;
[Dependency] private readonly IViewVariablesManager _vvm = default!;
[Dependency] private readonly IConsoleHost _conHost = default!;
+ [Dependency] private readonly IConfigurationManager _configurationManager = default!;
private ClickableEntityComparer _comparer = default!;
@@ -83,6 +86,8 @@ namespace Content.Client.Gameplay
_comparer = new ClickableEntityComparer();
CommandBinds.Builder
.Bind(ContentKeyFunctions.InspectEntity, new PointerInputCmdHandler(HandleInspect, outsidePrediction: true))
+ .Bind(ContentKeyFunctions.InspectServerComponent, new PointerInputCmdHandler(HandleInspectServerComponent, outsidePrediction: true))
+ .Bind(ContentKeyFunctions.InspectClientComponent, new PointerInputCmdHandler(HandleInspectClientComponent, outsidePrediction: true))
.Register();
}
@@ -99,6 +104,21 @@ namespace Content.Client.Gameplay
return true;
}
+ private bool HandleInspectServerComponent(ICommonSession? session, EntityCoordinates coords, EntityUid uid)
+ {
+ var component = _configurationManager.GetCVar(CCVars.DebugQuickInspect);
+ if (_entityManager.TryGetNetEntity(uid, out var net))
+ _conHost.ExecuteCommand($"vv /entity/{net.Value.Id}/{component}");
+ return true;
+ }
+
+ private bool HandleInspectClientComponent(ICommonSession? session, EntityCoordinates coords, EntityUid uid)
+ {
+ var component = _configurationManager.GetCVar(CCVars.DebugQuickInspect);
+ _conHost.ExecuteCommand($"vv /c/entity/{uid}/{component}");
+ return true;
+ }
+
public EntityUid? GetClickedEntity(MapCoordinates coordinates)
{
return GetClickedEntity(coordinates, _eyeManager.CurrentEye);
diff --git a/Content.Client/Gateway/UI/GatewayWindow.xaml.cs b/Content.Client/Gateway/UI/GatewayWindow.xaml.cs
index 9fb7c339d3..4e4076d98c 100644
--- a/Content.Client/Gateway/UI/GatewayWindow.xaml.cs
+++ b/Content.Client/Gateway/UI/GatewayWindow.xaml.cs
@@ -159,7 +159,7 @@ public sealed partial class GatewayWindow : FancyWindow,
if (Pressable())
{
- openButton.AddStyleClass(StyleBase.ButtonCaution);
+ openButton.AddStyleClass(StyleClass.Negative);
}
var buttonContainer = new BoxContainer()
diff --git a/Content.Client/Ghost/UI/ReturnToBodyMenu.cs b/Content.Client/Ghost/UI/ReturnToBodyMenu.cs
index 69f04993c9..384ffb6be6 100644
--- a/Content.Client/Ghost/UI/ReturnToBodyMenu.cs
+++ b/Content.Client/Ghost/UI/ReturnToBodyMenu.cs
@@ -15,7 +15,7 @@ public sealed class ReturnToBodyMenu : DefaultWindow
{
Title = Loc.GetString("ghost-return-to-body-title");
- Contents.AddChild(new BoxContainer
+ ContentsContainer.AddChild(new BoxContainer
{
Orientation = LayoutOrientation.Vertical,
Children =
diff --git a/Content.Client/Gravity/GravityGeneratorSystem.cs b/Content.Client/Gravity/GravityGeneratorSystem.cs
new file mode 100644
index 0000000000..b74ea35daa
--- /dev/null
+++ b/Content.Client/Gravity/GravityGeneratorSystem.cs
@@ -0,0 +1,8 @@
+using Content.Shared.Gravity;
+
+namespace Content.Client.Gravity;
+
+public sealed class GravityGeneratorSystem : SharedGravityGeneratorSystem
+{
+
+}
diff --git a/Content.Client/Gravity/GravitySystem.cs b/Content.Client/Gravity/GravitySystem.cs
index 60e043cc99..f1e09fdb44 100644
--- a/Content.Client/Gravity/GravitySystem.cs
+++ b/Content.Client/Gravity/GravitySystem.cs
@@ -12,14 +12,14 @@ public sealed partial class GravitySystem : SharedGravitySystem
public override void Initialize()
{
base.Initialize();
- SubscribeLocalEvent(OnAppearanceChange);
+ SubscribeLocalEvent(OnAppearanceChange);
InitializeShake();
}
///
/// Ensures that the visible state of gravity generators are synced with their sprites.
///
- private void OnAppearanceChange(EntityUid uid, SharedGravityGeneratorComponent comp, ref AppearanceChangeEvent args)
+ private void OnAppearanceChange(EntityUid uid, GravityGeneratorComponent comp, ref AppearanceChangeEvent args)
{
if (args.Sprite == null)
return;
diff --git a/Content.Client/HealthAnalyzer/UI/HealthAnalyzerWindow.xaml.cs b/Content.Client/HealthAnalyzer/UI/HealthAnalyzerWindow.xaml.cs
index 64432d7627..5280f66499 100644
--- a/Content.Client/HealthAnalyzer/UI/HealthAnalyzerWindow.xaml.cs
+++ b/Content.Client/HealthAnalyzer/UI/HealthAnalyzerWindow.xaml.cs
@@ -1,28 +1,22 @@
using System.Linq;
using System.Numerics;
-using Content.Client.Message;
using Content.Shared.Atmos;
using Content.Client.UserInterface.Controls;
-using Content.Shared.Alert;
-using Content.Shared.Damage;
+using Content.Shared.Damage.Components;
using Content.Shared.Damage.Prototypes;
using Content.Shared.FixedPoint;
using Content.Shared.Humanoid;
using Content.Shared.Humanoid.Prototypes;
using Content.Shared.IdentityManagement;
-using Content.Shared.Inventory;
using Content.Shared.MedicalScanner;
using Content.Shared.Mobs;
using Content.Shared.Mobs.Components;
-using Content.Shared.Mobs.Systems;
-using Content.Shared.Nutrition.Components;
using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface.XAML;
using Robust.Client.GameObjects;
using Robust.Client.Graphics;
using Robust.Client.UserInterface.Controls;
using Robust.Client.ResourceManagement;
-using Robust.Client.UserInterface;
using Robust.Shared.Prototypes;
using Robust.Shared.Utility;
diff --git a/Content.Client/Implants/UI/ChameleonControllerMenu.xaml.cs b/Content.Client/Implants/UI/ChameleonControllerMenu.xaml.cs
index c12ddb9319..6f66990b4e 100644
--- a/Content.Client/Implants/UI/ChameleonControllerMenu.xaml.cs
+++ b/Content.Client/Implants/UI/ChameleonControllerMenu.xaml.cs
@@ -116,7 +116,7 @@ public sealed partial class ChameleonControllerMenu : FancyWindow
var button = new Button
{
HorizontalExpand = true,
- StyleClasses = {StyleBase.ButtonSquare},
+ StyleClasses = {StyleClass.ButtonSquare},
ToolTip = Loc.GetString(name),
Text = Loc.GetString(name),
Margin = new Thickness(0, 0, 15, 0),
diff --git a/Content.Client/Implants/UI/ImplanterStatusControl.cs b/Content.Client/Implants/UI/ImplanterStatusControl.cs
index 24445eeecf..43579ae6be 100644
--- a/Content.Client/Implants/UI/ImplanterStatusControl.cs
+++ b/Content.Client/Implants/UI/ImplanterStatusControl.cs
@@ -19,7 +19,7 @@ public sealed class ImplanterStatusControl : Control
{
IoCManager.InjectDependencies(this);
_parent = parent;
- _label = new RichTextLabel { StyleClasses = { StyleNano.StyleClassItemStatus } };
+ _label = new RichTextLabel { StyleClasses = { StyleClass.ItemStatus } };
_label.MaxWidth = 350;
AddChild(new ClipControl { Children = { _label } });
diff --git a/Content.Client/Info/RulesAndInfoWindow.cs b/Content.Client/Info/RulesAndInfoWindow.cs
index b9131dcb3c..4f483cf26c 100644
--- a/Content.Client/Info/RulesAndInfoWindow.cs
+++ b/Content.Client/Info/RulesAndInfoWindow.cs
@@ -36,7 +36,7 @@ namespace Content.Client.Info
PopulateTutorial(tutorialList);
- Contents.AddChild(rootContainer);
+ ContentsContainer.AddChild(rootContainer);
SetSize = new Vector2(650, 650);
}
diff --git a/Content.Client/Info/RulesPopup.xaml b/Content.Client/Info/RulesPopup.xaml
index 80ed415550..c94f061865 100644
--- a/Content.Client/Info/RulesPopup.xaml
+++ b/Content.Client/Info/RulesPopup.xaml
@@ -16,7 +16,7 @@
Text="{Loc 'ui-rules-accept'}"
Disabled="True" />
diff --git a/Content.Client/Input/ContentContexts.cs b/Content.Client/Input/ContentContexts.cs
index e71302c7c5..9ef651c959 100644
--- a/Content.Client/Input/ContentContexts.cs
+++ b/Content.Client/Input/ContentContexts.cs
@@ -39,6 +39,8 @@ namespace Content.Client.Input
common.AddFunction(ContentKeyFunctions.ZoomIn);
common.AddFunction(ContentKeyFunctions.ResetZoom);
common.AddFunction(ContentKeyFunctions.InspectEntity);
+ common.AddFunction(ContentKeyFunctions.InspectServerComponent);
+ common.AddFunction(ContentKeyFunctions.InspectClientComponent);
common.AddFunction(ContentKeyFunctions.ToggleRoundEndSummaryWindow);
// Not in engine, because engine cannot check for sanbox/admin status before starting placement.
diff --git a/Content.Client/Instruments/UI/ChannelsMenu.xaml b/Content.Client/Instruments/UI/ChannelsMenu.xaml
index 20e4a3e923..e98b03e6b3 100644
--- a/Content.Client/Instruments/UI/ChannelsMenu.xaml
+++ b/Content.Client/Instruments/UI/ChannelsMenu.xaml
@@ -7,7 +7,7 @@
-
diff --git a/Content.Client/Inventory/StrippableBoundUserInterface.cs b/Content.Client/Inventory/StrippableBoundUserInterface.cs
index 381406d2ac..f9a6cd46d6 100644
--- a/Content.Client/Inventory/StrippableBoundUserInterface.cs
+++ b/Content.Client/Inventory/StrippableBoundUserInterface.cs
@@ -154,7 +154,7 @@ namespace Content.Client.Inventory
var button = new Button()
{
Text = Loc.GetString("strippable-bound-user-interface-stripping-menu-ensnare-button"),
- StyleClasses = { StyleBase.ButtonOpenRight }
+ StyleClasses = { StyleClass.ButtonOpenRight }
};
button.OnPressed += (_) => SendPredictedMessage(new StrippingEnsnareButtonPressed());
@@ -190,7 +190,7 @@ namespace Content.Client.Inventory
if (EntMan.TryGetComponent(heldEntity, out var virt))
{
button.Blocked = true;
- if (EntMan.TryGetComponent(Owner, out var cuff) && _cuffable.GetAllCuffs(cuff).Contains(virt.BlockingEntity))
+ if (_cuffable.TryGetAllCuffs(Owner, out var cuffs) && cuffs.Contains(virt.BlockingEntity))
button.BlockedRect.MouseFilter = MouseFilterMode.Ignore;
}
diff --git a/Content.Client/Kitchen/UI/MicrowaveMenu.xaml b/Content.Client/Kitchen/UI/MicrowaveMenu.xaml
index c99462d9e7..7f8cb9a17b 100644
--- a/Content.Client/Kitchen/UI/MicrowaveMenu.xaml
+++ b/Content.Client/Kitchen/UI/MicrowaveMenu.xaml
@@ -2,7 +2,6 @@
xmlns="https://spacestation14.io"
xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls"
xmlns:gfx="clr-namespace:Robust.Client.Graphics;assembly=Robust.Client"
- xmlns:style="clr-namespace:Content.Client.Stylesheets"
Title="{Loc 'microwave-menu-title'}"
MinWidth="512"
MinSize="512 256">
@@ -78,14 +77,14 @@
Name="StartButton"
Access="Public"
Text="{Loc 'microwave-menu-start-button'}"
- StyleClasses="ButtonColorGreen"
+ StyleClasses="positive"
TextAlign="Center" />
diff --git a/Content.Client/Labels/UI/HandLabelerBoundUserInterface.cs b/Content.Client/Labels/UI/HandLabelerBoundUserInterface.cs
index b9b58f2322..95d5cc7ab3 100644
--- a/Content.Client/Labels/UI/HandLabelerBoundUserInterface.cs
+++ b/Content.Client/Labels/UI/HandLabelerBoundUserInterface.cs
@@ -33,6 +33,7 @@ namespace Content.Client.Labels.UI
_window.OnLabelChanged += OnLabelChanged;
Reload();
+ _window.SetInitialLabelState(); // Must be after Reload() has set the label text
}
private void OnLabelChanged(string newLabel)
diff --git a/Content.Client/Labels/UI/HandLabelerWindow.xaml b/Content.Client/Labels/UI/HandLabelerWindow.xaml
index 0bf03410c1..7bbadb843d 100644
--- a/Content.Client/Labels/UI/HandLabelerWindow.xaml
+++ b/Content.Client/Labels/UI/HandLabelerWindow.xaml
@@ -1,8 +1,14 @@
-
+ Title="{Loc 'hand-labeler-ui-header'}"
+ SetWidth="400"
+ MinWidth="150">
+
+
+
+
+
diff --git a/Content.Client/Labels/UI/HandLabelerWindow.xaml.cs b/Content.Client/Labels/UI/HandLabelerWindow.xaml.cs
index 528e227f55..32c9d980a4 100644
--- a/Content.Client/Labels/UI/HandLabelerWindow.xaml.cs
+++ b/Content.Client/Labels/UI/HandLabelerWindow.xaml.cs
@@ -16,6 +16,7 @@ namespace Content.Client.Labels.UI
// TODO LineEdit Make this a bool on the LineEdit control
private string _label = string.Empty;
+ private string _initialLabel = string.Empty;
public HandLabelerWindow()
{
@@ -25,6 +26,7 @@ namespace Content.Client.Labels.UI
{
_label = e.Text;
OnLabelChanged?.Invoke(_label);
+ UpdateButtons();
};
LabelLineEdit.OnFocusEnter += _ => _focused = true;
@@ -33,12 +35,14 @@ namespace Content.Client.Labels.UI
_focused = false;
LabelLineEdit.Text = _label;
};
+ ResetLabelButton.OnPressed += _ => LabelLineEdit.SetText(_initialLabel, true);
+ ClearLabelButton.OnPressed += _ => LabelLineEdit.SetText("", true);
}
protected override void Opened()
{
base.Opened();
-
+
// Give the editor keyboard focus, since that's the only
// thing the user will want to be doing with this UI
LabelLineEdit.GrabKeyboardFocus();
@@ -51,7 +55,25 @@ namespace Content.Client.Labels.UI
_label = label;
if (!_focused)
+ {
LabelLineEdit.Text = label;
+ UpdateButtons();
+ }
+ }
+
+ public void SetInitialLabelState()
+ {
+ LabelLineEdit.Text = _label;
+ LabelLineEdit.CursorPosition = _label.Length;
+ LabelLineEdit.SelectionStart = 0;
+ _initialLabel = _label;
+ UpdateButtons();
+ }
+
+ public void UpdateButtons()
+ {
+ ResetLabelButton.Disabled = (LabelLineEdit.Text == _initialLabel);
+ ClearLabelButton.Disabled = (LabelLineEdit.Text == "");
}
public void SetMaxLabelLength(int maxLength)
diff --git a/Content.Client/LateJoin/LateJoinGui.cs b/Content.Client/LateJoin/LateJoinGui.cs
index 31c30eb8cb..5d39407ccf 100644
--- a/Content.Client/LateJoin/LateJoinGui.cs
+++ b/Content.Client/LateJoin/LateJoinGui.cs
@@ -61,7 +61,7 @@ namespace Content.Client.LateJoin
VerticalExpand = true,
};
- Contents.AddChild(_base);
+ ContentsContainer.AddChild(_base);
_jobRequirements.Updated += RebuildUI;
RebuildUI();
diff --git a/Content.Client/Launcher/LauncherConnectingGui.xaml.cs b/Content.Client/Launcher/LauncherConnectingGui.xaml.cs
index bd2bc6eaf8..afc34edff8 100644
--- a/Content.Client/Launcher/LauncherConnectingGui.xaml.cs
+++ b/Content.Client/Launcher/LauncherConnectingGui.xaml.cs
@@ -55,7 +55,7 @@ namespace Content.Client.Launcher
LayoutContainer.SetAnchorPreset(this, LayoutContainer.LayoutPreset.Wide);
- Stylesheet = IoCManager.Resolve().SheetSpace;
+ Stylesheet = IoCManager.Resolve().SheetSystem;
ChangeLoginTip();
RetryButton.OnPressed += ReconnectButtonPressed;
diff --git a/Content.Client/Lobby/LobbyState.cs b/Content.Client/Lobby/LobbyState.cs
index c29e89a1cf..c8e9574729 100644
--- a/Content.Client/Lobby/LobbyState.cs
+++ b/Content.Client/Lobby/LobbyState.cs
@@ -17,6 +17,7 @@ using Robust.Client.ResourceManagement;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls;
using Robust.Shared.Configuration;
+using Robust.Shared.Prototypes;
using Robust.Shared.Timing;
using Robust.Shared.Utility;
using Content.Client.Changelog;
@@ -46,6 +47,7 @@ namespace Content.Client.Lobby
[Dependency] private readonly IGameTiming _gameTiming = default!;
[Dependency] private readonly IVoteManager _voteManager = default!;
[Dependency] private readonly ClientsidePlaytimeTrackingManager _playtimeTracking = default!;
+ [Dependency] private readonly IPrototypeManager _protoMan = default!;
[Dependency] private readonly IParallaxManager _parallaxManager = default!;
[Dependency] private readonly ISerializationManager _serialization = default!;
[Dependency] private readonly IResourceManager _resource = default!;
diff --git a/Content.Client/Lobby/UI/CharacterPickerButton.xaml b/Content.Client/Lobby/UI/CharacterPickerButton.xaml
index ecd706f5a7..723da433a1 100644
--- a/Content.Client/Lobby/UI/CharacterPickerButton.xaml
+++ b/Content.Client/Lobby/UI/CharacterPickerButton.xaml
@@ -18,7 +18,7 @@
+ StyleClasses="negative"/>
diff --git a/Content.Client/Lobby/UI/CharacterSetupGui.xaml b/Content.Client/Lobby/UI/CharacterSetupGui.xaml
index ab93985b87..7dbade9dc7 100644
--- a/Content.Client/Lobby/UI/CharacterSetupGui.xaml
+++ b/Content.Client/Lobby/UI/CharacterSetupGui.xaml
@@ -28,19 +28,13 @@
Text="{Loc 'character-setup-gui-character-setup-close-button'}"
StyleClasses="ButtonBig"/>
-
-
-
-
+
-
-
-
-
+
diff --git a/Content.Client/Lobby/UI/HumanoidProfileEditor.xaml.cs b/Content.Client/Lobby/UI/HumanoidProfileEditor.xaml.cs
index 0d09cff0d0..6278fa682a 100644
--- a/Content.Client/Lobby/UI/HumanoidProfileEditor.xaml.cs
+++ b/Content.Client/Lobby/UI/HumanoidProfileEditor.xaml.cs
@@ -7,8 +7,8 @@ using Content.Client.Lobby.UI.Loadouts;
using Content.Client.Lobby.UI.Roles;
using Content.Client.Message;
using Content.Client.Players.PlayTimeTracking;
-using Content.Client.Sprite;
using Content.Client.Stylesheets;
+using Content.Client.Sprite;
using Content.Client.UserInterface.Systems.Guidebook;
using Content.Shared._Sunrise;
using Content.Shared._Sunrise.SunriseCCVars;
@@ -627,7 +627,7 @@ namespace Content.Client.Lobby.UI
{
Text = Loc.GetString(category.Name),
Margin = new Thickness(0, 10, 0, 0),
- StyleClasses = { StyleBase.StyleClassLabelHeading },
+ StyleClasses = { StyleClass.LabelHeading },
});
}
@@ -1613,7 +1613,7 @@ namespace Content.Client.Lobby.UI
return;
const string style = "SpeciesInfoDefault";
- SpeciesInfoButton.StyleClasses.Add(style);
+ SpeciesInfoButton.StyleIdentifier = style;
}
private void UpdateMarkings()
diff --git a/Content.Client/Lobby/UI/HumanoidProfileEditorSheetlet.cs b/Content.Client/Lobby/UI/HumanoidProfileEditorSheetlet.cs
new file mode 100644
index 0000000000..016541dc23
--- /dev/null
+++ b/Content.Client/Lobby/UI/HumanoidProfileEditorSheetlet.cs
@@ -0,0 +1,28 @@
+using Content.Client.Resources;
+using Content.Client.Stylesheets;
+using Robust.Client.UserInterface;
+using Robust.Client.UserInterface.Controls;
+using static Content.Client.Stylesheets.StylesheetHelpers;
+
+namespace Content.Client.Lobby.UI;
+
+[CommonSheetlet]
+public sealed class HumanoidProfileEditorSheetlet : Sheetlet
+{
+ public override StyleRule[] GetRules(PalettedStylesheet sheet, object config)
+ {
+ return
+ [
+ E()
+ .Identifier("SpeciesInfoDefault")
+ .Prop(TextureButton.StylePropertyTexture,
+ ResCache.GetTexture("/Textures/Interface/VerbIcons/information.svg.192dpi.png")),
+ // copied from `StyleNano`, but this is unused
+ // E()
+ // .Identifier("SpeciesInfoWarning")
+ // .Prop(TextureButton.StylePropertyTexture,
+ // ResCache.GetTexture("/Textures/Interface/info.svg.192dpi.png"))
+ // .Prop(Control.StylePropertyModulateSelf, sheet.HighlightPalette[0]),
+ ];
+ }
+}
diff --git a/Content.Client/Lobby/UI/Loadouts/LoadoutGroupContainer.xaml b/Content.Client/Lobby/UI/Loadouts/LoadoutGroupContainer.xaml
index 0deb1c82ba..f89b38ca8a 100644
--- a/Content.Client/Lobby/UI/Loadouts/LoadoutGroupContainer.xaml
+++ b/Content.Client/Lobby/UI/Loadouts/LoadoutGroupContainer.xaml
@@ -1,7 +1,7 @@
-
+
diff --git a/Content.Client/Lobby/UI/LobbyCharacterPreviewPanel.xaml.cs b/Content.Client/Lobby/UI/LobbyCharacterPreviewPanel.xaml.cs
index 9b1e7d50f8..988ece124f 100644
--- a/Content.Client/Lobby/UI/LobbyCharacterPreviewPanel.xaml.cs
+++ b/Content.Client/Lobby/UI/LobbyCharacterPreviewPanel.xaml.cs
@@ -1,6 +1,5 @@
using System.Numerics;
using Content.Client.UserInterface.Controls;
-using Prometheus;
using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls;
diff --git a/Content.Client/Lobby/UI/ObserveWarningWindow.xaml b/Content.Client/Lobby/UI/ObserveWarningWindow.xaml
index 2feac5792a..adc1673326 100644
--- a/Content.Client/Lobby/UI/ObserveWarningWindow.xaml
+++ b/Content.Client/Lobby/UI/ObserveWarningWindow.xaml
@@ -7,7 +7,7 @@
-
+
diff --git a/Content.Client/Lobby/UI/Roles/RequirementsSelector.xaml.cs b/Content.Client/Lobby/UI/Roles/RequirementsSelector.xaml.cs
index f0aab34a41..cd2714b671 100644
--- a/Content.Client/Lobby/UI/Roles/RequirementsSelector.xaml.cs
+++ b/Content.Client/Lobby/UI/Roles/RequirementsSelector.xaml.cs
@@ -35,9 +35,9 @@ public sealed partial class RequirementsSelector : BoxContainer
IoCManager.InjectDependencies(this);
_options = new RadioOptions(RadioOptionsLayout.Horizontal)
{
- FirstButtonStyle = StyleBase.ButtonOpenRight,
- ButtonStyle = StyleBase.ButtonOpenBoth,
- LastButtonStyle = StyleBase.ButtonOpenLeft,
+ FirstButtonStyle = StyleClass.ButtonOpenRight,
+ ButtonStyle = StyleClass.ButtonOpenBoth,
+ LastButtonStyle = StyleClass.ButtonOpenLeft,
HorizontalExpand = true,
};
//Override default radio option button width
@@ -54,7 +54,7 @@ public sealed partial class RequirementsSelector : BoxContainer
Text = Loc.GetString("role-timer-locked"),
Visible = true,
HorizontalAlignment = HAlignment.Center,
- StyleClasses = {StyleBase.StyleClassLabelSubText},
+ StyleClasses = {StyleClass.LabelSubText},
};
_lockStripe = new StripeBack()
diff --git a/Content.Client/MainMenu/UI/MainMenuControl.xaml.cs b/Content.Client/MainMenu/UI/MainMenuControl.xaml.cs
index 9341071447..27a57320a8 100644
--- a/Content.Client/MainMenu/UI/MainMenuControl.xaml.cs
+++ b/Content.Client/MainMenu/UI/MainMenuControl.xaml.cs
@@ -11,6 +11,9 @@ namespace Content.Client.MainMenu.UI;
[GenerateTypedNameReferences]
public sealed partial class MainMenuControl : Control
{
+ public const string StyleIdentifierMainMenu = "mainMenu";
+ public const string StyleIdentifierMainMenuVBox = "mainMenuVBox";
+
public MainMenuControl(IResourceCache resCache, IConfigurationManager configMan)
{
RobustXamlLoader.Load(this);
diff --git a/Content.Client/MainMenu/UI/MainMenuSheetlet.cs b/Content.Client/MainMenu/UI/MainMenuSheetlet.cs
new file mode 100644
index 0000000000..45171af3b7
--- /dev/null
+++ b/Content.Client/MainMenu/UI/MainMenuSheetlet.cs
@@ -0,0 +1,27 @@
+using Content.Client.Stylesheets;
+using Content.Client.Stylesheets.Fonts;
+using Content.Client.Stylesheets.Stylesheets;
+using Robust.Client.UserInterface;
+using Robust.Client.UserInterface.Controls;
+using static Content.Client.Stylesheets.StylesheetHelpers;
+
+namespace Content.Client.MainMenu.UI;
+
+[CommonSheetlet]
+public sealed class MainMenuSheetlet : Sheetlet
+{
+ public override StyleRule[] GetRules(NanotrasenStylesheet sheet, object config)
+ {
+ return
+ [
+ // make those buttons bigger
+ E