Compare commits
18 Commits
master
...
funnyfunny
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
aa621ece26 | ||
|
|
52880de47e | ||
|
|
eb289104ab | ||
|
|
db49a55481 | ||
|
|
f01725fdc7 | ||
|
|
0a6a560066 | ||
|
|
6f170bb45f | ||
|
|
cec07307bf | ||
|
|
bd80a1eb60 | ||
|
|
b0c2b92464 | ||
|
|
35e5025d3e | ||
|
|
146967b786 | ||
|
|
4b68d79729 | ||
|
|
8899695ed5 | ||
|
|
1d410590b6 | ||
|
|
24eb9d7493 | ||
|
|
565283ae26 | ||
|
|
d55800c575 |
4
.github/CODEOWNERS
vendored
4
.github/CODEOWNERS
vendored
@@ -1,2 +1,6 @@
|
|||||||
# TheShuEd
|
# TheShuEd
|
||||||
* @TheShuEd
|
* @TheShuEd
|
||||||
|
|
||||||
|
# TornadoTechnology
|
||||||
|
*.cs @Tornado-Technology
|
||||||
|
*.xaml @Tornado-Technology
|
||||||
|
|||||||
22
.github/FUNDING.yml
vendored
22
.github/FUNDING.yml
vendored
@@ -1,14 +1,14 @@
|
|||||||
# These are supported funding model platforms
|
# These are supported funding model platforms
|
||||||
|
|
||||||
#github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
|
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
|
||||||
#patreon: # Replace with a single Patreon username
|
patreon: # Replace with a single Patreon username
|
||||||
#open_collective: # Replace with a single Open Collective username
|
open_collective: # Replace with a single Open Collective username
|
||||||
#ko_fi: # Replace with a single Ko-fi username
|
ko_fi: # Replace with a single Ko-fi username
|
||||||
#tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
|
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
|
||||||
#community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
|
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
|
||||||
#liberapay: # Replace with a single Liberapay username
|
liberapay: # Replace with a single Liberapay username
|
||||||
#issuehunt: # Replace with a single IssueHunt username
|
issuehunt: # Replace with a single IssueHunt username
|
||||||
#lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
|
lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
|
||||||
#polar: # Replace with a single Polar username
|
polar: # Replace with a single Polar username
|
||||||
#buy_me_a_coffee: # Replace with a single Buy Me a Coffee username
|
buy_me_a_coffee: # Replace with a single Buy Me a Coffee username
|
||||||
custom: ['https://boosty.to/theshued']
|
custom: ['https://boosty.to/theshued']
|
||||||
|
|||||||
38
.github/workflows/cla.yml
vendored
Normal file
38
.github/workflows/cla.yml
vendored
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
name: "CLA Assistant"
|
||||||
|
on:
|
||||||
|
issue_comment:
|
||||||
|
types: [created]
|
||||||
|
pull_request_target:
|
||||||
|
types: [opened,closed,synchronize]
|
||||||
|
paths:
|
||||||
|
- '**CP14**'
|
||||||
|
|
||||||
|
# explicitly configure permissions, in case your GITHUB_TOKEN workflow permissions are set to read-only in repository settings
|
||||||
|
permissions:
|
||||||
|
actions: write
|
||||||
|
contents: write # this can be 'read' if the signatures are in remote repository
|
||||||
|
pull-requests: write
|
||||||
|
statuses: write
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
CLAAssistant:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: "CLA Assistant"
|
||||||
|
if: ((github.event.comment.body == 'recheck' || github.event.comment.body == 'I have read the CLA Document and I hereby sign the CLA') || github.event_name == 'pull_request_target') && github.actor != 'TheShuEd'
|
||||||
|
uses: contributor-assistant/github-action@v2.6.1
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
# the below token should have repo scope and must be manually added by you in the repository's secret
|
||||||
|
# This token is required only if you have configured to store the signatures in a remote repository/organization
|
||||||
|
# PERSONAL_ACCESS_TOKEN: ${{ secrets.PERSONAL_ACCESS_TOKEN }}
|
||||||
|
with:
|
||||||
|
path-to-signatures: 'signatures/version1/cla.json'
|
||||||
|
path-to-document: 'https://github.com/crystallpunk-14/crystall-punk-14/blob/master/CLA.md' # e.g. a CLA or a DCO document
|
||||||
|
# branch should not be protected
|
||||||
|
branch: 'master'
|
||||||
|
allowlist: TheShuEd,bot*
|
||||||
|
|
||||||
|
# the followings are the optional inputs - If the optional inputs are not given, then default values will be taken
|
||||||
|
#custom-pr-sign-comment: 'The signature to be committed in order to sign the CLA'
|
||||||
|
#custom-allsigned-prcomment: 'pull request comment when all contributors has signed, defaults to **CLA Assistant Lite bot** All Contributors have signed the CLA.'
|
||||||
2
.github/workflows/publish-testing.yml
vendored
2
.github/workflows/publish-testing.yml
vendored
@@ -34,7 +34,7 @@ jobs:
|
|||||||
run: dotnet build Content.Packaging --configuration Release --no-restore /m
|
run: dotnet build Content.Packaging --configuration Release --no-restore /m
|
||||||
|
|
||||||
- name: Package server
|
- name: Package server
|
||||||
run: dotnet run --project Content.Packaging server --platform win-x64 --platform win-arm64 --platform linux-x64 --platform linux-arm64 --platform osx-x64 --platform osx-arm64
|
run: dotnet run --project Content.Packaging server --platform win-x64 --platform linux-x64 --platform osx-x64 --platform linux-arm64
|
||||||
|
|
||||||
- name: Package client
|
- name: Package client
|
||||||
run: dotnet run --project Content.Packaging client --no-wipe-release
|
run: dotnet run --project Content.Packaging client --no-wipe-release
|
||||||
|
|||||||
2
.github/workflows/publish.yml
vendored
2
.github/workflows/publish.yml
vendored
@@ -41,7 +41,7 @@ jobs:
|
|||||||
run: dotnet build Content.Packaging --configuration Release --no-restore /m
|
run: dotnet build Content.Packaging --configuration Release --no-restore /m
|
||||||
|
|
||||||
- name: Package server
|
- name: Package server
|
||||||
run: dotnet run --project Content.Packaging server --platform win-x64 --platform win-arm64 --platform linux-x64 --platform linux-arm64 --platform osx-x64 --platform osx-arm64
|
run: dotnet run --project Content.Packaging server --platform win-x64 --platform linux-x64 --platform osx-x64 --platform linux-arm64
|
||||||
|
|
||||||
- name: Package client
|
- name: Package client
|
||||||
run: dotnet run --project Content.Packaging client --no-wipe-release
|
run: dotnet run --project Content.Packaging client --no-wipe-release
|
||||||
|
|||||||
2
.github/workflows/test-packaging.yml
vendored
2
.github/workflows/test-packaging.yml
vendored
@@ -60,7 +60,7 @@ jobs:
|
|||||||
run: dotnet build Content.Packaging --configuration Release --no-restore /m
|
run: dotnet build Content.Packaging --configuration Release --no-restore /m
|
||||||
|
|
||||||
- name: Package server
|
- name: Package server
|
||||||
run: dotnet run --project Content.Packaging server --platform win-x64 --platform win-arm64 --platform linux-x64 --platform linux-arm64 --platform osx-x64 --platform osx-arm64
|
run: dotnet run --project Content.Packaging server --platform win-x64 --platform linux-x64 --platform osx-x64 --platform linux-arm64
|
||||||
|
|
||||||
- name: Package client
|
- name: Package client
|
||||||
run: dotnet run --project Content.Packaging client --no-wipe-release
|
run: dotnet run --project Content.Packaging client --no-wipe-release
|
||||||
|
|||||||
@@ -1,19 +1,17 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
"""
|
# Installs git hooks, updates them, updates submodules, that kind of thing.
|
||||||
Installs git hooks, updates them, updates submodules, that kind of thing.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import os
|
|
||||||
import shutil
|
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
|
import os
|
||||||
|
import shutil
|
||||||
import time
|
import time
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import List
|
from typing import List
|
||||||
|
|
||||||
SOLUTION_PATH = Path("..") / "SpaceStation14.sln"
|
SOLUTION_PATH = Path("..") / "SpaceStation14.sln"
|
||||||
# If this doesn't match the saved version we overwrite them all.
|
# If this doesn't match the saved version we overwrite them all.
|
||||||
CURRENT_HOOKS_VERSION = "3"
|
CURRENT_HOOKS_VERSION = "2"
|
||||||
QUIET = len(sys.argv) == 2 and sys.argv[1] == "--quiet"
|
QUIET = len(sys.argv) == 2 and sys.argv[1] == "--quiet"
|
||||||
|
|
||||||
|
|
||||||
@@ -27,10 +25,12 @@ def run_command(command: List[str], capture: bool = False) -> subprocess.Complet
|
|||||||
|
|
||||||
sys.stdout.flush()
|
sys.stdout.flush()
|
||||||
|
|
||||||
|
completed = None
|
||||||
|
|
||||||
if capture:
|
if capture:
|
||||||
completed = subprocess.run(command, stdout=subprocess.PIPE, text=True)
|
completed = subprocess.run(command, cwd="..", stdout=subprocess.PIPE)
|
||||||
else:
|
else:
|
||||||
completed = subprocess.run(command)
|
completed = subprocess.run(command, cwd="..")
|
||||||
|
|
||||||
if completed.returncode != 0:
|
if completed.returncode != 0:
|
||||||
print("Error: command exited with code {}!".format(completed.returncode))
|
print("Error: command exited with code {}!".format(completed.returncode))
|
||||||
@@ -43,7 +43,7 @@ def update_submodules():
|
|||||||
Updates all submodules.
|
Updates all submodules.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if 'GITHUB_ACTIONS' in os.environ:
|
if ('GITHUB_ACTIONS' in os.environ):
|
||||||
return
|
return
|
||||||
|
|
||||||
if os.path.isfile("DISABLE_SUBMODULE_AUTOUPDATE"):
|
if os.path.isfile("DISABLE_SUBMODULE_AUTOUPDATE"):
|
||||||
@@ -76,21 +76,22 @@ def install_hooks():
|
|||||||
print("No hooks change detected.")
|
print("No hooks change detected.")
|
||||||
return
|
return
|
||||||
|
|
||||||
|
with open("INSTALLED_HOOKS_VERSION", "w") as f:
|
||||||
|
f.write(CURRENT_HOOKS_VERSION)
|
||||||
|
|
||||||
print("Hooks need updating.")
|
print("Hooks need updating.")
|
||||||
|
|
||||||
hooks_target_dir = Path(run_command(["git", "rev-parse", "--git-path", "hooks"], True).stdout.strip())
|
hooks_target_dir = Path("..")/".git"/"hooks"
|
||||||
hooks_source_dir = Path("hooks")
|
hooks_source_dir = Path("hooks")
|
||||||
|
|
||||||
# Clear entire tree since we need to kill deleted files too.
|
# Clear entire tree since we need to kill deleted files too.
|
||||||
for filename in os.listdir(hooks_target_dir):
|
for filename in os.listdir(str(hooks_target_dir)):
|
||||||
os.remove(hooks_target_dir / filename)
|
os.remove(str(hooks_target_dir/filename))
|
||||||
|
|
||||||
for filename in os.listdir(hooks_source_dir):
|
for filename in os.listdir(str(hooks_source_dir)):
|
||||||
print("Copying hook {}".format(filename))
|
print("Copying hook {}".format(filename))
|
||||||
shutil.copy2(hooks_source_dir / filename, hooks_target_dir / filename)
|
shutil.copy2(str(hooks_source_dir/filename),
|
||||||
|
str(hooks_target_dir/filename))
|
||||||
with open("INSTALLED_HOOKS_VERSION", "w") as f:
|
|
||||||
f.write(CURRENT_HOOKS_VERSION)
|
|
||||||
|
|
||||||
|
|
||||||
def reset_solution():
|
def reset_solution():
|
||||||
@@ -106,7 +107,8 @@ def reset_solution():
|
|||||||
|
|
||||||
def check_for_zip_download():
|
def check_for_zip_download():
|
||||||
# Check if .git exists,
|
# Check if .git exists,
|
||||||
if run_command(["git", "rev-parse"]).returncode != 0:
|
cur_dir = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
|
||||||
|
if not os.path.isdir(os.path.join(cur_dir, ".git")):
|
||||||
print("It appears that you downloaded this repository directly from GitHub. (Using the .zip download option) \n"
|
print("It appears that you downloaded this repository directly from GitHub. (Using the .zip download option) \n"
|
||||||
"When downloading straight from GitHub, it leaves out important information that git needs to function. "
|
"When downloading straight from GitHub, it leaves out important information that git needs to function. "
|
||||||
"Such as information to download the engine or even the ability to even be able to create contributions. \n"
|
"Such as information to download the engine or even the ability to even be able to create contributions. \n"
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
gitroot=$(git rev-parse --show-toplevel)
|
gitroot=`git rev-parse --show-toplevel`
|
||||||
|
|
||||||
cd "$gitroot/BuildChecker" || exit
|
cd "$gitroot/BuildChecker"
|
||||||
|
|
||||||
if [[ $(uname) == MINGW* || $(uname) == CYGWIN* ]]; then
|
if [[ `uname` == MINGW* || `uname` == CYGWIN* ]]; then
|
||||||
# Windows
|
# Windows
|
||||||
py -3 git_helper.py --quiet
|
py -3 git_helper.py --quiet
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
# Just call post-checkout since it does the same thing.
|
# Just call post-checkout since it does the same thing.
|
||||||
gitroot=$(git rev-parse --git-path hooks)
|
gitroot=`git rev-parse --show-toplevel`
|
||||||
bash "$gitroot/post-checkout"
|
bash "$gitroot/.git/hooks/post-checkout"
|
||||||
|
|||||||
@@ -1,174 +0,0 @@
|
|||||||
using System.Threading.Tasks;
|
|
||||||
using BenchmarkDotNet.Attributes;
|
|
||||||
using BenchmarkDotNet.Diagnosers;
|
|
||||||
using Content.IntegrationTests;
|
|
||||||
using Content.IntegrationTests.Pair;
|
|
||||||
using Content.Server.Atmos.Components;
|
|
||||||
using Content.Server.Atmos.EntitySystems;
|
|
||||||
using Content.Shared.Atmos.Components;
|
|
||||||
using Content.Shared.CCVar;
|
|
||||||
using Robust.Shared;
|
|
||||||
using Robust.Shared.Analyzers;
|
|
||||||
using Robust.Shared.Configuration;
|
|
||||||
using Robust.Shared.GameObjects;
|
|
||||||
using Robust.Shared.Map;
|
|
||||||
using Robust.Shared.Map.Components;
|
|
||||||
using Robust.Shared.Maths;
|
|
||||||
using Robust.Shared.Prototypes;
|
|
||||||
using Robust.Shared.Random;
|
|
||||||
|
|
||||||
namespace Content.Benchmarks;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Spawns N number of entities with a <see cref="DeltaPressureComponent"/> and
|
|
||||||
/// simulates them for a number of ticks M.
|
|
||||||
/// </summary>
|
|
||||||
[Virtual]
|
|
||||||
[GcServer(true)]
|
|
||||||
//[MemoryDiagnoser]
|
|
||||||
//[ThreadingDiagnoser]
|
|
||||||
public class DeltaPressureBenchmark
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Number of entities (windows, really) to spawn with a <see cref="DeltaPressureComponent"/>.
|
|
||||||
/// </summary>
|
|
||||||
[Params(1, 10, 100, 1000, 5000, 10000, 50000, 100000)]
|
|
||||||
public int EntityCount;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Number of entities that each parallel processing job will handle.
|
|
||||||
/// </summary>
|
|
||||||
// [Params(1, 10, 100, 1000, 5000, 10000)] For testing how multithreading parameters affect performance (THESE TESTS TAKE 16+ HOURS TO RUN)
|
|
||||||
[Params(10)]
|
|
||||||
public int BatchSize;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Number of entities to process per iteration in the DeltaPressure
|
|
||||||
/// processing loop.
|
|
||||||
/// </summary>
|
|
||||||
// [Params(100, 1000, 5000, 10000, 50000)]
|
|
||||||
[Params(1000)]
|
|
||||||
public int EntitiesPerIteration;
|
|
||||||
|
|
||||||
private readonly EntProtoId _windowProtoId = "Window";
|
|
||||||
private readonly EntProtoId _wallProtoId = "WallPlastitaniumIndestructible";
|
|
||||||
|
|
||||||
private TestPair _pair = default!;
|
|
||||||
private IEntityManager _entMan = default!;
|
|
||||||
private SharedMapSystem _map = default!;
|
|
||||||
private IRobustRandom _random = default!;
|
|
||||||
private IConfigurationManager _cvar = default!;
|
|
||||||
private ITileDefinitionManager _tileDefMan = default!;
|
|
||||||
private AtmosphereSystem _atmospereSystem = default!;
|
|
||||||
|
|
||||||
private Entity<GridAtmosphereComponent, GasTileOverlayComponent, MapGridComponent, TransformComponent>
|
|
||||||
_testEnt;
|
|
||||||
|
|
||||||
[GlobalSetup]
|
|
||||||
public async Task SetupAsync()
|
|
||||||
{
|
|
||||||
ProgramShared.PathOffset = "../../../../";
|
|
||||||
PoolManager.Startup();
|
|
||||||
_pair = await PoolManager.GetServerClient();
|
|
||||||
var server = _pair.Server;
|
|
||||||
|
|
||||||
var mapdata = await _pair.CreateTestMap();
|
|
||||||
|
|
||||||
_entMan = server.ResolveDependency<IEntityManager>();
|
|
||||||
_map = _entMan.System<SharedMapSystem>();
|
|
||||||
_random = server.ResolveDependency<IRobustRandom>();
|
|
||||||
_cvar = server.ResolveDependency<IConfigurationManager>();
|
|
||||||
_tileDefMan = server.ResolveDependency<ITileDefinitionManager>();
|
|
||||||
_atmospereSystem = _entMan.System<AtmosphereSystem>();
|
|
||||||
|
|
||||||
_random.SetSeed(69420); // Randomness needs to be deterministic for benchmarking.
|
|
||||||
|
|
||||||
_cvar.SetCVar(CCVars.DeltaPressureParallelToProcessPerIteration, EntitiesPerIteration);
|
|
||||||
_cvar.SetCVar(CCVars.DeltaPressureParallelBatchSize, BatchSize);
|
|
||||||
|
|
||||||
var plating = _tileDefMan["Plating"].TileId;
|
|
||||||
|
|
||||||
/*
|
|
||||||
Basically, we want to have a 5-wide grid of tiles.
|
|
||||||
Edges are walled, and the length of the grid is determined by N + 2.
|
|
||||||
Windows should only touch the top and bottom walls, and each other.
|
|
||||||
*/
|
|
||||||
|
|
||||||
var length = EntityCount + 2; // ensures we can spawn exactly N windows between side walls
|
|
||||||
const int height = 5;
|
|
||||||
|
|
||||||
await server.WaitPost(() =>
|
|
||||||
{
|
|
||||||
// Fill required tiles (extend grid) with plating
|
|
||||||
for (var x = 0; x < length; x++)
|
|
||||||
{
|
|
||||||
for (var y = 0; y < height; y++)
|
|
||||||
{
|
|
||||||
_map.SetTile(mapdata.Grid, mapdata.Grid, new Vector2i(x, y), new Tile(plating));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Spawn perimeter walls and windows row in the middle (y = 2)
|
|
||||||
const int midY = height / 2;
|
|
||||||
for (var x = 0; x < length; x++)
|
|
||||||
{
|
|
||||||
for (var y = 0; y < height; y++)
|
|
||||||
{
|
|
||||||
var coords = new EntityCoordinates(mapdata.Grid, x + 0.5f, y + 0.5f);
|
|
||||||
|
|
||||||
var isPerimeter = x == 0 || x == length - 1 || y == 0 || y == height - 1;
|
|
||||||
if (isPerimeter)
|
|
||||||
{
|
|
||||||
_entMan.SpawnEntity(_wallProtoId, coords);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Spawn windows only on the middle row, spanning interior (excluding side walls)
|
|
||||||
if (y == midY)
|
|
||||||
{
|
|
||||||
_entMan.SpawnEntity(_windowProtoId, coords);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Next we run the fixgridatmos command to ensure that we have some air on our grid.
|
|
||||||
// Wait a little bit as well.
|
|
||||||
// TODO: Unhardcode command magic string when fixgridatmos is an actual command we can ref and not just
|
|
||||||
// a stamp-on in AtmosphereSystem.
|
|
||||||
await _pair.WaitCommand("fixgridatmos " + mapdata.Grid.Owner, 1);
|
|
||||||
|
|
||||||
var uid = mapdata.Grid.Owner;
|
|
||||||
_testEnt = new Entity<GridAtmosphereComponent, GasTileOverlayComponent, MapGridComponent, TransformComponent>(
|
|
||||||
uid,
|
|
||||||
_entMan.GetComponent<GridAtmosphereComponent>(uid),
|
|
||||||
_entMan.GetComponent<GasTileOverlayComponent>(uid),
|
|
||||||
_entMan.GetComponent<MapGridComponent>(uid),
|
|
||||||
_entMan.GetComponent<TransformComponent>(uid));
|
|
||||||
}
|
|
||||||
|
|
||||||
[Benchmark]
|
|
||||||
public async Task PerformFullProcess()
|
|
||||||
{
|
|
||||||
await _pair.Server.WaitPost(() =>
|
|
||||||
{
|
|
||||||
while (!_atmospereSystem.RunProcessingStage(_testEnt, AtmosphereProcessingState.DeltaPressure)) { }
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
[Benchmark]
|
|
||||||
public async Task PerformSingleRunProcess()
|
|
||||||
{
|
|
||||||
await _pair.Server.WaitPost(() =>
|
|
||||||
{
|
|
||||||
_atmospereSystem.RunProcessingStage(_testEnt, AtmosphereProcessingState.DeltaPressure);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
[GlobalCleanup]
|
|
||||||
public async Task CleanupAsync()
|
|
||||||
{
|
|
||||||
await _pair.DisposeAsync();
|
|
||||||
PoolManager.Shutdown();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -47,7 +47,7 @@ public class MapLoadBenchmark
|
|||||||
PoolManager.Shutdown();
|
PoolManager.Shutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string[] MapsSource { get; } = { "Empty", "Saltern", "Box", "Bagel", "Dev", "CentComm", "Core", "TestTeg", "Packed", "Omega", "Reach", "Meta", "Marathon", "MeteorArena", "Fland", "Oasis", "Convex"};
|
public static readonly string[] MapsSource = { "Empty", "Saltern", "Box", "Bagel", "Dev", "CentComm", "Core", "TestTeg", "Packed", "Omega", "Reach", "Meta", "Marathon", "MeteorArena", "Fland", "Oasis", "Convex"};
|
||||||
|
|
||||||
[ParamsSource(nameof(MapsSource))]
|
[ParamsSource(nameof(MapsSource))]
|
||||||
public string Map;
|
public string Map;
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ using BenchmarkDotNet.Attributes;
|
|||||||
using Content.IntegrationTests;
|
using Content.IntegrationTests;
|
||||||
using Content.IntegrationTests.Pair;
|
using Content.IntegrationTests.Pair;
|
||||||
using Content.Server.Mind;
|
using Content.Server.Mind;
|
||||||
|
using Content.Server.Warps;
|
||||||
using Content.Shared.Warps;
|
using Content.Shared.Warps;
|
||||||
using Robust.Shared;
|
using Robust.Shared;
|
||||||
using Robust.Shared.Analyzers;
|
using Robust.Shared.Analyzers;
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ namespace Content.Client.Access.UI
|
|||||||
|
|
||||||
foreach (var access in accessLevels)
|
foreach (var access in accessLevels)
|
||||||
{
|
{
|
||||||
if (!protoManager.Resolve(access, out var accessLevel))
|
if (!protoManager.TryIndex(access, out var accessLevel))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ public sealed partial class GroupedAccessLevelChecklist : BoxContainer
|
|||||||
|
|
||||||
foreach (var accessGroup in _accessGroups)
|
foreach (var accessGroup in _accessGroups)
|
||||||
{
|
{
|
||||||
if (!_protoManager.Resolve(accessGroup, out var accessGroupProto))
|
if (!_protoManager.TryIndex(accessGroup, out var accessGroupProto))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
_groupedAccessLevels.Add(accessGroupProto, new());
|
_groupedAccessLevels.Add(accessGroupProto, new());
|
||||||
@@ -65,13 +65,13 @@ public sealed partial class GroupedAccessLevelChecklist : BoxContainer
|
|||||||
|
|
||||||
// Ensure that the 'general' access group is added to handle
|
// Ensure that the 'general' access group is added to handle
|
||||||
// misc. access levels that aren't associated with any group
|
// misc. access levels that aren't associated with any group
|
||||||
if (_protoManager.Resolve(GeneralAccessGroup, out var generalAccessProto))
|
if (_protoManager.TryIndex(GeneralAccessGroup, out var generalAccessProto))
|
||||||
_groupedAccessLevels.TryAdd(generalAccessProto, new());
|
_groupedAccessLevels.TryAdd(generalAccessProto, new());
|
||||||
|
|
||||||
// Assign known access levels with their associated groups
|
// Assign known access levels with their associated groups
|
||||||
foreach (var accessLevel in _accessLevels)
|
foreach (var accessLevel in _accessLevels)
|
||||||
{
|
{
|
||||||
if (!_protoManager.Resolve(accessLevel, out var accessLevelProto))
|
if (!_protoManager.TryIndex(accessLevel, out var accessLevelProto))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
var assigned = false;
|
var assigned = false;
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ using Content.Shared.Access.Systems;
|
|||||||
using Content.Shared.CCVar;
|
using Content.Shared.CCVar;
|
||||||
using Content.Shared.Containers.ItemSlots;
|
using Content.Shared.Containers.ItemSlots;
|
||||||
using Content.Shared.CrewManifest;
|
using Content.Shared.CrewManifest;
|
||||||
using Content.Shared.Roles;
|
|
||||||
using Robust.Shared.Configuration;
|
using Robust.Shared.Configuration;
|
||||||
using Robust.Shared.Prototypes;
|
using Robust.Shared.Prototypes;
|
||||||
using static Content.Shared.Access.Components.IdCardConsoleComponent;
|
using static Content.Shared.Access.Components.IdCardConsoleComponent;
|
||||||
@@ -75,7 +74,7 @@ namespace Content.Client.Access.UI
|
|||||||
_window?.UpdateState(castState);
|
_window?.UpdateState(castState);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SubmitData(string newFullName, string newJobTitle, List<ProtoId<AccessLevelPrototype>> newAccessList, ProtoId<JobPrototype> newJobPrototype)
|
public void SubmitData(string newFullName, string newJobTitle, List<ProtoId<AccessLevelPrototype>> newAccessList, string newJobPrototype)
|
||||||
{
|
{
|
||||||
if (newFullName.Length > _maxNameLength)
|
if (newFullName.Length > _maxNameLength)
|
||||||
newFullName = newFullName[.._maxNameLength];
|
newFullName = newFullName[.._maxNameLength];
|
||||||
|
|||||||
@@ -123,7 +123,7 @@ namespace Content.Client.Access.UI
|
|||||||
|
|
||||||
foreach (var group in job.AccessGroups)
|
foreach (var group in job.AccessGroups)
|
||||||
{
|
{
|
||||||
if (!_prototypeManager.Resolve(group, out AccessGroupPrototype? groupPrototype))
|
if (!_prototypeManager.TryIndex(group, out AccessGroupPrototype? groupPrototype))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
using Content.Shared.Administration.Components;
|
||||||
|
using Robust.Shared.GameStates;
|
||||||
|
|
||||||
|
namespace Content.Client.Administration.Components;
|
||||||
|
|
||||||
|
[RegisterComponent]
|
||||||
|
public sealed partial class HeadstandComponent : SharedHeadstandComponent
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
@@ -15,7 +15,6 @@ namespace Content.Client.Administration.Managers
|
|||||||
[Dependency] private readonly IPlayerManager _player = default!;
|
[Dependency] private readonly IPlayerManager _player = default!;
|
||||||
[Dependency] private readonly IClientNetManager _netMgr = default!;
|
[Dependency] private readonly IClientNetManager _netMgr = default!;
|
||||||
[Dependency] private readonly IClientConGroupController _conGroup = default!;
|
[Dependency] private readonly IClientConGroupController _conGroup = default!;
|
||||||
[Dependency] private readonly IClientConsoleHost _host = default!;
|
|
||||||
[Dependency] private readonly IResourceManager _res = default!;
|
[Dependency] private readonly IResourceManager _res = default!;
|
||||||
[Dependency] private readonly ILogManager _logManager = default!;
|
[Dependency] private readonly ILogManager _logManager = default!;
|
||||||
[Dependency] private readonly IUserInterfaceManager _userInterface = default!;
|
[Dependency] private readonly IUserInterfaceManager _userInterface = default!;
|
||||||
@@ -87,12 +86,12 @@ namespace Content.Client.Administration.Managers
|
|||||||
private void UpdateMessageRx(MsgUpdateAdminStatus message)
|
private void UpdateMessageRx(MsgUpdateAdminStatus message)
|
||||||
{
|
{
|
||||||
_availableCommands.Clear();
|
_availableCommands.Clear();
|
||||||
|
var host = IoCManager.Resolve<IClientConsoleHost>();
|
||||||
|
|
||||||
// Anything marked as Any we'll just add even if the server doesn't know about it.
|
// Anything marked as Any we'll just add even if the server doesn't know about it.
|
||||||
foreach (var (command, instance) in _host.AvailableCommands)
|
foreach (var (command, instance) in host.AvailableCommands)
|
||||||
{
|
{
|
||||||
if (Attribute.GetCustomAttribute(instance.GetType(), typeof(AnyCommandAttribute)) == null)
|
if (Attribute.GetCustomAttribute(instance.GetType(), typeof(AnyCommandAttribute)) == null) continue;
|
||||||
continue;
|
|
||||||
_availableCommands.Add(command);
|
_availableCommands.Add(command);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
using Content.Shared.Administration;
|
||||||
|
|
||||||
|
namespace Content.Client.Administration.Systems;
|
||||||
|
|
||||||
|
public sealed class AdminFrozenSystem : SharedAdminFrozenSystem
|
||||||
|
{
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
using Content.Shared.Administration.Components;
|
using Content.Client.Administration.Components;
|
||||||
using Robust.Client.GameObjects;
|
using Robust.Client.GameObjects;
|
||||||
|
|
||||||
namespace Content.Client.Administration.Systems;
|
namespace Content.Client.Administration.Systems;
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ public sealed partial class AdminMenuWindow : DefaultWindow
|
|||||||
|
|
||||||
public AdminMenuWindow()
|
public AdminMenuWindow()
|
||||||
{
|
{
|
||||||
MinSize = new Vector2(650, 250);
|
MinSize = new Vector2(650, 280);
|
||||||
Title = Loc.GetString("admin-menu-title");
|
Title = Loc.GetString("admin-menu-title");
|
||||||
RobustXamlLoader.Load(this);
|
RobustXamlLoader.Load(this);
|
||||||
MasterTabContainer.SetTabTitle((int) TabIndex.Admin, Loc.GetString("admin-menu-admin-tab"));
|
MasterTabContainer.SetTabTitle((int) TabIndex.Admin, Loc.GetString("admin-menu-admin-tab"));
|
||||||
|
|||||||
@@ -316,9 +316,8 @@ public sealed partial class BanPanel : DefaultWindow
|
|||||||
};
|
};
|
||||||
|
|
||||||
// This is adding the icon before the role name
|
// This is adding the icon before the role name
|
||||||
// TODO: This should not be using raw strings for prototypes as it means it won't be validated at all.
|
// Yeah, this is sus, but having to split the functions up and stuff is worse imo.
|
||||||
// I know the ban manager is doing the same thing, but that should not leak into UI code.
|
if (_protoMan.TryIndex<JobPrototype>(role, out var jobPrototype) && _protoMan.TryIndex(jobPrototype.Icon, out var iconProto))
|
||||||
if (_protoMan.TryIndex<JobPrototype>(role, out var jobPrototype) && _protoMan.Resolve(jobPrototype.Icon, out var iconProto))
|
|
||||||
{
|
{
|
||||||
var jobIconTexture = new TextureRect
|
var jobIconTexture = new TextureRect
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -57,43 +57,12 @@ public sealed partial class ObjectsTab : Control
|
|||||||
|
|
||||||
private void TeleportTo(NetEntity nent)
|
private void TeleportTo(NetEntity nent)
|
||||||
{
|
{
|
||||||
var selection = _selections[ObjectTypeOptions.SelectedId];
|
_console.ExecuteCommand($"tpto {nent}");
|
||||||
switch (selection)
|
|
||||||
{
|
|
||||||
case ObjectsTabSelection.Grids:
|
|
||||||
{
|
|
||||||
// directly teleport to the entity
|
|
||||||
_console.ExecuteCommand($"tpto {nent}");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case ObjectsTabSelection.Maps:
|
|
||||||
{
|
|
||||||
// teleport to the map, not to the map entity (which is in nullspace)
|
|
||||||
if (!_entityManager.TryGetEntity(nent, out var map) || !_entityManager.TryGetComponent<MapComponent>(map, out var mapComp))
|
|
||||||
break;
|
|
||||||
_console.ExecuteCommand($"tp 0 0 {mapComp.MapId}");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case ObjectsTabSelection.Stations:
|
|
||||||
{
|
|
||||||
// teleport to the station's largest grid, not to the station entity (which is in nullspace)
|
|
||||||
if (!_entityManager.TryGetEntity(nent, out var station))
|
|
||||||
break;
|
|
||||||
var largestGrid = _entityManager.EntitySysManager.GetEntitySystem<StationSystem>().GetLargestGrid(station.Value);
|
|
||||||
if (largestGrid == null)
|
|
||||||
break;
|
|
||||||
_console.ExecuteCommand($"tpto {largestGrid.Value}");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Delete(NetEntity nent)
|
private void Delete(NetEntity nent)
|
||||||
{
|
{
|
||||||
_console.ExecuteCommand($"delete {nent}");
|
_console.ExecuteCommand($"delete {nent}");
|
||||||
RefreshObjectList();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RefreshObjectList()
|
public void RefreshObjectList()
|
||||||
@@ -107,24 +76,28 @@ public sealed partial class ObjectsTab : Control
|
|||||||
switch (selection)
|
switch (selection)
|
||||||
{
|
{
|
||||||
case ObjectsTabSelection.Stations:
|
case ObjectsTabSelection.Stations:
|
||||||
entities.AddRange(_entityManager.EntitySysManager.GetEntitySystem<StationSystem>().GetStationNames());
|
entities.AddRange(_entityManager.EntitySysManager.GetEntitySystem<StationSystem>().Stations);
|
||||||
break;
|
break;
|
||||||
case ObjectsTabSelection.Grids:
|
case ObjectsTabSelection.Grids:
|
||||||
|
{
|
||||||
|
var query = _entityManager.AllEntityQueryEnumerator<MapGridComponent, MetaDataComponent>();
|
||||||
|
while (query.MoveNext(out var uid, out _, out var metadata))
|
||||||
{
|
{
|
||||||
var query = _entityManager.AllEntityQueryEnumerator<MapGridComponent, MetaDataComponent>();
|
entities.Add((metadata.EntityName, _entityManager.GetNetEntity(uid)));
|
||||||
while (query.MoveNext(out var uid, out _, out var metadata))
|
|
||||||
entities.Add((metadata.EntityName, _entityManager.GetNetEntity(uid)));
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
case ObjectsTabSelection.Maps:
|
case ObjectsTabSelection.Maps:
|
||||||
|
{
|
||||||
|
var query = _entityManager.AllEntityQueryEnumerator<MapComponent, MetaDataComponent>();
|
||||||
|
while (query.MoveNext(out var uid, out _, out var metadata))
|
||||||
{
|
{
|
||||||
var query = _entityManager.AllEntityQueryEnumerator<MapComponent, MetaDataComponent>();
|
entities.Add((metadata.EntityName, _entityManager.GetNetEntity(uid)));
|
||||||
while (query.MoveNext(out var uid, out _, out var metadata))
|
|
||||||
entities.Add((metadata.EntityName, _entityManager.GetNetEntity(uid)));
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
throw new ArgumentOutOfRangeException(nameof(selection), selection, null);
|
throw new ArgumentOutOfRangeException(nameof(selection), selection, null);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
<PanelContainer xmlns="https://spacestation14.io"
|
<PanelContainer xmlns="https://spacestation14.io"
|
||||||
xmlns:customControls="clr-namespace:Content.Client.Administration.UI.CustomControls"
|
xmlns:customControls="clr-namespace:Content.Client.Administration.UI.CustomControls"
|
||||||
xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls"
|
|
||||||
Name="BackgroundColorPanel">
|
Name="BackgroundColorPanel">
|
||||||
<BoxContainer Orientation="Horizontal"
|
<BoxContainer Orientation="Horizontal"
|
||||||
HorizontalExpand="True"
|
HorizontalExpand="True"
|
||||||
@@ -21,7 +20,7 @@
|
|||||||
HorizontalExpand="True"
|
HorizontalExpand="True"
|
||||||
ClipText="True"/>
|
ClipText="True"/>
|
||||||
<customControls:VSeparator/>
|
<customControls:VSeparator/>
|
||||||
<controls:ConfirmButton Name="DeleteButton"
|
<Button Name="DeleteButton"
|
||||||
Text="{Loc object-tab-entity-delete}"
|
Text="{Loc object-tab-entity-delete}"
|
||||||
SizeFlagsStretchRatio="3"
|
SizeFlagsStretchRatio="3"
|
||||||
HorizontalExpand="True"
|
HorizontalExpand="True"
|
||||||
|
|||||||
@@ -27,7 +27,12 @@
|
|||||||
<cc:CommandButton Name="ShowReasonButton" Command="panicbunker_show_reason"
|
<cc:CommandButton Name="ShowReasonButton" Command="panicbunker_show_reason"
|
||||||
ToggleMode="True" Text="{Loc admin-ui-panic-bunker-show-reason}"
|
ToggleMode="True" Text="{Loc admin-ui-panic-bunker-show-reason}"
|
||||||
ToolTip="{Loc admin-ui-panic-bunker-show-reason-tooltip}" />
|
ToolTip="{Loc admin-ui-panic-bunker-show-reason-tooltip}" />
|
||||||
<BoxContainer Orientation="Vertical" Margin="0 10 0 0">
|
<BoxContainer Orientation="Horizontal">
|
||||||
|
<Label Text="{Loc cp14-admin-ui-suspicious-warning-level-setting}" MinWidth="175" />
|
||||||
|
<OptionButton Name="SuspiciousWarningLevel" HorizontalAlignment="Left" Margin="4 0"
|
||||||
|
ToolTip="{Loc cp14-admin-ui-suspicious-warning-level-setting-desc}" />
|
||||||
|
</BoxContainer>
|
||||||
|
<BoxContainer Orientation="Vertical">
|
||||||
<BoxContainer Orientation="Horizontal" Margin="2">
|
<BoxContainer Orientation="Horizontal" Margin="2">
|
||||||
<Label Text="{Loc admin-ui-panic-bunker-min-account-age}" MinWidth="175" />
|
<Label Text="{Loc admin-ui-panic-bunker-min-account-age}" MinWidth="175" />
|
||||||
<LineEdit Name="MinAccountAge" MinWidth="50" Margin="0 0 5 0" />
|
<LineEdit Name="MinAccountAge" MinWidth="50" Margin="0 0 5 0" />
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
using Content.Shared.Administration.Events;
|
using Content.Shared.Administration.Events;
|
||||||
|
using Content.Shared.CCVar;
|
||||||
using Robust.Client.AutoGenerated;
|
using Robust.Client.AutoGenerated;
|
||||||
using Robust.Client.UserInterface;
|
using Robust.Client.UserInterface;
|
||||||
using Robust.Client.UserInterface.XAML;
|
using Robust.Client.UserInterface.XAML;
|
||||||
|
using Robust.Shared.Configuration;
|
||||||
using Robust.Shared.Console;
|
using Robust.Shared.Console;
|
||||||
|
|
||||||
namespace Content.Client.Administration.UI.Tabs.PanicBunkerTab;
|
namespace Content.Client.Administration.UI.Tabs.PanicBunkerTab;
|
||||||
@@ -10,9 +12,13 @@ namespace Content.Client.Administration.UI.Tabs.PanicBunkerTab;
|
|||||||
public sealed partial class PanicBunkerTab : Control
|
public sealed partial class PanicBunkerTab : Control
|
||||||
{
|
{
|
||||||
[Dependency] private readonly IConsoleHost _console = default!;
|
[Dependency] private readonly IConsoleHost _console = default!;
|
||||||
|
[Dependency] private readonly IConfigurationManager _cfg = default!;
|
||||||
|
|
||||||
private string _minAccountAge;
|
private string _minAccountAge;
|
||||||
private string _minOverallMinutes;
|
private string _minOverallMinutes;
|
||||||
|
// CrystallEdge suspicious activity warning system
|
||||||
|
private List<SuspiciousWarningLevelSelection> _suspiciousWarningLevelSelections = [];
|
||||||
|
private string _currentSuspiciousWarningLevel = string.Empty;
|
||||||
|
|
||||||
public PanicBunkerTab()
|
public PanicBunkerTab()
|
||||||
{
|
{
|
||||||
@@ -28,6 +34,21 @@ public sealed partial class PanicBunkerTab : Control
|
|||||||
MinOverallMinutes.OnTextEntered += args => SendMinOverallMinutes(args.Text);
|
MinOverallMinutes.OnTextEntered += args => SendMinOverallMinutes(args.Text);
|
||||||
MinOverallMinutes.OnFocusExit += args => SendMinOverallMinutes(args.Text);
|
MinOverallMinutes.OnFocusExit += args => SendMinOverallMinutes(args.Text);
|
||||||
_minOverallMinutes = MinOverallMinutes.Text;
|
_minOverallMinutes = MinOverallMinutes.Text;
|
||||||
|
|
||||||
|
// CrystallEdge suspicious activity warning system
|
||||||
|
foreach (var type in Enum.GetValues<SuspiciousWarningLevelSelection>())
|
||||||
|
{
|
||||||
|
_suspiciousWarningLevelSelections.Add(type);
|
||||||
|
SuspiciousWarningLevel.AddItem(GetLocalizedEnumValue(type));
|
||||||
|
}
|
||||||
|
|
||||||
|
UpdateSuspiciousWarningLevel();
|
||||||
|
|
||||||
|
SuspiciousWarningLevel.OnItemSelected += ev =>
|
||||||
|
{
|
||||||
|
SuspiciousWarningLevel.SelectId(ev.Id);
|
||||||
|
SendSuspiciousWarningLevel(_suspiciousWarningLevelSelections[ev.Id]);
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SendMinAccountAge(string text)
|
private void SendMinAccountAge(string text)
|
||||||
@@ -74,4 +95,43 @@ public sealed partial class PanicBunkerTab : Control
|
|||||||
MinOverallMinutes.Text = status.MinOverallMinutes.ToString();
|
MinOverallMinutes.Text = status.MinOverallMinutes.ToString();
|
||||||
_minOverallMinutes = MinOverallMinutes.Text;
|
_minOverallMinutes = MinOverallMinutes.Text;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CrystallEdge suspicious activity warning system
|
||||||
|
private enum SuspiciousWarningLevelSelection
|
||||||
|
{
|
||||||
|
Disabled,
|
||||||
|
Low,
|
||||||
|
Medium,
|
||||||
|
High,
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GetLocalizedEnumValue(SuspiciousWarningLevelSelection selection)
|
||||||
|
{
|
||||||
|
return selection switch
|
||||||
|
{
|
||||||
|
SuspiciousWarningLevelSelection.Disabled => Loc.GetString("cp14-admin-ui-suspicious-warning-level-disabled"),
|
||||||
|
SuspiciousWarningLevelSelection.Low => Loc.GetString("cp14-admin-ui-suspicious-warning-level-low"),
|
||||||
|
SuspiciousWarningLevelSelection.Medium => Loc.GetString("cp14-admin-ui-suspicious-warning-level-medium"),
|
||||||
|
SuspiciousWarningLevelSelection.High => Loc.GetString("cp14-admin-ui-suspicious-warning-level-high"),
|
||||||
|
_ => throw new ArgumentOutOfRangeException(nameof(selection), selection, null),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateSuspiciousWarningLevel()
|
||||||
|
{
|
||||||
|
_currentSuspiciousWarningLevel = _cfg.GetCVar(CCVars.SuspiciousAccountsWarningLevel);
|
||||||
|
if (!Enum.TryParse(_currentSuspiciousWarningLevel, true, out SuspiciousWarningLevelSelection currentSuspiciousWarningSelection))
|
||||||
|
{
|
||||||
|
throw new ArgumentOutOfRangeException(nameof(_currentSuspiciousWarningLevel),
|
||||||
|
_currentSuspiciousWarningLevel,
|
||||||
|
null);
|
||||||
|
}
|
||||||
|
|
||||||
|
SuspiciousWarningLevel.SelectId((int)currentSuspiciousWarningSelection);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SendSuspiciousWarningLevel(SuspiciousWarningLevelSelection selection)
|
||||||
|
{
|
||||||
|
_console.ExecuteCommand($"cp14.suspicious-warning-level {Enum.GetName(selection)}");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +0,0 @@
|
|||||||
using Content.Shared.Animals.Systems;
|
|
||||||
|
|
||||||
namespace Content.Client.Animals.Systems;
|
|
||||||
|
|
||||||
public sealed class ParrotMemorySystem : SharedParrotMemorySystem;
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
using Robust.Client.Graphics;
|
|
||||||
using SixLabors.ImageSharp.PixelFormats;
|
|
||||||
|
|
||||||
namespace Content.Client.Anomaly;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This component creates and handles the drawing of a ScreenTexture to be used on the Anomaly Scanner
|
|
||||||
/// for an indicator of Anomaly Severity.
|
|
||||||
/// </summary>
|
|
||||||
/// <remarks>
|
|
||||||
/// In the future I would like to make this a more generic "DynamicTextureComponent" that can contain a dictionary
|
|
||||||
/// of texture components like "Bar(offset, size, minimumValue, maximumValue, AppearanceKey, LayerMapKey)" that can
|
|
||||||
/// just draw a bar or other basic drawn element that will show up on a texture layer.
|
|
||||||
/// </remarks>
|
|
||||||
[RegisterComponent]
|
|
||||||
[Access(typeof(AnomalyScannerSystem))]
|
|
||||||
public sealed partial class AnomalyScannerScreenComponent : Component
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// This is the texture drawn as a layer on the Anomaly Scanner device.
|
|
||||||
/// </summary>
|
|
||||||
public OwnedTexture? ScreenTexture;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// A small buffer that we can reuse to draw the severity bar.
|
|
||||||
/// </summary>
|
|
||||||
public Rgba32[]? BarBuf;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The position of the top-left of the severity bar in pixels.
|
|
||||||
/// </summary>
|
|
||||||
[DataField(readOnly: true)]
|
|
||||||
public Vector2i Offset = new Vector2i(12, 17);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The width and height of the severity bar in pixels.
|
|
||||||
/// </summary>
|
|
||||||
[DataField(readOnly: true)]
|
|
||||||
public Vector2i Size = new Vector2i(10, 3);
|
|
||||||
}
|
|
||||||
@@ -1,110 +0,0 @@
|
|||||||
using System.Numerics;
|
|
||||||
using Content.Shared.Anomaly;
|
|
||||||
using Robust.Client.GameObjects;
|
|
||||||
using Robust.Client.Graphics;
|
|
||||||
using Robust.Shared.Utility;
|
|
||||||
using SixLabors.ImageSharp.PixelFormats;
|
|
||||||
|
|
||||||
namespace Content.Client.Anomaly;
|
|
||||||
|
|
||||||
/// <inheritdoc cref="SharedAnomalyScannerSystem"/>
|
|
||||||
public sealed class AnomalyScannerSystem : SharedAnomalyScannerSystem
|
|
||||||
{
|
|
||||||
[Dependency] private readonly IClyde _clyde = default!;
|
|
||||||
[Dependency] private readonly SpriteSystem _sprite = default!;
|
|
||||||
|
|
||||||
private const float MaxHueDegrees = 360f;
|
|
||||||
private const float GreenHueDegrees = 110f;
|
|
||||||
private const float RedHueDegrees = 0f;
|
|
||||||
private const float GreenHue = GreenHueDegrees / MaxHueDegrees;
|
|
||||||
private const float RedHue = RedHueDegrees / MaxHueDegrees;
|
|
||||||
|
|
||||||
|
|
||||||
// Just an array to initialize the pixels of a new OwnedTexture
|
|
||||||
private static readonly Rgba32[] EmptyTexture = new Rgba32[32*32];
|
|
||||||
|
|
||||||
public override void Initialize()
|
|
||||||
{
|
|
||||||
base.Initialize();
|
|
||||||
|
|
||||||
SubscribeLocalEvent<AnomalyScannerScreenComponent, ComponentInit>(OnComponentInit);
|
|
||||||
SubscribeLocalEvent<AnomalyScannerScreenComponent, ComponentStartup>(OnComponentStartup);
|
|
||||||
SubscribeLocalEvent<AnomalyScannerScreenComponent, AppearanceChangeEvent>(OnScannerAppearanceChanged);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnComponentInit(Entity<AnomalyScannerScreenComponent> ent, ref ComponentInit args)
|
|
||||||
{
|
|
||||||
if(!_sprite.TryGetLayer(ent.Owner, AnomalyScannerVisualLayers.Base, out var layer, true))
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Allocate the OwnedTexture
|
|
||||||
ent.Comp.ScreenTexture = _clyde.CreateBlankTexture<Rgba32>(layer.PixelSize);
|
|
||||||
|
|
||||||
if (layer.PixelSize.X < ent.Comp.Offset.X + ent.Comp.Size.X ||
|
|
||||||
layer.PixelSize.Y < ent.Comp.Offset.Y + ent.Comp.Size.Y)
|
|
||||||
{
|
|
||||||
// If the bar doesn't fit, just bail here, ScreenTexture and BarBuf will remain null, and appearance updates
|
|
||||||
// will do nothing.
|
|
||||||
DebugTools.Assert(false, "AnomalyScannerScreenComponent: Bar does not fit within sprite");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Initialize the texture
|
|
||||||
ent.Comp.ScreenTexture.SetSubImage((0, 0), layer.PixelSize, new ReadOnlySpan<Rgba32>(EmptyTexture));
|
|
||||||
|
|
||||||
// Initialize bar drawing buffer
|
|
||||||
ent.Comp.BarBuf = new Rgba32[ent.Comp.Size.X * ent.Comp.Size.Y];
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnComponentStartup(Entity<AnomalyScannerScreenComponent> ent, ref ComponentStartup args)
|
|
||||||
{
|
|
||||||
if (!TryComp<SpriteComponent>(ent, out var sprite))
|
|
||||||
return;
|
|
||||||
|
|
||||||
_sprite.LayerSetTexture((ent, sprite), AnomalyScannerVisualLayers.Screen, ent.Comp.ScreenTexture);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnScannerAppearanceChanged(Entity<AnomalyScannerScreenComponent> ent, ref AppearanceChangeEvent args)
|
|
||||||
{
|
|
||||||
if (args.Sprite is null || ent.Comp.ScreenTexture is null || ent.Comp.BarBuf is null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
args.AppearanceData.TryGetValue(AnomalyScannerVisuals.AnomalySeverity, out var severityObj);
|
|
||||||
if (severityObj is not float severity)
|
|
||||||
severity = 0;
|
|
||||||
|
|
||||||
// Get the bar length
|
|
||||||
var barLength = (int)(severity * ent.Comp.Size.X);
|
|
||||||
|
|
||||||
// Calculate the bar color
|
|
||||||
// Hue "angle" of two colors to interpolate between depending on severity
|
|
||||||
// Just a lerp from Green hue at severity = 0.5 to Red hue at 1.0
|
|
||||||
var hue = Math.Clamp(2*GreenHue * (1 - severity), RedHue, GreenHue);
|
|
||||||
var color = new Rgba32(Color.FromHsv(new Vector4(hue, 1f, 1f, 1f)).RGBA);
|
|
||||||
|
|
||||||
var transparent = new Rgba32(0, 0, 0, 255);
|
|
||||||
|
|
||||||
for(var y = 0; y < ent.Comp.Size.Y; y++)
|
|
||||||
{
|
|
||||||
for (var x = 0; x < ent.Comp.Size.X; x++)
|
|
||||||
{
|
|
||||||
ent.Comp.BarBuf[y*ent.Comp.Size.X + x] = x < barLength ? color : transparent;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copy the buffer to the texture
|
|
||||||
try
|
|
||||||
{
|
|
||||||
ent.Comp.ScreenTexture.SetSubImage(
|
|
||||||
ent.Comp.Offset,
|
|
||||||
ent.Comp.Size,
|
|
||||||
new ReadOnlySpan<Rgba32>(ent.Comp.BarBuf)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
catch (IndexOutOfRangeException)
|
|
||||||
{
|
|
||||||
Log.Warning($"Bar dimensions out of bounds with the texture on entity {ent.Owner}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -7,7 +7,7 @@ using Robust.Shared.Timing;
|
|||||||
|
|
||||||
namespace Content.Client.Anomaly;
|
namespace Content.Client.Anomaly;
|
||||||
|
|
||||||
public sealed partial class AnomalySystem : SharedAnomalySystem
|
public sealed class AnomalySystem : SharedAnomalySystem
|
||||||
{
|
{
|
||||||
[Dependency] private readonly IGameTiming _timing = default!;
|
[Dependency] private readonly IGameTiming _timing = default!;
|
||||||
[Dependency] private readonly FloatingVisualizerSystem _floating = default!;
|
[Dependency] private readonly FloatingVisualizerSystem _floating = default!;
|
||||||
@@ -24,7 +24,6 @@ public sealed partial class AnomalySystem : SharedAnomalySystem
|
|||||||
|
|
||||||
SubscribeLocalEvent<AnomalySupercriticalComponent, ComponentShutdown>(OnShutdown);
|
SubscribeLocalEvent<AnomalySupercriticalComponent, ComponentShutdown>(OnShutdown);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnStartup(EntityUid uid, AnomalyComponent component, ComponentStartup args)
|
private void OnStartup(EntityUid uid, AnomalyComponent component, ComponentStartup args)
|
||||||
{
|
{
|
||||||
_floating.FloatAnimation(uid, component.FloatingOffset, component.AnimationKey, component.AnimationTime);
|
_floating.FloatAnimation(uid, component.FloatingOffset, component.AnimationKey, component.AnimationTime);
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
using Content.Shared.Anomaly.Components;
|
using Content.Shared.Anomaly.Components;
|
||||||
using Content.Shared.Anomaly.Effects;
|
using Content.Shared.Anomaly.Effects;
|
||||||
using Content.Shared.Humanoid;
|
using Content.Shared.Body.Components;
|
||||||
using Robust.Client.GameObjects;
|
using Robust.Client.GameObjects;
|
||||||
|
|
||||||
namespace Content.Client.Anomaly.Effects;
|
namespace Content.Client.Anomaly.Effects;
|
||||||
@@ -25,8 +25,9 @@ public sealed class ClientInnerBodyAnomalySystem : SharedInnerBodyAnomalySystem
|
|||||||
|
|
||||||
var index = _sprite.LayerMapReserve((ent.Owner, sprite), ent.Comp.LayerMap);
|
var index = _sprite.LayerMapReserve((ent.Owner, sprite), ent.Comp.LayerMap);
|
||||||
|
|
||||||
if (TryComp<HumanoidAppearanceComponent>(ent, out var humanoidAppearance) &&
|
if (TryComp<BodyComponent>(ent, out var body) &&
|
||||||
ent.Comp.SpeciesSprites.TryGetValue(humanoidAppearance.Species, out var speciesSprite))
|
body.Prototype is not null &&
|
||||||
|
ent.Comp.SpeciesSprites.TryGetValue(body.Prototype.Value, out var speciesSprite))
|
||||||
{
|
{
|
||||||
_sprite.LayerSetSprite((ent.Owner, sprite), index, speciesSprite);
|
_sprite.LayerSetSprite((ent.Owner, sprite), index, speciesSprite);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -134,7 +134,7 @@ public sealed class AlignAtmosPipeLayers : SnapgridCenter
|
|||||||
|
|
||||||
var newProtoId = altPrototypes[(int)layer];
|
var newProtoId = altPrototypes[(int)layer];
|
||||||
|
|
||||||
if (!_protoManager.Resolve(newProtoId, out var newProto))
|
if (!_protoManager.TryIndex(newProtoId, out var newProto))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (newProto.Type != ConstructionType.Structure)
|
if (newProto.Type != ConstructionType.Structure)
|
||||||
|
|||||||
@@ -1,11 +1,46 @@
|
|||||||
using Content.Client.Atmos.Components;
|
using Content.Client.Atmos.Components;
|
||||||
using Robust.Client.GameObjects;
|
using Robust.Client.GameObjects;
|
||||||
|
using Content.Client.UserInterface.Systems.Storage.Controls;
|
||||||
using Content.Shared.Atmos.Piping;
|
using Content.Shared.Atmos.Piping;
|
||||||
|
using Content.Shared.Hands;
|
||||||
|
using Content.Shared.Atmos.Components;
|
||||||
|
using Content.Shared.Item;
|
||||||
|
|
||||||
namespace Content.Client.Atmos.EntitySystems;
|
namespace Content.Client.Atmos.EntitySystems;
|
||||||
|
|
||||||
public sealed class PipeColorVisualizerSystem : VisualizerSystem<PipeColorVisualsComponent>
|
public sealed class PipeColorVisualizerSystem : VisualizerSystem<PipeColorVisualsComponent>
|
||||||
{
|
{
|
||||||
|
[Dependency] private readonly SharedItemSystem _itemSystem = default!;
|
||||||
|
|
||||||
|
public override void Initialize()
|
||||||
|
{
|
||||||
|
base.Initialize();
|
||||||
|
|
||||||
|
SubscribeLocalEvent<PipeColorVisualsComponent, GetInhandVisualsEvent>(OnGetVisuals);
|
||||||
|
SubscribeLocalEvent<PipeColorVisualsComponent, BeforeRenderInGridEvent>(OnDrawInGrid);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This method is used to display the color changes of the pipe on the screen..
|
||||||
|
/// </summary>
|
||||||
|
private void OnGetVisuals(Entity<PipeColorVisualsComponent> item, ref GetInhandVisualsEvent args)
|
||||||
|
{
|
||||||
|
foreach (var (_, layerData) in args.Layers)
|
||||||
|
{
|
||||||
|
if (TryComp(item.Owner, out AtmosPipeColorComponent? pipeColor))
|
||||||
|
layerData.Color = pipeColor.Color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This method is used to change the pipe's color in a container grid.
|
||||||
|
/// </summary>
|
||||||
|
private void OnDrawInGrid(Entity<PipeColorVisualsComponent> item, ref BeforeRenderInGridEvent args)
|
||||||
|
{
|
||||||
|
if (TryComp(item.Owner, out AtmosPipeColorComponent? pipeColor))
|
||||||
|
args.Color = pipeColor.Color;
|
||||||
|
}
|
||||||
|
|
||||||
protected override void OnAppearanceChange(EntityUid uid, PipeColorVisualsComponent component, ref AppearanceChangeEvent args)
|
protected override void OnAppearanceChange(EntityUid uid, PipeColorVisualsComponent component, ref AppearanceChangeEvent args)
|
||||||
{
|
{
|
||||||
if (TryComp<SpriteComponent>(uid, out var sprite)
|
if (TryComp<SpriteComponent>(uid, out var sprite)
|
||||||
@@ -15,6 +50,8 @@ public sealed class PipeColorVisualizerSystem : VisualizerSystem<PipeColorVisual
|
|||||||
var layer = sprite[PipeVisualLayers.Pipe];
|
var layer = sprite[PipeVisualLayers.Pipe];
|
||||||
layer.Color = color.WithAlpha(layer.Color.A);
|
layer.Color = color.WithAlpha(layer.Color.A);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_itemSystem.VisualsChanged(uid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ public sealed partial class PumpControl : BoxContainer
|
|||||||
|
|
||||||
foreach (var value in Enum.GetValues<VentPumpDirection>())
|
foreach (var value in Enum.GetValues<VentPumpDirection>())
|
||||||
{
|
{
|
||||||
_pumpDirection.AddItem(Loc.GetString($"air-alarm-ui-pump-direction-{value.ToString().ToLower()}"), (int) value);
|
_pumpDirection.AddItem(Loc.GetString($"{value}"), (int) value);
|
||||||
}
|
}
|
||||||
|
|
||||||
_pumpDirection.SelectId((int) _data.PumpDirection);
|
_pumpDirection.SelectId((int) _data.PumpDirection);
|
||||||
@@ -72,7 +72,7 @@ public sealed partial class PumpControl : BoxContainer
|
|||||||
|
|
||||||
foreach (var value in Enum.GetValues<VentPressureBound>())
|
foreach (var value in Enum.GetValues<VentPressureBound>())
|
||||||
{
|
{
|
||||||
_pressureCheck.AddItem(Loc.GetString($"air-alarm-ui-pressure-bound-{value.ToString().ToLower()}"), (int) value);
|
_pressureCheck.AddItem(Loc.GetString($"{value}"), (int) value);
|
||||||
}
|
}
|
||||||
|
|
||||||
_pressureCheck.SelectId((int) _data.PressureChecks);
|
_pressureCheck.SelectId((int) _data.PressureChecks);
|
||||||
|
|||||||
@@ -27,15 +27,9 @@
|
|||||||
</BoxContainer>
|
</BoxContainer>
|
||||||
<!-- Lower row: every single gas -->
|
<!-- Lower row: every single gas -->
|
||||||
<Collapsible Margin="2 2 2 2">
|
<Collapsible Margin="2 2 2 2">
|
||||||
<CollapsibleHeading Title="{Loc 'air-alarm-ui-widget-gas-filters'}" />
|
<CollapsibleHeading Title="Gas filters" />
|
||||||
<CollapsibleBody Margin="20 0 0 0">
|
<CollapsibleBody Margin="20 0 0 0">
|
||||||
<BoxContainer Orientation="Vertical">
|
<GridContainer HorizontalExpand="True" Name="CGasContainer" Columns="3" />
|
||||||
<BoxContainer Margin="2">
|
|
||||||
<Button Name="CSelectAll" Text="{Loc 'air-alarm-ui-scrubber-select-all-gases-label'}" />
|
|
||||||
<Button Name="CDeselectAll" Text="{Loc 'air-alarm-ui-scrubber-deselect-all-gases-label'}" />
|
|
||||||
</BoxContainer>
|
|
||||||
<GridContainer Name="CGasContainer" Columns="3" />
|
|
||||||
</BoxContainer>
|
|
||||||
</CollapsibleBody>
|
</CollapsibleBody>
|
||||||
</Collapsible>
|
</Collapsible>
|
||||||
</BoxContainer>
|
</BoxContainer>
|
||||||
|
|||||||
@@ -1,21 +1,15 @@
|
|||||||
using Content.Shared.Atmos;
|
using Content.Shared.Atmos;
|
||||||
using Content.Shared.Atmos.EntitySystems;
|
|
||||||
using Content.Shared.Atmos.Monitor.Components;
|
using Content.Shared.Atmos.Monitor.Components;
|
||||||
using Content.Shared.Atmos.Piping.Unary.Components;
|
using Content.Shared.Atmos.Piping.Unary.Components;
|
||||||
using Content.Shared.Atmos.Prototypes;
|
|
||||||
using Robust.Client.AutoGenerated;
|
using Robust.Client.AutoGenerated;
|
||||||
using Robust.Client.UserInterface.Controls;
|
using Robust.Client.UserInterface.Controls;
|
||||||
using Robust.Client.UserInterface.XAML;
|
using Robust.Client.UserInterface.XAML;
|
||||||
using Robust.Shared.Prototypes;
|
|
||||||
|
|
||||||
namespace Content.Client.Atmos.Monitor.UI.Widgets;
|
namespace Content.Client.Atmos.Monitor.UI.Widgets;
|
||||||
|
|
||||||
[GenerateTypedNameReferences]
|
[GenerateTypedNameReferences]
|
||||||
public sealed partial class ScrubberControl : BoxContainer
|
public sealed partial class ScrubberControl : BoxContainer
|
||||||
{
|
{
|
||||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
|
||||||
[Dependency] private readonly IEntityManager _entMan = default!;
|
|
||||||
|
|
||||||
private GasVentScrubberData _data;
|
private GasVentScrubberData _data;
|
||||||
private string _address;
|
private string _address;
|
||||||
|
|
||||||
@@ -28,18 +22,12 @@ public sealed partial class ScrubberControl : BoxContainer
|
|||||||
private FloatSpinBox _volumeRate => CVolumeRate;
|
private FloatSpinBox _volumeRate => CVolumeRate;
|
||||||
private CheckBox _wideNet => CWideNet;
|
private CheckBox _wideNet => CWideNet;
|
||||||
private Button _copySettings => CCopySettings;
|
private Button _copySettings => CCopySettings;
|
||||||
private Button _selectAll => CSelectAll;
|
|
||||||
private Button _deselectAll => CDeselectAll;
|
|
||||||
|
|
||||||
private GridContainer _gases => CGasContainer;
|
private GridContainer _gases => CGasContainer;
|
||||||
private Dictionary<Gas, Button> _gasControls = new();
|
private Dictionary<Gas, Button> _gasControls = new();
|
||||||
|
|
||||||
public ScrubberControl(GasVentScrubberData data, string address)
|
public ScrubberControl(GasVentScrubberData data, string address)
|
||||||
{
|
{
|
||||||
|
|
||||||
IoCManager.InjectDependencies(this);
|
|
||||||
var atmosphereSystem = _entMan.System<SharedAtmosphereSystem>();
|
|
||||||
|
|
||||||
RobustXamlLoader.Load(this);
|
RobustXamlLoader.Load(this);
|
||||||
|
|
||||||
Name = address;
|
Name = address;
|
||||||
@@ -73,7 +61,7 @@ public sealed partial class ScrubberControl : BoxContainer
|
|||||||
|
|
||||||
foreach (var value in Enum.GetValues<ScrubberPumpDirection>())
|
foreach (var value in Enum.GetValues<ScrubberPumpDirection>())
|
||||||
{
|
{
|
||||||
_pumpDirection.AddItem(Loc.GetString($"air-alarm-ui-pump-direction-{value.ToString().ToLower()}"), (int) value);
|
_pumpDirection.AddItem(Loc.GetString($"{value}"), (int) value);
|
||||||
}
|
}
|
||||||
|
|
||||||
_pumpDirection.SelectId((int) _data.PumpDirection);
|
_pumpDirection.SelectId((int) _data.PumpDirection);
|
||||||
@@ -90,28 +78,12 @@ public sealed partial class ScrubberControl : BoxContainer
|
|||||||
ScrubberDataCopied?.Invoke(_data);
|
ScrubberDataCopied?.Invoke(_data);
|
||||||
};
|
};
|
||||||
|
|
||||||
var allGases = Enum.GetValues<Gas>();
|
foreach (var value in Enum.GetValues<Gas>())
|
||||||
_selectAll.OnPressed += _ =>
|
|
||||||
{
|
{
|
||||||
_data.FilterGases = new HashSet<Gas>(allGases);
|
|
||||||
ScrubberDataChanged?.Invoke(_address, _data);
|
|
||||||
};
|
|
||||||
|
|
||||||
_deselectAll.OnPressed += _ =>
|
|
||||||
{
|
|
||||||
_data.FilterGases = [];
|
|
||||||
ScrubberDataChanged?.Invoke(_address, _data);
|
|
||||||
};
|
|
||||||
|
|
||||||
foreach (var value in allGases)
|
|
||||||
{
|
|
||||||
ProtoId<GasPrototype> gasProtoId = atmosphereSystem.GetGas(value);
|
|
||||||
var gasName = _prototypeManager.Index(gasProtoId).Name;
|
|
||||||
|
|
||||||
var gasButton = new Button
|
var gasButton = new Button
|
||||||
{
|
{
|
||||||
Name = value.ToString(),
|
Name = value.ToString(),
|
||||||
Text = Loc.GetString(gasName),
|
Text = Loc.GetString($"{value}"),
|
||||||
ToggleMode = true,
|
ToggleMode = true,
|
||||||
HorizontalExpand = true,
|
HorizontalExpand = true,
|
||||||
Pressed = _data.FilterGases.Contains(value)
|
Pressed = _data.FilterGases.Contains(value)
|
||||||
|
|||||||
@@ -1,22 +1,16 @@
|
|||||||
using Content.Client.Message;
|
using Content.Client.Message;
|
||||||
using Content.Shared.Atmos;
|
using Content.Shared.Atmos;
|
||||||
using Content.Shared.Atmos.EntitySystems;
|
|
||||||
using Content.Shared.Atmos.Monitor;
|
using Content.Shared.Atmos.Monitor;
|
||||||
using Content.Shared.Atmos.Prototypes;
|
|
||||||
using Content.Shared.Temperature;
|
using Content.Shared.Temperature;
|
||||||
using Robust.Client.AutoGenerated;
|
using Robust.Client.AutoGenerated;
|
||||||
using Robust.Client.UserInterface.Controls;
|
using Robust.Client.UserInterface.Controls;
|
||||||
using Robust.Client.UserInterface.XAML;
|
using Robust.Client.UserInterface.XAML;
|
||||||
using Robust.Shared.Prototypes;
|
|
||||||
|
|
||||||
namespace Content.Client.Atmos.Monitor.UI.Widgets;
|
namespace Content.Client.Atmos.Monitor.UI.Widgets;
|
||||||
|
|
||||||
[GenerateTypedNameReferences]
|
[GenerateTypedNameReferences]
|
||||||
public sealed partial class SensorInfo : BoxContainer
|
public sealed partial class SensorInfo : BoxContainer
|
||||||
{
|
{
|
||||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
|
||||||
[Dependency] private readonly IEntityManager _entMan = default!;
|
|
||||||
|
|
||||||
public Action<string, AtmosMonitorThresholdType, AtmosAlarmThreshold, Gas?>? OnThresholdUpdate;
|
public Action<string, AtmosMonitorThresholdType, AtmosAlarmThreshold, Gas?>? OnThresholdUpdate;
|
||||||
public event Action<AtmosSensorData>? SensorDataCopied;
|
public event Action<AtmosSensorData>? SensorDataCopied;
|
||||||
private string _address;
|
private string _address;
|
||||||
@@ -29,9 +23,6 @@ public sealed partial class SensorInfo : BoxContainer
|
|||||||
|
|
||||||
public SensorInfo(AtmosSensorData data, string address)
|
public SensorInfo(AtmosSensorData data, string address)
|
||||||
{
|
{
|
||||||
IoCManager.InjectDependencies(this);
|
|
||||||
var atmosphereSystem = _entMan.System<SharedAtmosphereSystem>();
|
|
||||||
|
|
||||||
RobustXamlLoader.Load(this);
|
RobustXamlLoader.Load(this);
|
||||||
|
|
||||||
_address = address;
|
_address = address;
|
||||||
@@ -54,12 +45,8 @@ public sealed partial class SensorInfo : BoxContainer
|
|||||||
var label = new RichTextLabel();
|
var label = new RichTextLabel();
|
||||||
|
|
||||||
var fractionGas = amount / data.TotalMoles;
|
var fractionGas = amount / data.TotalMoles;
|
||||||
|
|
||||||
ProtoId<GasPrototype> gasProtoId = atmosphereSystem.GetGas(gas);
|
|
||||||
var gasName = _prototypeManager.Index(gasProtoId).Name;
|
|
||||||
|
|
||||||
label.SetMarkup(Loc.GetString("air-alarm-ui-gases-indicator",
|
label.SetMarkup(Loc.GetString("air-alarm-ui-gases-indicator",
|
||||||
("gas", Loc.GetString(gasName)),
|
("gas", $"{gas}"),
|
||||||
("color", AirAlarmWindow.ColorForThreshold(fractionGas, data.GasThresholds[gas])),
|
("color", AirAlarmWindow.ColorForThreshold(fractionGas, data.GasThresholds[gas])),
|
||||||
("amount", $"{amount:0.####}"),
|
("amount", $"{amount:0.####}"),
|
||||||
("percentage", $"{(100 * fractionGas):0.##}")));
|
("percentage", $"{(100 * fractionGas):0.##}")));
|
||||||
@@ -67,7 +54,7 @@ public sealed partial class SensorInfo : BoxContainer
|
|||||||
_gasLabels.Add(gas, label);
|
_gasLabels.Add(gas, label);
|
||||||
|
|
||||||
var threshold = data.GasThresholds[gas];
|
var threshold = data.GasThresholds[gas];
|
||||||
var gasThresholdControl = new ThresholdControl(Loc.GetString($"air-alarm-ui-thresholds-gas-title"), threshold, AtmosMonitorThresholdType.Gas, gas, 100);
|
var gasThresholdControl = new ThresholdControl(Loc.GetString($"air-alarm-ui-thresholds-gas-title", ("gas", $"{gas}")), threshold, AtmosMonitorThresholdType.Gas, gas, 100);
|
||||||
gasThresholdControl.Margin = new Thickness(20, 2, 2, 2);
|
gasThresholdControl.Margin = new Thickness(20, 2, 2, 2);
|
||||||
gasThresholdControl.ThresholdDataChanged += (type, alarmThreshold, arg3) =>
|
gasThresholdControl.ThresholdDataChanged += (type, alarmThreshold, arg3) =>
|
||||||
{
|
{
|
||||||
@@ -103,9 +90,6 @@ public sealed partial class SensorInfo : BoxContainer
|
|||||||
|
|
||||||
public void ChangeData(AtmosSensorData data)
|
public void ChangeData(AtmosSensorData data)
|
||||||
{
|
{
|
||||||
IoCManager.InjectDependencies(this);
|
|
||||||
var atmosphereSystem = _entMan.System<SharedAtmosphereSystem>();
|
|
||||||
|
|
||||||
SensorAddress.Title = Loc.GetString("air-alarm-ui-window-listing-title", ("address", _address), ("state", data.AlarmState));
|
SensorAddress.Title = Loc.GetString("air-alarm-ui-window-listing-title", ("address", _address), ("state", data.AlarmState));
|
||||||
|
|
||||||
AlarmStateLabel.SetMarkup(Loc.GetString("air-alarm-ui-window-alarm-state-indicator",
|
AlarmStateLabel.SetMarkup(Loc.GetString("air-alarm-ui-window-alarm-state-indicator",
|
||||||
@@ -128,12 +112,8 @@ public sealed partial class SensorInfo : BoxContainer
|
|||||||
}
|
}
|
||||||
|
|
||||||
var fractionGas = amount / data.TotalMoles;
|
var fractionGas = amount / data.TotalMoles;
|
||||||
|
|
||||||
ProtoId<GasPrototype> gasProtoId = atmosphereSystem.GetGas(gas);
|
|
||||||
var gasName = _prototypeManager.Index(gasProtoId).Name;
|
|
||||||
|
|
||||||
label.SetMarkup(Loc.GetString("air-alarm-ui-gases-indicator",
|
label.SetMarkup(Loc.GetString("air-alarm-ui-gases-indicator",
|
||||||
("gas", Loc.GetString(gasName)),
|
("gas", $"{gas}"),
|
||||||
("color", AirAlarmWindow.ColorForThreshold(fractionGas, data.GasThresholds[gas])),
|
("color", AirAlarmWindow.ColorForThreshold(fractionGas, data.GasThresholds[gas])),
|
||||||
("amount", $"{amount:0.####}"),
|
("amount", $"{amount:0.####}"),
|
||||||
("percentage", $"{(100 * fractionGas):0.##}")));
|
("percentage", $"{(100 * fractionGas):0.##}")));
|
||||||
|
|||||||
@@ -2,6 +2,6 @@
|
|||||||
HorizontalExpand="True" Orientation="Vertical"
|
HorizontalExpand="True" Orientation="Vertical"
|
||||||
Margin = "20 0 0 0" MinSize="160 0" >
|
Margin = "20 0 0 0" MinSize="160 0" >
|
||||||
<Label Name="CBoundLabel" HorizontalAlignment="Center" />
|
<Label Name="CBoundLabel" HorizontalAlignment="Center" />
|
||||||
<CheckBox Name="CBoundEnabled" HorizontalAlignment="Center" Text="{Loc 'air-alarm-ui-widget-enable'}" Pressed="True" />
|
<CheckBox Name="CBoundEnabled" HorizontalAlignment="Center" Text="{Loc 'Enable'}" Pressed="True" />
|
||||||
<FloatSpinBox Name="CSpinner" />
|
<FloatSpinBox Name="CSpinner" />
|
||||||
</BoxContainer>
|
</BoxContainer>
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
<CollapsibleBody Margin="20 0 0 0">
|
<CollapsibleBody Margin="20 0 0 0">
|
||||||
<BoxContainer Orientation="Vertical">
|
<BoxContainer Orientation="Vertical">
|
||||||
<BoxContainer Orientation="Horizontal">
|
<BoxContainer Orientation="Horizontal">
|
||||||
<CheckBox Name="CEnabled" Text="{Loc 'air-alarm-ui-widget-enable'}" />
|
<CheckBox Name="CEnabled" Text="{Loc 'Enabled'}" />
|
||||||
</BoxContainer>
|
</BoxContainer>
|
||||||
<!-- Upper row: Danger bounds -->
|
<!-- Upper row: Danger bounds -->
|
||||||
<BoxContainer Name="CDangerBounds" Orientation="Horizontal" Margin="0 0 0 2"/>
|
<BoxContainer Name="CDangerBounds" Orientation="Horizontal" Margin="0 0 0 2"/>
|
||||||
|
|||||||
@@ -208,7 +208,7 @@ namespace Content.Client.Atmos.UI
|
|||||||
});
|
});
|
||||||
presBox.AddChild(new Label
|
presBox.AddChild(new Label
|
||||||
{
|
{
|
||||||
Text = Loc.GetString("gas-analyzer-window-pressure-val-text", ("pressure", $"{gasMix.Pressure:0.00}")),
|
Text = Loc.GetString("gas-analyzer-window-pressure-val-text", ("pressure", $"{gasMix.Pressure:0.##}")),
|
||||||
Align = Label.AlignMode.Right,
|
Align = Label.AlignMode.Right,
|
||||||
HorizontalExpand = true
|
HorizontalExpand = true
|
||||||
});
|
});
|
||||||
@@ -232,8 +232,8 @@ namespace Content.Client.Atmos.UI
|
|||||||
tempBox.AddChild(new Label
|
tempBox.AddChild(new Label
|
||||||
{
|
{
|
||||||
Text = Loc.GetString("gas-analyzer-window-temperature-val-text",
|
Text = Loc.GetString("gas-analyzer-window-temperature-val-text",
|
||||||
("tempK", $"{gasMix.Temperature:0.0}"),
|
("tempK", $"{gasMix.Temperature:0.#}"),
|
||||||
("tempC", $"{TemperatureHelpers.KelvinToCelsius(gasMix.Temperature):0.0}")),
|
("tempC", $"{TemperatureHelpers.KelvinToCelsius(gasMix.Temperature):0.#}")),
|
||||||
Align = Label.AlignMode.Right,
|
Align = Label.AlignMode.Right,
|
||||||
HorizontalExpand = true
|
HorizontalExpand = true
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -3,13 +3,17 @@ using Content.Shared.CCVar;
|
|||||||
using Robust.Client.Graphics;
|
using Robust.Client.Graphics;
|
||||||
using Robust.Client.Player;
|
using Robust.Client.Player;
|
||||||
using Robust.Shared.Audio;
|
using Robust.Shared.Audio;
|
||||||
|
using Robust.Shared.Log;
|
||||||
using Robust.Shared.Configuration;
|
using Robust.Shared.Configuration;
|
||||||
|
using Robust.Shared.Map;
|
||||||
using Robust.Shared.Physics;
|
using Robust.Shared.Physics;
|
||||||
using Robust.Shared.Random;
|
using Robust.Shared.Random;
|
||||||
using Robust.Shared.Timing;
|
using Robust.Shared.Timing;
|
||||||
using Robust.Shared.Utility;
|
using Robust.Shared.Utility;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
|
using Robust.Client.GameObjects;
|
||||||
|
using Robust.Shared.Audio.Effects;
|
||||||
using Robust.Shared.Audio.Systems;
|
using Robust.Shared.Audio.Systems;
|
||||||
using Robust.Shared.Player;
|
using Robust.Shared.Player;
|
||||||
|
|
||||||
@@ -27,7 +31,6 @@ public sealed class AmbientSoundSystem : SharedAmbientSoundSystem
|
|||||||
[Dependency] private readonly SharedTransformSystem _xformSystem = default!;
|
[Dependency] private readonly SharedTransformSystem _xformSystem = default!;
|
||||||
[Dependency] private readonly IConfigurationManager _cfg = default!;
|
[Dependency] private readonly IConfigurationManager _cfg = default!;
|
||||||
[Dependency] private readonly IGameTiming _gameTiming = default!;
|
[Dependency] private readonly IGameTiming _gameTiming = default!;
|
||||||
[Dependency] private readonly IOverlayManager _overlayManager = default!;
|
|
||||||
[Dependency] private readonly IPlayerManager _playerManager = default!;
|
[Dependency] private readonly IPlayerManager _playerManager = default!;
|
||||||
[Dependency] private readonly IRobustRandom _random = default!;
|
[Dependency] private readonly IRobustRandom _random = default!;
|
||||||
|
|
||||||
@@ -62,19 +65,18 @@ public sealed class AmbientSoundSystem : SharedAmbientSoundSystem
|
|||||||
get => _overlayEnabled;
|
get => _overlayEnabled;
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
if (_overlayEnabled == value)
|
if (_overlayEnabled == value) return;
|
||||||
return;
|
|
||||||
|
|
||||||
_overlayEnabled = value;
|
_overlayEnabled = value;
|
||||||
|
var overlayManager = IoCManager.Resolve<IOverlayManager>();
|
||||||
|
|
||||||
if (_overlayEnabled)
|
if (_overlayEnabled)
|
||||||
{
|
{
|
||||||
_overlay = new AmbientSoundOverlay(EntityManager, this, EntityManager.System<EntityLookupSystem>());
|
_overlay = new AmbientSoundOverlay(EntityManager, this, EntityManager.System<EntityLookupSystem>());
|
||||||
_overlayManager.AddOverlay(_overlay);
|
overlayManager.AddOverlay(_overlay);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_overlayManager.RemoveOverlay(_overlay!);
|
overlayManager.RemoveOverlay(_overlay!);
|
||||||
_overlay = null;
|
_overlay = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,8 +3,11 @@ using Content.Client.Gameplay;
|
|||||||
using Content.Shared.Audio;
|
using Content.Shared.Audio;
|
||||||
using Content.Shared.CCVar;
|
using Content.Shared.CCVar;
|
||||||
using Content.Shared.GameTicking;
|
using Content.Shared.GameTicking;
|
||||||
|
using Content.Shared.Random;
|
||||||
using Content.Shared.Random.Rules;
|
using Content.Shared.Random.Rules;
|
||||||
|
using Robust.Client.GameObjects;
|
||||||
using Robust.Client.Player;
|
using Robust.Client.Player;
|
||||||
|
using Robust.Client.ResourceManagement;
|
||||||
using Robust.Client.State;
|
using Robust.Client.State;
|
||||||
using Robust.Shared.Audio;
|
using Robust.Shared.Audio;
|
||||||
using Robust.Shared.Audio.Components;
|
using Robust.Shared.Audio.Components;
|
||||||
@@ -22,7 +25,6 @@ public sealed partial class ContentAudioSystem
|
|||||||
{
|
{
|
||||||
[Dependency] private readonly IConfigurationManager _configManager = default!;
|
[Dependency] private readonly IConfigurationManager _configManager = default!;
|
||||||
[Dependency] private readonly IGameTiming _timing = default!;
|
[Dependency] private readonly IGameTiming _timing = default!;
|
||||||
[Dependency] private readonly ILogManager _logManager = default!;
|
|
||||||
[Dependency] private readonly IPlayerManager _player = default!;
|
[Dependency] private readonly IPlayerManager _player = default!;
|
||||||
[Dependency] private readonly IPrototypeManager _proto = default!;
|
[Dependency] private readonly IPrototypeManager _proto = default!;
|
||||||
[Dependency] private readonly IRobustRandom _random = default!;
|
[Dependency] private readonly IRobustRandom _random = default!;
|
||||||
@@ -59,7 +61,7 @@ public sealed partial class ContentAudioSystem
|
|||||||
private void InitializeAmbientMusic()
|
private void InitializeAmbientMusic()
|
||||||
{
|
{
|
||||||
Subs.CVar(_configManager, CCVars.AmbientMusicVolume, AmbienceCVarChanged, true);
|
Subs.CVar(_configManager, CCVars.AmbientMusicVolume, AmbienceCVarChanged, true);
|
||||||
_sawmill = _logManager.GetSawmill("audio.ambience");
|
_sawmill = IoCManager.Resolve<ILogManager>().GetSawmill("audio.ambience");
|
||||||
|
|
||||||
// Reset audio
|
// Reset audio
|
||||||
_nextAudio = TimeSpan.MaxValue;
|
_nextAudio = TimeSpan.MaxValue;
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ public sealed class JukeboxBoundUserInterface : BoundUserInterface
|
|||||||
|
|
||||||
_menu.SetAudioStream(jukebox.AudioStream);
|
_menu.SetAudioStream(jukebox.AudioStream);
|
||||||
|
|
||||||
if (_protoManager.Resolve(jukebox.SelectedSongId, out var songProto))
|
if (_protoManager.TryIndex(jukebox.SelectedSongId, out var songProto))
|
||||||
{
|
{
|
||||||
var length = EntMan.System<AudioSystem>().GetAudioLength(songProto.Path.Path.ToString());
|
var length = EntMan.System<AudioSystem>().GetAudioLength(songProto.Path.Path.ToString());
|
||||||
_menu.SetSelectedSong(songProto.Name, (float) length.TotalSeconds);
|
_menu.SetSelectedSong(songProto.Name, (float) length.TotalSeconds);
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ public sealed class BarSignSystem : VisualizerSystem<BarSignComponent>
|
|||||||
|
|
||||||
if (powered
|
if (powered
|
||||||
&& sign.Current != null
|
&& sign.Current != null
|
||||||
&& _prototypeManager.Resolve(sign.Current, out var proto))
|
&& _prototypeManager.TryIndex(sign.Current, out var proto))
|
||||||
{
|
{
|
||||||
SpriteSystem.LayerSetSprite((id, sprite), 0, proto.Icon);
|
SpriteSystem.LayerSetSprite((id, sprite), 0, proto.Icon);
|
||||||
sprite.LayerSetShader(0, "unshaded");
|
sprite.LayerSetShader(0, "unshaded");
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ public sealed class BarSignBoundUserInterface(EntityUid owner, Enum uiKey) : Bou
|
|||||||
|
|
||||||
public void Update(ProtoId<BarSignPrototype>? sign)
|
public void Update(ProtoId<BarSignPrototype>? sign)
|
||||||
{
|
{
|
||||||
if (_prototype.Resolve(sign, out var signPrototype))
|
if (_prototype.TryIndex(sign, out var signPrototype))
|
||||||
_menu?.UpdateState(signPrototype);
|
_menu?.UpdateState(signPrototype);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
|
using Content.Shared.Body.Components;
|
||||||
using Content.Shared.CardboardBox;
|
using Content.Shared.CardboardBox;
|
||||||
using Content.Shared.CardboardBox.Components;
|
using Content.Shared.CardboardBox.Components;
|
||||||
using Content.Shared.Examine;
|
using Content.Shared.Examine;
|
||||||
using Content.Shared.Mobs.Components;
|
|
||||||
using Content.Shared.Movement.Components;
|
using Content.Shared.Movement.Components;
|
||||||
using Robust.Client.GameObjects;
|
using Robust.Client.GameObjects;
|
||||||
|
|
||||||
@@ -15,13 +15,13 @@ public sealed class CardboardBoxSystem : SharedCardboardBoxSystem
|
|||||||
[Dependency] private readonly ExamineSystemShared _examine = default!;
|
[Dependency] private readonly ExamineSystemShared _examine = default!;
|
||||||
[Dependency] private readonly SpriteSystem _sprite = default!;
|
[Dependency] private readonly SpriteSystem _sprite = default!;
|
||||||
|
|
||||||
private EntityQuery<MobStateComponent> _mobStateQuery;
|
private EntityQuery<BodyComponent> _bodyQuery;
|
||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
base.Initialize();
|
base.Initialize();
|
||||||
|
|
||||||
_mobStateQuery = GetEntityQuery<MobStateComponent>();
|
_bodyQuery = GetEntityQuery<BodyComponent>();
|
||||||
|
|
||||||
SubscribeNetworkEvent<PlayBoxEffectMessage>(OnBoxEffect);
|
SubscribeNetworkEvent<PlayBoxEffectMessage>(OnBoxEffect);
|
||||||
}
|
}
|
||||||
@@ -66,8 +66,8 @@ public sealed class CardboardBoxSystem : SharedCardboardBoxSystem
|
|||||||
if (!_examine.InRangeUnOccluded(sourcePos, mapPos, box.Distance, null))
|
if (!_examine.InRangeUnOccluded(sourcePos, mapPos, box.Distance, null))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// no effect for non-mobs that have MobMover, such as mechs and vehicles.
|
// no effect for anything too exotic
|
||||||
if (!_mobStateQuery.HasComp(mob))
|
if (!_bodyQuery.HasComp(mob))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
var ent = Spawn(box.Effect, mapPos);
|
var ent = Spawn(box.Effect, mapPos);
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ public sealed partial class BountyEntry : BoxContainer
|
|||||||
|
|
||||||
UntilNextSkip = untilNextSkip;
|
UntilNextSkip = untilNextSkip;
|
||||||
|
|
||||||
if (!_prototype.Resolve<CargoBountyPrototype>(bounty.Bounty, out var bountyPrototype))
|
if (!_prototype.TryIndex<CargoBountyPrototype>(bounty.Bounty, out var bountyPrototype))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var items = new List<string>();
|
var items = new List<string>();
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ public sealed partial class BountyHistoryEntry : BoxContainer
|
|||||||
RobustXamlLoader.Load(this);
|
RobustXamlLoader.Load(this);
|
||||||
IoCManager.InjectDependencies(this);
|
IoCManager.InjectDependencies(this);
|
||||||
|
|
||||||
if (!_prototype.Resolve(bounty.Bounty, out var bountyPrototype))
|
if (!_prototype.TryIndex(bounty.Bounty, out var bountyPrototype))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var items = new List<string>();
|
var items = new List<string>();
|
||||||
|
|||||||
@@ -1,30 +0,0 @@
|
|||||||
using Content.Shared.Changeling.Components;
|
|
||||||
using Content.Shared.Changeling.Systems;
|
|
||||||
using Robust.Client.GameObjects;
|
|
||||||
|
|
||||||
namespace Content.Client.Changeling.Systems;
|
|
||||||
|
|
||||||
public sealed class ChangelingIdentitySystem : SharedChangelingIdentitySystem
|
|
||||||
{
|
|
||||||
[Dependency] private readonly UserInterfaceSystem _ui = default!;
|
|
||||||
|
|
||||||
public override void Initialize()
|
|
||||||
{
|
|
||||||
base.Initialize();
|
|
||||||
|
|
||||||
SubscribeLocalEvent<ChangelingIdentityComponent, AfterAutoHandleStateEvent>(OnAfterAutoHandleState);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnAfterAutoHandleState(Entity<ChangelingIdentityComponent> ent, ref AfterAutoHandleStateEvent args)
|
|
||||||
{
|
|
||||||
UpdateUi(ent);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void UpdateUi(EntityUid uid)
|
|
||||||
{
|
|
||||||
if (_ui.TryGetOpenUi(uid, ChangelingTransformUiKey.Key, out var bui))
|
|
||||||
{
|
|
||||||
bui.Update();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,68 +0,0 @@
|
|||||||
using Content.Client.Stylesheets;
|
|
||||||
using Content.Client.UserInterface.Controls;
|
|
||||||
using Content.Shared.Changeling.Components;
|
|
||||||
using Content.Shared.Changeling.Systems;
|
|
||||||
using JetBrains.Annotations;
|
|
||||||
using Robust.Client.UserInterface;
|
|
||||||
|
|
||||||
namespace Content.Client.Changeling.UI;
|
|
||||||
|
|
||||||
[UsedImplicitly]
|
|
||||||
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);
|
|
||||||
|
|
||||||
protected override void Open()
|
|
||||||
{
|
|
||||||
base.Open();
|
|
||||||
|
|
||||||
_menu = this.CreateWindow<SimpleRadialMenu>();
|
|
||||||
Update();
|
|
||||||
_menu.OpenOverMouseScreenPosition();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public override void Update()
|
|
||||||
{
|
|
||||||
if (_menu == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!EntMan.TryGetComponent<ChangelingIdentityComponent>(Owner, out var lingIdentity))
|
|
||||||
return;
|
|
||||||
|
|
||||||
var models = ConvertToButtons(lingIdentity.ConsumedIdentities, lingIdentity?.CurrentIdentity);
|
|
||||||
|
|
||||||
_menu.SetButtons(models);
|
|
||||||
}
|
|
||||||
|
|
||||||
private IEnumerable<RadialMenuOptionBase> ConvertToButtons(
|
|
||||||
IEnumerable<EntityUid> identities,
|
|
||||||
EntityUid? currentIdentity
|
|
||||||
)
|
|
||||||
{
|
|
||||||
var buttons = new List<RadialMenuOptionBase>();
|
|
||||||
foreach (var identity in identities)
|
|
||||||
{
|
|
||||||
if (!EntMan.TryGetComponent<MetaDataComponent>(identity, out var metadata))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
var option = new RadialMenuActionOption<NetEntity>(SendIdentitySelect, EntMan.GetNetEntity(identity))
|
|
||||||
{
|
|
||||||
IconSpecifier = RadialMenuIconSpecifier.With(identity),
|
|
||||||
ToolTip = metadata.EntityName,
|
|
||||||
BackgroundColor = (currentIdentity == identity) ? SelectedOptionBackground : null,
|
|
||||||
HoverBackgroundColor = (currentIdentity == identity) ? SelectedOptionHoverBackground : null
|
|
||||||
};
|
|
||||||
buttons.Add(option);
|
|
||||||
}
|
|
||||||
|
|
||||||
return buttons;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void SendIdentitySelect(NetEntity identityId)
|
|
||||||
{
|
|
||||||
SendPredictedMessage(new ChangelingTransformIdentitySelectMessage(identityId));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -27,7 +27,7 @@ public sealed class TypingIndicatorVisualizerSystem : VisualizerSystem<TypingInd
|
|||||||
if (overrideIndicator != null)
|
if (overrideIndicator != null)
|
||||||
currentTypingIndicator = overrideIndicator.Value;
|
currentTypingIndicator = overrideIndicator.Value;
|
||||||
|
|
||||||
if (!_prototypeManager.Resolve(currentTypingIndicator, out var proto))
|
if (!_prototypeManager.TryIndex(currentTypingIndicator, out var proto))
|
||||||
{
|
{
|
||||||
Log.Error($"Unknown typing indicator id: {component.TypingIndicatorPrototype}");
|
Log.Error($"Unknown typing indicator id: {component.TypingIndicatorPrototype}");
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ using Content.Client.Chemistry.UI;
|
|||||||
using Content.Client.Items;
|
using Content.Client.Items;
|
||||||
using Content.Shared.Chemistry.Components;
|
using Content.Shared.Chemistry.Components;
|
||||||
using Content.Shared.Chemistry.EntitySystems;
|
using Content.Shared.Chemistry.EntitySystems;
|
||||||
|
using Robust.Shared.GameStates;
|
||||||
|
|
||||||
namespace Content.Client.Chemistry.EntitySystems;
|
namespace Content.Client.Chemistry.EntitySystems;
|
||||||
|
|
||||||
@@ -10,7 +11,6 @@ public sealed class InjectorSystem : SharedInjectorSystem
|
|||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
base.Initialize();
|
base.Initialize();
|
||||||
|
Subs.ItemStatus<InjectorComponent>(ent => new InjectorStatusControl(ent, SolutionContainers));
|
||||||
Subs.ItemStatus<InjectorComponent>(ent => new InjectorStatusControl(ent, SolutionContainer));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,13 +38,13 @@ public sealed class InjectorStatusControl : Control
|
|||||||
// only updates the UI if any of the details are different than they previously were
|
// only updates the UI if any of the details are different than they previously were
|
||||||
if (PrevVolume == solution.Volume
|
if (PrevVolume == solution.Volume
|
||||||
&& PrevMaxVolume == solution.MaxVolume
|
&& PrevMaxVolume == solution.MaxVolume
|
||||||
&& PrevTransferAmount == _parent.Comp.CurrentTransferAmount
|
&& PrevTransferAmount == _parent.Comp.TransferAmount
|
||||||
&& PrevToggleState == _parent.Comp.ToggleState)
|
&& PrevToggleState == _parent.Comp.ToggleState)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
PrevVolume = solution.Volume;
|
PrevVolume = solution.Volume;
|
||||||
PrevMaxVolume = solution.MaxVolume;
|
PrevMaxVolume = solution.MaxVolume;
|
||||||
PrevTransferAmount = _parent.Comp.CurrentTransferAmount;
|
PrevTransferAmount = _parent.Comp.TransferAmount;
|
||||||
PrevToggleState = _parent.Comp.ToggleState;
|
PrevToggleState = _parent.Comp.ToggleState;
|
||||||
|
|
||||||
// Update current volume and injector state
|
// Update current volume and injector state
|
||||||
@@ -59,6 +59,6 @@ public sealed class InjectorStatusControl : Control
|
|||||||
("currentVolume", solution.Volume),
|
("currentVolume", solution.Volume),
|
||||||
("totalVolume", solution.MaxVolume),
|
("totalVolume", solution.MaxVolume),
|
||||||
("modeString", modeStringLocalized),
|
("modeString", modeStringLocalized),
|
||||||
("transferVolume", _parent.Comp.CurrentTransferAmount)));
|
("transferVolume", _parent.Comp.TransferAmount)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +0,0 @@
|
|||||||
using Content.Shared.Cloning;
|
|
||||||
|
|
||||||
namespace Content.Client.Cloning;
|
|
||||||
|
|
||||||
public sealed partial class CloningSystem : SharedCloningSystem;
|
|
||||||
@@ -1,10 +1,12 @@
|
|||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Numerics;
|
||||||
using Content.Client.DisplacementMap;
|
using Content.Client.DisplacementMap;
|
||||||
using Content.Client.Inventory;
|
using Content.Client.Inventory;
|
||||||
using Content.Shared.Clothing;
|
using Content.Shared.Clothing;
|
||||||
using Content.Shared.Clothing.Components;
|
using Content.Shared.Clothing.Components;
|
||||||
using Content.Shared.Clothing.EntitySystems;
|
using Content.Shared.Clothing.EntitySystems;
|
||||||
|
using Content.Shared.DisplacementMap;
|
||||||
using Content.Shared.Humanoid;
|
using Content.Shared.Humanoid;
|
||||||
using Content.Shared.Inventory;
|
using Content.Shared.Inventory;
|
||||||
using Content.Shared.Inventory.Events;
|
using Content.Shared.Inventory.Events;
|
||||||
@@ -12,6 +14,7 @@ using Content.Shared.Item;
|
|||||||
using Robust.Client.GameObjects;
|
using Robust.Client.GameObjects;
|
||||||
using Robust.Client.Graphics;
|
using Robust.Client.Graphics;
|
||||||
using Robust.Client.ResourceManagement;
|
using Robust.Client.ResourceManagement;
|
||||||
|
using Robust.Shared.Serialization.Manager;
|
||||||
using Robust.Shared.Serialization.TypeSerializers.Implementations;
|
using Robust.Shared.Serialization.TypeSerializers.Implementations;
|
||||||
using Robust.Shared.Utility;
|
using Robust.Shared.Utility;
|
||||||
using static Robust.Client.GameObjects.SpriteComponent;
|
using static Robust.Client.GameObjects.SpriteComponent;
|
||||||
@@ -179,7 +182,6 @@ public sealed class ClientClothingSystem : ClothingSystem
|
|||||||
var layer = new PrototypeLayerData();
|
var layer = new PrototypeLayerData();
|
||||||
layer.RsiPath = rsi.Path.ToString();
|
layer.RsiPath = rsi.Path.ToString();
|
||||||
layer.State = state;
|
layer.State = state;
|
||||||
layer.Scale = clothing.Scale;
|
|
||||||
layers = new() { layer };
|
layers = new() { layer };
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ public sealed class ChameleonBoundUserInterface : BoundUserInterface
|
|||||||
var newTargets = new List<EntProtoId>();
|
var newTargets = new List<EntProtoId>();
|
||||||
foreach (var target in targets)
|
foreach (var target in targets)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(target) || !_proto.Resolve(target, out EntityPrototype? proto))
|
if (string.IsNullOrEmpty(target) || !_proto.TryIndex(target, out EntityPrototype? proto))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!proto.TryGetComponent(out TagComponent? tag, EntMan.ComponentFactory) || !_tag.HasTag(tag, st.RequiredTag))
|
if (!proto.TryGetComponent(out TagComponent? tag, EntMan.ComponentFactory) || !_tag.HasTag(tag, st.RequiredTag))
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ public sealed partial class ChameleonMenu : DefaultWindow
|
|||||||
|
|
||||||
foreach (var id in _possibleIds)
|
foreach (var id in _possibleIds)
|
||||||
{
|
{
|
||||||
if (!_prototypeManager.Resolve(id, out EntityPrototype? proto))
|
if (!_prototypeManager.TryIndex(id, out EntityPrototype? proto))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
var lowId = id.Id.ToLowerInvariant();
|
var lowId = id.Id.ToLowerInvariant();
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ namespace Content.Client.Construction
|
|||||||
{
|
{
|
||||||
foreach (var constructionProto in PrototypeManager.EnumeratePrototypes<ConstructionPrototype>())
|
foreach (var constructionProto in PrototypeManager.EnumeratePrototypes<ConstructionPrototype>())
|
||||||
{
|
{
|
||||||
if (!PrototypeManager.Resolve(constructionProto.Graph, out var graphProto))
|
if (!PrototypeManager.TryIndex(constructionProto.Graph, out var graphProto))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (constructionProto.TargetNode is not { } targetNodeId)
|
if (constructionProto.TargetNode is not { } targetNodeId)
|
||||||
@@ -121,14 +121,17 @@ namespace Content.Client.Construction
|
|||||||
// If we got the id of the prototype, we exit the “recursion” by clearing the stack.
|
// If we got the id of the prototype, we exit the “recursion” by clearing the stack.
|
||||||
stack.Clear();
|
stack.Clear();
|
||||||
|
|
||||||
if (!PrototypeManager.Resolve(entityId, out var proto))
|
if (!PrototypeManager.TryIndex(constructionProto.ID, out ConstructionPrototype? recipe))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
var name = constructionProto.SetName.HasValue ? Loc.GetString(constructionProto.SetName) : proto.Name;
|
if (!PrototypeManager.TryIndex(entityId, out var proto))
|
||||||
var desc = constructionProto.SetDescription.HasValue ? Loc.GetString(constructionProto.SetDescription) : proto.Description;
|
continue;
|
||||||
|
|
||||||
constructionProto.Name = name;
|
var name = recipe.SetName.HasValue ? Loc.GetString(recipe.SetName) : proto.Name;
|
||||||
constructionProto.Description = desc;
|
var desc = recipe.SetDescription.HasValue ? Loc.GetString(recipe.SetDescription) : proto.Description;
|
||||||
|
|
||||||
|
recipe.Name = name;
|
||||||
|
recipe.Description = desc;
|
||||||
|
|
||||||
_recipesMetadataCache.Add(constructionProto.ID, entityId);
|
_recipesMetadataCache.Add(constructionProto.ID, entityId);
|
||||||
} while (stack.Count > 0);
|
} while (stack.Count > 0);
|
||||||
@@ -169,7 +172,7 @@ namespace Content.Client.Construction
|
|||||||
"construction-ghost-examine-message",
|
"construction-ghost-examine-message",
|
||||||
("name", component.Prototype.Name)));
|
("name", component.Prototype.Name)));
|
||||||
|
|
||||||
if (!PrototypeManager.Resolve(component.Prototype.Graph, out var graph))
|
if (!PrototypeManager.TryIndex(component.Prototype.Graph, out var graph))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var startNode = graph.Nodes[component.Prototype.StartNode];
|
var startNode = graph.Nodes[component.Prototype.StartNode];
|
||||||
|
|||||||
@@ -528,7 +528,7 @@ namespace Content.Client.Construction.UI
|
|||||||
|
|
||||||
foreach (var id in favorites)
|
foreach (var id in favorites)
|
||||||
{
|
{
|
||||||
if (_prototypeManager.TryIndex(id, out ConstructionPrototype? recipe))
|
if (_prototypeManager.TryIndex(id, out ConstructionPrototype? recipe, logError: false))
|
||||||
_favoritedRecipes.Add(recipe);
|
_favoritedRecipes.Add(recipe);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ public sealed partial class CreditsWindow : DefaultWindow
|
|||||||
|
|
||||||
private async void PopulateAttributions(BoxContainer attributionsContainer, int count)
|
private async void PopulateAttributions(BoxContainer attributionsContainer, int count)
|
||||||
{
|
{
|
||||||
attributionsContainer.RemoveAllChildren();
|
attributionsContainer.DisposeAllChildren();
|
||||||
|
|
||||||
if (_attributions.Count == 0)
|
if (_attributions.Count == 0)
|
||||||
{
|
{
|
||||||
@@ -253,8 +253,6 @@ public sealed partial class CreditsWindow : DefaultWindow
|
|||||||
|
|
||||||
private void PopulateLicenses(BoxContainer licensesContainer)
|
private void PopulateLicenses(BoxContainer licensesContainer)
|
||||||
{
|
{
|
||||||
licensesContainer.RemoveAllChildren();
|
|
||||||
|
|
||||||
foreach (var entry in CreditsManager.GetLicenses(_resourceManager).OrderBy(p => p.Name))
|
foreach (var entry in CreditsManager.GetLicenses(_resourceManager).OrderBy(p => p.Name))
|
||||||
{
|
{
|
||||||
licensesContainer.AddChild(new Label
|
licensesContainer.AddChild(new Label
|
||||||
@@ -271,8 +269,6 @@ public sealed partial class CreditsWindow : DefaultWindow
|
|||||||
|
|
||||||
private void PopulatePatrons(BoxContainer patronsContainer)
|
private void PopulatePatrons(BoxContainer patronsContainer)
|
||||||
{
|
{
|
||||||
patronsContainer.RemoveAllChildren();
|
|
||||||
|
|
||||||
var patrons = LoadPatrons();
|
var patrons = LoadPatrons();
|
||||||
|
|
||||||
// Do not show "become a patron" button on Steam builds
|
// Do not show "become a patron" button on Steam builds
|
||||||
@@ -322,8 +318,6 @@ public sealed partial class CreditsWindow : DefaultWindow
|
|||||||
|
|
||||||
private void PopulateContributors(BoxContainer ss14ContributorsContainer)
|
private void PopulateContributors(BoxContainer ss14ContributorsContainer)
|
||||||
{
|
{
|
||||||
ss14ContributorsContainer.RemoveAllChildren();
|
|
||||||
|
|
||||||
Button contributeButton;
|
Button contributeButton;
|
||||||
|
|
||||||
ss14ContributorsContainer.AddChild(new BoxContainer
|
ss14ContributorsContainer.AddChild(new BoxContainer
|
||||||
@@ -362,7 +356,6 @@ public sealed partial class CreditsWindow : DefaultWindow
|
|||||||
AddSection(Loc.GetString("credits-window-contributors-section-title"), "GitHub.txt");
|
AddSection(Loc.GetString("credits-window-contributors-section-title"), "GitHub.txt");
|
||||||
AddSection(Loc.GetString("credits-window-codebases-section-title"), "SpaceStation13.txt");
|
AddSection(Loc.GetString("credits-window-codebases-section-title"), "SpaceStation13.txt");
|
||||||
AddSection(Loc.GetString("credits-window-original-remake-team-section-title"), "OriginalRemake.txt");
|
AddSection(Loc.GetString("credits-window-original-remake-team-section-title"), "OriginalRemake.txt");
|
||||||
AddSection(Loc.GetString("credits-window-immortals-title"), "Immortals.txt", true);
|
|
||||||
AddSection(Loc.GetString("credits-window-special-thanks-section-title"), "SpecialThanks.txt", true);
|
AddSection(Loc.GetString("credits-window-special-thanks-section-title"), "SpecialThanks.txt", true);
|
||||||
|
|
||||||
var linkGithub = _cfg.GetCVar(CCVars.InfoLinksGithub);
|
var linkGithub = _cfg.GetCVar(CCVars.InfoLinksGithub);
|
||||||
|
|||||||
@@ -150,7 +150,7 @@ public sealed class DamageVisualsSystem : VisualizerSystem<DamageVisualsComponen
|
|||||||
// If the damage container on our entity's DamageableComponent
|
// If the damage container on our entity's DamageableComponent
|
||||||
// is not null, we can try to check through its groups.
|
// is not null, we can try to check through its groups.
|
||||||
if (damageComponent.DamageContainerID != null
|
if (damageComponent.DamageContainerID != null
|
||||||
&& _prototypeManager.Resolve<DamageContainerPrototype>(damageComponent.DamageContainerID, out var damageContainer))
|
&& _prototypeManager.TryIndex<DamageContainerPrototype>(damageComponent.DamageContainerID, out var damageContainer))
|
||||||
{
|
{
|
||||||
// Are we using damage overlay sprites by group?
|
// Are we using damage overlay sprites by group?
|
||||||
// Check if the container matches the supported groups,
|
// Check if the container matches the supported groups,
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
using System.Diagnostics.CodeAnalysis;
|
|
||||||
using Content.Shared.DisplacementMap;
|
using Content.Shared.DisplacementMap;
|
||||||
using Robust.Client.GameObjects;
|
using Robust.Client.GameObjects;
|
||||||
using Robust.Client.Graphics;
|
using Robust.Client.Graphics;
|
||||||
@@ -11,11 +10,6 @@ public sealed class DisplacementMapSystem : EntitySystem
|
|||||||
[Dependency] private readonly ISerializationManager _serialization = default!;
|
[Dependency] private readonly ISerializationManager _serialization = default!;
|
||||||
[Dependency] private readonly SpriteSystem _sprite = default!;
|
[Dependency] private readonly SpriteSystem _sprite = default!;
|
||||||
|
|
||||||
private static string? BuildDisplacementLayerKey(object key)
|
|
||||||
{
|
|
||||||
return key.ToString() is null ? null : $"{key}-displacement";
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Attempting to apply a displacement map to a specific layer of SpriteComponent
|
/// Attempting to apply a displacement map to a specific layer of SpriteComponent
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -25,23 +19,22 @@ public sealed class DisplacementMapSystem : EntitySystem
|
|||||||
/// <param name="key">Unique layer key, which will determine which layer to apply displacement map to</param>
|
/// <param name="key">Unique layer key, which will determine which layer to apply displacement map to</param>
|
||||||
/// <param name="displacementKey">The key of the new displacement map layer added by this function.</param>
|
/// <param name="displacementKey">The key of the new displacement map layer added by this function.</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public bool TryAddDisplacement(
|
public bool TryAddDisplacement(DisplacementData data,
|
||||||
DisplacementData data,
|
|
||||||
Entity<SpriteComponent> sprite,
|
Entity<SpriteComponent> sprite,
|
||||||
int index,
|
int index,
|
||||||
object key,
|
object key,
|
||||||
[NotNullWhen(true)] out string? displacementKey
|
out string displacementKey)
|
||||||
)
|
|
||||||
{
|
{
|
||||||
displacementKey = BuildDisplacementLayerKey(key);
|
displacementKey = $"{key}-displacement";
|
||||||
if (displacementKey is null)
|
|
||||||
|
if (key.ToString() is null)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
EnsureDisplacementIsNotOnSprite(sprite, key);
|
if (data.ShaderOverride != null)
|
||||||
|
|
||||||
if (data.ShaderOverride is not null)
|
|
||||||
sprite.Comp.LayerSetShader(index, data.ShaderOverride);
|
sprite.Comp.LayerSetShader(index, data.ShaderOverride);
|
||||||
|
|
||||||
|
_sprite.RemoveLayer(sprite.AsNullable(), displacementKey, false);
|
||||||
|
|
||||||
//allows you not to write it every time in the YML
|
//allows you not to write it every time in the YML
|
||||||
foreach (var pair in data.SizeMaps)
|
foreach (var pair in data.SizeMaps)
|
||||||
{
|
{
|
||||||
@@ -77,11 +70,7 @@ public sealed class DisplacementMapSystem : EntitySystem
|
|||||||
}
|
}
|
||||||
|
|
||||||
var displacementLayer = _serialization.CreateCopy(displacementDataLayer, notNullableOverride: true);
|
var displacementLayer = _serialization.CreateCopy(displacementDataLayer, notNullableOverride: true);
|
||||||
|
displacementLayer.CopyToShaderParameters!.LayerKey = key.ToString() ?? "this is impossible";
|
||||||
// This previously assigned a string reading "this is impossible" if key.ToString eval'd to false.
|
|
||||||
// However, for the sake of sanity, we've changed this to assert non-null - !.
|
|
||||||
// If this throws an error, we're not sorry. Nanotrasen thanks you for your service fixing this bug.
|
|
||||||
displacementLayer.CopyToShaderParameters!.LayerKey = key.ToString()!;
|
|
||||||
|
|
||||||
_sprite.AddLayer(sprite.AsNullable(), displacementLayer, index);
|
_sprite.AddLayer(sprite.AsNullable(), displacementLayer, index);
|
||||||
_sprite.LayerMapSet(sprite.AsNullable(), displacementKey, index);
|
_sprite.LayerMapSet(sprite.AsNullable(), displacementKey, index);
|
||||||
@@ -89,18 +78,14 @@ public sealed class DisplacementMapSystem : EntitySystem
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <inheritdoc cref="TryAddDisplacement"/>
|
||||||
/// Ensures that the displacement map associated with the given layer key is not in the Sprite's LayerMap.
|
[Obsolete("Use the Entity<SpriteComponent> overload")]
|
||||||
/// </summary>
|
public bool TryAddDisplacement(DisplacementData data,
|
||||||
/// <param name="sprite">The sprite to remove the displacement layer from.</param>
|
SpriteComponent sprite,
|
||||||
/// <param name="key">The key of the layer that is referenced by the displacement layer we want to remove.</param>
|
int index,
|
||||||
/// <param name="logMissing">Whether to report an error if the displacement map isn't on the sprite.</param>
|
object key,
|
||||||
public void EnsureDisplacementIsNotOnSprite(Entity<SpriteComponent> sprite, object key)
|
out string displacementKey)
|
||||||
{
|
{
|
||||||
var displacementLayerKey = BuildDisplacementLayerKey(key);
|
return TryAddDisplacement(data, (sprite.Owner, sprite), index, key, out displacementKey);
|
||||||
if (displacementLayerKey is null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
_sprite.RemoveLayer(sprite.AsNullable(), displacementLayerKey, false);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -142,7 +142,7 @@ public sealed class DoorSystem : SharedDoorSystem
|
|||||||
|
|
||||||
private void UpdateSpriteLayers(Entity<SpriteComponent> sprite, string targetProto)
|
private void UpdateSpriteLayers(Entity<SpriteComponent> sprite, string targetProto)
|
||||||
{
|
{
|
||||||
if (!_prototypeManager.Resolve(targetProto, out var target))
|
if (!_prototypeManager.TryIndex(targetProto, out var target))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!target.TryGetComponent(out SpriteComponent? targetSprite, _componentFactory))
|
if (!target.TryGetComponent(out SpriteComponent? targetSprite, _componentFactory))
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
using Content.Shared.Drunk;
|
using Content.Shared.Drunk;
|
||||||
using Content.Shared.StatusEffect;
|
using Content.Shared.StatusEffect;
|
||||||
using Content.Shared.StatusEffectNew;
|
|
||||||
using Robust.Client.Graphics;
|
using Robust.Client.Graphics;
|
||||||
using Robust.Client.Player;
|
using Robust.Client.Player;
|
||||||
using Robust.Shared.Enums;
|
using Robust.Shared.Enums;
|
||||||
@@ -44,21 +43,19 @@ public sealed class DrunkOverlay : Overlay
|
|||||||
if (playerEntity == null)
|
if (playerEntity == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var statusSys = _sysMan.GetEntitySystem<Shared.StatusEffectNew.StatusEffectsSystem>();
|
if (!_entityManager.HasComponent<DrunkComponent>(playerEntity)
|
||||||
if (!statusSys.TryGetMaxTime<DrunkStatusEffectComponent>(playerEntity.Value, out var status))
|
|| !_entityManager.TryGetComponent<StatusEffectsComponent>(playerEntity, out var status))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var time = status.Item2;
|
var statusSys = _sysMan.GetEntitySystem<StatusEffectsSystem>();
|
||||||
|
if (!statusSys.TryGetTime(playerEntity.Value, SharedDrunkSystem.DrunkKey, out var time, status))
|
||||||
|
return;
|
||||||
|
|
||||||
var power = SharedDrunkSystem.MagicNumber;
|
var curTime = _timing.CurTime;
|
||||||
|
var timeLeft = (float) (time.Value.Item2 - curTime).TotalSeconds;
|
||||||
|
|
||||||
if (time != null)
|
|
||||||
{
|
|
||||||
var curTime = _timing.CurTime;
|
|
||||||
power = (float) (time - curTime).Value.TotalSeconds;
|
|
||||||
}
|
|
||||||
|
|
||||||
CurrentBoozePower += 8f * (power * 0.5f - CurrentBoozePower) * args.DeltaSeconds / (power+1);
|
CurrentBoozePower += 8f * (0.5f*timeLeft - CurrentBoozePower) * args.DeltaSeconds / (timeLeft+1);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override bool BeforeDraw(in OverlayDrawArgs args)
|
protected override bool BeforeDraw(in OverlayDrawArgs args)
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
using Content.Shared.Drunk;
|
using Content.Shared.Drunk;
|
||||||
using Content.Shared.StatusEffectNew;
|
|
||||||
using Robust.Client.Graphics;
|
using Robust.Client.Graphics;
|
||||||
using Robust.Client.Player;
|
using Robust.Client.Player;
|
||||||
using Robust.Shared.Player;
|
using Robust.Shared.Player;
|
||||||
@@ -17,41 +16,38 @@ public sealed class DrunkSystem : SharedDrunkSystem
|
|||||||
{
|
{
|
||||||
base.Initialize();
|
base.Initialize();
|
||||||
|
|
||||||
SubscribeLocalEvent<DrunkStatusEffectComponent, StatusEffectAppliedEvent>(OnStatusApplied);
|
SubscribeLocalEvent<DrunkComponent, ComponentInit>(OnDrunkInit);
|
||||||
SubscribeLocalEvent<DrunkStatusEffectComponent, StatusEffectRemovedEvent>(OnStatusRemoved);
|
SubscribeLocalEvent<DrunkComponent, ComponentShutdown>(OnDrunkShutdown);
|
||||||
|
|
||||||
SubscribeLocalEvent<DrunkStatusEffectComponent, StatusEffectRelayedEvent<LocalPlayerAttachedEvent>>(OnPlayerAttached);
|
SubscribeLocalEvent<DrunkComponent, LocalPlayerAttachedEvent>(OnPlayerAttached);
|
||||||
SubscribeLocalEvent<DrunkStatusEffectComponent, StatusEffectRelayedEvent<LocalPlayerDetachedEvent>>(OnPlayerDetached);
|
SubscribeLocalEvent<DrunkComponent, LocalPlayerDetachedEvent>(OnPlayerDetached);
|
||||||
|
|
||||||
_overlay = new();
|
_overlay = new();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnStatusApplied(Entity<DrunkStatusEffectComponent> entity, ref StatusEffectAppliedEvent args)
|
private void OnPlayerAttached(EntityUid uid, DrunkComponent component, LocalPlayerAttachedEvent args)
|
||||||
{
|
|
||||||
if (!_overlayMan.HasOverlay<DrunkOverlay>())
|
|
||||||
_overlayMan.AddOverlay(_overlay);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnStatusRemoved(Entity<DrunkStatusEffectComponent> entity, ref StatusEffectRemovedEvent args)
|
|
||||||
{
|
|
||||||
if (Status.HasEffectComp<DrunkStatusEffectComponent>(args.Target))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (_player.LocalEntity != args.Target)
|
|
||||||
return;
|
|
||||||
|
|
||||||
_overlay.CurrentBoozePower = 0;
|
|
||||||
_overlayMan.RemoveOverlay(_overlay);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnPlayerAttached(Entity<DrunkStatusEffectComponent> entity, ref StatusEffectRelayedEvent<LocalPlayerAttachedEvent> args)
|
|
||||||
{
|
{
|
||||||
_overlayMan.AddOverlay(_overlay);
|
_overlayMan.AddOverlay(_overlay);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnPlayerDetached(Entity<DrunkStatusEffectComponent> entity, ref StatusEffectRelayedEvent<LocalPlayerDetachedEvent> args)
|
private void OnPlayerDetached(EntityUid uid, DrunkComponent component, LocalPlayerDetachedEvent args)
|
||||||
{
|
{
|
||||||
_overlay.CurrentBoozePower = 0;
|
_overlay.CurrentBoozePower = 0;
|
||||||
_overlayMan.RemoveOverlay(_overlay);
|
_overlayMan.RemoveOverlay(_overlay);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void OnDrunkInit(EntityUid uid, DrunkComponent component, ComponentInit args)
|
||||||
|
{
|
||||||
|
if (_player.LocalEntity == uid)
|
||||||
|
_overlayMan.AddOverlay(_overlay);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnDrunkShutdown(EntityUid uid, DrunkComponent component, ComponentShutdown args)
|
||||||
|
{
|
||||||
|
if (_player.LocalEntity == uid)
|
||||||
|
{
|
||||||
|
_overlay.CurrentBoozePower = 0;
|
||||||
|
_overlayMan.RemoveOverlay(_overlay);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
7
Content.Client/Explosion/SmokeOnTriggerSystem.cs
Normal file
7
Content.Client/Explosion/SmokeOnTriggerSystem.cs
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
using Content.Shared.Explosion.EntitySystems;
|
||||||
|
|
||||||
|
namespace Content.Client.Explosion;
|
||||||
|
|
||||||
|
public sealed class SmokeOnTriggerSystem : SharedSmokeOnTriggerSystem
|
||||||
|
{
|
||||||
|
}
|
||||||
7
Content.Client/Explosion/TriggerOnProximityComponent.cs
Normal file
7
Content.Client/Explosion/TriggerOnProximityComponent.cs
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
using Content.Shared.Explosion;
|
||||||
|
using Content.Shared.Explosion.Components;
|
||||||
|
|
||||||
|
namespace Content.Client.Explosion;
|
||||||
|
|
||||||
|
[RegisterComponent, Access(typeof(TriggerSystem))]
|
||||||
|
public sealed partial class TriggerOnProximityComponent : SharedTriggerOnProximityComponent {}
|
||||||
@@ -1,12 +1,11 @@
|
|||||||
using Content.Shared.Trigger;
|
using Content.Shared.Trigger;
|
||||||
using Content.Shared.Trigger.Components.Triggers;
|
|
||||||
using Robust.Client.Animations;
|
using Robust.Client.Animations;
|
||||||
using Robust.Client.GameObjects;
|
using Robust.Client.GameObjects;
|
||||||
using Robust.Shared.Animations;
|
using Robust.Shared.Animations;
|
||||||
|
|
||||||
namespace Content.Client.Trigger.Systems;
|
namespace Content.Client.Explosion;
|
||||||
|
|
||||||
public sealed class ProximityTriggerAnimationSystem : EntitySystem
|
public sealed partial class TriggerSystem
|
||||||
{
|
{
|
||||||
[Dependency] private readonly AnimationPlayerSystem _player = default!;
|
[Dependency] private readonly AnimationPlayerSystem _player = default!;
|
||||||
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
|
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
|
||||||
@@ -19,7 +18,7 @@ public sealed class ProximityTriggerAnimationSystem : EntitySystem
|
|||||||
|
|
||||||
private const string AnimKey = "proximity";
|
private const string AnimKey = "proximity";
|
||||||
|
|
||||||
private static readonly Animation FlasherAnimation = new Animation
|
private static readonly Animation _flasherAnimation = new Animation
|
||||||
{
|
{
|
||||||
Length = TimeSpan.FromSeconds(0.6f),
|
Length = TimeSpan.FromSeconds(0.6f),
|
||||||
AnimationTracks = {
|
AnimationTracks = {
|
||||||
@@ -43,10 +42,8 @@ public sealed class ProximityTriggerAnimationSystem : EntitySystem
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
public override void Initialize()
|
private void InitializeProximity()
|
||||||
{
|
{
|
||||||
base.Initialize();
|
|
||||||
|
|
||||||
SubscribeLocalEvent<TriggerOnProximityComponent, ComponentInit>(OnProximityInit);
|
SubscribeLocalEvent<TriggerOnProximityComponent, ComponentInit>(OnProximityInit);
|
||||||
SubscribeLocalEvent<TriggerOnProximityComponent, AppearanceChangeEvent>(OnProxAppChange);
|
SubscribeLocalEvent<TriggerOnProximityComponent, AppearanceChangeEvent>(OnProxAppChange);
|
||||||
SubscribeLocalEvent<TriggerOnProximityComponent, AnimationCompletedEvent>(OnProxAnimation);
|
SubscribeLocalEvent<TriggerOnProximityComponent, AnimationCompletedEvent>(OnProxAnimation);
|
||||||
@@ -97,7 +94,7 @@ public sealed class ProximityTriggerAnimationSystem : EntitySystem
|
|||||||
break;
|
break;
|
||||||
case ProximityTriggerVisuals.Active:
|
case ProximityTriggerVisuals.Active:
|
||||||
if (_player.HasRunningAnimation(uid, player, AnimKey)) return;
|
if (_player.HasRunningAnimation(uid, player, AnimKey)) return;
|
||||||
_player.Play((uid, player), FlasherAnimation, AnimKey);
|
_player.Play((uid, player), _flasherAnimation, AnimKey);
|
||||||
break;
|
break;
|
||||||
case ProximityTriggerVisuals.Off:
|
case ProximityTriggerVisuals.Off:
|
||||||
default:
|
default:
|
||||||
10
Content.Client/Explosion/TriggerSystem.cs
Normal file
10
Content.Client/Explosion/TriggerSystem.cs
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
namespace Content.Client.Explosion;
|
||||||
|
|
||||||
|
public sealed partial class TriggerSystem : EntitySystem
|
||||||
|
{
|
||||||
|
public override void Initialize()
|
||||||
|
{
|
||||||
|
base.Initialize();
|
||||||
|
InitializeProximity();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
using Content.Shared.Forensics.Systems;
|
|
||||||
|
|
||||||
namespace Content.Client.Forensics.Systems;
|
|
||||||
|
|
||||||
public sealed class ForensicsSystem : SharedForensicsSystem;
|
|
||||||
@@ -34,8 +34,6 @@ namespace Content.Client.GameTicking.Managers
|
|||||||
[ViewVariables] public TimeSpan StartTime { get; private set; }
|
[ViewVariables] public TimeSpan StartTime { get; private set; }
|
||||||
[ViewVariables] public new bool Paused { get; private set; }
|
[ViewVariables] public new bool Paused { get; private set; }
|
||||||
|
|
||||||
public override IReadOnlyList<(TimeSpan, string)> AllPreviousGameRules => new List<(TimeSpan, string)>();
|
|
||||||
|
|
||||||
[ViewVariables] public IReadOnlyDictionary<NetEntity, Dictionary<ProtoId<JobPrototype>, int?>> JobsAvailable => _jobsAvailable;
|
[ViewVariables] public IReadOnlyDictionary<NetEntity, Dictionary<ProtoId<JobPrototype>, int?>> JobsAvailable => _jobsAvailable;
|
||||||
[ViewVariables] public IReadOnlyDictionary<NetEntity, string> StationNames => _stationNames;
|
[ViewVariables] public IReadOnlyDictionary<NetEntity, string> StationNames => _stationNames;
|
||||||
|
|
||||||
|
|||||||
@@ -1,58 +1,25 @@
|
|||||||
using Content.Client.UserInterface.Controls;
|
|
||||||
using Content.Shared.Ghost.Roles;
|
using Content.Shared.Ghost.Roles;
|
||||||
using Content.Shared.Ghost.Roles.Components;
|
|
||||||
using Robust.Client.UserInterface;
|
using Robust.Client.UserInterface;
|
||||||
using Robust.Shared.Prototypes;
|
using Robust.Shared.Prototypes;
|
||||||
|
|
||||||
namespace Content.Client.Ghost;
|
namespace Content.Client.Ghost;
|
||||||
|
|
||||||
public sealed class GhostRoleRadioBoundUserInterface(EntityUid owner, Enum uiKey) : BoundUserInterface(owner, uiKey)
|
public sealed class GhostRoleRadioBoundUserInterface : BoundUserInterface
|
||||||
{
|
{
|
||||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
private GhostRoleRadioMenu? _ghostRoleRadioMenu;
|
||||||
|
|
||||||
private SimpleRadialMenu? _ghostRoleRadioMenu;
|
public GhostRoleRadioBoundUserInterface(EntityUid owner, Enum uiKey) : base(owner, uiKey)
|
||||||
|
{
|
||||||
|
IoCManager.InjectDependencies(this);
|
||||||
|
}
|
||||||
|
|
||||||
protected override void Open()
|
protected override void Open()
|
||||||
{
|
{
|
||||||
base.Open();
|
base.Open();
|
||||||
|
|
||||||
_ghostRoleRadioMenu = this.CreateWindow<SimpleRadialMenu>();
|
_ghostRoleRadioMenu = this.CreateWindow<GhostRoleRadioMenu>();
|
||||||
|
_ghostRoleRadioMenu.SetEntity(Owner);
|
||||||
// The purpose of this radial UI is for ghost role radios that allow you to select
|
_ghostRoleRadioMenu.SendGhostRoleRadioMessageAction += SendGhostRoleRadioMessage;
|
||||||
// more than one potential option, such as with kobolds/lizards.
|
|
||||||
// This means that it won't show anything if SelectablePrototypes is empty.
|
|
||||||
if (!EntMan.TryGetComponent<GhostRoleMobSpawnerComponent>(Owner, out var comp))
|
|
||||||
return;
|
|
||||||
|
|
||||||
var list = ConvertToButtons(comp.SelectablePrototypes);
|
|
||||||
|
|
||||||
_ghostRoleRadioMenu.SetButtons(list);
|
|
||||||
}
|
|
||||||
|
|
||||||
private IEnumerable<RadialMenuOptionBase> ConvertToButtons(List<ProtoId<GhostRolePrototype>> protoIds)
|
|
||||||
{
|
|
||||||
var list = new List<RadialMenuOptionBase>();
|
|
||||||
foreach (var ghostRoleProtoId in protoIds)
|
|
||||||
{
|
|
||||||
// For each prototype we find we want to create a button that uses the name of the ghost role
|
|
||||||
// as the hover tooltip, and the icon is taken from either the ghost role entityprototype
|
|
||||||
// or the indicated icon entityprototype.
|
|
||||||
if (!_prototypeManager.Resolve(ghostRoleProtoId, out var ghostRoleProto))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
var option = new RadialMenuActionOption<ProtoId<GhostRolePrototype>>(SendGhostRoleRadioMessage, ghostRoleProtoId)
|
|
||||||
{
|
|
||||||
ToolTip = Loc.GetString(ghostRoleProto.Name),
|
|
||||||
// pick the icon if it exists, otherwise fallback to the ghost role's entity
|
|
||||||
IconSpecifier = ghostRoleProto.IconPrototype != null
|
|
||||||
&& _prototypeManager.Resolve(ghostRoleProto.IconPrototype, out var iconProto)
|
|
||||||
? RadialMenuIconSpecifier.With(iconProto)
|
|
||||||
: RadialMenuIconSpecifier.With(ghostRoleProto.EntityPrototype)
|
|
||||||
};
|
|
||||||
list.Add(option);
|
|
||||||
}
|
|
||||||
|
|
||||||
return list;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SendGhostRoleRadioMessage(ProtoId<GhostRolePrototype> protoId)
|
private void SendGhostRoleRadioMessage(ProtoId<GhostRolePrototype> protoId)
|
||||||
|
|||||||
8
Content.Client/Ghost/GhostRoleRadioMenu.xaml
Normal file
8
Content.Client/Ghost/GhostRoleRadioMenu.xaml
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
<ui:RadialMenu
|
||||||
|
xmlns:ui="clr-namespace:Content.Client.UserInterface.Controls"
|
||||||
|
CloseButtonStyleClass="RadialMenuCloseButton"
|
||||||
|
VerticalExpand="True"
|
||||||
|
HorizontalExpand="True">
|
||||||
|
<ui:RadialContainer Name="Main">
|
||||||
|
</ui:RadialContainer>
|
||||||
|
</ui:RadialMenu>
|
||||||
105
Content.Client/Ghost/GhostRoleRadioMenu.xaml.cs
Normal file
105
Content.Client/Ghost/GhostRoleRadioMenu.xaml.cs
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
using Content.Client.UserInterface.Controls;
|
||||||
|
using Content.Shared.Ghost.Roles;
|
||||||
|
using Content.Shared.Ghost.Roles.Components;
|
||||||
|
using Robust.Client.UserInterface;
|
||||||
|
using Robust.Client.UserInterface.Controls;
|
||||||
|
using Robust.Client.UserInterface.XAML;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
using System.Numerics;
|
||||||
|
|
||||||
|
namespace Content.Client.Ghost;
|
||||||
|
|
||||||
|
public sealed partial class GhostRoleRadioMenu : RadialMenu
|
||||||
|
{
|
||||||
|
[Dependency] private readonly EntityManager _entityManager = default!;
|
||||||
|
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||||
|
|
||||||
|
public event Action<ProtoId<GhostRolePrototype>>? SendGhostRoleRadioMessageAction;
|
||||||
|
|
||||||
|
public EntityUid Entity { get; set; }
|
||||||
|
|
||||||
|
public GhostRoleRadioMenu()
|
||||||
|
{
|
||||||
|
IoCManager.InjectDependencies(this);
|
||||||
|
RobustXamlLoader.Load(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetEntity(EntityUid uid)
|
||||||
|
{
|
||||||
|
Entity = uid;
|
||||||
|
RefreshUI();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RefreshUI()
|
||||||
|
{
|
||||||
|
// The main control that will contain all the clickable options
|
||||||
|
var main = FindControl<RadialContainer>("Main");
|
||||||
|
|
||||||
|
// The purpose of this radial UI is for ghost role radios that allow you to select
|
||||||
|
// more than one potential option, such as with kobolds/lizards.
|
||||||
|
// This means that it won't show anything if SelectablePrototypes is empty.
|
||||||
|
if (!_entityManager.TryGetComponent<GhostRoleMobSpawnerComponent>(Entity, out var comp))
|
||||||
|
return;
|
||||||
|
|
||||||
|
foreach (var ghostRoleProtoString in comp.SelectablePrototypes)
|
||||||
|
{
|
||||||
|
// For each prototype we find we want to create a button that uses the name of the ghost role
|
||||||
|
// as the hover tooltip, and the icon is taken from either the ghost role entityprototype
|
||||||
|
// or the indicated icon entityprototype.
|
||||||
|
if (!_prototypeManager.TryIndex<GhostRolePrototype>(ghostRoleProtoString, out var ghostRoleProto))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
var button = new GhostRoleRadioMenuButton()
|
||||||
|
{
|
||||||
|
SetSize = new Vector2(64, 64),
|
||||||
|
ToolTip = Loc.GetString(ghostRoleProto.Name),
|
||||||
|
ProtoId = ghostRoleProto.ID,
|
||||||
|
};
|
||||||
|
|
||||||
|
var entProtoView = new EntityPrototypeView()
|
||||||
|
{
|
||||||
|
SetSize = new Vector2(48, 48),
|
||||||
|
VerticalAlignment = VAlignment.Center,
|
||||||
|
HorizontalAlignment = HAlignment.Center,
|
||||||
|
Stretch = SpriteView.StretchMode.Fill
|
||||||
|
};
|
||||||
|
|
||||||
|
// pick the icon if it exists, otherwise fallback to the ghost role's entity
|
||||||
|
if (_prototypeManager.TryIndex(ghostRoleProto.IconPrototype, out var iconProto))
|
||||||
|
entProtoView.SetPrototype(iconProto);
|
||||||
|
else
|
||||||
|
entProtoView.SetPrototype(ghostRoleProto.EntityPrototype);
|
||||||
|
|
||||||
|
button.AddChild(entProtoView);
|
||||||
|
main.AddChild(button);
|
||||||
|
AddGhostRoleRadioMenuButtonOnClickActions(main);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AddGhostRoleRadioMenuButtonOnClickActions(Control control)
|
||||||
|
{
|
||||||
|
var mainControl = control as RadialContainer;
|
||||||
|
|
||||||
|
if (mainControl == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
foreach (var child in mainControl.Children)
|
||||||
|
{
|
||||||
|
var castChild = child as GhostRoleRadioMenuButton;
|
||||||
|
|
||||||
|
if (castChild == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
castChild.OnButtonUp += _ =>
|
||||||
|
{
|
||||||
|
SendGhostRoleRadioMessageAction?.Invoke(castChild.ProtoId);
|
||||||
|
Close();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed class GhostRoleRadioMenuButton : RadialMenuTextureButtonWithSector
|
||||||
|
{
|
||||||
|
public ProtoId<GhostRolePrototype> ProtoId { get; set; }
|
||||||
|
}
|
||||||
@@ -136,7 +136,6 @@ namespace Content.Client.Ghost
|
|||||||
//_actions.RemoveAction(uid, component.ToggleGhostHearingActionEntity); //Dont need in CP14
|
//_actions.RemoveAction(uid, component.ToggleGhostHearingActionEntity); //Dont need in CP14
|
||||||
//CP14
|
//CP14
|
||||||
_actions.RemoveAction(uid, component.CP14ToggleRoofActionEntity);
|
_actions.RemoveAction(uid, component.CP14ToggleRoofActionEntity);
|
||||||
_actions.RemoveAction(uid, component.CP14RespawnActionEntity);
|
|
||||||
//CP14 end
|
//CP14 end
|
||||||
|
|
||||||
if (uid != _playerManager.LocalEntity)
|
if (uid != _playerManager.LocalEntity)
|
||||||
|
|||||||
@@ -5,17 +5,14 @@ using Content.Client.Guidebook.Richtext;
|
|||||||
using Content.Client.Message;
|
using Content.Client.Message;
|
||||||
using Content.Client.UserInterface.ControlExtensions;
|
using Content.Client.UserInterface.ControlExtensions;
|
||||||
using Content.Shared.Body.Prototypes;
|
using Content.Shared.Body.Prototypes;
|
||||||
using Content.Shared.CCVar;
|
|
||||||
using Content.Shared.Chemistry.Reaction;
|
using Content.Shared.Chemistry.Reaction;
|
||||||
using Content.Shared.Chemistry.Reagent;
|
using Content.Shared.Chemistry.Reagent;
|
||||||
using Content.Shared.Contraband;
|
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
using Robust.Client.AutoGenerated;
|
using Robust.Client.AutoGenerated;
|
||||||
using Robust.Client.Graphics;
|
using Robust.Client.Graphics;
|
||||||
using Robust.Client.UserInterface;
|
using Robust.Client.UserInterface;
|
||||||
using Robust.Client.UserInterface.Controls;
|
using Robust.Client.UserInterface.Controls;
|
||||||
using Robust.Client.UserInterface.XAML;
|
using Robust.Client.UserInterface.XAML;
|
||||||
using Robust.Shared.Configuration;
|
|
||||||
using Robust.Shared.Prototypes;
|
using Robust.Shared.Prototypes;
|
||||||
using Robust.Shared.Utility;
|
using Robust.Shared.Utility;
|
||||||
|
|
||||||
@@ -30,10 +27,8 @@ public sealed partial class GuideReagentEmbed : BoxContainer, IDocumentTag, ISea
|
|||||||
[Dependency] private readonly IEntitySystemManager _systemManager = default!;
|
[Dependency] private readonly IEntitySystemManager _systemManager = default!;
|
||||||
[Dependency] private readonly ILogManager _logManager = default!;
|
[Dependency] private readonly ILogManager _logManager = default!;
|
||||||
[Dependency] private readonly IPrototypeManager _prototype = default!;
|
[Dependency] private readonly IPrototypeManager _prototype = default!;
|
||||||
[Dependency] private readonly IConfigurationManager _config = default!;
|
|
||||||
|
|
||||||
private readonly ChemistryGuideDataSystem _chemistryGuideData;
|
private readonly ChemistryGuideDataSystem _chemistryGuideData;
|
||||||
private readonly ContrabandSystem _contraband;
|
|
||||||
private readonly ISawmill _sawmill;
|
private readonly ISawmill _sawmill;
|
||||||
|
|
||||||
public IPrototype? RepresentedPrototype { get; private set; }
|
public IPrototype? RepresentedPrototype { get; private set; }
|
||||||
@@ -44,7 +39,6 @@ public sealed partial class GuideReagentEmbed : BoxContainer, IDocumentTag, ISea
|
|||||||
IoCManager.InjectDependencies(this);
|
IoCManager.InjectDependencies(this);
|
||||||
_sawmill = _logManager.GetSawmill("guidebook.reagent");
|
_sawmill = _logManager.GetSawmill("guidebook.reagent");
|
||||||
_chemistryGuideData = _systemManager.GetEntitySystem<ChemistryGuideDataSystem>();
|
_chemistryGuideData = _systemManager.GetEntitySystem<ChemistryGuideDataSystem>();
|
||||||
_contraband = _systemManager.GetEntitySystem<ContrabandSystem>();
|
|
||||||
MouseFilter = MouseFilterMode.Stop;
|
MouseFilter = MouseFilterMode.Stop;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -210,25 +204,6 @@ public sealed partial class GuideReagentEmbed : BoxContainer, IDocumentTag, ISea
|
|||||||
description.PushNewline();
|
description.PushNewline();
|
||||||
description.AddMarkupOrThrow(Loc.GetString("guidebook-reagent-physical-description",
|
description.AddMarkupOrThrow(Loc.GetString("guidebook-reagent-physical-description",
|
||||||
("description", reagent.LocalizedPhysicalDescription)));
|
("description", reagent.LocalizedPhysicalDescription)));
|
||||||
|
|
||||||
if (_config.GetCVar(CCVars.ContrabandExamine))
|
|
||||||
{
|
|
||||||
// Department-restricted text
|
|
||||||
if (reagent.AllowedJobs.Count > 0 || reagent.AllowedDepartments.Count > 0)
|
|
||||||
{
|
|
||||||
description.PushNewline();
|
|
||||||
description.AddMarkupPermissive(
|
|
||||||
_contraband.GenerateDepartmentExamineMessage(reagent.AllowedDepartments, reagent.AllowedJobs, ContrabandItemType.Reagent));
|
|
||||||
}
|
|
||||||
// Other contraband text
|
|
||||||
else if (reagent.ContrabandSeverity != null &&
|
|
||||||
_prototype.Resolve(reagent.ContrabandSeverity.Value, out var severity))
|
|
||||||
{
|
|
||||||
description.PushNewline();
|
|
||||||
description.AddMarkupPermissive(Loc.GetString(severity.ExamineText, ("type", ContrabandItemType.Reagent)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ReagentDescription.SetMessage(description);
|
ReagentDescription.SetMessage(description);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ public sealed partial class DocumentParsingManager
|
|||||||
|
|
||||||
public bool TryAddMarkup(Control control, ProtoId<GuideEntryPrototype> entryId, bool log = true)
|
public bool TryAddMarkup(Control control, ProtoId<GuideEntryPrototype> entryId, bool log = true)
|
||||||
{
|
{
|
||||||
if (!_prototype.Resolve(entryId, out var entry))
|
if (!_prototype.TryIndex(entryId, out var entry))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
using var file = _resourceManager.ContentFileReadText(entry.Text);
|
using var file = _resourceManager.ContentFileReadText(entry.Text);
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
using Content.Shared.HotPotato;
|
using Content.Shared.HotPotato;
|
||||||
using Robust.Shared.Random;
|
using Robust.Shared.Random;
|
||||||
using Robust.Shared.Prototypes;
|
|
||||||
using Robust.Shared.Timing;
|
using Robust.Shared.Timing;
|
||||||
|
|
||||||
namespace Content.Client.HotPotato;
|
namespace Content.Client.HotPotato;
|
||||||
@@ -11,9 +10,6 @@ public sealed class HotPotatoSystem : SharedHotPotatoSystem
|
|||||||
[Dependency] private readonly IRobustRandom _random = default!;
|
[Dependency] private readonly IRobustRandom _random = default!;
|
||||||
[Dependency] private readonly SharedTransformSystem _transform = default!;
|
[Dependency] private readonly SharedTransformSystem _transform = default!;
|
||||||
|
|
||||||
private readonly EntProtoId _hotPotatoEffectId = "HotPotatoEffect";
|
|
||||||
|
|
||||||
// TODO: particle system
|
|
||||||
public override void Update(float frameTime)
|
public override void Update(float frameTime)
|
||||||
{
|
{
|
||||||
base.Update(frameTime);
|
base.Update(frameTime);
|
||||||
@@ -27,7 +23,7 @@ public sealed class HotPotatoSystem : SharedHotPotatoSystem
|
|||||||
if (_timing.CurTime < comp.TargetTime)
|
if (_timing.CurTime < comp.TargetTime)
|
||||||
continue;
|
continue;
|
||||||
comp.TargetTime = _timing.CurTime + TimeSpan.FromSeconds(comp.EffectCooldown);
|
comp.TargetTime = _timing.CurTime + TimeSpan.FromSeconds(comp.EffectCooldown);
|
||||||
Spawn(_hotPotatoEffectId, _transform.GetMapCoordinates(uid).Offset(_random.NextVector2(0.25f)));
|
Spawn("HotPotatoEffect", _transform.GetMapCoordinates(uid).Offset(_random.NextVector2(0.25f)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -300,26 +300,25 @@ public sealed class HumanoidAppearanceSystem : SharedHumanoidAppearanceSystem
|
|||||||
private void RemoveMarking(Marking marking, Entity<SpriteComponent> spriteEnt)
|
private void RemoveMarking(Marking marking, Entity<SpriteComponent> spriteEnt)
|
||||||
{
|
{
|
||||||
if (!_markingManager.TryGetMarking(marking, out var prototype))
|
if (!_markingManager.TryGetMarking(marking, out var prototype))
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
foreach (var sprite in prototype.Sprites)
|
foreach (var sprite in prototype.Sprites)
|
||||||
{
|
{
|
||||||
if (sprite is not SpriteSpecifier.Rsi rsi)
|
if (sprite is not SpriteSpecifier.Rsi rsi)
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
var layerId = $"{marking.MarkingId}-{rsi.RsiState}";
|
var layerId = $"{marking.MarkingId}-{rsi.RsiState}";
|
||||||
if (!_sprite.LayerMapTryGet(spriteEnt.AsNullable(), layerId, out var index, false))
|
if (!_sprite.LayerMapTryGet(spriteEnt.AsNullable(), layerId, out var index, false))
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
_sprite.LayerMapRemove(spriteEnt.AsNullable(), layerId);
|
_sprite.LayerMapRemove(spriteEnt.AsNullable(), layerId);
|
||||||
_sprite.RemoveLayer(spriteEnt.AsNullable(), index);
|
_sprite.RemoveLayer(spriteEnt.AsNullable(), index);
|
||||||
|
|
||||||
// If this marking is one that can be displaced, we need to remove the displacement as well; otherwise
|
|
||||||
// altering a marking at runtime can lead to the renderer falling over.
|
|
||||||
// The Vulps must be shaved.
|
|
||||||
// (https://github.com/space-wizards/space-station-14/issues/40135).
|
|
||||||
if (prototype.CanBeDisplaced)
|
|
||||||
_displacement.EnsureDisplacementIsNotOnSprite(spriteEnt, layerId);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -358,7 +357,9 @@ public sealed class HumanoidAppearanceSystem : SharedHumanoidAppearanceSystem
|
|||||||
var sprite = entity.Comp2;
|
var sprite = entity.Comp2;
|
||||||
|
|
||||||
if (!_sprite.LayerMapTryGet((entity.Owner, sprite), markingPrototype.BodyPart, out var targetLayer, false))
|
if (!_sprite.LayerMapTryGet((entity.Owner, sprite), markingPrototype.BodyPart, out var targetLayer, false))
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
visible &= !IsHidden(humanoid, markingPrototype.BodyPart);
|
visible &= !IsHidden(humanoid, markingPrototype.BodyPart);
|
||||||
visible &= humanoid.BaseLayers.TryGetValue(markingPrototype.BodyPart, out var setting)
|
visible &= humanoid.BaseLayers.TryGetValue(markingPrototype.BodyPart, out var setting)
|
||||||
@@ -369,7 +370,9 @@ public sealed class HumanoidAppearanceSystem : SharedHumanoidAppearanceSystem
|
|||||||
var markingSprite = markingPrototype.Sprites[j];
|
var markingSprite = markingPrototype.Sprites[j];
|
||||||
|
|
||||||
if (markingSprite is not SpriteSpecifier.Rsi rsi)
|
if (markingSprite is not SpriteSpecifier.Rsi rsi)
|
||||||
return;
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
var layerId = $"{markingPrototype.ID}-{rsi.RsiState}";
|
var layerId = $"{markingPrototype.ID}-{rsi.RsiState}";
|
||||||
|
|
||||||
@@ -383,18 +386,26 @@ public sealed class HumanoidAppearanceSystem : SharedHumanoidAppearanceSystem
|
|||||||
_sprite.LayerSetVisible((entity.Owner, sprite), layerId, visible);
|
_sprite.LayerSetVisible((entity.Owner, sprite), layerId, visible);
|
||||||
|
|
||||||
if (!visible || setting == null) // this is kinda implied
|
if (!visible || setting == null) // this is kinda implied
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// Okay so if the marking prototype is modified but we load old marking data this may no longer be valid
|
// Okay so if the marking prototype is modified but we load old marking data this may no longer be valid
|
||||||
// and we need to check the index is correct.
|
// and we need to check the index is correct.
|
||||||
// So if that happens just default to white?
|
// So if that happens just default to white?
|
||||||
if (colors != null && j < colors.Count)
|
if (colors != null && j < colors.Count)
|
||||||
|
{
|
||||||
_sprite.LayerSetColor((entity.Owner, sprite), layerId, colors[j]);
|
_sprite.LayerSetColor((entity.Owner, sprite), layerId, colors[j]);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
_sprite.LayerSetColor((entity.Owner, sprite), layerId, Color.White);
|
_sprite.LayerSetColor((entity.Owner, sprite), layerId, Color.White);
|
||||||
|
}
|
||||||
|
|
||||||
if (humanoid.MarkingsDisplacement.TryGetValue(markingPrototype.BodyPart, out var displacementData) && markingPrototype.CanBeDisplaced)
|
if (humanoid.MarkingsDisplacement.TryGetValue(markingPrototype.BodyPart, out var displacementData) && markingPrototype.CanBeDisplaced)
|
||||||
|
{
|
||||||
_displacement.TryAddDisplacement(displacementData, (entity.Owner, sprite), targetLayer + j + 1, layerId, out _);
|
_displacement.TryAddDisplacement(displacementData, (entity.Owner, sprite), targetLayer + j + 1, layerId, out _);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -23,12 +23,10 @@ public sealed class ImplanterSystem : SharedImplanterSystem
|
|||||||
{
|
{
|
||||||
if (_uiSystem.TryGetOpenUi<DeimplantBoundUserInterface>(uid, DeimplantUiKey.Key, out var bui))
|
if (_uiSystem.TryGetOpenUi<DeimplantBoundUserInterface>(uid, DeimplantUiKey.Key, out var bui))
|
||||||
{
|
{
|
||||||
// TODO: Don't use protoId for deimplanting
|
|
||||||
// and especially not raw strings!
|
|
||||||
Dictionary<string, string> implants = new();
|
Dictionary<string, string> implants = new();
|
||||||
foreach (var implant in component.DeimplantWhitelist)
|
foreach (var implant in component.DeimplantWhitelist)
|
||||||
{
|
{
|
||||||
if (_proto.Resolve(implant, out var proto))
|
if (_proto.TryIndex(implant, out var proto))
|
||||||
implants.Add(proto.ID, proto.Name);
|
implants.Add(proto.ID, proto.Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +0,0 @@
|
|||||||
using Content.Shared.Implants;
|
|
||||||
|
|
||||||
namespace Content.Client.Implants;
|
|
||||||
|
|
||||||
public sealed class SubdermalImplantSystem : SharedSubdermalImplantSystem;
|
|
||||||
@@ -62,7 +62,7 @@ public sealed partial class ChameleonControllerMenu : FancyWindow
|
|||||||
// Go through every outfit and add them to the correct department.
|
// Go through every outfit and add them to the correct department.
|
||||||
foreach (var outfit in _outfits)
|
foreach (var outfit in _outfits)
|
||||||
{
|
{
|
||||||
_prototypeManager.Resolve(outfit.Job, out var jobProto);
|
_prototypeManager.TryIndex(outfit.Job, out var jobProto);
|
||||||
|
|
||||||
var name = outfit.LoadoutName ?? outfit.Name ?? jobProto?.Name ?? "Prototype has no name or job.";
|
var name = outfit.LoadoutName ?? outfit.Name ?? jobProto?.Name ?? "Prototype has no name or job.";
|
||||||
|
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ public sealed class ImplanterStatusControl : Control
|
|||||||
if (_parent.CurrentMode == ImplanterToggleMode.Draw)
|
if (_parent.CurrentMode == ImplanterToggleMode.Draw)
|
||||||
{
|
{
|
||||||
string implantName = _parent.DeimplantChosen != null
|
string implantName = _parent.DeimplantChosen != null
|
||||||
? (_prototype.Resolve(_parent.DeimplantChosen.Value, out EntityPrototype? implantProto) ? implantProto.Name : Loc.GetString("implanter-empty-text"))
|
? (_prototype.TryIndex(_parent.DeimplantChosen.Value, out EntityPrototype? implantProto) ? implantProto.Name : Loc.GetString("implanter-empty-text"))
|
||||||
: Loc.GetString("implanter-empty-text");
|
: Loc.GetString("implanter-empty-text");
|
||||||
|
|
||||||
_label.SetMarkup(Loc.GetString("implanter-label-draw",
|
_label.SetMarkup(Loc.GetString("implanter-label-draw",
|
||||||
|
|||||||
@@ -294,6 +294,7 @@ public sealed partial class InstrumentSystem : SharedInstrumentSystem
|
|||||||
SetMaster(uid, null);
|
SetMaster(uid, null);
|
||||||
TrySetChannels(uid, data);
|
TrySetChannels(uid, data);
|
||||||
|
|
||||||
|
instrument.MidiEventBuffer.Clear();
|
||||||
instrument.Renderer.OnMidiEvent += instrument.MidiEventBuffer.Add;
|
instrument.Renderer.OnMidiEvent += instrument.MidiEventBuffer.Add;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ namespace Content.Client.Inventory
|
|||||||
{
|
{
|
||||||
[Dependency] private readonly IPlayerManager _playerManager = default!;
|
[Dependency] private readonly IPlayerManager _playerManager = default!;
|
||||||
[Dependency] private readonly IUserInterfaceManager _ui = default!;
|
[Dependency] private readonly IUserInterfaceManager _ui = default!;
|
||||||
|
[Dependency] private readonly IGameTiming _timing = default!;
|
||||||
[Dependency] private readonly ClientClothingSystem _clothingVisualsSystem = default!;
|
[Dependency] private readonly ClientClothingSystem _clothingVisualsSystem = default!;
|
||||||
[Dependency] private readonly ExamineSystem _examine = default!;
|
[Dependency] private readonly ExamineSystem _examine = default!;
|
||||||
|
|
||||||
@@ -114,13 +115,6 @@ namespace Content.Client.Inventory
|
|||||||
OnLinkInventorySlots?.Invoke(uid, component);
|
OnLinkInventorySlots?.Invoke(uid, component);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnInit(Entity<InventoryComponent> ent, ref ComponentInit args)
|
|
||||||
{
|
|
||||||
base.OnInit(ent, ref args);
|
|
||||||
|
|
||||||
_clothingVisualsSystem.InitClothing(ent.Owner, ent.Comp);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Shutdown()
|
public override void Shutdown()
|
||||||
{
|
{
|
||||||
CommandBinds.Unregister<ClientInventorySystem>();
|
CommandBinds.Unregister<ClientInventorySystem>();
|
||||||
@@ -267,6 +261,7 @@ namespace Content.Client.Inventory
|
|||||||
TryAddSlotData((ent.Owner, inventorySlots), (SlotData)slot);
|
TryAddSlotData((ent.Owner, inventorySlots), (SlotData)slot);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_clothingVisualsSystem.InitClothing(ent, ent.Comp);
|
||||||
if (ent.Owner == _playerManager.LocalEntity)
|
if (ent.Owner == _playerManager.LocalEntity)
|
||||||
ReloadInventory(inventorySlots);
|
ReloadInventory(inventorySlots);
|
||||||
}
|
}
|
||||||
|
|||||||
8
Content.Client/Kitchen/KitchenSpikeSystem.cs
Normal file
8
Content.Client/Kitchen/KitchenSpikeSystem.cs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
using Content.Shared.Kitchen;
|
||||||
|
|
||||||
|
namespace Content.Client.Kitchen;
|
||||||
|
|
||||||
|
public sealed class KitchenSpikeSystem : SharedKitchenSpikeSystem
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
@@ -30,10 +30,6 @@ namespace Content.Client.Lathe.UI
|
|||||||
{
|
{
|
||||||
SendMessage(new LatheQueueRecipeMessage(recipe, amount));
|
SendMessage(new LatheQueueRecipeMessage(recipe, amount));
|
||||||
};
|
};
|
||||||
_menu.QueueDeleteAction += index => SendMessage(new LatheDeleteRequestMessage(index));
|
|
||||||
_menu.QueueMoveUpAction += index => SendMessage(new LatheMoveRequestMessage(index, -1));
|
|
||||||
_menu.QueueMoveDownAction += index => SendMessage(new LatheMoveRequestMessage(index, 1));
|
|
||||||
_menu.DeleteFabricatingAction += () => SendMessage(new LatheAbortFabricationMessage());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void UpdateState(BoundUserInterfaceState state)
|
protected override void UpdateState(BoundUserInterfaceState state)
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
<DefaultWindow
|
<DefaultWindow
|
||||||
xmlns="https://spacestation14.io"
|
xmlns="https://spacestation14.io"
|
||||||
xmlns:gfx="clr-namespace:Robust.Client.Graphics;assembly=Robust.Client"
|
xmlns:gfx="clr-namespace:Robust.Client.Graphics;assembly=Robust.Client"
|
||||||
xmlns:system="clr-namespace:System;assembly=System.Runtime"
|
|
||||||
xmlns:ui="clr-namespace:Content.Client.Materials.UI"
|
xmlns:ui="clr-namespace:Content.Client.Materials.UI"
|
||||||
Title="{Loc 'lathe-menu-title'}"
|
Title="{Loc 'lathe-menu-title'}"
|
||||||
MinSize="550 450"
|
MinSize="550 450"
|
||||||
@@ -111,18 +110,6 @@
|
|||||||
HorizontalAlignment="Left"
|
HorizontalAlignment="Left"
|
||||||
Margin="130 0 0 0">
|
Margin="130 0 0 0">
|
||||||
</Label>
|
</Label>
|
||||||
<Button
|
|
||||||
Name="DeleteFabricating"
|
|
||||||
Margin="0"
|
|
||||||
Text="✖"
|
|
||||||
SetSize="38 32"
|
|
||||||
HorizontalAlignment="Right"
|
|
||||||
ToolTip="{Loc 'lathe-menu-delete-fabricating-tooltip'}">
|
|
||||||
<Button.StyleClasses>
|
|
||||||
<system:String>Caution</system:String>
|
|
||||||
<system:String>OpenLeft</system:String>
|
|
||||||
</Button.StyleClasses>
|
|
||||||
</Button>
|
|
||||||
</PanelContainer>
|
</PanelContainer>
|
||||||
</BoxContainer>
|
</BoxContainer>
|
||||||
<ScrollContainer VerticalExpand="True" HScrollEnabled="False">
|
<ScrollContainer VerticalExpand="True" HScrollEnabled="False">
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ using Robust.Client.UserInterface.Controls;
|
|||||||
using Robust.Client.UserInterface.CustomControls;
|
using Robust.Client.UserInterface.CustomControls;
|
||||||
using Robust.Client.UserInterface.XAML;
|
using Robust.Client.UserInterface.XAML;
|
||||||
using Robust.Shared.Prototypes;
|
using Robust.Shared.Prototypes;
|
||||||
using Robust.Shared.Utility;
|
|
||||||
|
|
||||||
namespace Content.Client.Lathe.UI;
|
namespace Content.Client.Lathe.UI;
|
||||||
|
|
||||||
@@ -27,10 +26,6 @@ public sealed partial class LatheMenu : DefaultWindow
|
|||||||
|
|
||||||
public event Action<BaseButton.ButtonEventArgs>? OnServerListButtonPressed;
|
public event Action<BaseButton.ButtonEventArgs>? OnServerListButtonPressed;
|
||||||
public event Action<string, int>? RecipeQueueAction;
|
public event Action<string, int>? RecipeQueueAction;
|
||||||
public event Action<int>? QueueDeleteAction;
|
|
||||||
public event Action<int>? QueueMoveUpAction;
|
|
||||||
public event Action<int>? QueueMoveDownAction;
|
|
||||||
public event Action? DeleteFabricatingAction;
|
|
||||||
|
|
||||||
public List<ProtoId<LatheRecipePrototype>> Recipes = new();
|
public List<ProtoId<LatheRecipePrototype>> Recipes = new();
|
||||||
|
|
||||||
@@ -55,21 +50,12 @@ public sealed partial class LatheMenu : DefaultWindow
|
|||||||
};
|
};
|
||||||
AmountLineEdit.OnTextChanged += _ =>
|
AmountLineEdit.OnTextChanged += _ =>
|
||||||
{
|
{
|
||||||
if (int.TryParse(AmountLineEdit.Text, out var amount))
|
|
||||||
{
|
|
||||||
if (amount > LatheSystem.MaxItemsPerRequest)
|
|
||||||
AmountLineEdit.Text = LatheSystem.MaxItemsPerRequest.ToString();
|
|
||||||
else if (amount < 0)
|
|
||||||
AmountLineEdit.Text = "0";
|
|
||||||
}
|
|
||||||
|
|
||||||
PopulateRecipes();
|
PopulateRecipes();
|
||||||
};
|
};
|
||||||
|
|
||||||
FilterOption.OnItemSelected += OnItemSelected;
|
FilterOption.OnItemSelected += OnItemSelected;
|
||||||
|
|
||||||
ServerListButton.OnPressed += a => OnServerListButtonPressed?.Invoke(a);
|
ServerListButton.OnPressed += a => OnServerListButtonPressed?.Invoke(a);
|
||||||
DeleteFabricating.OnPressed += _ => DeleteFabricatingAction?.Invoke();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetEntity(EntityUid uid)
|
public void SetEntity(EntityUid uid)
|
||||||
@@ -97,7 +83,7 @@ public sealed partial class LatheMenu : DefaultWindow
|
|||||||
var recipesToShow = new List<LatheRecipePrototype>();
|
var recipesToShow = new List<LatheRecipePrototype>();
|
||||||
foreach (var recipe in Recipes)
|
foreach (var recipe in Recipes)
|
||||||
{
|
{
|
||||||
if (!_prototypeManager.Resolve(recipe, out var proto))
|
if (!_prototypeManager.TryIndex(recipe, out var proto))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Category filtering
|
// Category filtering
|
||||||
@@ -129,50 +115,21 @@ public sealed partial class LatheMenu : DefaultWindow
|
|||||||
RecipeCount.Text = Loc.GetString("lathe-menu-recipe-count", ("count", recipesToShow.Count));
|
RecipeCount.Text = Loc.GetString("lathe-menu-recipe-count", ("count", recipesToShow.Count));
|
||||||
|
|
||||||
var sortedRecipesToShow = recipesToShow.OrderBy(_lathe.GetRecipeName);
|
var sortedRecipesToShow = recipesToShow.OrderBy(_lathe.GetRecipeName);
|
||||||
|
RecipeList.Children.Clear();
|
||||||
// Get the existing list of queue controls
|
|
||||||
var oldChildCount = RecipeList.ChildCount;
|
|
||||||
_entityManager.TryGetComponent(Entity, out LatheComponent? lathe);
|
_entityManager.TryGetComponent(Entity, out LatheComponent? lathe);
|
||||||
|
|
||||||
int idx = 0;
|
|
||||||
foreach (var prototype in sortedRecipesToShow)
|
foreach (var prototype in sortedRecipesToShow)
|
||||||
{
|
{
|
||||||
var canProduce = _lathe.CanProduce(Entity, prototype, quantity, component: lathe);
|
var canProduce = _lathe.CanProduce(Entity, prototype, quantity, component: lathe);
|
||||||
var tooltipFunction = () => GenerateTooltipText(prototype);
|
|
||||||
|
|
||||||
if (idx >= oldChildCount)
|
var control = new RecipeControl(_lathe, prototype, () => GenerateTooltipText(prototype), canProduce, GetRecipeDisplayControl(prototype));
|
||||||
|
control.OnButtonPressed += s =>
|
||||||
{
|
{
|
||||||
var control = new RecipeControl(_lathe, prototype, tooltipFunction, canProduce, GetRecipeDisplayControl(prototype));
|
if (!int.TryParse(AmountLineEdit.Text, out var amount) || amount <= 0)
|
||||||
control.OnButtonPressed += s =>
|
amount = 1;
|
||||||
{
|
RecipeQueueAction?.Invoke(s, amount);
|
||||||
if (!int.TryParse(AmountLineEdit.Text, out var amount) || amount <= 0)
|
};
|
||||||
amount = 1;
|
RecipeList.AddChild(control);
|
||||||
RecipeQueueAction?.Invoke(s, amount);
|
|
||||||
};
|
|
||||||
RecipeList.AddChild(control);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var child = RecipeList.GetChild(idx) as RecipeControl;
|
|
||||||
|
|
||||||
if (child == null)
|
|
||||||
{
|
|
||||||
DebugTools.Assert($"Lathe menu recipe control at {idx} is not of type RecipeControl"); // Something's gone terribly wrong.
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
child.SetRecipe(prototype);
|
|
||||||
child.SetTooltipSupplier(tooltipFunction);
|
|
||||||
child.SetCanProduce(canProduce);
|
|
||||||
child.SetDisplayControl(GetRecipeDisplayControl(prototype));
|
|
||||||
}
|
|
||||||
idx++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Shrink list if new list is shorter than old list.
|
|
||||||
for (var childIdx = oldChildCount - 1; idx <= childIdx; childIdx--)
|
|
||||||
{
|
|
||||||
RecipeList.RemoveChild(childIdx);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -183,7 +140,7 @@ public sealed partial class LatheMenu : DefaultWindow
|
|||||||
|
|
||||||
foreach (var (id, amount) in prototype.Materials)
|
foreach (var (id, amount) in prototype.Materials)
|
||||||
{
|
{
|
||||||
if (!_prototypeManager.Resolve(id, out var proto))
|
if (!_prototypeManager.TryIndex(id, out var proto))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
var adjustedAmount = SharedLatheSystem.AdjustMaterial(amount, prototype.ApplyMaterialDiscount, multiplier);
|
var adjustedAmount = SharedLatheSystem.AdjustMaterial(amount, prototype.ApplyMaterialDiscount, multiplier);
|
||||||
@@ -266,53 +223,25 @@ public sealed partial class LatheMenu : DefaultWindow
|
|||||||
/// Populates the build queue list with all queued items
|
/// Populates the build queue list with all queued items
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="queue"></param>
|
/// <param name="queue"></param>
|
||||||
public void PopulateQueueList(IReadOnlyCollection<LatheRecipeBatch> queue)
|
public void PopulateQueueList(IReadOnlyCollection<ProtoId<LatheRecipePrototype>> queue)
|
||||||
{
|
{
|
||||||
// Get the existing list of queue controls
|
QueueList.DisposeAllChildren();
|
||||||
var oldChildCount = QueueList.ChildCount;
|
|
||||||
|
|
||||||
var idx = 0;
|
var idx = 1;
|
||||||
foreach (var batch in queue)
|
foreach (var recipeProto in queue)
|
||||||
{
|
{
|
||||||
var recipe = _prototypeManager.Index(batch.Recipe);
|
var recipe = _prototypeManager.Index(recipeProto);
|
||||||
|
var queuedRecipeBox = new BoxContainer();
|
||||||
|
queuedRecipeBox.Orientation = BoxContainer.LayoutOrientation.Horizontal;
|
||||||
|
|
||||||
var itemName = _lathe.GetRecipeName(batch.Recipe);
|
queuedRecipeBox.AddChild(GetRecipeDisplayControl(recipe));
|
||||||
string displayText;
|
|
||||||
if (batch.ItemsRequested > 1)
|
|
||||||
displayText = Loc.GetString("lathe-menu-item-batch", ("index", idx + 1), ("name", itemName), ("printed", batch.ItemsPrinted), ("total", batch.ItemsRequested));
|
|
||||||
else
|
|
||||||
displayText = Loc.GetString("lathe-menu-item-single", ("index", idx + 1), ("name", itemName));
|
|
||||||
|
|
||||||
if (idx >= oldChildCount)
|
var queuedRecipeLabel = new Label();
|
||||||
{
|
queuedRecipeLabel.Text = $"{idx}. {_lathe.GetRecipeName(recipe)}";
|
||||||
var queuedRecipeBox = new QueuedRecipeControl(displayText, idx, GetRecipeDisplayControl(recipe));
|
queuedRecipeBox.AddChild(queuedRecipeLabel);
|
||||||
queuedRecipeBox.OnDeletePressed += s => QueueDeleteAction?.Invoke(s);
|
QueueList.AddChild(queuedRecipeBox);
|
||||||
queuedRecipeBox.OnMoveUpPressed += s => QueueMoveUpAction?.Invoke(s);
|
|
||||||
queuedRecipeBox.OnMoveDownPressed += s => QueueMoveDownAction?.Invoke(s);
|
|
||||||
QueueList.AddChild(queuedRecipeBox);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var child = QueueList.GetChild(idx) as QueuedRecipeControl;
|
|
||||||
|
|
||||||
if (child == null)
|
|
||||||
{
|
|
||||||
DebugTools.Assert($"Lathe menu queued recipe control at {idx} is not of type QueuedRecipeControl"); // Something's gone terribly wrong.
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
child.SetDisplayText(displayText);
|
|
||||||
child.SetIndex(idx);
|
|
||||||
child.SetDisplayControl(GetRecipeDisplayControl(recipe));
|
|
||||||
}
|
|
||||||
idx++;
|
idx++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Shrink list if new list is shorter than old list.
|
|
||||||
for (var childIdx = oldChildCount - 1; idx <= childIdx; childIdx--)
|
|
||||||
{
|
|
||||||
QueueList.RemoveChild(childIdx);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetQueueInfo(ProtoId<LatheRecipePrototype>? recipeProto)
|
public void SetQueueInfo(ProtoId<LatheRecipePrototype>? recipeProto)
|
||||||
|
|||||||
@@ -1,35 +0,0 @@
|
|||||||
<Control xmlns="https://spacestation14.io"
|
|
||||||
xmlns:system="clr-namespace:System;assembly=System.Runtime">
|
|
||||||
<BoxContainer Orientation="Horizontal">
|
|
||||||
<BoxContainer
|
|
||||||
Name="RecipeDisplayContainer"
|
|
||||||
Margin="0 0 4 0"
|
|
||||||
HorizontalAlignment="Center"
|
|
||||||
VerticalAlignment="Center"
|
|
||||||
MinSize="32 32"
|
|
||||||
/>
|
|
||||||
<Label Name="RecipeName" HorizontalExpand="True" />
|
|
||||||
<Button
|
|
||||||
Name="MoveUp"
|
|
||||||
Margin="0"
|
|
||||||
Text="⏶"
|
|
||||||
StyleClasses="OpenRight"
|
|
||||||
ToolTip="{Loc 'lathe-menu-move-up-tooltip'}"/>
|
|
||||||
<Button
|
|
||||||
Name="MoveDown"
|
|
||||||
Margin="0"
|
|
||||||
Text="⏷"
|
|
||||||
StyleClasses="OpenBoth"
|
|
||||||
ToolTip="{Loc 'lathe-menu-move-down-tooltip'}"/>
|
|
||||||
<Button
|
|
||||||
Name="Delete"
|
|
||||||
Margin="0"
|
|
||||||
Text="✖"
|
|
||||||
ToolTip="{Loc 'lathe-menu-delete-item-tooltip'}">
|
|
||||||
<Button.StyleClasses>
|
|
||||||
<system:String>Caution</system:String>
|
|
||||||
<system:String>OpenLeft</system:String>
|
|
||||||
</Button.StyleClasses>
|
|
||||||
</Button>
|
|
||||||
</BoxContainer>
|
|
||||||
</Control>
|
|
||||||
@@ -1,56 +0,0 @@
|
|||||||
using Robust.Client.AutoGenerated;
|
|
||||||
using Robust.Client.UserInterface;
|
|
||||||
using Robust.Client.UserInterface.XAML;
|
|
||||||
|
|
||||||
namespace Content.Client.Lathe.UI;
|
|
||||||
|
|
||||||
[GenerateTypedNameReferences]
|
|
||||||
public sealed partial class QueuedRecipeControl : Control
|
|
||||||
{
|
|
||||||
public Action<int>? OnDeletePressed;
|
|
||||||
public Action<int>? OnMoveUpPressed;
|
|
||||||
public Action<int>? OnMoveDownPressed;
|
|
||||||
|
|
||||||
private int _index;
|
|
||||||
|
|
||||||
public QueuedRecipeControl(string displayText, int index, Control displayControl)
|
|
||||||
{
|
|
||||||
RobustXamlLoader.Load(this);
|
|
||||||
|
|
||||||
SetDisplayText(displayText);
|
|
||||||
SetDisplayControl(displayControl);
|
|
||||||
SetIndex(index);
|
|
||||||
_index = index;
|
|
||||||
|
|
||||||
MoveUp.OnPressed += (_) =>
|
|
||||||
{
|
|
||||||
OnMoveUpPressed?.Invoke(_index);
|
|
||||||
};
|
|
||||||
|
|
||||||
MoveDown.OnPressed += (_) =>
|
|
||||||
{
|
|
||||||
OnMoveDownPressed?.Invoke(_index);
|
|
||||||
};
|
|
||||||
|
|
||||||
Delete.OnPressed += (_) =>
|
|
||||||
{
|
|
||||||
OnDeletePressed?.Invoke(_index);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SetDisplayText(string displayText)
|
|
||||||
{
|
|
||||||
RecipeName.Text = displayText;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SetDisplayControl(Control displayControl)
|
|
||||||
{
|
|
||||||
RecipeDisplayContainer.Children.Clear();
|
|
||||||
RecipeDisplayContainer.AddChild(displayControl);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SetIndex(int index)
|
|
||||||
{
|
|
||||||
_index = index;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -2,7 +2,6 @@ using Content.Shared.Research.Prototypes;
|
|||||||
using Robust.Client.AutoGenerated;
|
using Robust.Client.AutoGenerated;
|
||||||
using Robust.Client.UserInterface;
|
using Robust.Client.UserInterface;
|
||||||
using Robust.Client.UserInterface.XAML;
|
using Robust.Client.UserInterface.XAML;
|
||||||
using Robust.Shared.Prototypes;
|
|
||||||
|
|
||||||
namespace Content.Client.Lathe.UI;
|
namespace Content.Client.Lathe.UI;
|
||||||
|
|
||||||
@@ -12,47 +11,20 @@ public sealed partial class RecipeControl : Control
|
|||||||
public Action<string>? OnButtonPressed;
|
public Action<string>? OnButtonPressed;
|
||||||
public Func<string> TooltipTextSupplier;
|
public Func<string> TooltipTextSupplier;
|
||||||
|
|
||||||
private ProtoId<LatheRecipePrototype> _recipeId;
|
|
||||||
private LatheSystem _latheSystem;
|
|
||||||
|
|
||||||
public RecipeControl(LatheSystem latheSystem, LatheRecipePrototype recipe, Func<string> tooltipTextSupplier, bool canProduce, Control displayControl)
|
public RecipeControl(LatheSystem latheSystem, LatheRecipePrototype recipe, Func<string> tooltipTextSupplier, bool canProduce, Control displayControl)
|
||||||
{
|
{
|
||||||
RobustXamlLoader.Load(this);
|
RobustXamlLoader.Load(this);
|
||||||
|
|
||||||
_latheSystem = latheSystem;
|
RecipeName.Text = latheSystem.GetRecipeName(recipe);
|
||||||
_recipeId = recipe.ID;
|
RecipeDisplayContainer.AddChild(displayControl);
|
||||||
|
Button.Disabled = !canProduce;
|
||||||
TooltipTextSupplier = tooltipTextSupplier;
|
TooltipTextSupplier = tooltipTextSupplier;
|
||||||
SetRecipe(recipe);
|
Button.TooltipSupplier = SupplyTooltip;
|
||||||
SetCanProduce(canProduce);
|
|
||||||
SetDisplayControl(displayControl);
|
|
||||||
|
|
||||||
Button.OnPressed += (_) =>
|
Button.OnPressed += (_) =>
|
||||||
{
|
{
|
||||||
OnButtonPressed?.Invoke(_recipeId);
|
OnButtonPressed?.Invoke(recipe.ID);
|
||||||
};
|
};
|
||||||
Button.TooltipSupplier = SupplyTooltip;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SetRecipe(LatheRecipePrototype recipe)
|
|
||||||
{
|
|
||||||
RecipeName.Text = _latheSystem.GetRecipeName(recipe);
|
|
||||||
_recipeId = recipe.ID;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SetTooltipSupplier(Func<string> tooltipTextSupplier)
|
|
||||||
{
|
|
||||||
TooltipTextSupplier = tooltipTextSupplier;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SetCanProduce(bool canProduce)
|
|
||||||
{
|
|
||||||
Button.Disabled = !canProduce;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SetDisplayControl(Control displayControl)
|
|
||||||
{
|
|
||||||
RecipeDisplayContainer.Children.Clear();
|
|
||||||
RecipeDisplayContainer.AddChild(displayControl);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Control? SupplyTooltip(Control sender)
|
private Control? SupplyTooltip(Control sender)
|
||||||
|
|||||||
@@ -1,46 +1,36 @@
|
|||||||
using Content.Shared.Light.Components;
|
using Content.Shared.Light.Components;
|
||||||
using Content.Shared.Light.EntitySystems;
|
|
||||||
using Robust.Client.GameObjects;
|
using Robust.Client.GameObjects;
|
||||||
|
|
||||||
namespace Content.Client.Light.EntitySystems;
|
namespace Content.Client.Light.Visualizers;
|
||||||
|
|
||||||
public sealed class LightBulbSystem : SharedLightBulbSystem
|
public sealed class LightBulbSystem : VisualizerSystem<LightBulbComponent>
|
||||||
{
|
{
|
||||||
[Dependency] private readonly AppearanceSystem _appearance = default!;
|
protected override void OnAppearanceChange(EntityUid uid, LightBulbComponent comp, ref AppearanceChangeEvent args)
|
||||||
[Dependency] private readonly SpriteSystem _sprite = default!;
|
|
||||||
|
|
||||||
public override void Initialize()
|
|
||||||
{
|
|
||||||
base.Initialize();
|
|
||||||
SubscribeLocalEvent<LightBulbComponent, AppearanceChangeEvent>(OnAppearanceChange);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnAppearanceChange(EntityUid uid, LightBulbComponent comp, ref AppearanceChangeEvent args)
|
|
||||||
{
|
{
|
||||||
if (args.Sprite == null)
|
if (args.Sprite == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// update sprite state
|
// update sprite state
|
||||||
if (_appearance.TryGetData<LightBulbState>(uid, LightBulbVisuals.State, out var state, args.Component))
|
if (AppearanceSystem.TryGetData<LightBulbState>(uid, LightBulbVisuals.State, out var state, args.Component))
|
||||||
{
|
{
|
||||||
switch (state)
|
switch (state)
|
||||||
{
|
{
|
||||||
case LightBulbState.Normal:
|
case LightBulbState.Normal:
|
||||||
_sprite.LayerSetRsiState((uid, args.Sprite), LightBulbVisualLayers.Base, comp.NormalSpriteState);
|
SpriteSystem.LayerSetRsiState((uid, args.Sprite), LightBulbVisualLayers.Base, comp.NormalSpriteState);
|
||||||
break;
|
break;
|
||||||
case LightBulbState.Broken:
|
case LightBulbState.Broken:
|
||||||
_sprite.LayerSetRsiState((uid, args.Sprite), LightBulbVisualLayers.Base, comp.BrokenSpriteState);
|
SpriteSystem.LayerSetRsiState((uid, args.Sprite), LightBulbVisualLayers.Base, comp.BrokenSpriteState);
|
||||||
break;
|
break;
|
||||||
case LightBulbState.Burned:
|
case LightBulbState.Burned:
|
||||||
_sprite.LayerSetRsiState((uid, args.Sprite), LightBulbVisualLayers.Base, comp.BurnedSpriteState);
|
SpriteSystem.LayerSetRsiState((uid, args.Sprite), LightBulbVisualLayers.Base, comp.BurnedSpriteState);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// also update sprites color
|
// also update sprites color
|
||||||
if (_appearance.TryGetData<Color>(uid, LightBulbVisuals.Color, out var color, args.Component))
|
if (AppearanceSystem.TryGetData<Color>(uid, LightBulbVisuals.Color, out var color, args.Component))
|
||||||
{
|
{
|
||||||
_sprite.SetColor((uid, args.Sprite), color);
|
SpriteSystem.SetColor((uid, args.Sprite), color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +0,0 @@
|
|||||||
using Content.Shared.Light.EntitySystems;
|
|
||||||
|
|
||||||
namespace Content.Client.Light.EntitySystems;
|
|
||||||
|
|
||||||
public sealed class PoweredLightSystem : SharedPoweredLightSystem;
|
|
||||||
@@ -72,7 +72,6 @@ public sealed class LobbyUIController : UIController, IOnStateEntered<LobbyState
|
|||||||
});
|
});
|
||||||
|
|
||||||
_configurationManager.OnValueChanged(CCVars.GameRoleTimers, _ => RefreshProfileEditor());
|
_configurationManager.OnValueChanged(CCVars.GameRoleTimers, _ => RefreshProfileEditor());
|
||||||
_configurationManager.OnValueChanged(CCVars.GameRoleLoadoutTimers, _ => RefreshProfileEditor());
|
|
||||||
|
|
||||||
_configurationManager.OnValueChanged(CCVars.GameRoleWhitelist, _ => RefreshProfileEditor());
|
_configurationManager.OnValueChanged(CCVars.GameRoleWhitelist, _ => RefreshProfileEditor());
|
||||||
}
|
}
|
||||||
@@ -362,7 +361,7 @@ public sealed class LobbyUIController : UIController, IOnStateEntered<LobbyState
|
|||||||
{
|
{
|
||||||
foreach (var loadout in group)
|
foreach (var loadout in group)
|
||||||
{
|
{
|
||||||
if (!_prototypeManager.Resolve(loadout.Prototype, out var loadoutProto))
|
if (!_prototypeManager.TryIndex(loadout.Prototype, out var loadoutProto))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
_spawn.EquipStartingGear(uid, loadoutProto);
|
_spawn.EquipStartingGear(uid, loadoutProto);
|
||||||
@@ -385,14 +384,14 @@ public sealed class LobbyUIController : UIController, IOnStateEntered<LobbyState
|
|||||||
{
|
{
|
||||||
foreach (var loadout in loadouts)
|
foreach (var loadout in loadouts)
|
||||||
{
|
{
|
||||||
if (!_prototypeManager.Resolve(loadout.Prototype, out var loadoutProto))
|
if (!_prototypeManager.TryIndex(loadout.Prototype, out var loadoutProto))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// TODO: Need some way to apply starting gear to an entity and replace existing stuff coz holy fucking shit dude.
|
// TODO: Need some way to apply starting gear to an entity and replace existing stuff coz holy fucking shit dude.
|
||||||
foreach (var slot in slots)
|
foreach (var slot in slots)
|
||||||
{
|
{
|
||||||
// Try startinggear first
|
// Try startinggear first
|
||||||
if (_prototypeManager.Resolve(loadoutProto.StartingGear, out var loadoutGear))
|
if (_prototypeManager.TryIndex(loadoutProto.StartingGear, out var loadoutGear))
|
||||||
{
|
{
|
||||||
var itemType = ((IEquipmentLoadout) loadoutGear).GetGear(slot.Name);
|
var itemType = ((IEquipmentLoadout) loadoutGear).GetGear(slot.Name);
|
||||||
|
|
||||||
@@ -427,7 +426,7 @@ public sealed class LobbyUIController : UIController, IOnStateEntered<LobbyState
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_prototypeManager.Resolve(job.StartingGear, out var gear))
|
if (!_prototypeManager.TryIndex(job.StartingGear, out var gear))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
foreach (var slot in slots)
|
foreach (var slot in slots)
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ using Content.Client.Players.PlayTimeTracking;
|
|||||||
using Content.Client.Sprite;
|
using Content.Client.Sprite;
|
||||||
using Content.Client.Stylesheets;
|
using Content.Client.Stylesheets;
|
||||||
using Content.Client.UserInterface.Systems.Guidebook;
|
using Content.Client.UserInterface.Systems.Guidebook;
|
||||||
|
using Content.Shared._CP14.Humanoid;
|
||||||
using Content.Shared.CCVar;
|
using Content.Shared.CCVar;
|
||||||
using Content.Shared.Clothing;
|
using Content.Shared.Clothing;
|
||||||
using Content.Shared.GameTicking;
|
using Content.Shared.GameTicking;
|
||||||
@@ -810,7 +811,7 @@ namespace Content.Client.Lobby.UI
|
|||||||
if (_prototypeManager.HasIndex<GuideEntryPrototype>(species))
|
if (_prototypeManager.HasIndex<GuideEntryPrototype>(species))
|
||||||
page = new ProtoId<GuideEntryPrototype>(species.Id); // Gross. See above todo comment.
|
page = new ProtoId<GuideEntryPrototype>(species.Id); // Gross. See above todo comment.
|
||||||
|
|
||||||
if (_prototypeManager.Resolve(DefaultSpeciesGuidebook, out var guideRoot))
|
if (_prototypeManager.TryIndex(DefaultSpeciesGuidebook, out var guideRoot))
|
||||||
{
|
{
|
||||||
var dict = new Dictionary<ProtoId<GuideEntryPrototype>, GuideEntry>();
|
var dict = new Dictionary<ProtoId<GuideEntryPrototype>, GuideEntry>();
|
||||||
dict.Add(DefaultSpeciesGuidebook, guideRoot);
|
dict.Add(DefaultSpeciesGuidebook, guideRoot);
|
||||||
@@ -1020,7 +1021,7 @@ namespace Content.Client.Lobby.UI
|
|||||||
|
|
||||||
_loadoutWindow = new LoadoutWindow(Profile, roleLoadout, roleLoadoutProto, _playerManager.LocalSession, collection)
|
_loadoutWindow = new LoadoutWindow(Profile, roleLoadout, roleLoadoutProto, _playerManager.LocalSession, collection)
|
||||||
{
|
{
|
||||||
Title = Loc.GetString("loadout-window-title-loadout", ("job", $"{jobProto?.LocalizedName}")),
|
Title = jobProto?.ID + "-loadout",
|
||||||
};
|
};
|
||||||
|
|
||||||
// Refresh the buttons etc.
|
// Refresh the buttons etc.
|
||||||
@@ -1088,11 +1089,10 @@ namespace Content.Client.Lobby.UI
|
|||||||
if (Profile is null) return;
|
if (Profile is null) return;
|
||||||
|
|
||||||
var skin = _prototypeManager.Index<SpeciesPrototype>(Profile.Species).SkinColoration;
|
var skin = _prototypeManager.Index<SpeciesPrototype>(Profile.Species).SkinColoration;
|
||||||
var strategy = _prototypeManager.Index(skin).Strategy;
|
|
||||||
|
|
||||||
switch (strategy.InputType)
|
switch (skin)
|
||||||
{
|
{
|
||||||
case SkinColorationStrategyInput.Unary:
|
case HumanoidSkinColor.HumanToned:
|
||||||
{
|
{
|
||||||
if (!Skin.Visible)
|
if (!Skin.Visible)
|
||||||
{
|
{
|
||||||
@@ -1100,14 +1100,13 @@ namespace Content.Client.Lobby.UI
|
|||||||
RgbSkinColorContainer.Visible = false;
|
RgbSkinColorContainer.Visible = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
var color = strategy.FromUnary(Skin.Value);
|
var color = SkinColor.HumanSkinTone((int) Skin.Value);
|
||||||
|
|
||||||
Markings.CurrentSkinColor = color;
|
Markings.CurrentSkinColor = color;
|
||||||
Profile = Profile.WithCharacterAppearance(Profile.Appearance.WithSkinColor(color));
|
Profile = Profile.WithCharacterAppearance(Profile.Appearance.WithSkinColor(color));//
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SkinColorationStrategyInput.Color:
|
case HumanoidSkinColor.Hues:
|
||||||
{
|
{
|
||||||
if (!RgbSkinColorContainer.Visible)
|
if (!RgbSkinColorContainer.Visible)
|
||||||
{
|
{
|
||||||
@@ -1115,13 +1114,54 @@ namespace Content.Client.Lobby.UI
|
|||||||
RgbSkinColorContainer.Visible = true;
|
RgbSkinColorContainer.Visible = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
var color = strategy.ClosestSkinColor(_rgbSkinColorSelector.Color);
|
Markings.CurrentSkinColor = _rgbSkinColorSelector.Color;
|
||||||
|
Profile = Profile.WithCharacterAppearance(Profile.Appearance.WithSkinColor(_rgbSkinColorSelector.Color));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case HumanoidSkinColor.TintedHues:
|
||||||
|
{
|
||||||
|
if (!RgbSkinColorContainer.Visible)
|
||||||
|
{
|
||||||
|
Skin.Visible = false;
|
||||||
|
RgbSkinColorContainer.Visible = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
var color = SkinColor.TintedHues(_rgbSkinColorSelector.Color);
|
||||||
|
|
||||||
Markings.CurrentSkinColor = color;
|
Markings.CurrentSkinColor = color;
|
||||||
Profile = Profile.WithCharacterAppearance(Profile.Appearance.WithSkinColor(color));
|
Profile = Profile.WithCharacterAppearance(Profile.Appearance.WithSkinColor(color));
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case HumanoidSkinColor.VoxFeathers:
|
||||||
|
{
|
||||||
|
if (!RgbSkinColorContainer.Visible)
|
||||||
|
{
|
||||||
|
Skin.Visible = false;
|
||||||
|
RgbSkinColorContainer.Visible = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
var color = SkinColor.ClosestVoxColor(_rgbSkinColorSelector.Color);
|
||||||
|
|
||||||
|
Markings.CurrentSkinColor = color;
|
||||||
|
Profile = Profile.WithCharacterAppearance(Profile.Appearance.WithSkinColor(color));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// CP14 - Custom HumanoidSkinColor - Start
|
||||||
|
case HumanoidSkinColor.TieflingHues:
|
||||||
|
{
|
||||||
|
if (!RgbSkinColorContainer.Visible)
|
||||||
|
{
|
||||||
|
Skin.Visible = false;
|
||||||
|
RgbSkinColorContainer.Visible = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
var color = CP14SkinColor.MakeTieflingHueValid(_rgbSkinColorSelector.Color);
|
||||||
|
|
||||||
|
Markings.CurrentSkinColor = color;
|
||||||
|
Profile = Profile.WithCharacterAppearance(Profile.Appearance.WithSkinColor(color));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// CP14 - Custom HumanoidSkinColor - End
|
||||||
}
|
}
|
||||||
|
|
||||||
ReloadProfilePreview();
|
ReloadProfilePreview();
|
||||||
@@ -1268,7 +1308,7 @@ namespace Content.Client.Lobby.UI
|
|||||||
var sexes = new List<Sex>();
|
var sexes = new List<Sex>();
|
||||||
|
|
||||||
// add species sex options, default to just none if we are in bizzaro world and have no species
|
// add species sex options, default to just none if we are in bizzaro world and have no species
|
||||||
if (_prototypeManager.Resolve<SpeciesPrototype>(Profile.Species, out var speciesProto))
|
if (_prototypeManager.TryIndex<SpeciesPrototype>(Profile.Species, out var speciesProto))
|
||||||
{
|
{
|
||||||
foreach (var sex in speciesProto.Sexes)
|
foreach (var sex in speciesProto.Sexes)
|
||||||
{
|
{
|
||||||
@@ -1298,11 +1338,10 @@ namespace Content.Client.Lobby.UI
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
var skin = _prototypeManager.Index<SpeciesPrototype>(Profile.Species).SkinColoration;
|
var skin = _prototypeManager.Index<SpeciesPrototype>(Profile.Species).SkinColoration;
|
||||||
var strategy = _prototypeManager.Index(skin).Strategy;
|
|
||||||
|
|
||||||
switch (strategy.InputType)
|
switch (skin)
|
||||||
{
|
{
|
||||||
case SkinColorationStrategyInput.Unary:
|
case HumanoidSkinColor.HumanToned:
|
||||||
{
|
{
|
||||||
if (!Skin.Visible)
|
if (!Skin.Visible)
|
||||||
{
|
{
|
||||||
@@ -1310,11 +1349,11 @@ namespace Content.Client.Lobby.UI
|
|||||||
RgbSkinColorContainer.Visible = false;
|
RgbSkinColorContainer.Visible = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Skin.Value = strategy.ToUnary(Profile.Appearance.SkinColor);
|
Skin.Value = SkinColor.HumanSkinToneFromColor(Profile.Appearance.SkinColor);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SkinColorationStrategyInput.Color:
|
case HumanoidSkinColor.Hues:
|
||||||
{
|
{
|
||||||
if (!RgbSkinColorContainer.Visible)
|
if (!RgbSkinColorContainer.Visible)
|
||||||
{
|
{
|
||||||
@@ -1322,11 +1361,49 @@ namespace Content.Client.Lobby.UI
|
|||||||
RgbSkinColorContainer.Visible = true;
|
RgbSkinColorContainer.Visible = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
_rgbSkinColorSelector.Color = strategy.ClosestSkinColor(Profile.Appearance.SkinColor);
|
// set the RGB values to the direct values otherwise
|
||||||
|
_rgbSkinColorSelector.Color = Profile.Appearance.SkinColor;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case HumanoidSkinColor.TintedHues:
|
||||||
|
{
|
||||||
|
if (!RgbSkinColorContainer.Visible)
|
||||||
|
{
|
||||||
|
Skin.Visible = false;
|
||||||
|
RgbSkinColorContainer.Visible = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// set the RGB values to the direct values otherwise
|
||||||
|
_rgbSkinColorSelector.Color = Profile.Appearance.SkinColor;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case HumanoidSkinColor.VoxFeathers:
|
||||||
|
{
|
||||||
|
if (!RgbSkinColorContainer.Visible)
|
||||||
|
{
|
||||||
|
Skin.Visible = false;
|
||||||
|
RgbSkinColorContainer.Visible = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
_rgbSkinColorSelector.Color = SkinColor.ClosestVoxColor(Profile.Appearance.SkinColor);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
// CP14 - Custom HumanoidSkinColor - Start
|
||||||
|
case HumanoidSkinColor.TieflingHues:
|
||||||
|
{
|
||||||
|
if (!RgbSkinColorContainer.Visible)
|
||||||
|
{
|
||||||
|
Skin.Visible = false;
|
||||||
|
RgbSkinColorContainer.Visible = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
_rgbSkinColorSelector.Color = CP14SkinColor.MakeTieflingHueValid(Profile.Appearance.SkinColor);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// CP14 - Custom HumanoidSkinColor - End
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UpdateSpeciesGuidebookIcon()
|
public void UpdateSpeciesGuidebookIcon()
|
||||||
@@ -1337,7 +1414,7 @@ namespace Content.Client.Lobby.UI
|
|||||||
if (species is null)
|
if (species is null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!_prototypeManager.Resolve<SpeciesPrototype>(species, out var speciesProto))
|
if (!_prototypeManager.TryIndex<SpeciesPrototype>(species, out var speciesProto))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Don't display the info button if no guide entry is found
|
// Don't display the info button if no guide entry is found
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ public sealed partial class LoadoutContainer : BoxContainer
|
|||||||
SelectButton.TooltipSupplier = _ => tooltip;
|
SelectButton.TooltipSupplier = _ => tooltip;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_protoManager.Resolve(proto, out var loadProto))
|
if (_protoManager.TryIndex(proto, out var loadProto))
|
||||||
{
|
{
|
||||||
var ent = loadProto.DummyEntity ?? _entManager.System<LoadoutSystem>().GetFirstOrNull(loadProto);
|
var ent = loadProto.DummyEntity ?? _entManager.System<LoadoutSystem>().GetFirstOrNull(loadProto);
|
||||||
|
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ public sealed partial class LoadoutGroupContainer : BoxContainer
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (protoMan.Resolve(loadout.Role, out var roleProto) && roleProto.Points != null && loadout.Points != null)
|
if (protoMan.TryIndex(loadout.Role, out var roleProto) && roleProto.Points != null && loadout.Points != null)
|
||||||
{
|
{
|
||||||
RestrictionsContainer.AddChild(new Label()
|
RestrictionsContainer.AddChild(new Label()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ public sealed partial class LoadoutWindow : FancyWindow
|
|||||||
{
|
{
|
||||||
foreach (var group in proto.Groups)
|
foreach (var group in proto.Groups)
|
||||||
{
|
{
|
||||||
if (!protoManager.Resolve(group, out var groupProto))
|
if (!protoManager.TryIndex(group, out var groupProto))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (groupProto.Hidden)
|
if (groupProto.Hidden)
|
||||||
|
|||||||
@@ -64,9 +64,7 @@ public sealed partial class CrewMonitoringNavMapControl : NavMapControl
|
|||||||
if (!LocalizedNames.TryGetValue(netEntity, out var name))
|
if (!LocalizedNames.TryGetValue(netEntity, out var name))
|
||||||
name = "Unknown";
|
name = "Unknown";
|
||||||
|
|
||||||
var message = name + "\n" + Loc.GetString("navmap-location",
|
var message = name + "\nLocation: [x = " + MathF.Round(blip.Coordinates.X) + ", y = " + MathF.Round(blip.Coordinates.Y) + "]";
|
||||||
("x", MathF.Round(blip.Coordinates.X)),
|
|
||||||
("y", MathF.Round(blip.Coordinates.Y)));
|
|
||||||
|
|
||||||
_trackedEntityLabel.Text = message;
|
_trackedEntityLabel.Text = message;
|
||||||
_trackedEntityPanel.Visible = true;
|
_trackedEntityPanel.Visible = true;
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user