From 36aceb178c855b381cb9b5868e4348fde1bedbd0 Mon Sep 17 00:00:00 2001 From: Pieter-Jan Briers Date: Tue, 29 Oct 2024 01:34:40 +0100 Subject: [PATCH 01/59] Database SnakeCaseNaming fixes Fixes formatting of owned entity type property names. These are normally named "FooBar_Baz" by EF Core, but the snake case thing was turning them into "foo_bar__baz". The double underscore is now fixed. We don't *yet* have any EF Core owned entity in use, but I am planning to add one. I don't know if downstreams are using any so this should still be marked as a breaking change. Also fixed it creating and dropping a Compiled Regex instance for every name, the regex is now cached (and pregenerated). --- Content.Server.Database/SnakeCaseNaming.cs | 40 +++++++++++++--------- 1 file changed, 24 insertions(+), 16 deletions(-) diff --git a/Content.Server.Database/SnakeCaseNaming.cs b/Content.Server.Database/SnakeCaseNaming.cs index 27ce392cd5..3a67ffb9cd 100644 --- a/Content.Server.Database/SnakeCaseNaming.cs +++ b/Content.Server.Database/SnakeCaseNaming.cs @@ -82,7 +82,7 @@ namespace Content.Server.Database } } - public class SnakeCaseConvention : + public partial class SnakeCaseConvention : IEntityTypeAddedConvention, IEntityTypeAnnotationChangedConvention, IPropertyAddedConvention, @@ -99,22 +99,27 @@ namespace Content.Server.Database public static string RewriteName(string name) { - var regex = new Regex("[A-Z]+", RegexOptions.Compiled); - return regex.Replace( - name, - (Match match) => { - if (match.Index == 0 && (match.Value == "FK" || match.Value == "PK" || match.Value == "IX")) { - return match.Value; + return UpperCaseLocator() + .Replace( + name, + (Match match) => { + if (match.Index == 0 && (match.Value == "FK" || match.Value == "PK" || match.Value == "IX")) { + return match.Value; + } + if (match.Value == "HWI") + return (match.Index == 0 ? "" : "_") + "hwi"; + if (match.Index == 0) + return match.Value.ToLower(); + if (match.Length > 1) + return $"_{match.Value[..^1].ToLower()}_{match.Value[^1..^0].ToLower()}"; + + // Do not add a _ if there is already one before this. This happens with owned entities. + if (name[match.Index - 1] == '_') + return match.Value.ToLower(); + + return "_" + match.Value.ToLower(); } - if (match.Value == "HWI") - return (match.Index == 0 ? "" : "_") + "hwi"; - if (match.Index == 0) - return match.Value.ToLower(); - if (match.Length > 1) - return $"_{match.Value[..^1].ToLower()}_{match.Value[^1..^0].ToLower()}"; - return "_" + match.Value.ToLower(); - } - ); + ); } public virtual void ProcessEntityTypeAdded( @@ -332,5 +337,8 @@ namespace Content.Server.Database } } } + + [GeneratedRegex("[A-Z]+", RegexOptions.Compiled)] + private static partial Regex UpperCaseLocator(); } } From 4f3db43696fbcc9144d2ad011bbb5f93f6deca7a Mon Sep 17 00:00:00 2001 From: Pieter-Jan Briers Date: Tue, 12 Nov 2024 01:51:23 +0100 Subject: [PATCH 02/59] Integrate Modern HWID into content This should be the primary changes for the future-proof "Modern HWID" system implemented into Robust and the auth server. HWIDs in the database have been given an additional column representing their version, legacy or modern. This is implemented via an EF Core owned entity. By manually setting the column name of the main value column, we can keep DB compatibility and the migration is just adding some type columns. This new HWID type has to be plumbed through everywhere, resulting in some breaking changes for the DB layer and such. New bans and player records are placed with the new modern HWID. Old bans are still checked against legacy HWIDs. Modern HWIDs are presented with a "V2-" prefix to admins, to allow distinguishing them. This is also integrated into the parsing logic for placing new bans. There's also some code cleanup to reduce copy pasting around the place from my changes. Requires latest engine to support ImmutableArray in NetSerializer. --- .../UI/BanPanel/BanPanel.xaml.cs | 11 +- .../Tests/Commands/PardonCommand.cs | 24 +- .../20241111170112_ModernHwid.Designer.cs | 2072 ++++++++++++++++ .../Postgres/20241111170112_ModernHwid.cs | 62 + ...20241111193608_ConnectionTrust.Designer.cs | 2076 +++++++++++++++++ .../20241111193608_ConnectionTrust.cs | 29 + .../PostgresServerDbContextModelSnapshot.cs | 162 +- .../20241111170107_ModernHwid.Designer.cs | 1995 ++++++++++++++++ .../Sqlite/20241111170107_ModernHwid.cs | 62 + ...20241111193602_ConnectionTrust.Designer.cs | 1999 ++++++++++++++++ .../Sqlite/20241111193602_ConnectionTrust.cs | 29 + .../SqliteServerDbContextModelSnapshot.cs | 161 +- Content.Server.Database/Model.cs | 88 +- .../Administration/BanList/BanListEui.cs | 8 +- Content.Server/Administration/BanPanelEui.cs | 10 +- .../Administration/Commands/BanListCommand.cs | 2 +- .../Commands/RoleBanListCommand.cs | 2 +- .../Administration/Managers/BanManager.cs | 12 +- .../Administration/Managers/IBanManager.cs | 4 +- .../Administration/PlayerLocator.cs | 99 +- .../Administration/PlayerPanelEui.cs | 4 +- .../Administration/Systems/BwoinkSystem.cs | 2 +- .../Connection/ConnectionManager.cs | 13 +- Content.Server/Connection/UserDataExt.cs | 24 + Content.Server/Database/BanMatcher.cs | 33 +- Content.Server/Database/DatabaseRecords.cs | 3 +- Content.Server/Database/ServerBanDef.cs | 5 +- Content.Server/Database/ServerDbBase.cs | 24 +- Content.Server/Database/ServerDbManager.cs | 35 +- Content.Server/Database/ServerDbPostgres.cs | 124 +- Content.Server/Database/ServerDbSqlite.cs | 55 +- Content.Server/Database/ServerRoleBanDef.cs | 5 +- Content.Shared.Database/TypedHwid.cs | 62 + .../Administration/BanPanelEuiState.cs | 4 +- 34 files changed, 9059 insertions(+), 241 deletions(-) create mode 100644 Content.Server.Database/Migrations/Postgres/20241111170112_ModernHwid.Designer.cs create mode 100644 Content.Server.Database/Migrations/Postgres/20241111170112_ModernHwid.cs create mode 100644 Content.Server.Database/Migrations/Postgres/20241111193608_ConnectionTrust.Designer.cs create mode 100644 Content.Server.Database/Migrations/Postgres/20241111193608_ConnectionTrust.cs create mode 100644 Content.Server.Database/Migrations/Sqlite/20241111170107_ModernHwid.Designer.cs create mode 100644 Content.Server.Database/Migrations/Sqlite/20241111170107_ModernHwid.cs create mode 100644 Content.Server.Database/Migrations/Sqlite/20241111193602_ConnectionTrust.Designer.cs create mode 100644 Content.Server.Database/Migrations/Sqlite/20241111193602_ConnectionTrust.cs create mode 100644 Content.Server/Connection/UserDataExt.cs create mode 100644 Content.Shared.Database/TypedHwid.cs diff --git a/Content.Client/Administration/UI/BanPanel/BanPanel.xaml.cs b/Content.Client/Administration/UI/BanPanel/BanPanel.xaml.cs index 588d62e560..3c7322d473 100644 --- a/Content.Client/Administration/UI/BanPanel/BanPanel.xaml.cs +++ b/Content.Client/Administration/UI/BanPanel/BanPanel.xaml.cs @@ -22,11 +22,11 @@ namespace Content.Client.Administration.UI.BanPanel; [GenerateTypedNameReferences] public sealed partial class BanPanel : DefaultWindow { - public event Action? BanSubmitted; + public event Action? BanSubmitted; public event Action? PlayerChanged; private string? PlayerUsername { get; set; } private (IPAddress, int)? IpAddress { get; set; } - private byte[]? Hwid { get; set; } + private ImmutableTypedHwid? Hwid { get; set; } private double TimeEntered { get; set; } private uint Multiplier { get; set; } private bool HasBanFlag { get; set; } @@ -371,9 +371,8 @@ public sealed partial class BanPanel : DefaultWindow private void OnHwidChanged() { var hwidString = HwidLine.Text; - var length = 3 * (hwidString.Length / 4) - hwidString.TakeLast(2).Count(c => c == '='); - Hwid = new byte[length]; - if (HwidCheckbox.Pressed && !(string.IsNullOrEmpty(hwidString) && LastConnCheckbox.Pressed) && !Convert.TryFromBase64String(hwidString, Hwid, out _)) + ImmutableTypedHwid? hwid = null; + if (HwidCheckbox.Pressed && !(string.IsNullOrEmpty(hwidString) && LastConnCheckbox.Pressed) && !ImmutableTypedHwid.TryParse(hwidString, out hwid)) { ErrorLevel |= ErrorLevelEnum.Hwid; HwidLine.ModulateSelfOverride = Color.Red; @@ -390,7 +389,7 @@ public sealed partial class BanPanel : DefaultWindow Hwid = null; return; } - Hwid = Convert.FromHexString(hwidString); + Hwid = hwid; } private void OnTypeChanged() diff --git a/Content.IntegrationTests/Tests/Commands/PardonCommand.cs b/Content.IntegrationTests/Tests/Commands/PardonCommand.cs index 4db9eabf5c..9e57cd4b0e 100644 --- a/Content.IntegrationTests/Tests/Commands/PardonCommand.cs +++ b/Content.IntegrationTests/Tests/Commands/PardonCommand.cs @@ -32,9 +32,9 @@ namespace Content.IntegrationTests.Tests.Commands // No bans on record Assert.Multiple(async () => { - Assert.That(await sDatabase.GetServerBanAsync(null, clientId, null), Is.Null); + Assert.That(await sDatabase.GetServerBanAsync(null, clientId, null, null), Is.Null); Assert.That(await sDatabase.GetServerBanAsync(1), Is.Null); - Assert.That(await sDatabase.GetServerBansAsync(null, clientId, null), Is.Empty); + Assert.That(await sDatabase.GetServerBansAsync(null, clientId, null, null), Is.Empty); }); // Try to pardon a ban that does not exist @@ -43,9 +43,9 @@ namespace Content.IntegrationTests.Tests.Commands // Still no bans on record Assert.Multiple(async () => { - Assert.That(await sDatabase.GetServerBanAsync(null, clientId, null), Is.Null); + Assert.That(await sDatabase.GetServerBanAsync(null, clientId, null, null), Is.Null); Assert.That(await sDatabase.GetServerBanAsync(1), Is.Null); - Assert.That(await sDatabase.GetServerBansAsync(null, clientId, null), Is.Empty); + Assert.That(await sDatabase.GetServerBansAsync(null, clientId, null, null), Is.Empty); }); var banReason = "test"; @@ -57,9 +57,9 @@ namespace Content.IntegrationTests.Tests.Commands // Should have one ban on record now Assert.Multiple(async () => { - Assert.That(await sDatabase.GetServerBanAsync(null, clientId, null), Is.Not.Null); + Assert.That(await sDatabase.GetServerBanAsync(null, clientId, null, null), Is.Not.Null); Assert.That(await sDatabase.GetServerBanAsync(1), Is.Not.Null); - Assert.That(await sDatabase.GetServerBansAsync(null, clientId, null), Has.Count.EqualTo(1)); + Assert.That(await sDatabase.GetServerBansAsync(null, clientId, null, null), Has.Count.EqualTo(1)); }); await pair.RunTicksSync(5); @@ -70,13 +70,13 @@ namespace Content.IntegrationTests.Tests.Commands await server.WaitPost(() => sConsole.ExecuteCommand("pardon 2")); // The existing ban is unaffected - Assert.That(await sDatabase.GetServerBanAsync(null, clientId, null), Is.Not.Null); + Assert.That(await sDatabase.GetServerBanAsync(null, clientId, null, null), Is.Not.Null); var ban = await sDatabase.GetServerBanAsync(1); Assert.Multiple(async () => { Assert.That(ban, Is.Not.Null); - Assert.That(await sDatabase.GetServerBansAsync(null, clientId, null), Has.Count.EqualTo(1)); + Assert.That(await sDatabase.GetServerBansAsync(null, clientId, null, null), Has.Count.EqualTo(1)); // Check that it matches Assert.That(ban.Id, Is.EqualTo(1)); @@ -95,7 +95,7 @@ namespace Content.IntegrationTests.Tests.Commands await server.WaitPost(() => sConsole.ExecuteCommand("pardon 1")); // No bans should be returned - Assert.That(await sDatabase.GetServerBanAsync(null, clientId, null), Is.Null); + Assert.That(await sDatabase.GetServerBanAsync(null, clientId, null, null), Is.Null); // Direct id lookup returns a pardoned ban var pardonedBan = await sDatabase.GetServerBanAsync(1); @@ -105,7 +105,7 @@ namespace Content.IntegrationTests.Tests.Commands Assert.That(pardonedBan, Is.Not.Null); // The list is still returned since that ignores pardons - Assert.That(await sDatabase.GetServerBansAsync(null, clientId, null), Has.Count.EqualTo(1)); + Assert.That(await sDatabase.GetServerBansAsync(null, clientId, null, null), Has.Count.EqualTo(1)); Assert.That(pardonedBan.Id, Is.EqualTo(1)); Assert.That(pardonedBan.UserId, Is.EqualTo(clientId)); @@ -133,13 +133,13 @@ namespace Content.IntegrationTests.Tests.Commands Assert.Multiple(async () => { // No bans should be returned - Assert.That(await sDatabase.GetServerBanAsync(null, clientId, null), Is.Null); + Assert.That(await sDatabase.GetServerBanAsync(null, clientId, null, null), Is.Null); // Direct id lookup returns a pardoned ban Assert.That(await sDatabase.GetServerBanAsync(1), Is.Not.Null); // The list is still returned since that ignores pardons - Assert.That(await sDatabase.GetServerBansAsync(null, clientId, null), Has.Count.EqualTo(1)); + Assert.That(await sDatabase.GetServerBansAsync(null, clientId, null, null), Has.Count.EqualTo(1)); }); // Reconnect client. Slightly faster than dirtying the pair. diff --git a/Content.Server.Database/Migrations/Postgres/20241111170112_ModernHwid.Designer.cs b/Content.Server.Database/Migrations/Postgres/20241111170112_ModernHwid.Designer.cs new file mode 100644 index 0000000000..155d6a163f --- /dev/null +++ b/Content.Server.Database/Migrations/Postgres/20241111170112_ModernHwid.Designer.cs @@ -0,0 +1,2072 @@ +// +using System; +using System.Net; +using System.Text.Json; +using Content.Server.Database; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; +using NpgsqlTypes; + +#nullable disable + +namespace Content.Server.Database.Migrations.Postgres +{ + [DbContext(typeof(PostgresServerDbContext))] + [Migration("20241111170112_ModernHwid")] + partial class ModernHwid + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.0") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("Content.Server.Database.Admin", b => + { + b.Property("UserId") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("user_id"); + + b.Property("AdminRankId") + .HasColumnType("integer") + .HasColumnName("admin_rank_id"); + + b.Property("Title") + .HasColumnType("text") + .HasColumnName("title"); + + b.HasKey("UserId") + .HasName("PK_admin"); + + b.HasIndex("AdminRankId") + .HasDatabaseName("IX_admin_admin_rank_id"); + + b.ToTable("admin", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AdminFlag", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("admin_flag_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AdminId") + .HasColumnType("uuid") + .HasColumnName("admin_id"); + + b.Property("Flag") + .IsRequired() + .HasColumnType("text") + .HasColumnName("flag"); + + b.Property("Negative") + .HasColumnType("boolean") + .HasColumnName("negative"); + + b.HasKey("Id") + .HasName("PK_admin_flag"); + + b.HasIndex("AdminId") + .HasDatabaseName("IX_admin_flag_admin_id"); + + b.HasIndex("Flag", "AdminId") + .IsUnique(); + + b.ToTable("admin_flag", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AdminLog", b => + { + b.Property("RoundId") + .HasColumnType("integer") + .HasColumnName("round_id"); + + b.Property("Id") + .HasColumnType("integer") + .HasColumnName("admin_log_id"); + + b.Property("Date") + .HasColumnType("timestamp with time zone") + .HasColumnName("date"); + + b.Property("Impact") + .HasColumnType("smallint") + .HasColumnName("impact"); + + b.Property("Json") + .IsRequired() + .HasColumnType("jsonb") + .HasColumnName("json"); + + b.Property("Message") + .IsRequired() + .HasColumnType("text") + .HasColumnName("message"); + + b.Property("Type") + .HasColumnType("integer") + .HasColumnName("type"); + + b.HasKey("RoundId", "Id") + .HasName("PK_admin_log"); + + b.HasIndex("Date"); + + b.HasIndex("Message") + .HasAnnotation("Npgsql:TsVectorConfig", "english"); + + NpgsqlIndexBuilderExtensions.HasMethod(b.HasIndex("Message"), "GIN"); + + b.HasIndex("Type") + .HasDatabaseName("IX_admin_log_type"); + + b.ToTable("admin_log", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AdminLogPlayer", b => + { + b.Property("RoundId") + .HasColumnType("integer") + .HasColumnName("round_id"); + + b.Property("LogId") + .HasColumnType("integer") + .HasColumnName("log_id"); + + b.Property("PlayerUserId") + .HasColumnType("uuid") + .HasColumnName("player_user_id"); + + b.HasKey("RoundId", "LogId", "PlayerUserId") + .HasName("PK_admin_log_player"); + + b.HasIndex("PlayerUserId") + .HasDatabaseName("IX_admin_log_player_player_user_id"); + + b.ToTable("admin_log_player", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AdminMessage", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("admin_messages_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("CreatedById") + .HasColumnType("uuid") + .HasColumnName("created_by_id"); + + b.Property("Deleted") + .HasColumnType("boolean") + .HasColumnName("deleted"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("DeletedById") + .HasColumnType("uuid") + .HasColumnName("deleted_by_id"); + + b.Property("Dismissed") + .HasColumnType("boolean") + .HasColumnName("dismissed"); + + b.Property("ExpirationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("expiration_time"); + + b.Property("LastEditedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("last_edited_at"); + + b.Property("LastEditedById") + .HasColumnType("uuid") + .HasColumnName("last_edited_by_id"); + + b.Property("Message") + .IsRequired() + .HasMaxLength(4096) + .HasColumnType("character varying(4096)") + .HasColumnName("message"); + + b.Property("PlayerUserId") + .HasColumnType("uuid") + .HasColumnName("player_user_id"); + + b.Property("PlaytimeAtNote") + .HasColumnType("interval") + .HasColumnName("playtime_at_note"); + + b.Property("RoundId") + .HasColumnType("integer") + .HasColumnName("round_id"); + + b.Property("Seen") + .HasColumnType("boolean") + .HasColumnName("seen"); + + b.HasKey("Id") + .HasName("PK_admin_messages"); + + b.HasIndex("CreatedById"); + + b.HasIndex("DeletedById"); + + b.HasIndex("LastEditedById"); + + b.HasIndex("PlayerUserId") + .HasDatabaseName("IX_admin_messages_player_user_id"); + + b.HasIndex("RoundId") + .HasDatabaseName("IX_admin_messages_round_id"); + + b.ToTable("admin_messages", null, t => + { + t.HasCheckConstraint("NotDismissedAndSeen", "NOT dismissed OR seen"); + }); + }); + + modelBuilder.Entity("Content.Server.Database.AdminNote", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("admin_notes_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("CreatedById") + .HasColumnType("uuid") + .HasColumnName("created_by_id"); + + b.Property("Deleted") + .HasColumnType("boolean") + .HasColumnName("deleted"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("DeletedById") + .HasColumnType("uuid") + .HasColumnName("deleted_by_id"); + + b.Property("ExpirationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("expiration_time"); + + b.Property("LastEditedAt") + .IsRequired() + .HasColumnType("timestamp with time zone") + .HasColumnName("last_edited_at"); + + b.Property("LastEditedById") + .HasColumnType("uuid") + .HasColumnName("last_edited_by_id"); + + b.Property("Message") + .IsRequired() + .HasMaxLength(4096) + .HasColumnType("character varying(4096)") + .HasColumnName("message"); + + b.Property("PlayerUserId") + .HasColumnType("uuid") + .HasColumnName("player_user_id"); + + b.Property("PlaytimeAtNote") + .HasColumnType("interval") + .HasColumnName("playtime_at_note"); + + b.Property("RoundId") + .HasColumnType("integer") + .HasColumnName("round_id"); + + b.Property("Secret") + .HasColumnType("boolean") + .HasColumnName("secret"); + + b.Property("Severity") + .HasColumnType("integer") + .HasColumnName("severity"); + + b.HasKey("Id") + .HasName("PK_admin_notes"); + + b.HasIndex("CreatedById"); + + b.HasIndex("DeletedById"); + + b.HasIndex("LastEditedById"); + + b.HasIndex("PlayerUserId") + .HasDatabaseName("IX_admin_notes_player_user_id"); + + b.HasIndex("RoundId") + .HasDatabaseName("IX_admin_notes_round_id"); + + b.ToTable("admin_notes", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AdminRank", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("admin_rank_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Name") + .IsRequired() + .HasColumnType("text") + .HasColumnName("name"); + + b.HasKey("Id") + .HasName("PK_admin_rank"); + + b.ToTable("admin_rank", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AdminRankFlag", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("admin_rank_flag_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AdminRankId") + .HasColumnType("integer") + .HasColumnName("admin_rank_id"); + + b.Property("Flag") + .IsRequired() + .HasColumnType("text") + .HasColumnName("flag"); + + b.HasKey("Id") + .HasName("PK_admin_rank_flag"); + + b.HasIndex("AdminRankId"); + + b.HasIndex("Flag", "AdminRankId") + .IsUnique(); + + b.ToTable("admin_rank_flag", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AdminWatchlist", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("admin_watchlists_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("CreatedById") + .HasColumnType("uuid") + .HasColumnName("created_by_id"); + + b.Property("Deleted") + .HasColumnType("boolean") + .HasColumnName("deleted"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("DeletedById") + .HasColumnType("uuid") + .HasColumnName("deleted_by_id"); + + b.Property("ExpirationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("expiration_time"); + + b.Property("LastEditedAt") + .IsRequired() + .HasColumnType("timestamp with time zone") + .HasColumnName("last_edited_at"); + + b.Property("LastEditedById") + .HasColumnType("uuid") + .HasColumnName("last_edited_by_id"); + + b.Property("Message") + .IsRequired() + .HasMaxLength(4096) + .HasColumnType("character varying(4096)") + .HasColumnName("message"); + + b.Property("PlayerUserId") + .HasColumnType("uuid") + .HasColumnName("player_user_id"); + + b.Property("PlaytimeAtNote") + .HasColumnType("interval") + .HasColumnName("playtime_at_note"); + + b.Property("RoundId") + .HasColumnType("integer") + .HasColumnName("round_id"); + + b.HasKey("Id") + .HasName("PK_admin_watchlists"); + + b.HasIndex("CreatedById"); + + b.HasIndex("DeletedById"); + + b.HasIndex("LastEditedById"); + + b.HasIndex("PlayerUserId") + .HasDatabaseName("IX_admin_watchlists_player_user_id"); + + b.HasIndex("RoundId") + .HasDatabaseName("IX_admin_watchlists_round_id"); + + b.ToTable("admin_watchlists", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Antag", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("antag_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AntagName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("antag_name"); + + b.Property("ProfileId") + .HasColumnType("integer") + .HasColumnName("profile_id"); + + b.HasKey("Id") + .HasName("PK_antag"); + + b.HasIndex("ProfileId", "AntagName") + .IsUnique(); + + b.ToTable("antag", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AssignedUserId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("assigned_user_id_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("UserId") + .HasColumnType("uuid") + .HasColumnName("user_id"); + + b.Property("UserName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("user_name"); + + b.HasKey("Id") + .HasName("PK_assigned_user_id"); + + b.HasIndex("UserId") + .IsUnique(); + + b.HasIndex("UserName") + .IsUnique(); + + b.ToTable("assigned_user_id", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.BanTemplate", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("ban_template_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AutoDelete") + .HasColumnType("boolean") + .HasColumnName("auto_delete"); + + b.Property("ExemptFlags") + .HasColumnType("integer") + .HasColumnName("exempt_flags"); + + b.Property("Hidden") + .HasColumnType("boolean") + .HasColumnName("hidden"); + + b.Property("Length") + .HasColumnType("interval") + .HasColumnName("length"); + + b.Property("Reason") + .IsRequired() + .HasColumnType("text") + .HasColumnName("reason"); + + b.Property("Severity") + .HasColumnType("integer") + .HasColumnName("severity"); + + b.Property("Title") + .IsRequired() + .HasColumnType("text") + .HasColumnName("title"); + + b.HasKey("Id") + .HasName("PK_ban_template"); + + b.ToTable("ban_template", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Blacklist", b => + { + b.Property("UserId") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("user_id"); + + b.HasKey("UserId") + .HasName("PK_blacklist"); + + b.ToTable("blacklist", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.ConnectionLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("connection_log_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Address") + .IsRequired() + .HasColumnType("inet") + .HasColumnName("address"); + + b.Property("Denied") + .HasColumnType("smallint") + .HasColumnName("denied"); + + b.Property("ServerId") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0) + .HasColumnName("server_id"); + + b.Property("Time") + .HasColumnType("timestamp with time zone") + .HasColumnName("time"); + + b.Property("UserId") + .HasColumnType("uuid") + .HasColumnName("user_id"); + + b.Property("UserName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("user_name"); + + b.HasKey("Id") + .HasName("PK_connection_log"); + + b.HasIndex("ServerId") + .HasDatabaseName("IX_connection_log_server_id"); + + b.HasIndex("Time"); + + b.HasIndex("UserId"); + + b.ToTable("connection_log", null, t => + { + t.HasCheckConstraint("AddressNotIPv6MappedIPv4", "NOT inet '::ffff:0.0.0.0/96' >>= address"); + }); + }); + + modelBuilder.Entity("Content.Server.Database.Job", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("job_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("JobName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("job_name"); + + b.Property("Priority") + .HasColumnType("integer") + .HasColumnName("priority"); + + b.Property("ProfileId") + .HasColumnType("integer") + .HasColumnName("profile_id"); + + b.HasKey("Id") + .HasName("PK_job"); + + b.HasIndex("ProfileId"); + + b.HasIndex("ProfileId", "JobName") + .IsUnique(); + + b.HasIndex(new[] { "ProfileId" }, "IX_job_one_high_priority") + .IsUnique() + .HasFilter("priority = 3"); + + b.ToTable("job", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.PlayTime", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("play_time_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("PlayerId") + .HasColumnType("uuid") + .HasColumnName("player_id"); + + b.Property("TimeSpent") + .HasColumnType("interval") + .HasColumnName("time_spent"); + + b.Property("Tracker") + .IsRequired() + .HasColumnType("text") + .HasColumnName("tracker"); + + b.HasKey("Id") + .HasName("PK_play_time"); + + b.HasIndex("PlayerId", "Tracker") + .IsUnique(); + + b.ToTable("play_time", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Player", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("player_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("FirstSeenTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("first_seen_time"); + + b.Property("LastReadRules") + .HasColumnType("timestamp with time zone") + .HasColumnName("last_read_rules"); + + b.Property("LastSeenAddress") + .IsRequired() + .HasColumnType("inet") + .HasColumnName("last_seen_address"); + + b.Property("LastSeenTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("last_seen_time"); + + b.Property("LastSeenUserName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("last_seen_user_name"); + + b.Property("UserId") + .HasColumnType("uuid") + .HasColumnName("user_id"); + + b.HasKey("Id") + .HasName("PK_player"); + + b.HasAlternateKey("UserId") + .HasName("ak_player_user_id"); + + b.HasIndex("LastSeenUserName"); + + b.HasIndex("UserId") + .IsUnique(); + + b.ToTable("player", null, t => + { + t.HasCheckConstraint("LastSeenAddressNotIPv6MappedIPv4", "NOT inet '::ffff:0.0.0.0/96' >>= last_seen_address"); + }); + }); + + modelBuilder.Entity("Content.Server.Database.Preference", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("preference_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AdminOOCColor") + .IsRequired() + .HasColumnType("text") + .HasColumnName("admin_ooc_color"); + + b.Property("SelectedCharacterSlot") + .HasColumnType("integer") + .HasColumnName("selected_character_slot"); + + b.Property("UserId") + .HasColumnType("uuid") + .HasColumnName("user_id"); + + b.HasKey("Id") + .HasName("PK_preference"); + + b.HasIndex("UserId") + .IsUnique(); + + b.ToTable("preference", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Profile", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("profile_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Age") + .HasColumnType("integer") + .HasColumnName("age"); + + b.Property("CharacterName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("char_name"); + + b.Property("EyeColor") + .IsRequired() + .HasColumnType("text") + .HasColumnName("eye_color"); + + b.Property("FacialHairColor") + .IsRequired() + .HasColumnType("text") + .HasColumnName("facial_hair_color"); + + b.Property("FacialHairName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("facial_hair_name"); + + b.Property("FlavorText") + .IsRequired() + .HasColumnType("text") + .HasColumnName("flavor_text"); + + b.Property("Gender") + .IsRequired() + .HasColumnType("text") + .HasColumnName("gender"); + + b.Property("HairColor") + .IsRequired() + .HasColumnType("text") + .HasColumnName("hair_color"); + + b.Property("HairName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("hair_name"); + + b.Property("Markings") + .HasColumnType("jsonb") + .HasColumnName("markings"); + + b.Property("PreferenceId") + .HasColumnType("integer") + .HasColumnName("preference_id"); + + b.Property("PreferenceUnavailable") + .HasColumnType("integer") + .HasColumnName("pref_unavailable"); + + b.Property("Sex") + .IsRequired() + .HasColumnType("text") + .HasColumnName("sex"); + + b.Property("SkinColor") + .IsRequired() + .HasColumnType("text") + .HasColumnName("skin_color"); + + b.Property("Slot") + .HasColumnType("integer") + .HasColumnName("slot"); + + b.Property("SpawnPriority") + .HasColumnType("integer") + .HasColumnName("spawn_priority"); + + b.Property("Species") + .IsRequired() + .HasColumnType("text") + .HasColumnName("species"); + + b.HasKey("Id") + .HasName("PK_profile"); + + b.HasIndex("PreferenceId") + .HasDatabaseName("IX_profile_preference_id"); + + b.HasIndex("Slot", "PreferenceId") + .IsUnique(); + + b.ToTable("profile", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.ProfileLoadout", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("profile_loadout_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("LoadoutName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("loadout_name"); + + b.Property("ProfileLoadoutGroupId") + .HasColumnType("integer") + .HasColumnName("profile_loadout_group_id"); + + b.HasKey("Id") + .HasName("PK_profile_loadout"); + + b.HasIndex("ProfileLoadoutGroupId"); + + b.ToTable("profile_loadout", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.ProfileLoadoutGroup", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("profile_loadout_group_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("GroupName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("group_name"); + + b.Property("ProfileRoleLoadoutId") + .HasColumnType("integer") + .HasColumnName("profile_role_loadout_id"); + + b.HasKey("Id") + .HasName("PK_profile_loadout_group"); + + b.HasIndex("ProfileRoleLoadoutId"); + + b.ToTable("profile_loadout_group", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.ProfileRoleLoadout", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("profile_role_loadout_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ProfileId") + .HasColumnType("integer") + .HasColumnName("profile_id"); + + b.Property("RoleName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("role_name"); + + b.HasKey("Id") + .HasName("PK_profile_role_loadout"); + + b.HasIndex("ProfileId"); + + b.ToTable("profile_role_loadout", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.RoleWhitelist", b => + { + b.Property("PlayerUserId") + .HasColumnType("uuid") + .HasColumnName("player_user_id"); + + b.Property("RoleId") + .HasColumnType("text") + .HasColumnName("role_id"); + + b.HasKey("PlayerUserId", "RoleId") + .HasName("PK_role_whitelists"); + + b.ToTable("role_whitelists", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Round", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("round_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ServerId") + .HasColumnType("integer") + .HasColumnName("server_id"); + + b.Property("StartDate") + .HasColumnType("timestamp with time zone") + .HasColumnName("start_date"); + + b.HasKey("Id") + .HasName("PK_round"); + + b.HasIndex("ServerId") + .HasDatabaseName("IX_round_server_id"); + + b.HasIndex("StartDate"); + + b.ToTable("round", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Server", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("server_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Name") + .IsRequired() + .HasColumnType("text") + .HasColumnName("name"); + + b.HasKey("Id") + .HasName("PK_server"); + + b.ToTable("server", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.ServerBan", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("server_ban_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Address") + .HasColumnType("inet") + .HasColumnName("address"); + + b.Property("AutoDelete") + .HasColumnType("boolean") + .HasColumnName("auto_delete"); + + b.Property("BanTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("ban_time"); + + b.Property("BanningAdmin") + .HasColumnType("uuid") + .HasColumnName("banning_admin"); + + b.Property("ExemptFlags") + .HasColumnType("integer") + .HasColumnName("exempt_flags"); + + b.Property("ExpirationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("expiration_time"); + + b.Property("Hidden") + .HasColumnType("boolean") + .HasColumnName("hidden"); + + b.Property("LastEditedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("last_edited_at"); + + b.Property("LastEditedById") + .HasColumnType("uuid") + .HasColumnName("last_edited_by_id"); + + b.Property("PlayerUserId") + .HasColumnType("uuid") + .HasColumnName("player_user_id"); + + b.Property("PlaytimeAtNote") + .HasColumnType("interval") + .HasColumnName("playtime_at_note"); + + b.Property("Reason") + .IsRequired() + .HasColumnType("text") + .HasColumnName("reason"); + + b.Property("RoundId") + .HasColumnType("integer") + .HasColumnName("round_id"); + + b.Property("Severity") + .HasColumnType("integer") + .HasColumnName("severity"); + + b.HasKey("Id") + .HasName("PK_server_ban"); + + b.HasIndex("Address"); + + b.HasIndex("BanningAdmin"); + + b.HasIndex("LastEditedById"); + + b.HasIndex("PlayerUserId") + .HasDatabaseName("IX_server_ban_player_user_id"); + + b.HasIndex("RoundId") + .HasDatabaseName("IX_server_ban_round_id"); + + b.ToTable("server_ban", null, t => + { + t.HasCheckConstraint("AddressNotIPv6MappedIPv4", "NOT inet '::ffff:0.0.0.0/96' >>= address"); + + t.HasCheckConstraint("HaveEitherAddressOrUserIdOrHWId", "address IS NOT NULL OR player_user_id IS NOT NULL OR hwid IS NOT NULL"); + }); + }); + + modelBuilder.Entity("Content.Server.Database.ServerBanExemption", b => + { + b.Property("UserId") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("user_id"); + + b.Property("Flags") + .HasColumnType("integer") + .HasColumnName("flags"); + + b.HasKey("UserId") + .HasName("PK_server_ban_exemption"); + + b.ToTable("server_ban_exemption", null, t => + { + t.HasCheckConstraint("FlagsNotZero", "flags != 0"); + }); + }); + + modelBuilder.Entity("Content.Server.Database.ServerBanHit", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("server_ban_hit_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("BanId") + .HasColumnType("integer") + .HasColumnName("ban_id"); + + b.Property("ConnectionId") + .HasColumnType("integer") + .HasColumnName("connection_id"); + + b.HasKey("Id") + .HasName("PK_server_ban_hit"); + + b.HasIndex("BanId") + .HasDatabaseName("IX_server_ban_hit_ban_id"); + + b.HasIndex("ConnectionId") + .HasDatabaseName("IX_server_ban_hit_connection_id"); + + b.ToTable("server_ban_hit", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.ServerRoleBan", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("server_role_ban_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Address") + .HasColumnType("inet") + .HasColumnName("address"); + + b.Property("BanTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("ban_time"); + + b.Property("BanningAdmin") + .HasColumnType("uuid") + .HasColumnName("banning_admin"); + + b.Property("ExpirationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("expiration_time"); + + b.Property("Hidden") + .HasColumnType("boolean") + .HasColumnName("hidden"); + + b.Property("LastEditedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("last_edited_at"); + + b.Property("LastEditedById") + .HasColumnType("uuid") + .HasColumnName("last_edited_by_id"); + + b.Property("PlayerUserId") + .HasColumnType("uuid") + .HasColumnName("player_user_id"); + + b.Property("PlaytimeAtNote") + .HasColumnType("interval") + .HasColumnName("playtime_at_note"); + + b.Property("Reason") + .IsRequired() + .HasColumnType("text") + .HasColumnName("reason"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("text") + .HasColumnName("role_id"); + + b.Property("RoundId") + .HasColumnType("integer") + .HasColumnName("round_id"); + + b.Property("Severity") + .HasColumnType("integer") + .HasColumnName("severity"); + + b.HasKey("Id") + .HasName("PK_server_role_ban"); + + b.HasIndex("Address"); + + b.HasIndex("BanningAdmin"); + + b.HasIndex("LastEditedById"); + + b.HasIndex("PlayerUserId") + .HasDatabaseName("IX_server_role_ban_player_user_id"); + + b.HasIndex("RoundId") + .HasDatabaseName("IX_server_role_ban_round_id"); + + b.ToTable("server_role_ban", null, t => + { + t.HasCheckConstraint("AddressNotIPv6MappedIPv4", "NOT inet '::ffff:0.0.0.0/96' >>= address"); + + t.HasCheckConstraint("HaveEitherAddressOrUserIdOrHWId", "address IS NOT NULL OR player_user_id IS NOT NULL OR hwid IS NOT NULL"); + }); + }); + + modelBuilder.Entity("Content.Server.Database.ServerRoleUnban", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("role_unban_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("BanId") + .HasColumnType("integer") + .HasColumnName("ban_id"); + + b.Property("UnbanTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("unban_time"); + + b.Property("UnbanningAdmin") + .HasColumnType("uuid") + .HasColumnName("unbanning_admin"); + + b.HasKey("Id") + .HasName("PK_server_role_unban"); + + b.HasIndex("BanId") + .IsUnique(); + + b.ToTable("server_role_unban", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.ServerUnban", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("unban_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("BanId") + .HasColumnType("integer") + .HasColumnName("ban_id"); + + b.Property("UnbanTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("unban_time"); + + b.Property("UnbanningAdmin") + .HasColumnType("uuid") + .HasColumnName("unbanning_admin"); + + b.HasKey("Id") + .HasName("PK_server_unban"); + + b.HasIndex("BanId") + .IsUnique(); + + b.ToTable("server_unban", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Trait", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("trait_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ProfileId") + .HasColumnType("integer") + .HasColumnName("profile_id"); + + b.Property("TraitName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("trait_name"); + + b.HasKey("Id") + .HasName("PK_trait"); + + b.HasIndex("ProfileId", "TraitName") + .IsUnique(); + + b.ToTable("trait", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.UploadedResourceLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("uploaded_resource_log_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Data") + .IsRequired() + .HasColumnType("bytea") + .HasColumnName("data"); + + b.Property("Date") + .HasColumnType("timestamp with time zone") + .HasColumnName("date"); + + b.Property("Path") + .IsRequired() + .HasColumnType("text") + .HasColumnName("path"); + + b.Property("UserId") + .HasColumnType("uuid") + .HasColumnName("user_id"); + + b.HasKey("Id") + .HasName("PK_uploaded_resource_log"); + + b.ToTable("uploaded_resource_log", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Whitelist", b => + { + b.Property("UserId") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("user_id"); + + b.HasKey("UserId") + .HasName("PK_whitelist"); + + b.ToTable("whitelist", (string)null); + }); + + modelBuilder.Entity("PlayerRound", b => + { + b.Property("PlayersId") + .HasColumnType("integer") + .HasColumnName("players_id"); + + b.Property("RoundsId") + .HasColumnType("integer") + .HasColumnName("rounds_id"); + + b.HasKey("PlayersId", "RoundsId") + .HasName("PK_player_round"); + + b.HasIndex("RoundsId") + .HasDatabaseName("IX_player_round_rounds_id"); + + b.ToTable("player_round", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Admin", b => + { + b.HasOne("Content.Server.Database.AdminRank", "AdminRank") + .WithMany("Admins") + .HasForeignKey("AdminRankId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_admin_rank_admin_rank_id"); + + b.Navigation("AdminRank"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminFlag", b => + { + b.HasOne("Content.Server.Database.Admin", "Admin") + .WithMany("Flags") + .HasForeignKey("AdminId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_admin_flag_admin_admin_id"); + + b.Navigation("Admin"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminLog", b => + { + b.HasOne("Content.Server.Database.Round", "Round") + .WithMany("AdminLogs") + .HasForeignKey("RoundId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_admin_log_round_round_id"); + + b.Navigation("Round"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminLogPlayer", b => + { + b.HasOne("Content.Server.Database.Player", "Player") + .WithMany("AdminLogs") + .HasForeignKey("PlayerUserId") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_admin_log_player_player_player_user_id"); + + b.HasOne("Content.Server.Database.AdminLog", "Log") + .WithMany("Players") + .HasForeignKey("RoundId", "LogId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_admin_log_player_admin_log_round_id_log_id"); + + b.Navigation("Log"); + + b.Navigation("Player"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminMessage", b => + { + b.HasOne("Content.Server.Database.Player", "CreatedBy") + .WithMany("AdminMessagesCreated") + .HasForeignKey("CreatedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_messages_player_created_by_id"); + + b.HasOne("Content.Server.Database.Player", "DeletedBy") + .WithMany("AdminMessagesDeleted") + .HasForeignKey("DeletedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_messages_player_deleted_by_id"); + + b.HasOne("Content.Server.Database.Player", "LastEditedBy") + .WithMany("AdminMessagesLastEdited") + .HasForeignKey("LastEditedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_messages_player_last_edited_by_id"); + + b.HasOne("Content.Server.Database.Player", "Player") + .WithMany("AdminMessagesReceived") + .HasForeignKey("PlayerUserId") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("FK_admin_messages_player_player_user_id"); + + b.HasOne("Content.Server.Database.Round", "Round") + .WithMany() + .HasForeignKey("RoundId") + .HasConstraintName("FK_admin_messages_round_round_id"); + + b.Navigation("CreatedBy"); + + b.Navigation("DeletedBy"); + + b.Navigation("LastEditedBy"); + + b.Navigation("Player"); + + b.Navigation("Round"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminNote", b => + { + b.HasOne("Content.Server.Database.Player", "CreatedBy") + .WithMany("AdminNotesCreated") + .HasForeignKey("CreatedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_notes_player_created_by_id"); + + b.HasOne("Content.Server.Database.Player", "DeletedBy") + .WithMany("AdminNotesDeleted") + .HasForeignKey("DeletedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_notes_player_deleted_by_id"); + + b.HasOne("Content.Server.Database.Player", "LastEditedBy") + .WithMany("AdminNotesLastEdited") + .HasForeignKey("LastEditedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_notes_player_last_edited_by_id"); + + b.HasOne("Content.Server.Database.Player", "Player") + .WithMany("AdminNotesReceived") + .HasForeignKey("PlayerUserId") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("FK_admin_notes_player_player_user_id"); + + b.HasOne("Content.Server.Database.Round", "Round") + .WithMany() + .HasForeignKey("RoundId") + .HasConstraintName("FK_admin_notes_round_round_id"); + + b.Navigation("CreatedBy"); + + b.Navigation("DeletedBy"); + + b.Navigation("LastEditedBy"); + + b.Navigation("Player"); + + b.Navigation("Round"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminRankFlag", b => + { + b.HasOne("Content.Server.Database.AdminRank", "Rank") + .WithMany("Flags") + .HasForeignKey("AdminRankId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_admin_rank_flag_admin_rank_admin_rank_id"); + + b.Navigation("Rank"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminWatchlist", b => + { + b.HasOne("Content.Server.Database.Player", "CreatedBy") + .WithMany("AdminWatchlistsCreated") + .HasForeignKey("CreatedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_watchlists_player_created_by_id"); + + b.HasOne("Content.Server.Database.Player", "DeletedBy") + .WithMany("AdminWatchlistsDeleted") + .HasForeignKey("DeletedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_watchlists_player_deleted_by_id"); + + b.HasOne("Content.Server.Database.Player", "LastEditedBy") + .WithMany("AdminWatchlistsLastEdited") + .HasForeignKey("LastEditedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_watchlists_player_last_edited_by_id"); + + b.HasOne("Content.Server.Database.Player", "Player") + .WithMany("AdminWatchlistsReceived") + .HasForeignKey("PlayerUserId") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("FK_admin_watchlists_player_player_user_id"); + + b.HasOne("Content.Server.Database.Round", "Round") + .WithMany() + .HasForeignKey("RoundId") + .HasConstraintName("FK_admin_watchlists_round_round_id"); + + b.Navigation("CreatedBy"); + + b.Navigation("DeletedBy"); + + b.Navigation("LastEditedBy"); + + b.Navigation("Player"); + + b.Navigation("Round"); + }); + + modelBuilder.Entity("Content.Server.Database.Antag", b => + { + b.HasOne("Content.Server.Database.Profile", "Profile") + .WithMany("Antags") + .HasForeignKey("ProfileId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_antag_profile_profile_id"); + + b.Navigation("Profile"); + }); + + modelBuilder.Entity("Content.Server.Database.ConnectionLog", b => + { + b.HasOne("Content.Server.Database.Server", "Server") + .WithMany("ConnectionLogs") + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.SetNull) + .IsRequired() + .HasConstraintName("FK_connection_log_server_server_id"); + + b.OwnsOne("Content.Server.Database.TypedHwid", "HWId", b1 => + { + b1.Property("ConnectionLogId") + .HasColumnType("integer") + .HasColumnName("connection_log_id"); + + b1.Property("Hwid") + .IsRequired() + .HasColumnType("bytea") + .HasColumnName("hwid"); + + b1.Property("Type") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0) + .HasColumnName("hwid_type"); + + b1.HasKey("ConnectionLogId"); + + b1.ToTable("connection_log"); + + b1.WithOwner() + .HasForeignKey("ConnectionLogId") + .HasConstraintName("FK_connection_log_connection_log_connection_log_id"); + }); + + b.Navigation("HWId"); + + b.Navigation("Server"); + }); + + modelBuilder.Entity("Content.Server.Database.Job", b => + { + b.HasOne("Content.Server.Database.Profile", "Profile") + .WithMany("Jobs") + .HasForeignKey("ProfileId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_job_profile_profile_id"); + + b.Navigation("Profile"); + }); + + modelBuilder.Entity("Content.Server.Database.Player", b => + { + b.OwnsOne("Content.Server.Database.TypedHwid", "LastSeenHWId", b1 => + { + b1.Property("PlayerId") + .HasColumnType("integer") + .HasColumnName("player_id"); + + b1.Property("Hwid") + .IsRequired() + .HasColumnType("bytea") + .HasColumnName("last_seen_hwid"); + + b1.Property("Type") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0) + .HasColumnName("last_seen_hwid_type"); + + b1.HasKey("PlayerId"); + + b1.ToTable("player"); + + b1.WithOwner() + .HasForeignKey("PlayerId") + .HasConstraintName("FK_player_player_player_id"); + }); + + b.Navigation("LastSeenHWId"); + }); + + modelBuilder.Entity("Content.Server.Database.Profile", b => + { + b.HasOne("Content.Server.Database.Preference", "Preference") + .WithMany("Profiles") + .HasForeignKey("PreferenceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_profile_preference_preference_id"); + + b.Navigation("Preference"); + }); + + modelBuilder.Entity("Content.Server.Database.ProfileLoadout", b => + { + b.HasOne("Content.Server.Database.ProfileLoadoutGroup", "ProfileLoadoutGroup") + .WithMany("Loadouts") + .HasForeignKey("ProfileLoadoutGroupId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_profile_loadout_profile_loadout_group_profile_loadout_group~"); + + b.Navigation("ProfileLoadoutGroup"); + }); + + modelBuilder.Entity("Content.Server.Database.ProfileLoadoutGroup", b => + { + b.HasOne("Content.Server.Database.ProfileRoleLoadout", "ProfileRoleLoadout") + .WithMany("Groups") + .HasForeignKey("ProfileRoleLoadoutId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_profile_loadout_group_profile_role_loadout_profile_role_loa~"); + + b.Navigation("ProfileRoleLoadout"); + }); + + modelBuilder.Entity("Content.Server.Database.ProfileRoleLoadout", b => + { + b.HasOne("Content.Server.Database.Profile", "Profile") + .WithMany("Loadouts") + .HasForeignKey("ProfileId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_profile_role_loadout_profile_profile_id"); + + b.Navigation("Profile"); + }); + + modelBuilder.Entity("Content.Server.Database.RoleWhitelist", b => + { + b.HasOne("Content.Server.Database.Player", "Player") + .WithMany("JobWhitelists") + .HasForeignKey("PlayerUserId") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_role_whitelists_player_player_user_id"); + + b.Navigation("Player"); + }); + + modelBuilder.Entity("Content.Server.Database.Round", b => + { + b.HasOne("Content.Server.Database.Server", "Server") + .WithMany("Rounds") + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_round_server_server_id"); + + b.Navigation("Server"); + }); + + modelBuilder.Entity("Content.Server.Database.ServerBan", b => + { + b.HasOne("Content.Server.Database.Player", "CreatedBy") + .WithMany("AdminServerBansCreated") + .HasForeignKey("BanningAdmin") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_server_ban_player_banning_admin"); + + b.HasOne("Content.Server.Database.Player", "LastEditedBy") + .WithMany("AdminServerBansLastEdited") + .HasForeignKey("LastEditedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_server_ban_player_last_edited_by_id"); + + b.HasOne("Content.Server.Database.Round", "Round") + .WithMany() + .HasForeignKey("RoundId") + .HasConstraintName("FK_server_ban_round_round_id"); + + b.OwnsOne("Content.Server.Database.TypedHwid", "HWId", b1 => + { + b1.Property("ServerBanId") + .HasColumnType("integer") + .HasColumnName("server_ban_id"); + + b1.Property("Hwid") + .IsRequired() + .HasColumnType("bytea") + .HasColumnName("hwid"); + + b1.Property("Type") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0) + .HasColumnName("hwid_type"); + + b1.HasKey("ServerBanId"); + + b1.ToTable("server_ban"); + + b1.WithOwner() + .HasForeignKey("ServerBanId") + .HasConstraintName("FK_server_ban_server_ban_server_ban_id"); + }); + + b.Navigation("CreatedBy"); + + b.Navigation("HWId"); + + b.Navigation("LastEditedBy"); + + b.Navigation("Round"); + }); + + modelBuilder.Entity("Content.Server.Database.ServerBanHit", b => + { + b.HasOne("Content.Server.Database.ServerBan", "Ban") + .WithMany("BanHits") + .HasForeignKey("BanId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_server_ban_hit_server_ban_ban_id"); + + b.HasOne("Content.Server.Database.ConnectionLog", "Connection") + .WithMany("BanHits") + .HasForeignKey("ConnectionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_server_ban_hit_connection_log_connection_id"); + + b.Navigation("Ban"); + + b.Navigation("Connection"); + }); + + modelBuilder.Entity("Content.Server.Database.ServerRoleBan", b => + { + b.HasOne("Content.Server.Database.Player", "CreatedBy") + .WithMany("AdminServerRoleBansCreated") + .HasForeignKey("BanningAdmin") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_server_role_ban_player_banning_admin"); + + b.HasOne("Content.Server.Database.Player", "LastEditedBy") + .WithMany("AdminServerRoleBansLastEdited") + .HasForeignKey("LastEditedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_server_role_ban_player_last_edited_by_id"); + + b.HasOne("Content.Server.Database.Round", "Round") + .WithMany() + .HasForeignKey("RoundId") + .HasConstraintName("FK_server_role_ban_round_round_id"); + + b.OwnsOne("Content.Server.Database.TypedHwid", "HWId", b1 => + { + b1.Property("ServerRoleBanId") + .HasColumnType("integer") + .HasColumnName("server_role_ban_id"); + + b1.Property("Hwid") + .IsRequired() + .HasColumnType("bytea") + .HasColumnName("hwid"); + + b1.Property("Type") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0) + .HasColumnName("hwid_type"); + + b1.HasKey("ServerRoleBanId"); + + b1.ToTable("server_role_ban"); + + b1.WithOwner() + .HasForeignKey("ServerRoleBanId") + .HasConstraintName("FK_server_role_ban_server_role_ban_server_role_ban_id"); + }); + + b.Navigation("CreatedBy"); + + b.Navigation("HWId"); + + b.Navigation("LastEditedBy"); + + b.Navigation("Round"); + }); + + modelBuilder.Entity("Content.Server.Database.ServerRoleUnban", b => + { + b.HasOne("Content.Server.Database.ServerRoleBan", "Ban") + .WithOne("Unban") + .HasForeignKey("Content.Server.Database.ServerRoleUnban", "BanId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_server_role_unban_server_role_ban_ban_id"); + + b.Navigation("Ban"); + }); + + modelBuilder.Entity("Content.Server.Database.ServerUnban", b => + { + b.HasOne("Content.Server.Database.ServerBan", "Ban") + .WithOne("Unban") + .HasForeignKey("Content.Server.Database.ServerUnban", "BanId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_server_unban_server_ban_ban_id"); + + b.Navigation("Ban"); + }); + + modelBuilder.Entity("Content.Server.Database.Trait", b => + { + b.HasOne("Content.Server.Database.Profile", "Profile") + .WithMany("Traits") + .HasForeignKey("ProfileId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_trait_profile_profile_id"); + + b.Navigation("Profile"); + }); + + modelBuilder.Entity("PlayerRound", b => + { + b.HasOne("Content.Server.Database.Player", null) + .WithMany() + .HasForeignKey("PlayersId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_player_round_player_players_id"); + + b.HasOne("Content.Server.Database.Round", null) + .WithMany() + .HasForeignKey("RoundsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_player_round_round_rounds_id"); + }); + + modelBuilder.Entity("Content.Server.Database.Admin", b => + { + b.Navigation("Flags"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminLog", b => + { + b.Navigation("Players"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminRank", b => + { + b.Navigation("Admins"); + + b.Navigation("Flags"); + }); + + modelBuilder.Entity("Content.Server.Database.ConnectionLog", b => + { + b.Navigation("BanHits"); + }); + + modelBuilder.Entity("Content.Server.Database.Player", b => + { + b.Navigation("AdminLogs"); + + b.Navigation("AdminMessagesCreated"); + + b.Navigation("AdminMessagesDeleted"); + + b.Navigation("AdminMessagesLastEdited"); + + b.Navigation("AdminMessagesReceived"); + + b.Navigation("AdminNotesCreated"); + + b.Navigation("AdminNotesDeleted"); + + b.Navigation("AdminNotesLastEdited"); + + b.Navigation("AdminNotesReceived"); + + b.Navigation("AdminServerBansCreated"); + + b.Navigation("AdminServerBansLastEdited"); + + b.Navigation("AdminServerRoleBansCreated"); + + b.Navigation("AdminServerRoleBansLastEdited"); + + b.Navigation("AdminWatchlistsCreated"); + + b.Navigation("AdminWatchlistsDeleted"); + + b.Navigation("AdminWatchlistsLastEdited"); + + b.Navigation("AdminWatchlistsReceived"); + + b.Navigation("JobWhitelists"); + }); + + modelBuilder.Entity("Content.Server.Database.Preference", b => + { + b.Navigation("Profiles"); + }); + + modelBuilder.Entity("Content.Server.Database.Profile", b => + { + b.Navigation("Antags"); + + b.Navigation("Jobs"); + + b.Navigation("Loadouts"); + + b.Navigation("Traits"); + }); + + modelBuilder.Entity("Content.Server.Database.ProfileLoadoutGroup", b => + { + b.Navigation("Loadouts"); + }); + + modelBuilder.Entity("Content.Server.Database.ProfileRoleLoadout", b => + { + b.Navigation("Groups"); + }); + + modelBuilder.Entity("Content.Server.Database.Round", b => + { + b.Navigation("AdminLogs"); + }); + + modelBuilder.Entity("Content.Server.Database.Server", b => + { + b.Navigation("ConnectionLogs"); + + b.Navigation("Rounds"); + }); + + modelBuilder.Entity("Content.Server.Database.ServerBan", b => + { + b.Navigation("BanHits"); + + b.Navigation("Unban"); + }); + + modelBuilder.Entity("Content.Server.Database.ServerRoleBan", b => + { + b.Navigation("Unban"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Content.Server.Database/Migrations/Postgres/20241111170112_ModernHwid.cs b/Content.Server.Database/Migrations/Postgres/20241111170112_ModernHwid.cs new file mode 100644 index 0000000000..c70a5ffaa5 --- /dev/null +++ b/Content.Server.Database/Migrations/Postgres/20241111170112_ModernHwid.cs @@ -0,0 +1,62 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Content.Server.Database.Migrations.Postgres +{ + /// + public partial class ModernHwid : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "hwid_type", + table: "server_role_ban", + type: "integer", + nullable: true, + defaultValue: 0); + + migrationBuilder.AddColumn( + name: "hwid_type", + table: "server_ban", + type: "integer", + nullable: true, + defaultValue: 0); + + migrationBuilder.AddColumn( + name: "last_seen_hwid_type", + table: "player", + type: "integer", + nullable: true, + defaultValue: 0); + + migrationBuilder.AddColumn( + name: "hwid_type", + table: "connection_log", + type: "integer", + nullable: true, + defaultValue: 0); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "hwid_type", + table: "server_role_ban"); + + migrationBuilder.DropColumn( + name: "hwid_type", + table: "server_ban"); + + migrationBuilder.DropColumn( + name: "last_seen_hwid_type", + table: "player"); + + migrationBuilder.DropColumn( + name: "hwid_type", + table: "connection_log"); + } + } +} diff --git a/Content.Server.Database/Migrations/Postgres/20241111193608_ConnectionTrust.Designer.cs b/Content.Server.Database/Migrations/Postgres/20241111193608_ConnectionTrust.Designer.cs new file mode 100644 index 0000000000..dc1b4a0eeb --- /dev/null +++ b/Content.Server.Database/Migrations/Postgres/20241111193608_ConnectionTrust.Designer.cs @@ -0,0 +1,2076 @@ +// +using System; +using System.Net; +using System.Text.Json; +using Content.Server.Database; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; +using NpgsqlTypes; + +#nullable disable + +namespace Content.Server.Database.Migrations.Postgres +{ + [DbContext(typeof(PostgresServerDbContext))] + [Migration("20241111193608_ConnectionTrust")] + partial class ConnectionTrust + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.0") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("Content.Server.Database.Admin", b => + { + b.Property("UserId") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("user_id"); + + b.Property("AdminRankId") + .HasColumnType("integer") + .HasColumnName("admin_rank_id"); + + b.Property("Title") + .HasColumnType("text") + .HasColumnName("title"); + + b.HasKey("UserId") + .HasName("PK_admin"); + + b.HasIndex("AdminRankId") + .HasDatabaseName("IX_admin_admin_rank_id"); + + b.ToTable("admin", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AdminFlag", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("admin_flag_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AdminId") + .HasColumnType("uuid") + .HasColumnName("admin_id"); + + b.Property("Flag") + .IsRequired() + .HasColumnType("text") + .HasColumnName("flag"); + + b.Property("Negative") + .HasColumnType("boolean") + .HasColumnName("negative"); + + b.HasKey("Id") + .HasName("PK_admin_flag"); + + b.HasIndex("AdminId") + .HasDatabaseName("IX_admin_flag_admin_id"); + + b.HasIndex("Flag", "AdminId") + .IsUnique(); + + b.ToTable("admin_flag", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AdminLog", b => + { + b.Property("RoundId") + .HasColumnType("integer") + .HasColumnName("round_id"); + + b.Property("Id") + .HasColumnType("integer") + .HasColumnName("admin_log_id"); + + b.Property("Date") + .HasColumnType("timestamp with time zone") + .HasColumnName("date"); + + b.Property("Impact") + .HasColumnType("smallint") + .HasColumnName("impact"); + + b.Property("Json") + .IsRequired() + .HasColumnType("jsonb") + .HasColumnName("json"); + + b.Property("Message") + .IsRequired() + .HasColumnType("text") + .HasColumnName("message"); + + b.Property("Type") + .HasColumnType("integer") + .HasColumnName("type"); + + b.HasKey("RoundId", "Id") + .HasName("PK_admin_log"); + + b.HasIndex("Date"); + + b.HasIndex("Message") + .HasAnnotation("Npgsql:TsVectorConfig", "english"); + + NpgsqlIndexBuilderExtensions.HasMethod(b.HasIndex("Message"), "GIN"); + + b.HasIndex("Type") + .HasDatabaseName("IX_admin_log_type"); + + b.ToTable("admin_log", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AdminLogPlayer", b => + { + b.Property("RoundId") + .HasColumnType("integer") + .HasColumnName("round_id"); + + b.Property("LogId") + .HasColumnType("integer") + .HasColumnName("log_id"); + + b.Property("PlayerUserId") + .HasColumnType("uuid") + .HasColumnName("player_user_id"); + + b.HasKey("RoundId", "LogId", "PlayerUserId") + .HasName("PK_admin_log_player"); + + b.HasIndex("PlayerUserId") + .HasDatabaseName("IX_admin_log_player_player_user_id"); + + b.ToTable("admin_log_player", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AdminMessage", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("admin_messages_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("CreatedById") + .HasColumnType("uuid") + .HasColumnName("created_by_id"); + + b.Property("Deleted") + .HasColumnType("boolean") + .HasColumnName("deleted"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("DeletedById") + .HasColumnType("uuid") + .HasColumnName("deleted_by_id"); + + b.Property("Dismissed") + .HasColumnType("boolean") + .HasColumnName("dismissed"); + + b.Property("ExpirationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("expiration_time"); + + b.Property("LastEditedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("last_edited_at"); + + b.Property("LastEditedById") + .HasColumnType("uuid") + .HasColumnName("last_edited_by_id"); + + b.Property("Message") + .IsRequired() + .HasMaxLength(4096) + .HasColumnType("character varying(4096)") + .HasColumnName("message"); + + b.Property("PlayerUserId") + .HasColumnType("uuid") + .HasColumnName("player_user_id"); + + b.Property("PlaytimeAtNote") + .HasColumnType("interval") + .HasColumnName("playtime_at_note"); + + b.Property("RoundId") + .HasColumnType("integer") + .HasColumnName("round_id"); + + b.Property("Seen") + .HasColumnType("boolean") + .HasColumnName("seen"); + + b.HasKey("Id") + .HasName("PK_admin_messages"); + + b.HasIndex("CreatedById"); + + b.HasIndex("DeletedById"); + + b.HasIndex("LastEditedById"); + + b.HasIndex("PlayerUserId") + .HasDatabaseName("IX_admin_messages_player_user_id"); + + b.HasIndex("RoundId") + .HasDatabaseName("IX_admin_messages_round_id"); + + b.ToTable("admin_messages", null, t => + { + t.HasCheckConstraint("NotDismissedAndSeen", "NOT dismissed OR seen"); + }); + }); + + modelBuilder.Entity("Content.Server.Database.AdminNote", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("admin_notes_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("CreatedById") + .HasColumnType("uuid") + .HasColumnName("created_by_id"); + + b.Property("Deleted") + .HasColumnType("boolean") + .HasColumnName("deleted"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("DeletedById") + .HasColumnType("uuid") + .HasColumnName("deleted_by_id"); + + b.Property("ExpirationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("expiration_time"); + + b.Property("LastEditedAt") + .IsRequired() + .HasColumnType("timestamp with time zone") + .HasColumnName("last_edited_at"); + + b.Property("LastEditedById") + .HasColumnType("uuid") + .HasColumnName("last_edited_by_id"); + + b.Property("Message") + .IsRequired() + .HasMaxLength(4096) + .HasColumnType("character varying(4096)") + .HasColumnName("message"); + + b.Property("PlayerUserId") + .HasColumnType("uuid") + .HasColumnName("player_user_id"); + + b.Property("PlaytimeAtNote") + .HasColumnType("interval") + .HasColumnName("playtime_at_note"); + + b.Property("RoundId") + .HasColumnType("integer") + .HasColumnName("round_id"); + + b.Property("Secret") + .HasColumnType("boolean") + .HasColumnName("secret"); + + b.Property("Severity") + .HasColumnType("integer") + .HasColumnName("severity"); + + b.HasKey("Id") + .HasName("PK_admin_notes"); + + b.HasIndex("CreatedById"); + + b.HasIndex("DeletedById"); + + b.HasIndex("LastEditedById"); + + b.HasIndex("PlayerUserId") + .HasDatabaseName("IX_admin_notes_player_user_id"); + + b.HasIndex("RoundId") + .HasDatabaseName("IX_admin_notes_round_id"); + + b.ToTable("admin_notes", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AdminRank", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("admin_rank_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Name") + .IsRequired() + .HasColumnType("text") + .HasColumnName("name"); + + b.HasKey("Id") + .HasName("PK_admin_rank"); + + b.ToTable("admin_rank", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AdminRankFlag", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("admin_rank_flag_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AdminRankId") + .HasColumnType("integer") + .HasColumnName("admin_rank_id"); + + b.Property("Flag") + .IsRequired() + .HasColumnType("text") + .HasColumnName("flag"); + + b.HasKey("Id") + .HasName("PK_admin_rank_flag"); + + b.HasIndex("AdminRankId"); + + b.HasIndex("Flag", "AdminRankId") + .IsUnique(); + + b.ToTable("admin_rank_flag", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AdminWatchlist", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("admin_watchlists_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("CreatedById") + .HasColumnType("uuid") + .HasColumnName("created_by_id"); + + b.Property("Deleted") + .HasColumnType("boolean") + .HasColumnName("deleted"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("DeletedById") + .HasColumnType("uuid") + .HasColumnName("deleted_by_id"); + + b.Property("ExpirationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("expiration_time"); + + b.Property("LastEditedAt") + .IsRequired() + .HasColumnType("timestamp with time zone") + .HasColumnName("last_edited_at"); + + b.Property("LastEditedById") + .HasColumnType("uuid") + .HasColumnName("last_edited_by_id"); + + b.Property("Message") + .IsRequired() + .HasMaxLength(4096) + .HasColumnType("character varying(4096)") + .HasColumnName("message"); + + b.Property("PlayerUserId") + .HasColumnType("uuid") + .HasColumnName("player_user_id"); + + b.Property("PlaytimeAtNote") + .HasColumnType("interval") + .HasColumnName("playtime_at_note"); + + b.Property("RoundId") + .HasColumnType("integer") + .HasColumnName("round_id"); + + b.HasKey("Id") + .HasName("PK_admin_watchlists"); + + b.HasIndex("CreatedById"); + + b.HasIndex("DeletedById"); + + b.HasIndex("LastEditedById"); + + b.HasIndex("PlayerUserId") + .HasDatabaseName("IX_admin_watchlists_player_user_id"); + + b.HasIndex("RoundId") + .HasDatabaseName("IX_admin_watchlists_round_id"); + + b.ToTable("admin_watchlists", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Antag", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("antag_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AntagName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("antag_name"); + + b.Property("ProfileId") + .HasColumnType("integer") + .HasColumnName("profile_id"); + + b.HasKey("Id") + .HasName("PK_antag"); + + b.HasIndex("ProfileId", "AntagName") + .IsUnique(); + + b.ToTable("antag", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AssignedUserId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("assigned_user_id_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("UserId") + .HasColumnType("uuid") + .HasColumnName("user_id"); + + b.Property("UserName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("user_name"); + + b.HasKey("Id") + .HasName("PK_assigned_user_id"); + + b.HasIndex("UserId") + .IsUnique(); + + b.HasIndex("UserName") + .IsUnique(); + + b.ToTable("assigned_user_id", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.BanTemplate", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("ban_template_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AutoDelete") + .HasColumnType("boolean") + .HasColumnName("auto_delete"); + + b.Property("ExemptFlags") + .HasColumnType("integer") + .HasColumnName("exempt_flags"); + + b.Property("Hidden") + .HasColumnType("boolean") + .HasColumnName("hidden"); + + b.Property("Length") + .HasColumnType("interval") + .HasColumnName("length"); + + b.Property("Reason") + .IsRequired() + .HasColumnType("text") + .HasColumnName("reason"); + + b.Property("Severity") + .HasColumnType("integer") + .HasColumnName("severity"); + + b.Property("Title") + .IsRequired() + .HasColumnType("text") + .HasColumnName("title"); + + b.HasKey("Id") + .HasName("PK_ban_template"); + + b.ToTable("ban_template", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Blacklist", b => + { + b.Property("UserId") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("user_id"); + + b.HasKey("UserId") + .HasName("PK_blacklist"); + + b.ToTable("blacklist", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.ConnectionLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("connection_log_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Address") + .IsRequired() + .HasColumnType("inet") + .HasColumnName("address"); + + b.Property("Denied") + .HasColumnType("smallint") + .HasColumnName("denied"); + + b.Property("ServerId") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0) + .HasColumnName("server_id"); + + b.Property("Time") + .HasColumnType("timestamp with time zone") + .HasColumnName("time"); + + b.Property("Trust") + .HasColumnType("real") + .HasColumnName("trust"); + + b.Property("UserId") + .HasColumnType("uuid") + .HasColumnName("user_id"); + + b.Property("UserName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("user_name"); + + b.HasKey("Id") + .HasName("PK_connection_log"); + + b.HasIndex("ServerId") + .HasDatabaseName("IX_connection_log_server_id"); + + b.HasIndex("Time"); + + b.HasIndex("UserId"); + + b.ToTable("connection_log", null, t => + { + t.HasCheckConstraint("AddressNotIPv6MappedIPv4", "NOT inet '::ffff:0.0.0.0/96' >>= address"); + }); + }); + + modelBuilder.Entity("Content.Server.Database.Job", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("job_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("JobName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("job_name"); + + b.Property("Priority") + .HasColumnType("integer") + .HasColumnName("priority"); + + b.Property("ProfileId") + .HasColumnType("integer") + .HasColumnName("profile_id"); + + b.HasKey("Id") + .HasName("PK_job"); + + b.HasIndex("ProfileId"); + + b.HasIndex("ProfileId", "JobName") + .IsUnique(); + + b.HasIndex(new[] { "ProfileId" }, "IX_job_one_high_priority") + .IsUnique() + .HasFilter("priority = 3"); + + b.ToTable("job", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.PlayTime", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("play_time_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("PlayerId") + .HasColumnType("uuid") + .HasColumnName("player_id"); + + b.Property("TimeSpent") + .HasColumnType("interval") + .HasColumnName("time_spent"); + + b.Property("Tracker") + .IsRequired() + .HasColumnType("text") + .HasColumnName("tracker"); + + b.HasKey("Id") + .HasName("PK_play_time"); + + b.HasIndex("PlayerId", "Tracker") + .IsUnique(); + + b.ToTable("play_time", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Player", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("player_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("FirstSeenTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("first_seen_time"); + + b.Property("LastReadRules") + .HasColumnType("timestamp with time zone") + .HasColumnName("last_read_rules"); + + b.Property("LastSeenAddress") + .IsRequired() + .HasColumnType("inet") + .HasColumnName("last_seen_address"); + + b.Property("LastSeenTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("last_seen_time"); + + b.Property("LastSeenUserName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("last_seen_user_name"); + + b.Property("UserId") + .HasColumnType("uuid") + .HasColumnName("user_id"); + + b.HasKey("Id") + .HasName("PK_player"); + + b.HasAlternateKey("UserId") + .HasName("ak_player_user_id"); + + b.HasIndex("LastSeenUserName"); + + b.HasIndex("UserId") + .IsUnique(); + + b.ToTable("player", null, t => + { + t.HasCheckConstraint("LastSeenAddressNotIPv6MappedIPv4", "NOT inet '::ffff:0.0.0.0/96' >>= last_seen_address"); + }); + }); + + modelBuilder.Entity("Content.Server.Database.Preference", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("preference_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AdminOOCColor") + .IsRequired() + .HasColumnType("text") + .HasColumnName("admin_ooc_color"); + + b.Property("SelectedCharacterSlot") + .HasColumnType("integer") + .HasColumnName("selected_character_slot"); + + b.Property("UserId") + .HasColumnType("uuid") + .HasColumnName("user_id"); + + b.HasKey("Id") + .HasName("PK_preference"); + + b.HasIndex("UserId") + .IsUnique(); + + b.ToTable("preference", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Profile", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("profile_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Age") + .HasColumnType("integer") + .HasColumnName("age"); + + b.Property("CharacterName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("char_name"); + + b.Property("EyeColor") + .IsRequired() + .HasColumnType("text") + .HasColumnName("eye_color"); + + b.Property("FacialHairColor") + .IsRequired() + .HasColumnType("text") + .HasColumnName("facial_hair_color"); + + b.Property("FacialHairName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("facial_hair_name"); + + b.Property("FlavorText") + .IsRequired() + .HasColumnType("text") + .HasColumnName("flavor_text"); + + b.Property("Gender") + .IsRequired() + .HasColumnType("text") + .HasColumnName("gender"); + + b.Property("HairColor") + .IsRequired() + .HasColumnType("text") + .HasColumnName("hair_color"); + + b.Property("HairName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("hair_name"); + + b.Property("Markings") + .HasColumnType("jsonb") + .HasColumnName("markings"); + + b.Property("PreferenceId") + .HasColumnType("integer") + .HasColumnName("preference_id"); + + b.Property("PreferenceUnavailable") + .HasColumnType("integer") + .HasColumnName("pref_unavailable"); + + b.Property("Sex") + .IsRequired() + .HasColumnType("text") + .HasColumnName("sex"); + + b.Property("SkinColor") + .IsRequired() + .HasColumnType("text") + .HasColumnName("skin_color"); + + b.Property("Slot") + .HasColumnType("integer") + .HasColumnName("slot"); + + b.Property("SpawnPriority") + .HasColumnType("integer") + .HasColumnName("spawn_priority"); + + b.Property("Species") + .IsRequired() + .HasColumnType("text") + .HasColumnName("species"); + + b.HasKey("Id") + .HasName("PK_profile"); + + b.HasIndex("PreferenceId") + .HasDatabaseName("IX_profile_preference_id"); + + b.HasIndex("Slot", "PreferenceId") + .IsUnique(); + + b.ToTable("profile", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.ProfileLoadout", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("profile_loadout_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("LoadoutName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("loadout_name"); + + b.Property("ProfileLoadoutGroupId") + .HasColumnType("integer") + .HasColumnName("profile_loadout_group_id"); + + b.HasKey("Id") + .HasName("PK_profile_loadout"); + + b.HasIndex("ProfileLoadoutGroupId"); + + b.ToTable("profile_loadout", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.ProfileLoadoutGroup", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("profile_loadout_group_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("GroupName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("group_name"); + + b.Property("ProfileRoleLoadoutId") + .HasColumnType("integer") + .HasColumnName("profile_role_loadout_id"); + + b.HasKey("Id") + .HasName("PK_profile_loadout_group"); + + b.HasIndex("ProfileRoleLoadoutId"); + + b.ToTable("profile_loadout_group", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.ProfileRoleLoadout", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("profile_role_loadout_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ProfileId") + .HasColumnType("integer") + .HasColumnName("profile_id"); + + b.Property("RoleName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("role_name"); + + b.HasKey("Id") + .HasName("PK_profile_role_loadout"); + + b.HasIndex("ProfileId"); + + b.ToTable("profile_role_loadout", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.RoleWhitelist", b => + { + b.Property("PlayerUserId") + .HasColumnType("uuid") + .HasColumnName("player_user_id"); + + b.Property("RoleId") + .HasColumnType("text") + .HasColumnName("role_id"); + + b.HasKey("PlayerUserId", "RoleId") + .HasName("PK_role_whitelists"); + + b.ToTable("role_whitelists", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Round", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("round_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ServerId") + .HasColumnType("integer") + .HasColumnName("server_id"); + + b.Property("StartDate") + .HasColumnType("timestamp with time zone") + .HasColumnName("start_date"); + + b.HasKey("Id") + .HasName("PK_round"); + + b.HasIndex("ServerId") + .HasDatabaseName("IX_round_server_id"); + + b.HasIndex("StartDate"); + + b.ToTable("round", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Server", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("server_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Name") + .IsRequired() + .HasColumnType("text") + .HasColumnName("name"); + + b.HasKey("Id") + .HasName("PK_server"); + + b.ToTable("server", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.ServerBan", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("server_ban_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Address") + .HasColumnType("inet") + .HasColumnName("address"); + + b.Property("AutoDelete") + .HasColumnType("boolean") + .HasColumnName("auto_delete"); + + b.Property("BanTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("ban_time"); + + b.Property("BanningAdmin") + .HasColumnType("uuid") + .HasColumnName("banning_admin"); + + b.Property("ExemptFlags") + .HasColumnType("integer") + .HasColumnName("exempt_flags"); + + b.Property("ExpirationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("expiration_time"); + + b.Property("Hidden") + .HasColumnType("boolean") + .HasColumnName("hidden"); + + b.Property("LastEditedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("last_edited_at"); + + b.Property("LastEditedById") + .HasColumnType("uuid") + .HasColumnName("last_edited_by_id"); + + b.Property("PlayerUserId") + .HasColumnType("uuid") + .HasColumnName("player_user_id"); + + b.Property("PlaytimeAtNote") + .HasColumnType("interval") + .HasColumnName("playtime_at_note"); + + b.Property("Reason") + .IsRequired() + .HasColumnType("text") + .HasColumnName("reason"); + + b.Property("RoundId") + .HasColumnType("integer") + .HasColumnName("round_id"); + + b.Property("Severity") + .HasColumnType("integer") + .HasColumnName("severity"); + + b.HasKey("Id") + .HasName("PK_server_ban"); + + b.HasIndex("Address"); + + b.HasIndex("BanningAdmin"); + + b.HasIndex("LastEditedById"); + + b.HasIndex("PlayerUserId") + .HasDatabaseName("IX_server_ban_player_user_id"); + + b.HasIndex("RoundId") + .HasDatabaseName("IX_server_ban_round_id"); + + b.ToTable("server_ban", null, t => + { + t.HasCheckConstraint("AddressNotIPv6MappedIPv4", "NOT inet '::ffff:0.0.0.0/96' >>= address"); + + t.HasCheckConstraint("HaveEitherAddressOrUserIdOrHWId", "address IS NOT NULL OR player_user_id IS NOT NULL OR hwid IS NOT NULL"); + }); + }); + + modelBuilder.Entity("Content.Server.Database.ServerBanExemption", b => + { + b.Property("UserId") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("user_id"); + + b.Property("Flags") + .HasColumnType("integer") + .HasColumnName("flags"); + + b.HasKey("UserId") + .HasName("PK_server_ban_exemption"); + + b.ToTable("server_ban_exemption", null, t => + { + t.HasCheckConstraint("FlagsNotZero", "flags != 0"); + }); + }); + + modelBuilder.Entity("Content.Server.Database.ServerBanHit", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("server_ban_hit_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("BanId") + .HasColumnType("integer") + .HasColumnName("ban_id"); + + b.Property("ConnectionId") + .HasColumnType("integer") + .HasColumnName("connection_id"); + + b.HasKey("Id") + .HasName("PK_server_ban_hit"); + + b.HasIndex("BanId") + .HasDatabaseName("IX_server_ban_hit_ban_id"); + + b.HasIndex("ConnectionId") + .HasDatabaseName("IX_server_ban_hit_connection_id"); + + b.ToTable("server_ban_hit", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.ServerRoleBan", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("server_role_ban_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Address") + .HasColumnType("inet") + .HasColumnName("address"); + + b.Property("BanTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("ban_time"); + + b.Property("BanningAdmin") + .HasColumnType("uuid") + .HasColumnName("banning_admin"); + + b.Property("ExpirationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("expiration_time"); + + b.Property("Hidden") + .HasColumnType("boolean") + .HasColumnName("hidden"); + + b.Property("LastEditedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("last_edited_at"); + + b.Property("LastEditedById") + .HasColumnType("uuid") + .HasColumnName("last_edited_by_id"); + + b.Property("PlayerUserId") + .HasColumnType("uuid") + .HasColumnName("player_user_id"); + + b.Property("PlaytimeAtNote") + .HasColumnType("interval") + .HasColumnName("playtime_at_note"); + + b.Property("Reason") + .IsRequired() + .HasColumnType("text") + .HasColumnName("reason"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("text") + .HasColumnName("role_id"); + + b.Property("RoundId") + .HasColumnType("integer") + .HasColumnName("round_id"); + + b.Property("Severity") + .HasColumnType("integer") + .HasColumnName("severity"); + + b.HasKey("Id") + .HasName("PK_server_role_ban"); + + b.HasIndex("Address"); + + b.HasIndex("BanningAdmin"); + + b.HasIndex("LastEditedById"); + + b.HasIndex("PlayerUserId") + .HasDatabaseName("IX_server_role_ban_player_user_id"); + + b.HasIndex("RoundId") + .HasDatabaseName("IX_server_role_ban_round_id"); + + b.ToTable("server_role_ban", null, t => + { + t.HasCheckConstraint("AddressNotIPv6MappedIPv4", "NOT inet '::ffff:0.0.0.0/96' >>= address"); + + t.HasCheckConstraint("HaveEitherAddressOrUserIdOrHWId", "address IS NOT NULL OR player_user_id IS NOT NULL OR hwid IS NOT NULL"); + }); + }); + + modelBuilder.Entity("Content.Server.Database.ServerRoleUnban", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("role_unban_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("BanId") + .HasColumnType("integer") + .HasColumnName("ban_id"); + + b.Property("UnbanTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("unban_time"); + + b.Property("UnbanningAdmin") + .HasColumnType("uuid") + .HasColumnName("unbanning_admin"); + + b.HasKey("Id") + .HasName("PK_server_role_unban"); + + b.HasIndex("BanId") + .IsUnique(); + + b.ToTable("server_role_unban", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.ServerUnban", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("unban_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("BanId") + .HasColumnType("integer") + .HasColumnName("ban_id"); + + b.Property("UnbanTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("unban_time"); + + b.Property("UnbanningAdmin") + .HasColumnType("uuid") + .HasColumnName("unbanning_admin"); + + b.HasKey("Id") + .HasName("PK_server_unban"); + + b.HasIndex("BanId") + .IsUnique(); + + b.ToTable("server_unban", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Trait", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("trait_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ProfileId") + .HasColumnType("integer") + .HasColumnName("profile_id"); + + b.Property("TraitName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("trait_name"); + + b.HasKey("Id") + .HasName("PK_trait"); + + b.HasIndex("ProfileId", "TraitName") + .IsUnique(); + + b.ToTable("trait", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.UploadedResourceLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("uploaded_resource_log_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Data") + .IsRequired() + .HasColumnType("bytea") + .HasColumnName("data"); + + b.Property("Date") + .HasColumnType("timestamp with time zone") + .HasColumnName("date"); + + b.Property("Path") + .IsRequired() + .HasColumnType("text") + .HasColumnName("path"); + + b.Property("UserId") + .HasColumnType("uuid") + .HasColumnName("user_id"); + + b.HasKey("Id") + .HasName("PK_uploaded_resource_log"); + + b.ToTable("uploaded_resource_log", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Whitelist", b => + { + b.Property("UserId") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("user_id"); + + b.HasKey("UserId") + .HasName("PK_whitelist"); + + b.ToTable("whitelist", (string)null); + }); + + modelBuilder.Entity("PlayerRound", b => + { + b.Property("PlayersId") + .HasColumnType("integer") + .HasColumnName("players_id"); + + b.Property("RoundsId") + .HasColumnType("integer") + .HasColumnName("rounds_id"); + + b.HasKey("PlayersId", "RoundsId") + .HasName("PK_player_round"); + + b.HasIndex("RoundsId") + .HasDatabaseName("IX_player_round_rounds_id"); + + b.ToTable("player_round", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Admin", b => + { + b.HasOne("Content.Server.Database.AdminRank", "AdminRank") + .WithMany("Admins") + .HasForeignKey("AdminRankId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_admin_rank_admin_rank_id"); + + b.Navigation("AdminRank"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminFlag", b => + { + b.HasOne("Content.Server.Database.Admin", "Admin") + .WithMany("Flags") + .HasForeignKey("AdminId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_admin_flag_admin_admin_id"); + + b.Navigation("Admin"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminLog", b => + { + b.HasOne("Content.Server.Database.Round", "Round") + .WithMany("AdminLogs") + .HasForeignKey("RoundId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_admin_log_round_round_id"); + + b.Navigation("Round"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminLogPlayer", b => + { + b.HasOne("Content.Server.Database.Player", "Player") + .WithMany("AdminLogs") + .HasForeignKey("PlayerUserId") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_admin_log_player_player_player_user_id"); + + b.HasOne("Content.Server.Database.AdminLog", "Log") + .WithMany("Players") + .HasForeignKey("RoundId", "LogId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_admin_log_player_admin_log_round_id_log_id"); + + b.Navigation("Log"); + + b.Navigation("Player"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminMessage", b => + { + b.HasOne("Content.Server.Database.Player", "CreatedBy") + .WithMany("AdminMessagesCreated") + .HasForeignKey("CreatedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_messages_player_created_by_id"); + + b.HasOne("Content.Server.Database.Player", "DeletedBy") + .WithMany("AdminMessagesDeleted") + .HasForeignKey("DeletedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_messages_player_deleted_by_id"); + + b.HasOne("Content.Server.Database.Player", "LastEditedBy") + .WithMany("AdminMessagesLastEdited") + .HasForeignKey("LastEditedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_messages_player_last_edited_by_id"); + + b.HasOne("Content.Server.Database.Player", "Player") + .WithMany("AdminMessagesReceived") + .HasForeignKey("PlayerUserId") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("FK_admin_messages_player_player_user_id"); + + b.HasOne("Content.Server.Database.Round", "Round") + .WithMany() + .HasForeignKey("RoundId") + .HasConstraintName("FK_admin_messages_round_round_id"); + + b.Navigation("CreatedBy"); + + b.Navigation("DeletedBy"); + + b.Navigation("LastEditedBy"); + + b.Navigation("Player"); + + b.Navigation("Round"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminNote", b => + { + b.HasOne("Content.Server.Database.Player", "CreatedBy") + .WithMany("AdminNotesCreated") + .HasForeignKey("CreatedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_notes_player_created_by_id"); + + b.HasOne("Content.Server.Database.Player", "DeletedBy") + .WithMany("AdminNotesDeleted") + .HasForeignKey("DeletedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_notes_player_deleted_by_id"); + + b.HasOne("Content.Server.Database.Player", "LastEditedBy") + .WithMany("AdminNotesLastEdited") + .HasForeignKey("LastEditedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_notes_player_last_edited_by_id"); + + b.HasOne("Content.Server.Database.Player", "Player") + .WithMany("AdminNotesReceived") + .HasForeignKey("PlayerUserId") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("FK_admin_notes_player_player_user_id"); + + b.HasOne("Content.Server.Database.Round", "Round") + .WithMany() + .HasForeignKey("RoundId") + .HasConstraintName("FK_admin_notes_round_round_id"); + + b.Navigation("CreatedBy"); + + b.Navigation("DeletedBy"); + + b.Navigation("LastEditedBy"); + + b.Navigation("Player"); + + b.Navigation("Round"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminRankFlag", b => + { + b.HasOne("Content.Server.Database.AdminRank", "Rank") + .WithMany("Flags") + .HasForeignKey("AdminRankId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_admin_rank_flag_admin_rank_admin_rank_id"); + + b.Navigation("Rank"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminWatchlist", b => + { + b.HasOne("Content.Server.Database.Player", "CreatedBy") + .WithMany("AdminWatchlistsCreated") + .HasForeignKey("CreatedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_watchlists_player_created_by_id"); + + b.HasOne("Content.Server.Database.Player", "DeletedBy") + .WithMany("AdminWatchlistsDeleted") + .HasForeignKey("DeletedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_watchlists_player_deleted_by_id"); + + b.HasOne("Content.Server.Database.Player", "LastEditedBy") + .WithMany("AdminWatchlistsLastEdited") + .HasForeignKey("LastEditedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_watchlists_player_last_edited_by_id"); + + b.HasOne("Content.Server.Database.Player", "Player") + .WithMany("AdminWatchlistsReceived") + .HasForeignKey("PlayerUserId") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("FK_admin_watchlists_player_player_user_id"); + + b.HasOne("Content.Server.Database.Round", "Round") + .WithMany() + .HasForeignKey("RoundId") + .HasConstraintName("FK_admin_watchlists_round_round_id"); + + b.Navigation("CreatedBy"); + + b.Navigation("DeletedBy"); + + b.Navigation("LastEditedBy"); + + b.Navigation("Player"); + + b.Navigation("Round"); + }); + + modelBuilder.Entity("Content.Server.Database.Antag", b => + { + b.HasOne("Content.Server.Database.Profile", "Profile") + .WithMany("Antags") + .HasForeignKey("ProfileId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_antag_profile_profile_id"); + + b.Navigation("Profile"); + }); + + modelBuilder.Entity("Content.Server.Database.ConnectionLog", b => + { + b.HasOne("Content.Server.Database.Server", "Server") + .WithMany("ConnectionLogs") + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.SetNull) + .IsRequired() + .HasConstraintName("FK_connection_log_server_server_id"); + + b.OwnsOne("Content.Server.Database.TypedHwid", "HWId", b1 => + { + b1.Property("ConnectionLogId") + .HasColumnType("integer") + .HasColumnName("connection_log_id"); + + b1.Property("Hwid") + .IsRequired() + .HasColumnType("bytea") + .HasColumnName("hwid"); + + b1.Property("Type") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0) + .HasColumnName("hwid_type"); + + b1.HasKey("ConnectionLogId"); + + b1.ToTable("connection_log"); + + b1.WithOwner() + .HasForeignKey("ConnectionLogId") + .HasConstraintName("FK_connection_log_connection_log_connection_log_id"); + }); + + b.Navigation("HWId"); + + b.Navigation("Server"); + }); + + modelBuilder.Entity("Content.Server.Database.Job", b => + { + b.HasOne("Content.Server.Database.Profile", "Profile") + .WithMany("Jobs") + .HasForeignKey("ProfileId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_job_profile_profile_id"); + + b.Navigation("Profile"); + }); + + modelBuilder.Entity("Content.Server.Database.Player", b => + { + b.OwnsOne("Content.Server.Database.TypedHwid", "LastSeenHWId", b1 => + { + b1.Property("PlayerId") + .HasColumnType("integer") + .HasColumnName("player_id"); + + b1.Property("Hwid") + .IsRequired() + .HasColumnType("bytea") + .HasColumnName("last_seen_hwid"); + + b1.Property("Type") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0) + .HasColumnName("last_seen_hwid_type"); + + b1.HasKey("PlayerId"); + + b1.ToTable("player"); + + b1.WithOwner() + .HasForeignKey("PlayerId") + .HasConstraintName("FK_player_player_player_id"); + }); + + b.Navigation("LastSeenHWId"); + }); + + modelBuilder.Entity("Content.Server.Database.Profile", b => + { + b.HasOne("Content.Server.Database.Preference", "Preference") + .WithMany("Profiles") + .HasForeignKey("PreferenceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_profile_preference_preference_id"); + + b.Navigation("Preference"); + }); + + modelBuilder.Entity("Content.Server.Database.ProfileLoadout", b => + { + b.HasOne("Content.Server.Database.ProfileLoadoutGroup", "ProfileLoadoutGroup") + .WithMany("Loadouts") + .HasForeignKey("ProfileLoadoutGroupId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_profile_loadout_profile_loadout_group_profile_loadout_group~"); + + b.Navigation("ProfileLoadoutGroup"); + }); + + modelBuilder.Entity("Content.Server.Database.ProfileLoadoutGroup", b => + { + b.HasOne("Content.Server.Database.ProfileRoleLoadout", "ProfileRoleLoadout") + .WithMany("Groups") + .HasForeignKey("ProfileRoleLoadoutId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_profile_loadout_group_profile_role_loadout_profile_role_loa~"); + + b.Navigation("ProfileRoleLoadout"); + }); + + modelBuilder.Entity("Content.Server.Database.ProfileRoleLoadout", b => + { + b.HasOne("Content.Server.Database.Profile", "Profile") + .WithMany("Loadouts") + .HasForeignKey("ProfileId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_profile_role_loadout_profile_profile_id"); + + b.Navigation("Profile"); + }); + + modelBuilder.Entity("Content.Server.Database.RoleWhitelist", b => + { + b.HasOne("Content.Server.Database.Player", "Player") + .WithMany("JobWhitelists") + .HasForeignKey("PlayerUserId") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_role_whitelists_player_player_user_id"); + + b.Navigation("Player"); + }); + + modelBuilder.Entity("Content.Server.Database.Round", b => + { + b.HasOne("Content.Server.Database.Server", "Server") + .WithMany("Rounds") + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_round_server_server_id"); + + b.Navigation("Server"); + }); + + modelBuilder.Entity("Content.Server.Database.ServerBan", b => + { + b.HasOne("Content.Server.Database.Player", "CreatedBy") + .WithMany("AdminServerBansCreated") + .HasForeignKey("BanningAdmin") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_server_ban_player_banning_admin"); + + b.HasOne("Content.Server.Database.Player", "LastEditedBy") + .WithMany("AdminServerBansLastEdited") + .HasForeignKey("LastEditedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_server_ban_player_last_edited_by_id"); + + b.HasOne("Content.Server.Database.Round", "Round") + .WithMany() + .HasForeignKey("RoundId") + .HasConstraintName("FK_server_ban_round_round_id"); + + b.OwnsOne("Content.Server.Database.TypedHwid", "HWId", b1 => + { + b1.Property("ServerBanId") + .HasColumnType("integer") + .HasColumnName("server_ban_id"); + + b1.Property("Hwid") + .IsRequired() + .HasColumnType("bytea") + .HasColumnName("hwid"); + + b1.Property("Type") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0) + .HasColumnName("hwid_type"); + + b1.HasKey("ServerBanId"); + + b1.ToTable("server_ban"); + + b1.WithOwner() + .HasForeignKey("ServerBanId") + .HasConstraintName("FK_server_ban_server_ban_server_ban_id"); + }); + + b.Navigation("CreatedBy"); + + b.Navigation("HWId"); + + b.Navigation("LastEditedBy"); + + b.Navigation("Round"); + }); + + modelBuilder.Entity("Content.Server.Database.ServerBanHit", b => + { + b.HasOne("Content.Server.Database.ServerBan", "Ban") + .WithMany("BanHits") + .HasForeignKey("BanId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_server_ban_hit_server_ban_ban_id"); + + b.HasOne("Content.Server.Database.ConnectionLog", "Connection") + .WithMany("BanHits") + .HasForeignKey("ConnectionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_server_ban_hit_connection_log_connection_id"); + + b.Navigation("Ban"); + + b.Navigation("Connection"); + }); + + modelBuilder.Entity("Content.Server.Database.ServerRoleBan", b => + { + b.HasOne("Content.Server.Database.Player", "CreatedBy") + .WithMany("AdminServerRoleBansCreated") + .HasForeignKey("BanningAdmin") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_server_role_ban_player_banning_admin"); + + b.HasOne("Content.Server.Database.Player", "LastEditedBy") + .WithMany("AdminServerRoleBansLastEdited") + .HasForeignKey("LastEditedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_server_role_ban_player_last_edited_by_id"); + + b.HasOne("Content.Server.Database.Round", "Round") + .WithMany() + .HasForeignKey("RoundId") + .HasConstraintName("FK_server_role_ban_round_round_id"); + + b.OwnsOne("Content.Server.Database.TypedHwid", "HWId", b1 => + { + b1.Property("ServerRoleBanId") + .HasColumnType("integer") + .HasColumnName("server_role_ban_id"); + + b1.Property("Hwid") + .IsRequired() + .HasColumnType("bytea") + .HasColumnName("hwid"); + + b1.Property("Type") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0) + .HasColumnName("hwid_type"); + + b1.HasKey("ServerRoleBanId"); + + b1.ToTable("server_role_ban"); + + b1.WithOwner() + .HasForeignKey("ServerRoleBanId") + .HasConstraintName("FK_server_role_ban_server_role_ban_server_role_ban_id"); + }); + + b.Navigation("CreatedBy"); + + b.Navigation("HWId"); + + b.Navigation("LastEditedBy"); + + b.Navigation("Round"); + }); + + modelBuilder.Entity("Content.Server.Database.ServerRoleUnban", b => + { + b.HasOne("Content.Server.Database.ServerRoleBan", "Ban") + .WithOne("Unban") + .HasForeignKey("Content.Server.Database.ServerRoleUnban", "BanId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_server_role_unban_server_role_ban_ban_id"); + + b.Navigation("Ban"); + }); + + modelBuilder.Entity("Content.Server.Database.ServerUnban", b => + { + b.HasOne("Content.Server.Database.ServerBan", "Ban") + .WithOne("Unban") + .HasForeignKey("Content.Server.Database.ServerUnban", "BanId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_server_unban_server_ban_ban_id"); + + b.Navigation("Ban"); + }); + + modelBuilder.Entity("Content.Server.Database.Trait", b => + { + b.HasOne("Content.Server.Database.Profile", "Profile") + .WithMany("Traits") + .HasForeignKey("ProfileId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_trait_profile_profile_id"); + + b.Navigation("Profile"); + }); + + modelBuilder.Entity("PlayerRound", b => + { + b.HasOne("Content.Server.Database.Player", null) + .WithMany() + .HasForeignKey("PlayersId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_player_round_player_players_id"); + + b.HasOne("Content.Server.Database.Round", null) + .WithMany() + .HasForeignKey("RoundsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_player_round_round_rounds_id"); + }); + + modelBuilder.Entity("Content.Server.Database.Admin", b => + { + b.Navigation("Flags"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminLog", b => + { + b.Navigation("Players"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminRank", b => + { + b.Navigation("Admins"); + + b.Navigation("Flags"); + }); + + modelBuilder.Entity("Content.Server.Database.ConnectionLog", b => + { + b.Navigation("BanHits"); + }); + + modelBuilder.Entity("Content.Server.Database.Player", b => + { + b.Navigation("AdminLogs"); + + b.Navigation("AdminMessagesCreated"); + + b.Navigation("AdminMessagesDeleted"); + + b.Navigation("AdminMessagesLastEdited"); + + b.Navigation("AdminMessagesReceived"); + + b.Navigation("AdminNotesCreated"); + + b.Navigation("AdminNotesDeleted"); + + b.Navigation("AdminNotesLastEdited"); + + b.Navigation("AdminNotesReceived"); + + b.Navigation("AdminServerBansCreated"); + + b.Navigation("AdminServerBansLastEdited"); + + b.Navigation("AdminServerRoleBansCreated"); + + b.Navigation("AdminServerRoleBansLastEdited"); + + b.Navigation("AdminWatchlistsCreated"); + + b.Navigation("AdminWatchlistsDeleted"); + + b.Navigation("AdminWatchlistsLastEdited"); + + b.Navigation("AdminWatchlistsReceived"); + + b.Navigation("JobWhitelists"); + }); + + modelBuilder.Entity("Content.Server.Database.Preference", b => + { + b.Navigation("Profiles"); + }); + + modelBuilder.Entity("Content.Server.Database.Profile", b => + { + b.Navigation("Antags"); + + b.Navigation("Jobs"); + + b.Navigation("Loadouts"); + + b.Navigation("Traits"); + }); + + modelBuilder.Entity("Content.Server.Database.ProfileLoadoutGroup", b => + { + b.Navigation("Loadouts"); + }); + + modelBuilder.Entity("Content.Server.Database.ProfileRoleLoadout", b => + { + b.Navigation("Groups"); + }); + + modelBuilder.Entity("Content.Server.Database.Round", b => + { + b.Navigation("AdminLogs"); + }); + + modelBuilder.Entity("Content.Server.Database.Server", b => + { + b.Navigation("ConnectionLogs"); + + b.Navigation("Rounds"); + }); + + modelBuilder.Entity("Content.Server.Database.ServerBan", b => + { + b.Navigation("BanHits"); + + b.Navigation("Unban"); + }); + + modelBuilder.Entity("Content.Server.Database.ServerRoleBan", b => + { + b.Navigation("Unban"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Content.Server.Database/Migrations/Postgres/20241111193608_ConnectionTrust.cs b/Content.Server.Database/Migrations/Postgres/20241111193608_ConnectionTrust.cs new file mode 100644 index 0000000000..debb36aacc --- /dev/null +++ b/Content.Server.Database/Migrations/Postgres/20241111193608_ConnectionTrust.cs @@ -0,0 +1,29 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Content.Server.Database.Migrations.Postgres +{ + /// + public partial class ConnectionTrust : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "trust", + table: "connection_log", + type: "real", + nullable: false, + defaultValue: 0f); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "trust", + table: "connection_log"); + } + } +} diff --git a/Content.Server.Database/Migrations/Postgres/PostgresServerDbContextModelSnapshot.cs b/Content.Server.Database/Migrations/Postgres/PostgresServerDbContextModelSnapshot.cs index 1f64f6e51a..7544438631 100644 --- a/Content.Server.Database/Migrations/Postgres/PostgresServerDbContextModelSnapshot.cs +++ b/Content.Server.Database/Migrations/Postgres/PostgresServerDbContextModelSnapshot.cs @@ -512,20 +512,6 @@ namespace Content.Server.Database.Migrations.Postgres b.ToTable("assigned_user_id", (string)null); }); - modelBuilder.Entity("Content.Server.Database.Blacklist", - b => - { - b.Property("UserId") - .ValueGeneratedOnAdd() - .HasColumnType("uuid") - .HasColumnName("user_id"); - - b.HasKey("UserId") - .HasName("PK_blacklist"); - - b.ToTable("blacklist", (string) null); - }); - modelBuilder.Entity("Content.Server.Database.BanTemplate", b => { b.Property("Id") @@ -571,6 +557,19 @@ namespace Content.Server.Database.Migrations.Postgres b.ToTable("ban_template", (string)null); }); + modelBuilder.Entity("Content.Server.Database.Blacklist", b => + { + b.Property("UserId") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("user_id"); + + b.HasKey("UserId") + .HasName("PK_blacklist"); + + b.ToTable("blacklist", (string)null); + }); + modelBuilder.Entity("Content.Server.Database.ConnectionLog", b => { b.Property("Id") @@ -589,10 +588,6 @@ namespace Content.Server.Database.Migrations.Postgres .HasColumnType("smallint") .HasColumnName("denied"); - b.Property("HWId") - .HasColumnType("bytea") - .HasColumnName("hwid"); - b.Property("ServerId") .ValueGeneratedOnAdd() .HasColumnType("integer") @@ -603,6 +598,10 @@ namespace Content.Server.Database.Migrations.Postgres .HasColumnType("timestamp with time zone") .HasColumnName("time"); + b.Property("Trust") + .HasColumnType("real") + .HasColumnName("trust"); + b.Property("UserId") .HasColumnType("uuid") .HasColumnName("user_id"); @@ -718,10 +717,6 @@ namespace Content.Server.Database.Migrations.Postgres .HasColumnType("inet") .HasColumnName("last_seen_address"); - b.Property("LastSeenHWId") - .HasColumnType("bytea") - .HasColumnName("last_seen_hwid"); - b.Property("LastSeenTime") .HasColumnType("timestamp with time zone") .HasColumnName("last_seen_time"); @@ -1058,10 +1053,6 @@ namespace Content.Server.Database.Migrations.Postgres .HasColumnType("timestamp with time zone") .HasColumnName("expiration_time"); - b.Property("HWId") - .HasColumnType("bytea") - .HasColumnName("hwid"); - b.Property("Hidden") .HasColumnType("boolean") .HasColumnName("hidden"); @@ -1192,10 +1183,6 @@ namespace Content.Server.Database.Migrations.Postgres .HasColumnType("timestamp with time zone") .HasColumnName("expiration_time"); - b.Property("HWId") - .HasColumnType("bytea") - .HasColumnName("hwid"); - b.Property("Hidden") .HasColumnType("boolean") .HasColumnName("hidden"); @@ -1637,6 +1624,34 @@ namespace Content.Server.Database.Migrations.Postgres .IsRequired() .HasConstraintName("FK_connection_log_server_server_id"); + b.OwnsOne("Content.Server.Database.TypedHwid", "HWId", b1 => + { + b1.Property("ConnectionLogId") + .HasColumnType("integer") + .HasColumnName("connection_log_id"); + + b1.Property("Hwid") + .IsRequired() + .HasColumnType("bytea") + .HasColumnName("hwid"); + + b1.Property("Type") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0) + .HasColumnName("hwid_type"); + + b1.HasKey("ConnectionLogId"); + + b1.ToTable("connection_log"); + + b1.WithOwner() + .HasForeignKey("ConnectionLogId") + .HasConstraintName("FK_connection_log_connection_log_connection_log_id"); + }); + + b.Navigation("HWId"); + b.Navigation("Server"); }); @@ -1652,6 +1667,37 @@ namespace Content.Server.Database.Migrations.Postgres b.Navigation("Profile"); }); + modelBuilder.Entity("Content.Server.Database.Player", b => + { + b.OwnsOne("Content.Server.Database.TypedHwid", "LastSeenHWId", b1 => + { + b1.Property("PlayerId") + .HasColumnType("integer") + .HasColumnName("player_id"); + + b1.Property("Hwid") + .IsRequired() + .HasColumnType("bytea") + .HasColumnName("last_seen_hwid"); + + b1.Property("Type") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0) + .HasColumnName("last_seen_hwid_type"); + + b1.HasKey("PlayerId"); + + b1.ToTable("player"); + + b1.WithOwner() + .HasForeignKey("PlayerId") + .HasConstraintName("FK_player_player_player_id"); + }); + + b.Navigation("LastSeenHWId"); + }); + modelBuilder.Entity("Content.Server.Database.Profile", b => { b.HasOne("Content.Server.Database.Preference", "Preference") @@ -1746,8 +1792,36 @@ namespace Content.Server.Database.Migrations.Postgres .HasForeignKey("RoundId") .HasConstraintName("FK_server_ban_round_round_id"); + b.OwnsOne("Content.Server.Database.TypedHwid", "HWId", b1 => + { + b1.Property("ServerBanId") + .HasColumnType("integer") + .HasColumnName("server_ban_id"); + + b1.Property("Hwid") + .IsRequired() + .HasColumnType("bytea") + .HasColumnName("hwid"); + + b1.Property("Type") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0) + .HasColumnName("hwid_type"); + + b1.HasKey("ServerBanId"); + + b1.ToTable("server_ban"); + + b1.WithOwner() + .HasForeignKey("ServerBanId") + .HasConstraintName("FK_server_ban_server_ban_server_ban_id"); + }); + b.Navigation("CreatedBy"); + b.Navigation("HWId"); + b.Navigation("LastEditedBy"); b.Navigation("Round"); @@ -1795,8 +1869,36 @@ namespace Content.Server.Database.Migrations.Postgres .HasForeignKey("RoundId") .HasConstraintName("FK_server_role_ban_round_round_id"); + b.OwnsOne("Content.Server.Database.TypedHwid", "HWId", b1 => + { + b1.Property("ServerRoleBanId") + .HasColumnType("integer") + .HasColumnName("server_role_ban_id"); + + b1.Property("Hwid") + .IsRequired() + .HasColumnType("bytea") + .HasColumnName("hwid"); + + b1.Property("Type") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0) + .HasColumnName("hwid_type"); + + b1.HasKey("ServerRoleBanId"); + + b1.ToTable("server_role_ban"); + + b1.WithOwner() + .HasForeignKey("ServerRoleBanId") + .HasConstraintName("FK_server_role_ban_server_role_ban_server_role_ban_id"); + }); + b.Navigation("CreatedBy"); + b.Navigation("HWId"); + b.Navigation("LastEditedBy"); b.Navigation("Round"); diff --git a/Content.Server.Database/Migrations/Sqlite/20241111170107_ModernHwid.Designer.cs b/Content.Server.Database/Migrations/Sqlite/20241111170107_ModernHwid.Designer.cs new file mode 100644 index 0000000000..56a9fe0a05 --- /dev/null +++ b/Content.Server.Database/Migrations/Sqlite/20241111170107_ModernHwid.Designer.cs @@ -0,0 +1,1995 @@ +// +using System; +using Content.Server.Database; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace Content.Server.Database.Migrations.Sqlite +{ + [DbContext(typeof(SqliteServerDbContext))] + [Migration("20241111170107_ModernHwid")] + partial class ModernHwid + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "8.0.0"); + + modelBuilder.Entity("Content.Server.Database.Admin", b => + { + b.Property("UserId") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT") + .HasColumnName("user_id"); + + b.Property("AdminRankId") + .HasColumnType("INTEGER") + .HasColumnName("admin_rank_id"); + + b.Property("Title") + .HasColumnType("TEXT") + .HasColumnName("title"); + + b.HasKey("UserId") + .HasName("PK_admin"); + + b.HasIndex("AdminRankId") + .HasDatabaseName("IX_admin_admin_rank_id"); + + b.ToTable("admin", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AdminFlag", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("admin_flag_id"); + + b.Property("AdminId") + .HasColumnType("TEXT") + .HasColumnName("admin_id"); + + b.Property("Flag") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("flag"); + + b.Property("Negative") + .HasColumnType("INTEGER") + .HasColumnName("negative"); + + b.HasKey("Id") + .HasName("PK_admin_flag"); + + b.HasIndex("AdminId") + .HasDatabaseName("IX_admin_flag_admin_id"); + + b.HasIndex("Flag", "AdminId") + .IsUnique(); + + b.ToTable("admin_flag", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AdminLog", b => + { + b.Property("RoundId") + .HasColumnType("INTEGER") + .HasColumnName("round_id"); + + b.Property("Id") + .HasColumnType("INTEGER") + .HasColumnName("admin_log_id"); + + b.Property("Date") + .HasColumnType("TEXT") + .HasColumnName("date"); + + b.Property("Impact") + .HasColumnType("INTEGER") + .HasColumnName("impact"); + + b.Property("Json") + .IsRequired() + .HasColumnType("jsonb") + .HasColumnName("json"); + + b.Property("Message") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("message"); + + b.Property("Type") + .HasColumnType("INTEGER") + .HasColumnName("type"); + + b.HasKey("RoundId", "Id") + .HasName("PK_admin_log"); + + b.HasIndex("Date"); + + b.HasIndex("Type") + .HasDatabaseName("IX_admin_log_type"); + + b.ToTable("admin_log", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AdminLogPlayer", b => + { + b.Property("RoundId") + .HasColumnType("INTEGER") + .HasColumnName("round_id"); + + b.Property("LogId") + .HasColumnType("INTEGER") + .HasColumnName("log_id"); + + b.Property("PlayerUserId") + .HasColumnType("TEXT") + .HasColumnName("player_user_id"); + + b.HasKey("RoundId", "LogId", "PlayerUserId") + .HasName("PK_admin_log_player"); + + b.HasIndex("PlayerUserId") + .HasDatabaseName("IX_admin_log_player_player_user_id"); + + b.ToTable("admin_log_player", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AdminMessage", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("admin_messages_id"); + + b.Property("CreatedAt") + .HasColumnType("TEXT") + .HasColumnName("created_at"); + + b.Property("CreatedById") + .HasColumnType("TEXT") + .HasColumnName("created_by_id"); + + b.Property("Deleted") + .HasColumnType("INTEGER") + .HasColumnName("deleted"); + + b.Property("DeletedAt") + .HasColumnType("TEXT") + .HasColumnName("deleted_at"); + + b.Property("DeletedById") + .HasColumnType("TEXT") + .HasColumnName("deleted_by_id"); + + b.Property("Dismissed") + .HasColumnType("INTEGER") + .HasColumnName("dismissed"); + + b.Property("ExpirationTime") + .HasColumnType("TEXT") + .HasColumnName("expiration_time"); + + b.Property("LastEditedAt") + .HasColumnType("TEXT") + .HasColumnName("last_edited_at"); + + b.Property("LastEditedById") + .HasColumnType("TEXT") + .HasColumnName("last_edited_by_id"); + + b.Property("Message") + .IsRequired() + .HasMaxLength(4096) + .HasColumnType("TEXT") + .HasColumnName("message"); + + b.Property("PlayerUserId") + .HasColumnType("TEXT") + .HasColumnName("player_user_id"); + + b.Property("PlaytimeAtNote") + .HasColumnType("TEXT") + .HasColumnName("playtime_at_note"); + + b.Property("RoundId") + .HasColumnType("INTEGER") + .HasColumnName("round_id"); + + b.Property("Seen") + .HasColumnType("INTEGER") + .HasColumnName("seen"); + + b.HasKey("Id") + .HasName("PK_admin_messages"); + + b.HasIndex("CreatedById"); + + b.HasIndex("DeletedById"); + + b.HasIndex("LastEditedById"); + + b.HasIndex("PlayerUserId") + .HasDatabaseName("IX_admin_messages_player_user_id"); + + b.HasIndex("RoundId") + .HasDatabaseName("IX_admin_messages_round_id"); + + b.ToTable("admin_messages", null, t => + { + t.HasCheckConstraint("NotDismissedAndSeen", "NOT dismissed OR seen"); + }); + }); + + modelBuilder.Entity("Content.Server.Database.AdminNote", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("admin_notes_id"); + + b.Property("CreatedAt") + .HasColumnType("TEXT") + .HasColumnName("created_at"); + + b.Property("CreatedById") + .HasColumnType("TEXT") + .HasColumnName("created_by_id"); + + b.Property("Deleted") + .HasColumnType("INTEGER") + .HasColumnName("deleted"); + + b.Property("DeletedAt") + .HasColumnType("TEXT") + .HasColumnName("deleted_at"); + + b.Property("DeletedById") + .HasColumnType("TEXT") + .HasColumnName("deleted_by_id"); + + b.Property("ExpirationTime") + .HasColumnType("TEXT") + .HasColumnName("expiration_time"); + + b.Property("LastEditedAt") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("last_edited_at"); + + b.Property("LastEditedById") + .HasColumnType("TEXT") + .HasColumnName("last_edited_by_id"); + + b.Property("Message") + .IsRequired() + .HasMaxLength(4096) + .HasColumnType("TEXT") + .HasColumnName("message"); + + b.Property("PlayerUserId") + .HasColumnType("TEXT") + .HasColumnName("player_user_id"); + + b.Property("PlaytimeAtNote") + .HasColumnType("TEXT") + .HasColumnName("playtime_at_note"); + + b.Property("RoundId") + .HasColumnType("INTEGER") + .HasColumnName("round_id"); + + b.Property("Secret") + .HasColumnType("INTEGER") + .HasColumnName("secret"); + + b.Property("Severity") + .HasColumnType("INTEGER") + .HasColumnName("severity"); + + b.HasKey("Id") + .HasName("PK_admin_notes"); + + b.HasIndex("CreatedById"); + + b.HasIndex("DeletedById"); + + b.HasIndex("LastEditedById"); + + b.HasIndex("PlayerUserId") + .HasDatabaseName("IX_admin_notes_player_user_id"); + + b.HasIndex("RoundId") + .HasDatabaseName("IX_admin_notes_round_id"); + + b.ToTable("admin_notes", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AdminRank", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("admin_rank_id"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("name"); + + b.HasKey("Id") + .HasName("PK_admin_rank"); + + b.ToTable("admin_rank", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AdminRankFlag", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("admin_rank_flag_id"); + + b.Property("AdminRankId") + .HasColumnType("INTEGER") + .HasColumnName("admin_rank_id"); + + b.Property("Flag") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("flag"); + + b.HasKey("Id") + .HasName("PK_admin_rank_flag"); + + b.HasIndex("AdminRankId"); + + b.HasIndex("Flag", "AdminRankId") + .IsUnique(); + + b.ToTable("admin_rank_flag", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AdminWatchlist", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("admin_watchlists_id"); + + b.Property("CreatedAt") + .HasColumnType("TEXT") + .HasColumnName("created_at"); + + b.Property("CreatedById") + .HasColumnType("TEXT") + .HasColumnName("created_by_id"); + + b.Property("Deleted") + .HasColumnType("INTEGER") + .HasColumnName("deleted"); + + b.Property("DeletedAt") + .HasColumnType("TEXT") + .HasColumnName("deleted_at"); + + b.Property("DeletedById") + .HasColumnType("TEXT") + .HasColumnName("deleted_by_id"); + + b.Property("ExpirationTime") + .HasColumnType("TEXT") + .HasColumnName("expiration_time"); + + b.Property("LastEditedAt") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("last_edited_at"); + + b.Property("LastEditedById") + .HasColumnType("TEXT") + .HasColumnName("last_edited_by_id"); + + b.Property("Message") + .IsRequired() + .HasMaxLength(4096) + .HasColumnType("TEXT") + .HasColumnName("message"); + + b.Property("PlayerUserId") + .HasColumnType("TEXT") + .HasColumnName("player_user_id"); + + b.Property("PlaytimeAtNote") + .HasColumnType("TEXT") + .HasColumnName("playtime_at_note"); + + b.Property("RoundId") + .HasColumnType("INTEGER") + .HasColumnName("round_id"); + + b.HasKey("Id") + .HasName("PK_admin_watchlists"); + + b.HasIndex("CreatedById"); + + b.HasIndex("DeletedById"); + + b.HasIndex("LastEditedById"); + + b.HasIndex("PlayerUserId") + .HasDatabaseName("IX_admin_watchlists_player_user_id"); + + b.HasIndex("RoundId") + .HasDatabaseName("IX_admin_watchlists_round_id"); + + b.ToTable("admin_watchlists", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Antag", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("antag_id"); + + b.Property("AntagName") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("antag_name"); + + b.Property("ProfileId") + .HasColumnType("INTEGER") + .HasColumnName("profile_id"); + + b.HasKey("Id") + .HasName("PK_antag"); + + b.HasIndex("ProfileId", "AntagName") + .IsUnique(); + + b.ToTable("antag", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AssignedUserId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("assigned_user_id_id"); + + b.Property("UserId") + .HasColumnType("TEXT") + .HasColumnName("user_id"); + + b.Property("UserName") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("user_name"); + + b.HasKey("Id") + .HasName("PK_assigned_user_id"); + + b.HasIndex("UserId") + .IsUnique(); + + b.HasIndex("UserName") + .IsUnique(); + + b.ToTable("assigned_user_id", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.BanTemplate", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("ban_template_id"); + + b.Property("AutoDelete") + .HasColumnType("INTEGER") + .HasColumnName("auto_delete"); + + b.Property("ExemptFlags") + .HasColumnType("INTEGER") + .HasColumnName("exempt_flags"); + + b.Property("Hidden") + .HasColumnType("INTEGER") + .HasColumnName("hidden"); + + b.Property("Length") + .HasColumnType("TEXT") + .HasColumnName("length"); + + b.Property("Reason") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("reason"); + + b.Property("Severity") + .HasColumnType("INTEGER") + .HasColumnName("severity"); + + b.Property("Title") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("title"); + + b.HasKey("Id") + .HasName("PK_ban_template"); + + b.ToTable("ban_template", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Blacklist", b => + { + b.Property("UserId") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT") + .HasColumnName("user_id"); + + b.HasKey("UserId") + .HasName("PK_blacklist"); + + b.ToTable("blacklist", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.ConnectionLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("connection_log_id"); + + b.Property("Address") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("address"); + + b.Property("Denied") + .HasColumnType("INTEGER") + .HasColumnName("denied"); + + b.Property("ServerId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValue(0) + .HasColumnName("server_id"); + + b.Property("Time") + .HasColumnType("TEXT") + .HasColumnName("time"); + + b.Property("UserId") + .HasColumnType("TEXT") + .HasColumnName("user_id"); + + b.Property("UserName") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("user_name"); + + b.HasKey("Id") + .HasName("PK_connection_log"); + + b.HasIndex("ServerId") + .HasDatabaseName("IX_connection_log_server_id"); + + b.HasIndex("Time"); + + b.HasIndex("UserId"); + + b.ToTable("connection_log", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Job", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("job_id"); + + b.Property("JobName") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("job_name"); + + b.Property("Priority") + .HasColumnType("INTEGER") + .HasColumnName("priority"); + + b.Property("ProfileId") + .HasColumnType("INTEGER") + .HasColumnName("profile_id"); + + b.HasKey("Id") + .HasName("PK_job"); + + b.HasIndex("ProfileId"); + + b.HasIndex("ProfileId", "JobName") + .IsUnique(); + + b.HasIndex(new[] { "ProfileId" }, "IX_job_one_high_priority") + .IsUnique() + .HasFilter("priority = 3"); + + b.ToTable("job", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.PlayTime", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("play_time_id"); + + b.Property("PlayerId") + .HasColumnType("TEXT") + .HasColumnName("player_id"); + + b.Property("TimeSpent") + .HasColumnType("TEXT") + .HasColumnName("time_spent"); + + b.Property("Tracker") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("tracker"); + + b.HasKey("Id") + .HasName("PK_play_time"); + + b.HasIndex("PlayerId", "Tracker") + .IsUnique(); + + b.ToTable("play_time", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Player", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("player_id"); + + b.Property("FirstSeenTime") + .HasColumnType("TEXT") + .HasColumnName("first_seen_time"); + + b.Property("LastReadRules") + .HasColumnType("TEXT") + .HasColumnName("last_read_rules"); + + b.Property("LastSeenAddress") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("last_seen_address"); + + b.Property("LastSeenTime") + .HasColumnType("TEXT") + .HasColumnName("last_seen_time"); + + b.Property("LastSeenUserName") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("last_seen_user_name"); + + b.Property("UserId") + .HasColumnType("TEXT") + .HasColumnName("user_id"); + + b.HasKey("Id") + .HasName("PK_player"); + + b.HasAlternateKey("UserId") + .HasName("ak_player_user_id"); + + b.HasIndex("LastSeenUserName"); + + b.HasIndex("UserId") + .IsUnique(); + + b.ToTable("player", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Preference", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("preference_id"); + + b.Property("AdminOOCColor") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("admin_ooc_color"); + + b.Property("SelectedCharacterSlot") + .HasColumnType("INTEGER") + .HasColumnName("selected_character_slot"); + + b.Property("UserId") + .HasColumnType("TEXT") + .HasColumnName("user_id"); + + b.HasKey("Id") + .HasName("PK_preference"); + + b.HasIndex("UserId") + .IsUnique(); + + b.ToTable("preference", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Profile", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("profile_id"); + + b.Property("Age") + .HasColumnType("INTEGER") + .HasColumnName("age"); + + b.Property("CharacterName") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("char_name"); + + b.Property("EyeColor") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("eye_color"); + + b.Property("FacialHairColor") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("facial_hair_color"); + + b.Property("FacialHairName") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("facial_hair_name"); + + b.Property("FlavorText") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("flavor_text"); + + b.Property("Gender") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("gender"); + + b.Property("HairColor") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("hair_color"); + + b.Property("HairName") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("hair_name"); + + b.Property("Markings") + .HasColumnType("jsonb") + .HasColumnName("markings"); + + b.Property("PreferenceId") + .HasColumnType("INTEGER") + .HasColumnName("preference_id"); + + b.Property("PreferenceUnavailable") + .HasColumnType("INTEGER") + .HasColumnName("pref_unavailable"); + + b.Property("Sex") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("sex"); + + b.Property("SkinColor") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("skin_color"); + + b.Property("Slot") + .HasColumnType("INTEGER") + .HasColumnName("slot"); + + b.Property("SpawnPriority") + .HasColumnType("INTEGER") + .HasColumnName("spawn_priority"); + + b.Property("Species") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("species"); + + b.HasKey("Id") + .HasName("PK_profile"); + + b.HasIndex("PreferenceId") + .HasDatabaseName("IX_profile_preference_id"); + + b.HasIndex("Slot", "PreferenceId") + .IsUnique(); + + b.ToTable("profile", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.ProfileLoadout", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("profile_loadout_id"); + + b.Property("LoadoutName") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("loadout_name"); + + b.Property("ProfileLoadoutGroupId") + .HasColumnType("INTEGER") + .HasColumnName("profile_loadout_group_id"); + + b.HasKey("Id") + .HasName("PK_profile_loadout"); + + b.HasIndex("ProfileLoadoutGroupId"); + + b.ToTable("profile_loadout", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.ProfileLoadoutGroup", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("profile_loadout_group_id"); + + b.Property("GroupName") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("group_name"); + + b.Property("ProfileRoleLoadoutId") + .HasColumnType("INTEGER") + .HasColumnName("profile_role_loadout_id"); + + b.HasKey("Id") + .HasName("PK_profile_loadout_group"); + + b.HasIndex("ProfileRoleLoadoutId"); + + b.ToTable("profile_loadout_group", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.ProfileRoleLoadout", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("profile_role_loadout_id"); + + b.Property("ProfileId") + .HasColumnType("INTEGER") + .HasColumnName("profile_id"); + + b.Property("RoleName") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("role_name"); + + b.HasKey("Id") + .HasName("PK_profile_role_loadout"); + + b.HasIndex("ProfileId"); + + b.ToTable("profile_role_loadout", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.RoleWhitelist", b => + { + b.Property("PlayerUserId") + .HasColumnType("TEXT") + .HasColumnName("player_user_id"); + + b.Property("RoleId") + .HasColumnType("TEXT") + .HasColumnName("role_id"); + + b.HasKey("PlayerUserId", "RoleId") + .HasName("PK_role_whitelists"); + + b.ToTable("role_whitelists", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Round", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("round_id"); + + b.Property("ServerId") + .HasColumnType("INTEGER") + .HasColumnName("server_id"); + + b.Property("StartDate") + .HasColumnType("TEXT") + .HasColumnName("start_date"); + + b.HasKey("Id") + .HasName("PK_round"); + + b.HasIndex("ServerId") + .HasDatabaseName("IX_round_server_id"); + + b.HasIndex("StartDate"); + + b.ToTable("round", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Server", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("server_id"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("name"); + + b.HasKey("Id") + .HasName("PK_server"); + + b.ToTable("server", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.ServerBan", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("server_ban_id"); + + b.Property("Address") + .HasColumnType("TEXT") + .HasColumnName("address"); + + b.Property("AutoDelete") + .HasColumnType("INTEGER") + .HasColumnName("auto_delete"); + + b.Property("BanTime") + .HasColumnType("TEXT") + .HasColumnName("ban_time"); + + b.Property("BanningAdmin") + .HasColumnType("TEXT") + .HasColumnName("banning_admin"); + + b.Property("ExemptFlags") + .HasColumnType("INTEGER") + .HasColumnName("exempt_flags"); + + b.Property("ExpirationTime") + .HasColumnType("TEXT") + .HasColumnName("expiration_time"); + + b.Property("Hidden") + .HasColumnType("INTEGER") + .HasColumnName("hidden"); + + b.Property("LastEditedAt") + .HasColumnType("TEXT") + .HasColumnName("last_edited_at"); + + b.Property("LastEditedById") + .HasColumnType("TEXT") + .HasColumnName("last_edited_by_id"); + + b.Property("PlayerUserId") + .HasColumnType("TEXT") + .HasColumnName("player_user_id"); + + b.Property("PlaytimeAtNote") + .HasColumnType("TEXT") + .HasColumnName("playtime_at_note"); + + b.Property("Reason") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("reason"); + + b.Property("RoundId") + .HasColumnType("INTEGER") + .HasColumnName("round_id"); + + b.Property("Severity") + .HasColumnType("INTEGER") + .HasColumnName("severity"); + + b.HasKey("Id") + .HasName("PK_server_ban"); + + b.HasIndex("Address"); + + b.HasIndex("BanningAdmin"); + + b.HasIndex("LastEditedById"); + + b.HasIndex("PlayerUserId") + .HasDatabaseName("IX_server_ban_player_user_id"); + + b.HasIndex("RoundId") + .HasDatabaseName("IX_server_ban_round_id"); + + b.ToTable("server_ban", null, t => + { + t.HasCheckConstraint("HaveEitherAddressOrUserIdOrHWId", "address IS NOT NULL OR player_user_id IS NOT NULL OR hwid IS NOT NULL"); + }); + }); + + modelBuilder.Entity("Content.Server.Database.ServerBanExemption", b => + { + b.Property("UserId") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT") + .HasColumnName("user_id"); + + b.Property("Flags") + .HasColumnType("INTEGER") + .HasColumnName("flags"); + + b.HasKey("UserId") + .HasName("PK_server_ban_exemption"); + + b.ToTable("server_ban_exemption", null, t => + { + t.HasCheckConstraint("FlagsNotZero", "flags != 0"); + }); + }); + + modelBuilder.Entity("Content.Server.Database.ServerBanHit", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("server_ban_hit_id"); + + b.Property("BanId") + .HasColumnType("INTEGER") + .HasColumnName("ban_id"); + + b.Property("ConnectionId") + .HasColumnType("INTEGER") + .HasColumnName("connection_id"); + + b.HasKey("Id") + .HasName("PK_server_ban_hit"); + + b.HasIndex("BanId") + .HasDatabaseName("IX_server_ban_hit_ban_id"); + + b.HasIndex("ConnectionId") + .HasDatabaseName("IX_server_ban_hit_connection_id"); + + b.ToTable("server_ban_hit", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.ServerRoleBan", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("server_role_ban_id"); + + b.Property("Address") + .HasColumnType("TEXT") + .HasColumnName("address"); + + b.Property("BanTime") + .HasColumnType("TEXT") + .HasColumnName("ban_time"); + + b.Property("BanningAdmin") + .HasColumnType("TEXT") + .HasColumnName("banning_admin"); + + b.Property("ExpirationTime") + .HasColumnType("TEXT") + .HasColumnName("expiration_time"); + + b.Property("Hidden") + .HasColumnType("INTEGER") + .HasColumnName("hidden"); + + b.Property("LastEditedAt") + .HasColumnType("TEXT") + .HasColumnName("last_edited_at"); + + b.Property("LastEditedById") + .HasColumnType("TEXT") + .HasColumnName("last_edited_by_id"); + + b.Property("PlayerUserId") + .HasColumnType("TEXT") + .HasColumnName("player_user_id"); + + b.Property("PlaytimeAtNote") + .HasColumnType("TEXT") + .HasColumnName("playtime_at_note"); + + b.Property("Reason") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("reason"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("role_id"); + + b.Property("RoundId") + .HasColumnType("INTEGER") + .HasColumnName("round_id"); + + b.Property("Severity") + .HasColumnType("INTEGER") + .HasColumnName("severity"); + + b.HasKey("Id") + .HasName("PK_server_role_ban"); + + b.HasIndex("Address"); + + b.HasIndex("BanningAdmin"); + + b.HasIndex("LastEditedById"); + + b.HasIndex("PlayerUserId") + .HasDatabaseName("IX_server_role_ban_player_user_id"); + + b.HasIndex("RoundId") + .HasDatabaseName("IX_server_role_ban_round_id"); + + b.ToTable("server_role_ban", null, t => + { + t.HasCheckConstraint("HaveEitherAddressOrUserIdOrHWId", "address IS NOT NULL OR player_user_id IS NOT NULL OR hwid IS NOT NULL"); + }); + }); + + modelBuilder.Entity("Content.Server.Database.ServerRoleUnban", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("role_unban_id"); + + b.Property("BanId") + .HasColumnType("INTEGER") + .HasColumnName("ban_id"); + + b.Property("UnbanTime") + .HasColumnType("TEXT") + .HasColumnName("unban_time"); + + b.Property("UnbanningAdmin") + .HasColumnType("TEXT") + .HasColumnName("unbanning_admin"); + + b.HasKey("Id") + .HasName("PK_server_role_unban"); + + b.HasIndex("BanId") + .IsUnique(); + + b.ToTable("server_role_unban", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.ServerUnban", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("unban_id"); + + b.Property("BanId") + .HasColumnType("INTEGER") + .HasColumnName("ban_id"); + + b.Property("UnbanTime") + .HasColumnType("TEXT") + .HasColumnName("unban_time"); + + b.Property("UnbanningAdmin") + .HasColumnType("TEXT") + .HasColumnName("unbanning_admin"); + + b.HasKey("Id") + .HasName("PK_server_unban"); + + b.HasIndex("BanId") + .IsUnique(); + + b.ToTable("server_unban", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Trait", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("trait_id"); + + b.Property("ProfileId") + .HasColumnType("INTEGER") + .HasColumnName("profile_id"); + + b.Property("TraitName") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("trait_name"); + + b.HasKey("Id") + .HasName("PK_trait"); + + b.HasIndex("ProfileId", "TraitName") + .IsUnique(); + + b.ToTable("trait", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.UploadedResourceLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("uploaded_resource_log_id"); + + b.Property("Data") + .IsRequired() + .HasColumnType("BLOB") + .HasColumnName("data"); + + b.Property("Date") + .HasColumnType("TEXT") + .HasColumnName("date"); + + b.Property("Path") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("path"); + + b.Property("UserId") + .HasColumnType("TEXT") + .HasColumnName("user_id"); + + b.HasKey("Id") + .HasName("PK_uploaded_resource_log"); + + b.ToTable("uploaded_resource_log", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Whitelist", b => + { + b.Property("UserId") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT") + .HasColumnName("user_id"); + + b.HasKey("UserId") + .HasName("PK_whitelist"); + + b.ToTable("whitelist", (string)null); + }); + + modelBuilder.Entity("PlayerRound", b => + { + b.Property("PlayersId") + .HasColumnType("INTEGER") + .HasColumnName("players_id"); + + b.Property("RoundsId") + .HasColumnType("INTEGER") + .HasColumnName("rounds_id"); + + b.HasKey("PlayersId", "RoundsId") + .HasName("PK_player_round"); + + b.HasIndex("RoundsId") + .HasDatabaseName("IX_player_round_rounds_id"); + + b.ToTable("player_round", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Admin", b => + { + b.HasOne("Content.Server.Database.AdminRank", "AdminRank") + .WithMany("Admins") + .HasForeignKey("AdminRankId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_admin_rank_admin_rank_id"); + + b.Navigation("AdminRank"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminFlag", b => + { + b.HasOne("Content.Server.Database.Admin", "Admin") + .WithMany("Flags") + .HasForeignKey("AdminId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_admin_flag_admin_admin_id"); + + b.Navigation("Admin"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminLog", b => + { + b.HasOne("Content.Server.Database.Round", "Round") + .WithMany("AdminLogs") + .HasForeignKey("RoundId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_admin_log_round_round_id"); + + b.Navigation("Round"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminLogPlayer", b => + { + b.HasOne("Content.Server.Database.Player", "Player") + .WithMany("AdminLogs") + .HasForeignKey("PlayerUserId") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_admin_log_player_player_player_user_id"); + + b.HasOne("Content.Server.Database.AdminLog", "Log") + .WithMany("Players") + .HasForeignKey("RoundId", "LogId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_admin_log_player_admin_log_round_id_log_id"); + + b.Navigation("Log"); + + b.Navigation("Player"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminMessage", b => + { + b.HasOne("Content.Server.Database.Player", "CreatedBy") + .WithMany("AdminMessagesCreated") + .HasForeignKey("CreatedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_messages_player_created_by_id"); + + b.HasOne("Content.Server.Database.Player", "DeletedBy") + .WithMany("AdminMessagesDeleted") + .HasForeignKey("DeletedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_messages_player_deleted_by_id"); + + b.HasOne("Content.Server.Database.Player", "LastEditedBy") + .WithMany("AdminMessagesLastEdited") + .HasForeignKey("LastEditedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_messages_player_last_edited_by_id"); + + b.HasOne("Content.Server.Database.Player", "Player") + .WithMany("AdminMessagesReceived") + .HasForeignKey("PlayerUserId") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("FK_admin_messages_player_player_user_id"); + + b.HasOne("Content.Server.Database.Round", "Round") + .WithMany() + .HasForeignKey("RoundId") + .HasConstraintName("FK_admin_messages_round_round_id"); + + b.Navigation("CreatedBy"); + + b.Navigation("DeletedBy"); + + b.Navigation("LastEditedBy"); + + b.Navigation("Player"); + + b.Navigation("Round"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminNote", b => + { + b.HasOne("Content.Server.Database.Player", "CreatedBy") + .WithMany("AdminNotesCreated") + .HasForeignKey("CreatedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_notes_player_created_by_id"); + + b.HasOne("Content.Server.Database.Player", "DeletedBy") + .WithMany("AdminNotesDeleted") + .HasForeignKey("DeletedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_notes_player_deleted_by_id"); + + b.HasOne("Content.Server.Database.Player", "LastEditedBy") + .WithMany("AdminNotesLastEdited") + .HasForeignKey("LastEditedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_notes_player_last_edited_by_id"); + + b.HasOne("Content.Server.Database.Player", "Player") + .WithMany("AdminNotesReceived") + .HasForeignKey("PlayerUserId") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("FK_admin_notes_player_player_user_id"); + + b.HasOne("Content.Server.Database.Round", "Round") + .WithMany() + .HasForeignKey("RoundId") + .HasConstraintName("FK_admin_notes_round_round_id"); + + b.Navigation("CreatedBy"); + + b.Navigation("DeletedBy"); + + b.Navigation("LastEditedBy"); + + b.Navigation("Player"); + + b.Navigation("Round"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminRankFlag", b => + { + b.HasOne("Content.Server.Database.AdminRank", "Rank") + .WithMany("Flags") + .HasForeignKey("AdminRankId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_admin_rank_flag_admin_rank_admin_rank_id"); + + b.Navigation("Rank"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminWatchlist", b => + { + b.HasOne("Content.Server.Database.Player", "CreatedBy") + .WithMany("AdminWatchlistsCreated") + .HasForeignKey("CreatedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_watchlists_player_created_by_id"); + + b.HasOne("Content.Server.Database.Player", "DeletedBy") + .WithMany("AdminWatchlistsDeleted") + .HasForeignKey("DeletedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_watchlists_player_deleted_by_id"); + + b.HasOne("Content.Server.Database.Player", "LastEditedBy") + .WithMany("AdminWatchlistsLastEdited") + .HasForeignKey("LastEditedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_watchlists_player_last_edited_by_id"); + + b.HasOne("Content.Server.Database.Player", "Player") + .WithMany("AdminWatchlistsReceived") + .HasForeignKey("PlayerUserId") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("FK_admin_watchlists_player_player_user_id"); + + b.HasOne("Content.Server.Database.Round", "Round") + .WithMany() + .HasForeignKey("RoundId") + .HasConstraintName("FK_admin_watchlists_round_round_id"); + + b.Navigation("CreatedBy"); + + b.Navigation("DeletedBy"); + + b.Navigation("LastEditedBy"); + + b.Navigation("Player"); + + b.Navigation("Round"); + }); + + modelBuilder.Entity("Content.Server.Database.Antag", b => + { + b.HasOne("Content.Server.Database.Profile", "Profile") + .WithMany("Antags") + .HasForeignKey("ProfileId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_antag_profile_profile_id"); + + b.Navigation("Profile"); + }); + + modelBuilder.Entity("Content.Server.Database.ConnectionLog", b => + { + b.HasOne("Content.Server.Database.Server", "Server") + .WithMany("ConnectionLogs") + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.SetNull) + .IsRequired() + .HasConstraintName("FK_connection_log_server_server_id"); + + b.OwnsOne("Content.Server.Database.TypedHwid", "HWId", b1 => + { + b1.Property("ConnectionLogId") + .HasColumnType("INTEGER") + .HasColumnName("connection_log_id"); + + b1.Property("Hwid") + .IsRequired() + .HasColumnType("BLOB") + .HasColumnName("hwid"); + + b1.Property("Type") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValue(0) + .HasColumnName("hwid_type"); + + b1.HasKey("ConnectionLogId"); + + b1.ToTable("connection_log"); + + b1.WithOwner() + .HasForeignKey("ConnectionLogId") + .HasConstraintName("FK_connection_log_connection_log_connection_log_id"); + }); + + b.Navigation("HWId"); + + b.Navigation("Server"); + }); + + modelBuilder.Entity("Content.Server.Database.Job", b => + { + b.HasOne("Content.Server.Database.Profile", "Profile") + .WithMany("Jobs") + .HasForeignKey("ProfileId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_job_profile_profile_id"); + + b.Navigation("Profile"); + }); + + modelBuilder.Entity("Content.Server.Database.Player", b => + { + b.OwnsOne("Content.Server.Database.TypedHwid", "LastSeenHWId", b1 => + { + b1.Property("PlayerId") + .HasColumnType("INTEGER") + .HasColumnName("player_id"); + + b1.Property("Hwid") + .IsRequired() + .HasColumnType("BLOB") + .HasColumnName("last_seen_hwid"); + + b1.Property("Type") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValue(0) + .HasColumnName("last_seen_hwid_type"); + + b1.HasKey("PlayerId"); + + b1.ToTable("player"); + + b1.WithOwner() + .HasForeignKey("PlayerId") + .HasConstraintName("FK_player_player_player_id"); + }); + + b.Navigation("LastSeenHWId"); + }); + + modelBuilder.Entity("Content.Server.Database.Profile", b => + { + b.HasOne("Content.Server.Database.Preference", "Preference") + .WithMany("Profiles") + .HasForeignKey("PreferenceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_profile_preference_preference_id"); + + b.Navigation("Preference"); + }); + + modelBuilder.Entity("Content.Server.Database.ProfileLoadout", b => + { + b.HasOne("Content.Server.Database.ProfileLoadoutGroup", "ProfileLoadoutGroup") + .WithMany("Loadouts") + .HasForeignKey("ProfileLoadoutGroupId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_profile_loadout_profile_loadout_group_profile_loadout_group_id"); + + b.Navigation("ProfileLoadoutGroup"); + }); + + modelBuilder.Entity("Content.Server.Database.ProfileLoadoutGroup", b => + { + b.HasOne("Content.Server.Database.ProfileRoleLoadout", "ProfileRoleLoadout") + .WithMany("Groups") + .HasForeignKey("ProfileRoleLoadoutId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_profile_loadout_group_profile_role_loadout_profile_role_loadout_id"); + + b.Navigation("ProfileRoleLoadout"); + }); + + modelBuilder.Entity("Content.Server.Database.ProfileRoleLoadout", b => + { + b.HasOne("Content.Server.Database.Profile", "Profile") + .WithMany("Loadouts") + .HasForeignKey("ProfileId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_profile_role_loadout_profile_profile_id"); + + b.Navigation("Profile"); + }); + + modelBuilder.Entity("Content.Server.Database.RoleWhitelist", b => + { + b.HasOne("Content.Server.Database.Player", "Player") + .WithMany("JobWhitelists") + .HasForeignKey("PlayerUserId") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_role_whitelists_player_player_user_id"); + + b.Navigation("Player"); + }); + + modelBuilder.Entity("Content.Server.Database.Round", b => + { + b.HasOne("Content.Server.Database.Server", "Server") + .WithMany("Rounds") + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_round_server_server_id"); + + b.Navigation("Server"); + }); + + modelBuilder.Entity("Content.Server.Database.ServerBan", b => + { + b.HasOne("Content.Server.Database.Player", "CreatedBy") + .WithMany("AdminServerBansCreated") + .HasForeignKey("BanningAdmin") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_server_ban_player_banning_admin"); + + b.HasOne("Content.Server.Database.Player", "LastEditedBy") + .WithMany("AdminServerBansLastEdited") + .HasForeignKey("LastEditedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_server_ban_player_last_edited_by_id"); + + b.HasOne("Content.Server.Database.Round", "Round") + .WithMany() + .HasForeignKey("RoundId") + .HasConstraintName("FK_server_ban_round_round_id"); + + b.OwnsOne("Content.Server.Database.TypedHwid", "HWId", b1 => + { + b1.Property("ServerBanId") + .HasColumnType("INTEGER") + .HasColumnName("server_ban_id"); + + b1.Property("Hwid") + .IsRequired() + .HasColumnType("BLOB") + .HasColumnName("hwid"); + + b1.Property("Type") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValue(0) + .HasColumnName("hwid_type"); + + b1.HasKey("ServerBanId"); + + b1.ToTable("server_ban"); + + b1.WithOwner() + .HasForeignKey("ServerBanId") + .HasConstraintName("FK_server_ban_server_ban_server_ban_id"); + }); + + b.Navigation("CreatedBy"); + + b.Navigation("HWId"); + + b.Navigation("LastEditedBy"); + + b.Navigation("Round"); + }); + + modelBuilder.Entity("Content.Server.Database.ServerBanHit", b => + { + b.HasOne("Content.Server.Database.ServerBan", "Ban") + .WithMany("BanHits") + .HasForeignKey("BanId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_server_ban_hit_server_ban_ban_id"); + + b.HasOne("Content.Server.Database.ConnectionLog", "Connection") + .WithMany("BanHits") + .HasForeignKey("ConnectionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_server_ban_hit_connection_log_connection_id"); + + b.Navigation("Ban"); + + b.Navigation("Connection"); + }); + + modelBuilder.Entity("Content.Server.Database.ServerRoleBan", b => + { + b.HasOne("Content.Server.Database.Player", "CreatedBy") + .WithMany("AdminServerRoleBansCreated") + .HasForeignKey("BanningAdmin") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_server_role_ban_player_banning_admin"); + + b.HasOne("Content.Server.Database.Player", "LastEditedBy") + .WithMany("AdminServerRoleBansLastEdited") + .HasForeignKey("LastEditedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_server_role_ban_player_last_edited_by_id"); + + b.HasOne("Content.Server.Database.Round", "Round") + .WithMany() + .HasForeignKey("RoundId") + .HasConstraintName("FK_server_role_ban_round_round_id"); + + b.OwnsOne("Content.Server.Database.TypedHwid", "HWId", b1 => + { + b1.Property("ServerRoleBanId") + .HasColumnType("INTEGER") + .HasColumnName("server_role_ban_id"); + + b1.Property("Hwid") + .IsRequired() + .HasColumnType("BLOB") + .HasColumnName("hwid"); + + b1.Property("Type") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValue(0) + .HasColumnName("hwid_type"); + + b1.HasKey("ServerRoleBanId"); + + b1.ToTable("server_role_ban"); + + b1.WithOwner() + .HasForeignKey("ServerRoleBanId") + .HasConstraintName("FK_server_role_ban_server_role_ban_server_role_ban_id"); + }); + + b.Navigation("CreatedBy"); + + b.Navigation("HWId"); + + b.Navigation("LastEditedBy"); + + b.Navigation("Round"); + }); + + modelBuilder.Entity("Content.Server.Database.ServerRoleUnban", b => + { + b.HasOne("Content.Server.Database.ServerRoleBan", "Ban") + .WithOne("Unban") + .HasForeignKey("Content.Server.Database.ServerRoleUnban", "BanId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_server_role_unban_server_role_ban_ban_id"); + + b.Navigation("Ban"); + }); + + modelBuilder.Entity("Content.Server.Database.ServerUnban", b => + { + b.HasOne("Content.Server.Database.ServerBan", "Ban") + .WithOne("Unban") + .HasForeignKey("Content.Server.Database.ServerUnban", "BanId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_server_unban_server_ban_ban_id"); + + b.Navigation("Ban"); + }); + + modelBuilder.Entity("Content.Server.Database.Trait", b => + { + b.HasOne("Content.Server.Database.Profile", "Profile") + .WithMany("Traits") + .HasForeignKey("ProfileId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_trait_profile_profile_id"); + + b.Navigation("Profile"); + }); + + modelBuilder.Entity("PlayerRound", b => + { + b.HasOne("Content.Server.Database.Player", null) + .WithMany() + .HasForeignKey("PlayersId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_player_round_player_players_id"); + + b.HasOne("Content.Server.Database.Round", null) + .WithMany() + .HasForeignKey("RoundsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_player_round_round_rounds_id"); + }); + + modelBuilder.Entity("Content.Server.Database.Admin", b => + { + b.Navigation("Flags"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminLog", b => + { + b.Navigation("Players"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminRank", b => + { + b.Navigation("Admins"); + + b.Navigation("Flags"); + }); + + modelBuilder.Entity("Content.Server.Database.ConnectionLog", b => + { + b.Navigation("BanHits"); + }); + + modelBuilder.Entity("Content.Server.Database.Player", b => + { + b.Navigation("AdminLogs"); + + b.Navigation("AdminMessagesCreated"); + + b.Navigation("AdminMessagesDeleted"); + + b.Navigation("AdminMessagesLastEdited"); + + b.Navigation("AdminMessagesReceived"); + + b.Navigation("AdminNotesCreated"); + + b.Navigation("AdminNotesDeleted"); + + b.Navigation("AdminNotesLastEdited"); + + b.Navigation("AdminNotesReceived"); + + b.Navigation("AdminServerBansCreated"); + + b.Navigation("AdminServerBansLastEdited"); + + b.Navigation("AdminServerRoleBansCreated"); + + b.Navigation("AdminServerRoleBansLastEdited"); + + b.Navigation("AdminWatchlistsCreated"); + + b.Navigation("AdminWatchlistsDeleted"); + + b.Navigation("AdminWatchlistsLastEdited"); + + b.Navigation("AdminWatchlistsReceived"); + + b.Navigation("JobWhitelists"); + }); + + modelBuilder.Entity("Content.Server.Database.Preference", b => + { + b.Navigation("Profiles"); + }); + + modelBuilder.Entity("Content.Server.Database.Profile", b => + { + b.Navigation("Antags"); + + b.Navigation("Jobs"); + + b.Navigation("Loadouts"); + + b.Navigation("Traits"); + }); + + modelBuilder.Entity("Content.Server.Database.ProfileLoadoutGroup", b => + { + b.Navigation("Loadouts"); + }); + + modelBuilder.Entity("Content.Server.Database.ProfileRoleLoadout", b => + { + b.Navigation("Groups"); + }); + + modelBuilder.Entity("Content.Server.Database.Round", b => + { + b.Navigation("AdminLogs"); + }); + + modelBuilder.Entity("Content.Server.Database.Server", b => + { + b.Navigation("ConnectionLogs"); + + b.Navigation("Rounds"); + }); + + modelBuilder.Entity("Content.Server.Database.ServerBan", b => + { + b.Navigation("BanHits"); + + b.Navigation("Unban"); + }); + + modelBuilder.Entity("Content.Server.Database.ServerRoleBan", b => + { + b.Navigation("Unban"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Content.Server.Database/Migrations/Sqlite/20241111170107_ModernHwid.cs b/Content.Server.Database/Migrations/Sqlite/20241111170107_ModernHwid.cs new file mode 100644 index 0000000000..97b5dafd03 --- /dev/null +++ b/Content.Server.Database/Migrations/Sqlite/20241111170107_ModernHwid.cs @@ -0,0 +1,62 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Content.Server.Database.Migrations.Sqlite +{ + /// + public partial class ModernHwid : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "hwid_type", + table: "server_role_ban", + type: "INTEGER", + nullable: true, + defaultValue: 0); + + migrationBuilder.AddColumn( + name: "hwid_type", + table: "server_ban", + type: "INTEGER", + nullable: true, + defaultValue: 0); + + migrationBuilder.AddColumn( + name: "last_seen_hwid_type", + table: "player", + type: "INTEGER", + nullable: true, + defaultValue: 0); + + migrationBuilder.AddColumn( + name: "hwid_type", + table: "connection_log", + type: "INTEGER", + nullable: true, + defaultValue: 0); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "hwid_type", + table: "server_role_ban"); + + migrationBuilder.DropColumn( + name: "hwid_type", + table: "server_ban"); + + migrationBuilder.DropColumn( + name: "last_seen_hwid_type", + table: "player"); + + migrationBuilder.DropColumn( + name: "hwid_type", + table: "connection_log"); + } + } +} diff --git a/Content.Server.Database/Migrations/Sqlite/20241111193602_ConnectionTrust.Designer.cs b/Content.Server.Database/Migrations/Sqlite/20241111193602_ConnectionTrust.Designer.cs new file mode 100644 index 0000000000..bd4e20a464 --- /dev/null +++ b/Content.Server.Database/Migrations/Sqlite/20241111193602_ConnectionTrust.Designer.cs @@ -0,0 +1,1999 @@ +// +using System; +using Content.Server.Database; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace Content.Server.Database.Migrations.Sqlite +{ + [DbContext(typeof(SqliteServerDbContext))] + [Migration("20241111193602_ConnectionTrust")] + partial class ConnectionTrust + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "8.0.0"); + + modelBuilder.Entity("Content.Server.Database.Admin", b => + { + b.Property("UserId") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT") + .HasColumnName("user_id"); + + b.Property("AdminRankId") + .HasColumnType("INTEGER") + .HasColumnName("admin_rank_id"); + + b.Property("Title") + .HasColumnType("TEXT") + .HasColumnName("title"); + + b.HasKey("UserId") + .HasName("PK_admin"); + + b.HasIndex("AdminRankId") + .HasDatabaseName("IX_admin_admin_rank_id"); + + b.ToTable("admin", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AdminFlag", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("admin_flag_id"); + + b.Property("AdminId") + .HasColumnType("TEXT") + .HasColumnName("admin_id"); + + b.Property("Flag") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("flag"); + + b.Property("Negative") + .HasColumnType("INTEGER") + .HasColumnName("negative"); + + b.HasKey("Id") + .HasName("PK_admin_flag"); + + b.HasIndex("AdminId") + .HasDatabaseName("IX_admin_flag_admin_id"); + + b.HasIndex("Flag", "AdminId") + .IsUnique(); + + b.ToTable("admin_flag", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AdminLog", b => + { + b.Property("RoundId") + .HasColumnType("INTEGER") + .HasColumnName("round_id"); + + b.Property("Id") + .HasColumnType("INTEGER") + .HasColumnName("admin_log_id"); + + b.Property("Date") + .HasColumnType("TEXT") + .HasColumnName("date"); + + b.Property("Impact") + .HasColumnType("INTEGER") + .HasColumnName("impact"); + + b.Property("Json") + .IsRequired() + .HasColumnType("jsonb") + .HasColumnName("json"); + + b.Property("Message") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("message"); + + b.Property("Type") + .HasColumnType("INTEGER") + .HasColumnName("type"); + + b.HasKey("RoundId", "Id") + .HasName("PK_admin_log"); + + b.HasIndex("Date"); + + b.HasIndex("Type") + .HasDatabaseName("IX_admin_log_type"); + + b.ToTable("admin_log", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AdminLogPlayer", b => + { + b.Property("RoundId") + .HasColumnType("INTEGER") + .HasColumnName("round_id"); + + b.Property("LogId") + .HasColumnType("INTEGER") + .HasColumnName("log_id"); + + b.Property("PlayerUserId") + .HasColumnType("TEXT") + .HasColumnName("player_user_id"); + + b.HasKey("RoundId", "LogId", "PlayerUserId") + .HasName("PK_admin_log_player"); + + b.HasIndex("PlayerUserId") + .HasDatabaseName("IX_admin_log_player_player_user_id"); + + b.ToTable("admin_log_player", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AdminMessage", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("admin_messages_id"); + + b.Property("CreatedAt") + .HasColumnType("TEXT") + .HasColumnName("created_at"); + + b.Property("CreatedById") + .HasColumnType("TEXT") + .HasColumnName("created_by_id"); + + b.Property("Deleted") + .HasColumnType("INTEGER") + .HasColumnName("deleted"); + + b.Property("DeletedAt") + .HasColumnType("TEXT") + .HasColumnName("deleted_at"); + + b.Property("DeletedById") + .HasColumnType("TEXT") + .HasColumnName("deleted_by_id"); + + b.Property("Dismissed") + .HasColumnType("INTEGER") + .HasColumnName("dismissed"); + + b.Property("ExpirationTime") + .HasColumnType("TEXT") + .HasColumnName("expiration_time"); + + b.Property("LastEditedAt") + .HasColumnType("TEXT") + .HasColumnName("last_edited_at"); + + b.Property("LastEditedById") + .HasColumnType("TEXT") + .HasColumnName("last_edited_by_id"); + + b.Property("Message") + .IsRequired() + .HasMaxLength(4096) + .HasColumnType("TEXT") + .HasColumnName("message"); + + b.Property("PlayerUserId") + .HasColumnType("TEXT") + .HasColumnName("player_user_id"); + + b.Property("PlaytimeAtNote") + .HasColumnType("TEXT") + .HasColumnName("playtime_at_note"); + + b.Property("RoundId") + .HasColumnType("INTEGER") + .HasColumnName("round_id"); + + b.Property("Seen") + .HasColumnType("INTEGER") + .HasColumnName("seen"); + + b.HasKey("Id") + .HasName("PK_admin_messages"); + + b.HasIndex("CreatedById"); + + b.HasIndex("DeletedById"); + + b.HasIndex("LastEditedById"); + + b.HasIndex("PlayerUserId") + .HasDatabaseName("IX_admin_messages_player_user_id"); + + b.HasIndex("RoundId") + .HasDatabaseName("IX_admin_messages_round_id"); + + b.ToTable("admin_messages", null, t => + { + t.HasCheckConstraint("NotDismissedAndSeen", "NOT dismissed OR seen"); + }); + }); + + modelBuilder.Entity("Content.Server.Database.AdminNote", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("admin_notes_id"); + + b.Property("CreatedAt") + .HasColumnType("TEXT") + .HasColumnName("created_at"); + + b.Property("CreatedById") + .HasColumnType("TEXT") + .HasColumnName("created_by_id"); + + b.Property("Deleted") + .HasColumnType("INTEGER") + .HasColumnName("deleted"); + + b.Property("DeletedAt") + .HasColumnType("TEXT") + .HasColumnName("deleted_at"); + + b.Property("DeletedById") + .HasColumnType("TEXT") + .HasColumnName("deleted_by_id"); + + b.Property("ExpirationTime") + .HasColumnType("TEXT") + .HasColumnName("expiration_time"); + + b.Property("LastEditedAt") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("last_edited_at"); + + b.Property("LastEditedById") + .HasColumnType("TEXT") + .HasColumnName("last_edited_by_id"); + + b.Property("Message") + .IsRequired() + .HasMaxLength(4096) + .HasColumnType("TEXT") + .HasColumnName("message"); + + b.Property("PlayerUserId") + .HasColumnType("TEXT") + .HasColumnName("player_user_id"); + + b.Property("PlaytimeAtNote") + .HasColumnType("TEXT") + .HasColumnName("playtime_at_note"); + + b.Property("RoundId") + .HasColumnType("INTEGER") + .HasColumnName("round_id"); + + b.Property("Secret") + .HasColumnType("INTEGER") + .HasColumnName("secret"); + + b.Property("Severity") + .HasColumnType("INTEGER") + .HasColumnName("severity"); + + b.HasKey("Id") + .HasName("PK_admin_notes"); + + b.HasIndex("CreatedById"); + + b.HasIndex("DeletedById"); + + b.HasIndex("LastEditedById"); + + b.HasIndex("PlayerUserId") + .HasDatabaseName("IX_admin_notes_player_user_id"); + + b.HasIndex("RoundId") + .HasDatabaseName("IX_admin_notes_round_id"); + + b.ToTable("admin_notes", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AdminRank", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("admin_rank_id"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("name"); + + b.HasKey("Id") + .HasName("PK_admin_rank"); + + b.ToTable("admin_rank", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AdminRankFlag", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("admin_rank_flag_id"); + + b.Property("AdminRankId") + .HasColumnType("INTEGER") + .HasColumnName("admin_rank_id"); + + b.Property("Flag") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("flag"); + + b.HasKey("Id") + .HasName("PK_admin_rank_flag"); + + b.HasIndex("AdminRankId"); + + b.HasIndex("Flag", "AdminRankId") + .IsUnique(); + + b.ToTable("admin_rank_flag", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AdminWatchlist", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("admin_watchlists_id"); + + b.Property("CreatedAt") + .HasColumnType("TEXT") + .HasColumnName("created_at"); + + b.Property("CreatedById") + .HasColumnType("TEXT") + .HasColumnName("created_by_id"); + + b.Property("Deleted") + .HasColumnType("INTEGER") + .HasColumnName("deleted"); + + b.Property("DeletedAt") + .HasColumnType("TEXT") + .HasColumnName("deleted_at"); + + b.Property("DeletedById") + .HasColumnType("TEXT") + .HasColumnName("deleted_by_id"); + + b.Property("ExpirationTime") + .HasColumnType("TEXT") + .HasColumnName("expiration_time"); + + b.Property("LastEditedAt") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("last_edited_at"); + + b.Property("LastEditedById") + .HasColumnType("TEXT") + .HasColumnName("last_edited_by_id"); + + b.Property("Message") + .IsRequired() + .HasMaxLength(4096) + .HasColumnType("TEXT") + .HasColumnName("message"); + + b.Property("PlayerUserId") + .HasColumnType("TEXT") + .HasColumnName("player_user_id"); + + b.Property("PlaytimeAtNote") + .HasColumnType("TEXT") + .HasColumnName("playtime_at_note"); + + b.Property("RoundId") + .HasColumnType("INTEGER") + .HasColumnName("round_id"); + + b.HasKey("Id") + .HasName("PK_admin_watchlists"); + + b.HasIndex("CreatedById"); + + b.HasIndex("DeletedById"); + + b.HasIndex("LastEditedById"); + + b.HasIndex("PlayerUserId") + .HasDatabaseName("IX_admin_watchlists_player_user_id"); + + b.HasIndex("RoundId") + .HasDatabaseName("IX_admin_watchlists_round_id"); + + b.ToTable("admin_watchlists", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Antag", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("antag_id"); + + b.Property("AntagName") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("antag_name"); + + b.Property("ProfileId") + .HasColumnType("INTEGER") + .HasColumnName("profile_id"); + + b.HasKey("Id") + .HasName("PK_antag"); + + b.HasIndex("ProfileId", "AntagName") + .IsUnique(); + + b.ToTable("antag", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AssignedUserId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("assigned_user_id_id"); + + b.Property("UserId") + .HasColumnType("TEXT") + .HasColumnName("user_id"); + + b.Property("UserName") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("user_name"); + + b.HasKey("Id") + .HasName("PK_assigned_user_id"); + + b.HasIndex("UserId") + .IsUnique(); + + b.HasIndex("UserName") + .IsUnique(); + + b.ToTable("assigned_user_id", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.BanTemplate", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("ban_template_id"); + + b.Property("AutoDelete") + .HasColumnType("INTEGER") + .HasColumnName("auto_delete"); + + b.Property("ExemptFlags") + .HasColumnType("INTEGER") + .HasColumnName("exempt_flags"); + + b.Property("Hidden") + .HasColumnType("INTEGER") + .HasColumnName("hidden"); + + b.Property("Length") + .HasColumnType("TEXT") + .HasColumnName("length"); + + b.Property("Reason") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("reason"); + + b.Property("Severity") + .HasColumnType("INTEGER") + .HasColumnName("severity"); + + b.Property("Title") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("title"); + + b.HasKey("Id") + .HasName("PK_ban_template"); + + b.ToTable("ban_template", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Blacklist", b => + { + b.Property("UserId") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT") + .HasColumnName("user_id"); + + b.HasKey("UserId") + .HasName("PK_blacklist"); + + b.ToTable("blacklist", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.ConnectionLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("connection_log_id"); + + b.Property("Address") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("address"); + + b.Property("Denied") + .HasColumnType("INTEGER") + .HasColumnName("denied"); + + b.Property("ServerId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValue(0) + .HasColumnName("server_id"); + + b.Property("Time") + .HasColumnType("TEXT") + .HasColumnName("time"); + + b.Property("Trust") + .HasColumnType("REAL") + .HasColumnName("trust"); + + b.Property("UserId") + .HasColumnType("TEXT") + .HasColumnName("user_id"); + + b.Property("UserName") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("user_name"); + + b.HasKey("Id") + .HasName("PK_connection_log"); + + b.HasIndex("ServerId") + .HasDatabaseName("IX_connection_log_server_id"); + + b.HasIndex("Time"); + + b.HasIndex("UserId"); + + b.ToTable("connection_log", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Job", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("job_id"); + + b.Property("JobName") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("job_name"); + + b.Property("Priority") + .HasColumnType("INTEGER") + .HasColumnName("priority"); + + b.Property("ProfileId") + .HasColumnType("INTEGER") + .HasColumnName("profile_id"); + + b.HasKey("Id") + .HasName("PK_job"); + + b.HasIndex("ProfileId"); + + b.HasIndex("ProfileId", "JobName") + .IsUnique(); + + b.HasIndex(new[] { "ProfileId" }, "IX_job_one_high_priority") + .IsUnique() + .HasFilter("priority = 3"); + + b.ToTable("job", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.PlayTime", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("play_time_id"); + + b.Property("PlayerId") + .HasColumnType("TEXT") + .HasColumnName("player_id"); + + b.Property("TimeSpent") + .HasColumnType("TEXT") + .HasColumnName("time_spent"); + + b.Property("Tracker") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("tracker"); + + b.HasKey("Id") + .HasName("PK_play_time"); + + b.HasIndex("PlayerId", "Tracker") + .IsUnique(); + + b.ToTable("play_time", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Player", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("player_id"); + + b.Property("FirstSeenTime") + .HasColumnType("TEXT") + .HasColumnName("first_seen_time"); + + b.Property("LastReadRules") + .HasColumnType("TEXT") + .HasColumnName("last_read_rules"); + + b.Property("LastSeenAddress") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("last_seen_address"); + + b.Property("LastSeenTime") + .HasColumnType("TEXT") + .HasColumnName("last_seen_time"); + + b.Property("LastSeenUserName") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("last_seen_user_name"); + + b.Property("UserId") + .HasColumnType("TEXT") + .HasColumnName("user_id"); + + b.HasKey("Id") + .HasName("PK_player"); + + b.HasAlternateKey("UserId") + .HasName("ak_player_user_id"); + + b.HasIndex("LastSeenUserName"); + + b.HasIndex("UserId") + .IsUnique(); + + b.ToTable("player", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Preference", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("preference_id"); + + b.Property("AdminOOCColor") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("admin_ooc_color"); + + b.Property("SelectedCharacterSlot") + .HasColumnType("INTEGER") + .HasColumnName("selected_character_slot"); + + b.Property("UserId") + .HasColumnType("TEXT") + .HasColumnName("user_id"); + + b.HasKey("Id") + .HasName("PK_preference"); + + b.HasIndex("UserId") + .IsUnique(); + + b.ToTable("preference", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Profile", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("profile_id"); + + b.Property("Age") + .HasColumnType("INTEGER") + .HasColumnName("age"); + + b.Property("CharacterName") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("char_name"); + + b.Property("EyeColor") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("eye_color"); + + b.Property("FacialHairColor") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("facial_hair_color"); + + b.Property("FacialHairName") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("facial_hair_name"); + + b.Property("FlavorText") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("flavor_text"); + + b.Property("Gender") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("gender"); + + b.Property("HairColor") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("hair_color"); + + b.Property("HairName") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("hair_name"); + + b.Property("Markings") + .HasColumnType("jsonb") + .HasColumnName("markings"); + + b.Property("PreferenceId") + .HasColumnType("INTEGER") + .HasColumnName("preference_id"); + + b.Property("PreferenceUnavailable") + .HasColumnType("INTEGER") + .HasColumnName("pref_unavailable"); + + b.Property("Sex") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("sex"); + + b.Property("SkinColor") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("skin_color"); + + b.Property("Slot") + .HasColumnType("INTEGER") + .HasColumnName("slot"); + + b.Property("SpawnPriority") + .HasColumnType("INTEGER") + .HasColumnName("spawn_priority"); + + b.Property("Species") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("species"); + + b.HasKey("Id") + .HasName("PK_profile"); + + b.HasIndex("PreferenceId") + .HasDatabaseName("IX_profile_preference_id"); + + b.HasIndex("Slot", "PreferenceId") + .IsUnique(); + + b.ToTable("profile", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.ProfileLoadout", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("profile_loadout_id"); + + b.Property("LoadoutName") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("loadout_name"); + + b.Property("ProfileLoadoutGroupId") + .HasColumnType("INTEGER") + .HasColumnName("profile_loadout_group_id"); + + b.HasKey("Id") + .HasName("PK_profile_loadout"); + + b.HasIndex("ProfileLoadoutGroupId"); + + b.ToTable("profile_loadout", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.ProfileLoadoutGroup", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("profile_loadout_group_id"); + + b.Property("GroupName") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("group_name"); + + b.Property("ProfileRoleLoadoutId") + .HasColumnType("INTEGER") + .HasColumnName("profile_role_loadout_id"); + + b.HasKey("Id") + .HasName("PK_profile_loadout_group"); + + b.HasIndex("ProfileRoleLoadoutId"); + + b.ToTable("profile_loadout_group", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.ProfileRoleLoadout", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("profile_role_loadout_id"); + + b.Property("ProfileId") + .HasColumnType("INTEGER") + .HasColumnName("profile_id"); + + b.Property("RoleName") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("role_name"); + + b.HasKey("Id") + .HasName("PK_profile_role_loadout"); + + b.HasIndex("ProfileId"); + + b.ToTable("profile_role_loadout", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.RoleWhitelist", b => + { + b.Property("PlayerUserId") + .HasColumnType("TEXT") + .HasColumnName("player_user_id"); + + b.Property("RoleId") + .HasColumnType("TEXT") + .HasColumnName("role_id"); + + b.HasKey("PlayerUserId", "RoleId") + .HasName("PK_role_whitelists"); + + b.ToTable("role_whitelists", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Round", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("round_id"); + + b.Property("ServerId") + .HasColumnType("INTEGER") + .HasColumnName("server_id"); + + b.Property("StartDate") + .HasColumnType("TEXT") + .HasColumnName("start_date"); + + b.HasKey("Id") + .HasName("PK_round"); + + b.HasIndex("ServerId") + .HasDatabaseName("IX_round_server_id"); + + b.HasIndex("StartDate"); + + b.ToTable("round", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Server", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("server_id"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("name"); + + b.HasKey("Id") + .HasName("PK_server"); + + b.ToTable("server", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.ServerBan", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("server_ban_id"); + + b.Property("Address") + .HasColumnType("TEXT") + .HasColumnName("address"); + + b.Property("AutoDelete") + .HasColumnType("INTEGER") + .HasColumnName("auto_delete"); + + b.Property("BanTime") + .HasColumnType("TEXT") + .HasColumnName("ban_time"); + + b.Property("BanningAdmin") + .HasColumnType("TEXT") + .HasColumnName("banning_admin"); + + b.Property("ExemptFlags") + .HasColumnType("INTEGER") + .HasColumnName("exempt_flags"); + + b.Property("ExpirationTime") + .HasColumnType("TEXT") + .HasColumnName("expiration_time"); + + b.Property("Hidden") + .HasColumnType("INTEGER") + .HasColumnName("hidden"); + + b.Property("LastEditedAt") + .HasColumnType("TEXT") + .HasColumnName("last_edited_at"); + + b.Property("LastEditedById") + .HasColumnType("TEXT") + .HasColumnName("last_edited_by_id"); + + b.Property("PlayerUserId") + .HasColumnType("TEXT") + .HasColumnName("player_user_id"); + + b.Property("PlaytimeAtNote") + .HasColumnType("TEXT") + .HasColumnName("playtime_at_note"); + + b.Property("Reason") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("reason"); + + b.Property("RoundId") + .HasColumnType("INTEGER") + .HasColumnName("round_id"); + + b.Property("Severity") + .HasColumnType("INTEGER") + .HasColumnName("severity"); + + b.HasKey("Id") + .HasName("PK_server_ban"); + + b.HasIndex("Address"); + + b.HasIndex("BanningAdmin"); + + b.HasIndex("LastEditedById"); + + b.HasIndex("PlayerUserId") + .HasDatabaseName("IX_server_ban_player_user_id"); + + b.HasIndex("RoundId") + .HasDatabaseName("IX_server_ban_round_id"); + + b.ToTable("server_ban", null, t => + { + t.HasCheckConstraint("HaveEitherAddressOrUserIdOrHWId", "address IS NOT NULL OR player_user_id IS NOT NULL OR hwid IS NOT NULL"); + }); + }); + + modelBuilder.Entity("Content.Server.Database.ServerBanExemption", b => + { + b.Property("UserId") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT") + .HasColumnName("user_id"); + + b.Property("Flags") + .HasColumnType("INTEGER") + .HasColumnName("flags"); + + b.HasKey("UserId") + .HasName("PK_server_ban_exemption"); + + b.ToTable("server_ban_exemption", null, t => + { + t.HasCheckConstraint("FlagsNotZero", "flags != 0"); + }); + }); + + modelBuilder.Entity("Content.Server.Database.ServerBanHit", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("server_ban_hit_id"); + + b.Property("BanId") + .HasColumnType("INTEGER") + .HasColumnName("ban_id"); + + b.Property("ConnectionId") + .HasColumnType("INTEGER") + .HasColumnName("connection_id"); + + b.HasKey("Id") + .HasName("PK_server_ban_hit"); + + b.HasIndex("BanId") + .HasDatabaseName("IX_server_ban_hit_ban_id"); + + b.HasIndex("ConnectionId") + .HasDatabaseName("IX_server_ban_hit_connection_id"); + + b.ToTable("server_ban_hit", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.ServerRoleBan", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("server_role_ban_id"); + + b.Property("Address") + .HasColumnType("TEXT") + .HasColumnName("address"); + + b.Property("BanTime") + .HasColumnType("TEXT") + .HasColumnName("ban_time"); + + b.Property("BanningAdmin") + .HasColumnType("TEXT") + .HasColumnName("banning_admin"); + + b.Property("ExpirationTime") + .HasColumnType("TEXT") + .HasColumnName("expiration_time"); + + b.Property("Hidden") + .HasColumnType("INTEGER") + .HasColumnName("hidden"); + + b.Property("LastEditedAt") + .HasColumnType("TEXT") + .HasColumnName("last_edited_at"); + + b.Property("LastEditedById") + .HasColumnType("TEXT") + .HasColumnName("last_edited_by_id"); + + b.Property("PlayerUserId") + .HasColumnType("TEXT") + .HasColumnName("player_user_id"); + + b.Property("PlaytimeAtNote") + .HasColumnType("TEXT") + .HasColumnName("playtime_at_note"); + + b.Property("Reason") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("reason"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("role_id"); + + b.Property("RoundId") + .HasColumnType("INTEGER") + .HasColumnName("round_id"); + + b.Property("Severity") + .HasColumnType("INTEGER") + .HasColumnName("severity"); + + b.HasKey("Id") + .HasName("PK_server_role_ban"); + + b.HasIndex("Address"); + + b.HasIndex("BanningAdmin"); + + b.HasIndex("LastEditedById"); + + b.HasIndex("PlayerUserId") + .HasDatabaseName("IX_server_role_ban_player_user_id"); + + b.HasIndex("RoundId") + .HasDatabaseName("IX_server_role_ban_round_id"); + + b.ToTable("server_role_ban", null, t => + { + t.HasCheckConstraint("HaveEitherAddressOrUserIdOrHWId", "address IS NOT NULL OR player_user_id IS NOT NULL OR hwid IS NOT NULL"); + }); + }); + + modelBuilder.Entity("Content.Server.Database.ServerRoleUnban", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("role_unban_id"); + + b.Property("BanId") + .HasColumnType("INTEGER") + .HasColumnName("ban_id"); + + b.Property("UnbanTime") + .HasColumnType("TEXT") + .HasColumnName("unban_time"); + + b.Property("UnbanningAdmin") + .HasColumnType("TEXT") + .HasColumnName("unbanning_admin"); + + b.HasKey("Id") + .HasName("PK_server_role_unban"); + + b.HasIndex("BanId") + .IsUnique(); + + b.ToTable("server_role_unban", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.ServerUnban", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("unban_id"); + + b.Property("BanId") + .HasColumnType("INTEGER") + .HasColumnName("ban_id"); + + b.Property("UnbanTime") + .HasColumnType("TEXT") + .HasColumnName("unban_time"); + + b.Property("UnbanningAdmin") + .HasColumnType("TEXT") + .HasColumnName("unbanning_admin"); + + b.HasKey("Id") + .HasName("PK_server_unban"); + + b.HasIndex("BanId") + .IsUnique(); + + b.ToTable("server_unban", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Trait", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("trait_id"); + + b.Property("ProfileId") + .HasColumnType("INTEGER") + .HasColumnName("profile_id"); + + b.Property("TraitName") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("trait_name"); + + b.HasKey("Id") + .HasName("PK_trait"); + + b.HasIndex("ProfileId", "TraitName") + .IsUnique(); + + b.ToTable("trait", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.UploadedResourceLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("uploaded_resource_log_id"); + + b.Property("Data") + .IsRequired() + .HasColumnType("BLOB") + .HasColumnName("data"); + + b.Property("Date") + .HasColumnType("TEXT") + .HasColumnName("date"); + + b.Property("Path") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("path"); + + b.Property("UserId") + .HasColumnType("TEXT") + .HasColumnName("user_id"); + + b.HasKey("Id") + .HasName("PK_uploaded_resource_log"); + + b.ToTable("uploaded_resource_log", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Whitelist", b => + { + b.Property("UserId") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT") + .HasColumnName("user_id"); + + b.HasKey("UserId") + .HasName("PK_whitelist"); + + b.ToTable("whitelist", (string)null); + }); + + modelBuilder.Entity("PlayerRound", b => + { + b.Property("PlayersId") + .HasColumnType("INTEGER") + .HasColumnName("players_id"); + + b.Property("RoundsId") + .HasColumnType("INTEGER") + .HasColumnName("rounds_id"); + + b.HasKey("PlayersId", "RoundsId") + .HasName("PK_player_round"); + + b.HasIndex("RoundsId") + .HasDatabaseName("IX_player_round_rounds_id"); + + b.ToTable("player_round", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Admin", b => + { + b.HasOne("Content.Server.Database.AdminRank", "AdminRank") + .WithMany("Admins") + .HasForeignKey("AdminRankId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_admin_rank_admin_rank_id"); + + b.Navigation("AdminRank"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminFlag", b => + { + b.HasOne("Content.Server.Database.Admin", "Admin") + .WithMany("Flags") + .HasForeignKey("AdminId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_admin_flag_admin_admin_id"); + + b.Navigation("Admin"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminLog", b => + { + b.HasOne("Content.Server.Database.Round", "Round") + .WithMany("AdminLogs") + .HasForeignKey("RoundId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_admin_log_round_round_id"); + + b.Navigation("Round"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminLogPlayer", b => + { + b.HasOne("Content.Server.Database.Player", "Player") + .WithMany("AdminLogs") + .HasForeignKey("PlayerUserId") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_admin_log_player_player_player_user_id"); + + b.HasOne("Content.Server.Database.AdminLog", "Log") + .WithMany("Players") + .HasForeignKey("RoundId", "LogId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_admin_log_player_admin_log_round_id_log_id"); + + b.Navigation("Log"); + + b.Navigation("Player"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminMessage", b => + { + b.HasOne("Content.Server.Database.Player", "CreatedBy") + .WithMany("AdminMessagesCreated") + .HasForeignKey("CreatedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_messages_player_created_by_id"); + + b.HasOne("Content.Server.Database.Player", "DeletedBy") + .WithMany("AdminMessagesDeleted") + .HasForeignKey("DeletedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_messages_player_deleted_by_id"); + + b.HasOne("Content.Server.Database.Player", "LastEditedBy") + .WithMany("AdminMessagesLastEdited") + .HasForeignKey("LastEditedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_messages_player_last_edited_by_id"); + + b.HasOne("Content.Server.Database.Player", "Player") + .WithMany("AdminMessagesReceived") + .HasForeignKey("PlayerUserId") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("FK_admin_messages_player_player_user_id"); + + b.HasOne("Content.Server.Database.Round", "Round") + .WithMany() + .HasForeignKey("RoundId") + .HasConstraintName("FK_admin_messages_round_round_id"); + + b.Navigation("CreatedBy"); + + b.Navigation("DeletedBy"); + + b.Navigation("LastEditedBy"); + + b.Navigation("Player"); + + b.Navigation("Round"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminNote", b => + { + b.HasOne("Content.Server.Database.Player", "CreatedBy") + .WithMany("AdminNotesCreated") + .HasForeignKey("CreatedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_notes_player_created_by_id"); + + b.HasOne("Content.Server.Database.Player", "DeletedBy") + .WithMany("AdminNotesDeleted") + .HasForeignKey("DeletedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_notes_player_deleted_by_id"); + + b.HasOne("Content.Server.Database.Player", "LastEditedBy") + .WithMany("AdminNotesLastEdited") + .HasForeignKey("LastEditedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_notes_player_last_edited_by_id"); + + b.HasOne("Content.Server.Database.Player", "Player") + .WithMany("AdminNotesReceived") + .HasForeignKey("PlayerUserId") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("FK_admin_notes_player_player_user_id"); + + b.HasOne("Content.Server.Database.Round", "Round") + .WithMany() + .HasForeignKey("RoundId") + .HasConstraintName("FK_admin_notes_round_round_id"); + + b.Navigation("CreatedBy"); + + b.Navigation("DeletedBy"); + + b.Navigation("LastEditedBy"); + + b.Navigation("Player"); + + b.Navigation("Round"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminRankFlag", b => + { + b.HasOne("Content.Server.Database.AdminRank", "Rank") + .WithMany("Flags") + .HasForeignKey("AdminRankId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_admin_rank_flag_admin_rank_admin_rank_id"); + + b.Navigation("Rank"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminWatchlist", b => + { + b.HasOne("Content.Server.Database.Player", "CreatedBy") + .WithMany("AdminWatchlistsCreated") + .HasForeignKey("CreatedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_watchlists_player_created_by_id"); + + b.HasOne("Content.Server.Database.Player", "DeletedBy") + .WithMany("AdminWatchlistsDeleted") + .HasForeignKey("DeletedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_watchlists_player_deleted_by_id"); + + b.HasOne("Content.Server.Database.Player", "LastEditedBy") + .WithMany("AdminWatchlistsLastEdited") + .HasForeignKey("LastEditedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_watchlists_player_last_edited_by_id"); + + b.HasOne("Content.Server.Database.Player", "Player") + .WithMany("AdminWatchlistsReceived") + .HasForeignKey("PlayerUserId") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("FK_admin_watchlists_player_player_user_id"); + + b.HasOne("Content.Server.Database.Round", "Round") + .WithMany() + .HasForeignKey("RoundId") + .HasConstraintName("FK_admin_watchlists_round_round_id"); + + b.Navigation("CreatedBy"); + + b.Navigation("DeletedBy"); + + b.Navigation("LastEditedBy"); + + b.Navigation("Player"); + + b.Navigation("Round"); + }); + + modelBuilder.Entity("Content.Server.Database.Antag", b => + { + b.HasOne("Content.Server.Database.Profile", "Profile") + .WithMany("Antags") + .HasForeignKey("ProfileId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_antag_profile_profile_id"); + + b.Navigation("Profile"); + }); + + modelBuilder.Entity("Content.Server.Database.ConnectionLog", b => + { + b.HasOne("Content.Server.Database.Server", "Server") + .WithMany("ConnectionLogs") + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.SetNull) + .IsRequired() + .HasConstraintName("FK_connection_log_server_server_id"); + + b.OwnsOne("Content.Server.Database.TypedHwid", "HWId", b1 => + { + b1.Property("ConnectionLogId") + .HasColumnType("INTEGER") + .HasColumnName("connection_log_id"); + + b1.Property("Hwid") + .IsRequired() + .HasColumnType("BLOB") + .HasColumnName("hwid"); + + b1.Property("Type") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValue(0) + .HasColumnName("hwid_type"); + + b1.HasKey("ConnectionLogId"); + + b1.ToTable("connection_log"); + + b1.WithOwner() + .HasForeignKey("ConnectionLogId") + .HasConstraintName("FK_connection_log_connection_log_connection_log_id"); + }); + + b.Navigation("HWId"); + + b.Navigation("Server"); + }); + + modelBuilder.Entity("Content.Server.Database.Job", b => + { + b.HasOne("Content.Server.Database.Profile", "Profile") + .WithMany("Jobs") + .HasForeignKey("ProfileId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_job_profile_profile_id"); + + b.Navigation("Profile"); + }); + + modelBuilder.Entity("Content.Server.Database.Player", b => + { + b.OwnsOne("Content.Server.Database.TypedHwid", "LastSeenHWId", b1 => + { + b1.Property("PlayerId") + .HasColumnType("INTEGER") + .HasColumnName("player_id"); + + b1.Property("Hwid") + .IsRequired() + .HasColumnType("BLOB") + .HasColumnName("last_seen_hwid"); + + b1.Property("Type") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValue(0) + .HasColumnName("last_seen_hwid_type"); + + b1.HasKey("PlayerId"); + + b1.ToTable("player"); + + b1.WithOwner() + .HasForeignKey("PlayerId") + .HasConstraintName("FK_player_player_player_id"); + }); + + b.Navigation("LastSeenHWId"); + }); + + modelBuilder.Entity("Content.Server.Database.Profile", b => + { + b.HasOne("Content.Server.Database.Preference", "Preference") + .WithMany("Profiles") + .HasForeignKey("PreferenceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_profile_preference_preference_id"); + + b.Navigation("Preference"); + }); + + modelBuilder.Entity("Content.Server.Database.ProfileLoadout", b => + { + b.HasOne("Content.Server.Database.ProfileLoadoutGroup", "ProfileLoadoutGroup") + .WithMany("Loadouts") + .HasForeignKey("ProfileLoadoutGroupId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_profile_loadout_profile_loadout_group_profile_loadout_group_id"); + + b.Navigation("ProfileLoadoutGroup"); + }); + + modelBuilder.Entity("Content.Server.Database.ProfileLoadoutGroup", b => + { + b.HasOne("Content.Server.Database.ProfileRoleLoadout", "ProfileRoleLoadout") + .WithMany("Groups") + .HasForeignKey("ProfileRoleLoadoutId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_profile_loadout_group_profile_role_loadout_profile_role_loadout_id"); + + b.Navigation("ProfileRoleLoadout"); + }); + + modelBuilder.Entity("Content.Server.Database.ProfileRoleLoadout", b => + { + b.HasOne("Content.Server.Database.Profile", "Profile") + .WithMany("Loadouts") + .HasForeignKey("ProfileId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_profile_role_loadout_profile_profile_id"); + + b.Navigation("Profile"); + }); + + modelBuilder.Entity("Content.Server.Database.RoleWhitelist", b => + { + b.HasOne("Content.Server.Database.Player", "Player") + .WithMany("JobWhitelists") + .HasForeignKey("PlayerUserId") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_role_whitelists_player_player_user_id"); + + b.Navigation("Player"); + }); + + modelBuilder.Entity("Content.Server.Database.Round", b => + { + b.HasOne("Content.Server.Database.Server", "Server") + .WithMany("Rounds") + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_round_server_server_id"); + + b.Navigation("Server"); + }); + + modelBuilder.Entity("Content.Server.Database.ServerBan", b => + { + b.HasOne("Content.Server.Database.Player", "CreatedBy") + .WithMany("AdminServerBansCreated") + .HasForeignKey("BanningAdmin") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_server_ban_player_banning_admin"); + + b.HasOne("Content.Server.Database.Player", "LastEditedBy") + .WithMany("AdminServerBansLastEdited") + .HasForeignKey("LastEditedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_server_ban_player_last_edited_by_id"); + + b.HasOne("Content.Server.Database.Round", "Round") + .WithMany() + .HasForeignKey("RoundId") + .HasConstraintName("FK_server_ban_round_round_id"); + + b.OwnsOne("Content.Server.Database.TypedHwid", "HWId", b1 => + { + b1.Property("ServerBanId") + .HasColumnType("INTEGER") + .HasColumnName("server_ban_id"); + + b1.Property("Hwid") + .IsRequired() + .HasColumnType("BLOB") + .HasColumnName("hwid"); + + b1.Property("Type") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValue(0) + .HasColumnName("hwid_type"); + + b1.HasKey("ServerBanId"); + + b1.ToTable("server_ban"); + + b1.WithOwner() + .HasForeignKey("ServerBanId") + .HasConstraintName("FK_server_ban_server_ban_server_ban_id"); + }); + + b.Navigation("CreatedBy"); + + b.Navigation("HWId"); + + b.Navigation("LastEditedBy"); + + b.Navigation("Round"); + }); + + modelBuilder.Entity("Content.Server.Database.ServerBanHit", b => + { + b.HasOne("Content.Server.Database.ServerBan", "Ban") + .WithMany("BanHits") + .HasForeignKey("BanId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_server_ban_hit_server_ban_ban_id"); + + b.HasOne("Content.Server.Database.ConnectionLog", "Connection") + .WithMany("BanHits") + .HasForeignKey("ConnectionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_server_ban_hit_connection_log_connection_id"); + + b.Navigation("Ban"); + + b.Navigation("Connection"); + }); + + modelBuilder.Entity("Content.Server.Database.ServerRoleBan", b => + { + b.HasOne("Content.Server.Database.Player", "CreatedBy") + .WithMany("AdminServerRoleBansCreated") + .HasForeignKey("BanningAdmin") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_server_role_ban_player_banning_admin"); + + b.HasOne("Content.Server.Database.Player", "LastEditedBy") + .WithMany("AdminServerRoleBansLastEdited") + .HasForeignKey("LastEditedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_server_role_ban_player_last_edited_by_id"); + + b.HasOne("Content.Server.Database.Round", "Round") + .WithMany() + .HasForeignKey("RoundId") + .HasConstraintName("FK_server_role_ban_round_round_id"); + + b.OwnsOne("Content.Server.Database.TypedHwid", "HWId", b1 => + { + b1.Property("ServerRoleBanId") + .HasColumnType("INTEGER") + .HasColumnName("server_role_ban_id"); + + b1.Property("Hwid") + .IsRequired() + .HasColumnType("BLOB") + .HasColumnName("hwid"); + + b1.Property("Type") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValue(0) + .HasColumnName("hwid_type"); + + b1.HasKey("ServerRoleBanId"); + + b1.ToTable("server_role_ban"); + + b1.WithOwner() + .HasForeignKey("ServerRoleBanId") + .HasConstraintName("FK_server_role_ban_server_role_ban_server_role_ban_id"); + }); + + b.Navigation("CreatedBy"); + + b.Navigation("HWId"); + + b.Navigation("LastEditedBy"); + + b.Navigation("Round"); + }); + + modelBuilder.Entity("Content.Server.Database.ServerRoleUnban", b => + { + b.HasOne("Content.Server.Database.ServerRoleBan", "Ban") + .WithOne("Unban") + .HasForeignKey("Content.Server.Database.ServerRoleUnban", "BanId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_server_role_unban_server_role_ban_ban_id"); + + b.Navigation("Ban"); + }); + + modelBuilder.Entity("Content.Server.Database.ServerUnban", b => + { + b.HasOne("Content.Server.Database.ServerBan", "Ban") + .WithOne("Unban") + .HasForeignKey("Content.Server.Database.ServerUnban", "BanId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_server_unban_server_ban_ban_id"); + + b.Navigation("Ban"); + }); + + modelBuilder.Entity("Content.Server.Database.Trait", b => + { + b.HasOne("Content.Server.Database.Profile", "Profile") + .WithMany("Traits") + .HasForeignKey("ProfileId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_trait_profile_profile_id"); + + b.Navigation("Profile"); + }); + + modelBuilder.Entity("PlayerRound", b => + { + b.HasOne("Content.Server.Database.Player", null) + .WithMany() + .HasForeignKey("PlayersId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_player_round_player_players_id"); + + b.HasOne("Content.Server.Database.Round", null) + .WithMany() + .HasForeignKey("RoundsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_player_round_round_rounds_id"); + }); + + modelBuilder.Entity("Content.Server.Database.Admin", b => + { + b.Navigation("Flags"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminLog", b => + { + b.Navigation("Players"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminRank", b => + { + b.Navigation("Admins"); + + b.Navigation("Flags"); + }); + + modelBuilder.Entity("Content.Server.Database.ConnectionLog", b => + { + b.Navigation("BanHits"); + }); + + modelBuilder.Entity("Content.Server.Database.Player", b => + { + b.Navigation("AdminLogs"); + + b.Navigation("AdminMessagesCreated"); + + b.Navigation("AdminMessagesDeleted"); + + b.Navigation("AdminMessagesLastEdited"); + + b.Navigation("AdminMessagesReceived"); + + b.Navigation("AdminNotesCreated"); + + b.Navigation("AdminNotesDeleted"); + + b.Navigation("AdminNotesLastEdited"); + + b.Navigation("AdminNotesReceived"); + + b.Navigation("AdminServerBansCreated"); + + b.Navigation("AdminServerBansLastEdited"); + + b.Navigation("AdminServerRoleBansCreated"); + + b.Navigation("AdminServerRoleBansLastEdited"); + + b.Navigation("AdminWatchlistsCreated"); + + b.Navigation("AdminWatchlistsDeleted"); + + b.Navigation("AdminWatchlistsLastEdited"); + + b.Navigation("AdminWatchlistsReceived"); + + b.Navigation("JobWhitelists"); + }); + + modelBuilder.Entity("Content.Server.Database.Preference", b => + { + b.Navigation("Profiles"); + }); + + modelBuilder.Entity("Content.Server.Database.Profile", b => + { + b.Navigation("Antags"); + + b.Navigation("Jobs"); + + b.Navigation("Loadouts"); + + b.Navigation("Traits"); + }); + + modelBuilder.Entity("Content.Server.Database.ProfileLoadoutGroup", b => + { + b.Navigation("Loadouts"); + }); + + modelBuilder.Entity("Content.Server.Database.ProfileRoleLoadout", b => + { + b.Navigation("Groups"); + }); + + modelBuilder.Entity("Content.Server.Database.Round", b => + { + b.Navigation("AdminLogs"); + }); + + modelBuilder.Entity("Content.Server.Database.Server", b => + { + b.Navigation("ConnectionLogs"); + + b.Navigation("Rounds"); + }); + + modelBuilder.Entity("Content.Server.Database.ServerBan", b => + { + b.Navigation("BanHits"); + + b.Navigation("Unban"); + }); + + modelBuilder.Entity("Content.Server.Database.ServerRoleBan", b => + { + b.Navigation("Unban"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Content.Server.Database/Migrations/Sqlite/20241111193602_ConnectionTrust.cs b/Content.Server.Database/Migrations/Sqlite/20241111193602_ConnectionTrust.cs new file mode 100644 index 0000000000..3a7fd784e1 --- /dev/null +++ b/Content.Server.Database/Migrations/Sqlite/20241111193602_ConnectionTrust.cs @@ -0,0 +1,29 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Content.Server.Database.Migrations.Sqlite +{ + /// + public partial class ConnectionTrust : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "trust", + table: "connection_log", + type: "REAL", + nullable: false, + defaultValue: 0f); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "trust", + table: "connection_log"); + } + } +} diff --git a/Content.Server.Database/Migrations/Sqlite/SqliteServerDbContextModelSnapshot.cs b/Content.Server.Database/Migrations/Sqlite/SqliteServerDbContextModelSnapshot.cs index 02d4416302..c63127874c 100644 --- a/Content.Server.Database/Migrations/Sqlite/SqliteServerDbContextModelSnapshot.cs +++ b/Content.Server.Database/Migrations/Sqlite/SqliteServerDbContextModelSnapshot.cs @@ -483,19 +483,6 @@ namespace Content.Server.Database.Migrations.Sqlite b.ToTable("assigned_user_id", (string)null); }); - modelBuilder.Entity("Content.Server.Database.Blacklist", - b => - { - b.Property("UserId") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT") - .HasColumnName("user_id"); - - b.HasKey("UserId") - .HasName("PK_blacklist"); - - b.ToTable("blacklist", (string) null); - }); modelBuilder.Entity("Content.Server.Database.BanTemplate", b => { b.Property("Id") @@ -539,6 +526,19 @@ namespace Content.Server.Database.Migrations.Sqlite b.ToTable("ban_template", (string)null); }); + modelBuilder.Entity("Content.Server.Database.Blacklist", b => + { + b.Property("UserId") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT") + .HasColumnName("user_id"); + + b.HasKey("UserId") + .HasName("PK_blacklist"); + + b.ToTable("blacklist", (string)null); + }); + modelBuilder.Entity("Content.Server.Database.ConnectionLog", b => { b.Property("Id") @@ -555,10 +555,6 @@ namespace Content.Server.Database.Migrations.Sqlite .HasColumnType("INTEGER") .HasColumnName("denied"); - b.Property("HWId") - .HasColumnType("BLOB") - .HasColumnName("hwid"); - b.Property("ServerId") .ValueGeneratedOnAdd() .HasColumnType("INTEGER") @@ -569,6 +565,10 @@ namespace Content.Server.Database.Migrations.Sqlite .HasColumnType("TEXT") .HasColumnName("time"); + b.Property("Trust") + .HasColumnType("REAL") + .HasColumnName("trust"); + b.Property("UserId") .HasColumnType("TEXT") .HasColumnName("user_id"); @@ -675,10 +675,6 @@ namespace Content.Server.Database.Migrations.Sqlite .HasColumnType("TEXT") .HasColumnName("last_seen_address"); - b.Property("LastSeenHWId") - .HasColumnType("BLOB") - .HasColumnName("last_seen_hwid"); - b.Property("LastSeenTime") .HasColumnType("TEXT") .HasColumnName("last_seen_time"); @@ -996,10 +992,6 @@ namespace Content.Server.Database.Migrations.Sqlite .HasColumnType("TEXT") .HasColumnName("expiration_time"); - b.Property("HWId") - .HasColumnType("BLOB") - .HasColumnName("hwid"); - b.Property("Hidden") .HasColumnType("INTEGER") .HasColumnName("hidden"); @@ -1124,10 +1116,6 @@ namespace Content.Server.Database.Migrations.Sqlite .HasColumnType("TEXT") .HasColumnName("expiration_time"); - b.Property("HWId") - .HasColumnType("BLOB") - .HasColumnName("hwid"); - b.Property("Hidden") .HasColumnType("INTEGER") .HasColumnName("hidden"); @@ -1559,6 +1547,34 @@ namespace Content.Server.Database.Migrations.Sqlite .IsRequired() .HasConstraintName("FK_connection_log_server_server_id"); + b.OwnsOne("Content.Server.Database.TypedHwid", "HWId", b1 => + { + b1.Property("ConnectionLogId") + .HasColumnType("INTEGER") + .HasColumnName("connection_log_id"); + + b1.Property("Hwid") + .IsRequired() + .HasColumnType("BLOB") + .HasColumnName("hwid"); + + b1.Property("Type") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValue(0) + .HasColumnName("hwid_type"); + + b1.HasKey("ConnectionLogId"); + + b1.ToTable("connection_log"); + + b1.WithOwner() + .HasForeignKey("ConnectionLogId") + .HasConstraintName("FK_connection_log_connection_log_connection_log_id"); + }); + + b.Navigation("HWId"); + b.Navigation("Server"); }); @@ -1574,6 +1590,37 @@ namespace Content.Server.Database.Migrations.Sqlite b.Navigation("Profile"); }); + modelBuilder.Entity("Content.Server.Database.Player", b => + { + b.OwnsOne("Content.Server.Database.TypedHwid", "LastSeenHWId", b1 => + { + b1.Property("PlayerId") + .HasColumnType("INTEGER") + .HasColumnName("player_id"); + + b1.Property("Hwid") + .IsRequired() + .HasColumnType("BLOB") + .HasColumnName("last_seen_hwid"); + + b1.Property("Type") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValue(0) + .HasColumnName("last_seen_hwid_type"); + + b1.HasKey("PlayerId"); + + b1.ToTable("player"); + + b1.WithOwner() + .HasForeignKey("PlayerId") + .HasConstraintName("FK_player_player_player_id"); + }); + + b.Navigation("LastSeenHWId"); + }); + modelBuilder.Entity("Content.Server.Database.Profile", b => { b.HasOne("Content.Server.Database.Preference", "Preference") @@ -1668,8 +1715,36 @@ namespace Content.Server.Database.Migrations.Sqlite .HasForeignKey("RoundId") .HasConstraintName("FK_server_ban_round_round_id"); + b.OwnsOne("Content.Server.Database.TypedHwid", "HWId", b1 => + { + b1.Property("ServerBanId") + .HasColumnType("INTEGER") + .HasColumnName("server_ban_id"); + + b1.Property("Hwid") + .IsRequired() + .HasColumnType("BLOB") + .HasColumnName("hwid"); + + b1.Property("Type") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValue(0) + .HasColumnName("hwid_type"); + + b1.HasKey("ServerBanId"); + + b1.ToTable("server_ban"); + + b1.WithOwner() + .HasForeignKey("ServerBanId") + .HasConstraintName("FK_server_ban_server_ban_server_ban_id"); + }); + b.Navigation("CreatedBy"); + b.Navigation("HWId"); + b.Navigation("LastEditedBy"); b.Navigation("Round"); @@ -1717,8 +1792,36 @@ namespace Content.Server.Database.Migrations.Sqlite .HasForeignKey("RoundId") .HasConstraintName("FK_server_role_ban_round_round_id"); + b.OwnsOne("Content.Server.Database.TypedHwid", "HWId", b1 => + { + b1.Property("ServerRoleBanId") + .HasColumnType("INTEGER") + .HasColumnName("server_role_ban_id"); + + b1.Property("Hwid") + .IsRequired() + .HasColumnType("BLOB") + .HasColumnName("hwid"); + + b1.Property("Type") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValue(0) + .HasColumnName("hwid_type"); + + b1.HasKey("ServerRoleBanId"); + + b1.ToTable("server_role_ban"); + + b1.WithOwner() + .HasForeignKey("ServerRoleBanId") + .HasConstraintName("FK_server_role_ban_server_role_ban_server_role_ban_id"); + }); + b.Navigation("CreatedBy"); + b.Navigation("HWId"); + b.Navigation("LastEditedBy"); b.Navigation("Round"); diff --git a/Content.Server.Database/Model.cs b/Content.Server.Database/Model.cs index 00b3cfea03..9190475b15 100644 --- a/Content.Server.Database/Model.cs +++ b/Content.Server.Database/Model.cs @@ -1,7 +1,9 @@ using System; using System.Collections.Generic; +using System.Collections.Immutable; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Net; using System.Text.Json; @@ -327,6 +329,47 @@ namespace Content.Server.Database .HasForeignKey(w => w.PlayerUserId) .HasPrincipalKey(p => p.UserId) .OnDelete(DeleteBehavior.Cascade); + + // Changes for modern HWID integration + modelBuilder.Entity() + .OwnsOne(p => p.LastSeenHWId) + .Property(p => p.Hwid) + .HasColumnName("last_seen_hwid"); + + modelBuilder.Entity() + .OwnsOne(p => p.LastSeenHWId) + .Property(p => p.Type) + .HasDefaultValue(HwidType.Legacy); + + modelBuilder.Entity() + .OwnsOne(p => p.HWId) + .Property(p => p.Hwid) + .HasColumnName("hwid"); + + modelBuilder.Entity() + .OwnsOne(p => p.HWId) + .Property(p => p.Type) + .HasDefaultValue(HwidType.Legacy); + + modelBuilder.Entity() + .OwnsOne(p => p.HWId) + .Property(p => p.Hwid) + .HasColumnName("hwid"); + + modelBuilder.Entity() + .OwnsOne(p => p.HWId) + .Property(p => p.Type) + .HasDefaultValue(HwidType.Legacy); + + modelBuilder.Entity() + .OwnsOne(p => p.HWId) + .Property(p => p.Hwid) + .HasColumnName("hwid"); + + modelBuilder.Entity() + .OwnsOne(p => p.HWId) + .Property(p => p.Type) + .HasDefaultValue(HwidType.Legacy); } public virtual IQueryable SearchLogs(IQueryable query, string searchText) @@ -519,7 +562,7 @@ namespace Content.Server.Database public string LastSeenUserName { get; set; } = null!; public DateTime LastSeenTime { get; set; } public IPAddress LastSeenAddress { get; set; } = null!; - public byte[]? LastSeenHWId { get; set; } + public TypedHwid? LastSeenHWId { get; set; } // Data that changes with each round public List Rounds { get; set; } = null!; @@ -668,7 +711,7 @@ namespace Content.Server.Database int Id { get; set; } Guid? PlayerUserId { get; set; } NpgsqlInet? Address { get; set; } - byte[]? HWId { get; set; } + TypedHwid? HWId { get; set; } DateTime BanTime { get; set; } DateTime? ExpirationTime { get; set; } string Reason { get; set; } @@ -753,7 +796,7 @@ namespace Content.Server.Database /// /// Hardware ID of the banned player. /// - public byte[]? HWId { get; set; } + public TypedHwid? HWId { get; set; } /// /// The time when the ban was applied by an administrator. @@ -891,7 +934,7 @@ namespace Content.Server.Database public DateTime Time { get; set; } public IPAddress Address { get; set; } = null!; - public byte[]? HWId { get; set; } + public TypedHwid? HWId { get; set; } public ConnectionDenyReason? Denied { get; set; } @@ -908,6 +951,8 @@ namespace Content.Server.Database public List BanHits { get; set; } = null!; public Server Server { get; set; } = null!; + + public float Trust { get; set; } } public enum ConnectionDenyReason : byte @@ -945,7 +990,7 @@ namespace Content.Server.Database public Guid? PlayerUserId { get; set; } [Required] public TimeSpan PlaytimeAtNote { get; set; } public NpgsqlInet? Address { get; set; } - public byte[]? HWId { get; set; } + public TypedHwid? HWId { get; set; } public DateTime BanTime { get; set; } @@ -1206,4 +1251,37 @@ namespace Content.Server.Database /// public bool Hidden { get; set; } } + + /// + /// A hardware ID value together with its . + /// + /// + [Owned] + public sealed class TypedHwid + { + public byte[] Hwid { get; set; } = default!; + public HwidType Type { get; set; } + + [return: NotNullIfNotNull(nameof(immutable))] + public static implicit operator TypedHwid?(ImmutableTypedHwid? immutable) + { + if (immutable == null) + return null; + + return new TypedHwid + { + Hwid = immutable.Hwid.ToArray(), + Type = immutable.Type, + }; + } + + [return: NotNullIfNotNull(nameof(hwid))] + public static implicit operator ImmutableTypedHwid?(TypedHwid? hwid) + { + if (hwid == null) + return null; + + return new ImmutableTypedHwid(hwid.Hwid.ToImmutableArray(), hwid.Type); + } + } } diff --git a/Content.Server/Administration/BanList/BanListEui.cs b/Content.Server/Administration/BanList/BanListEui.cs index 8ddc7459d7..2ca126bf16 100644 --- a/Content.Server/Administration/BanList/BanListEui.cs +++ b/Content.Server/Administration/BanList/BanListEui.cs @@ -54,7 +54,7 @@ public sealed class BanListEui : BaseEui private async Task LoadBans(NetUserId userId) { - foreach (var ban in await _db.GetServerBansAsync(null, userId, null)) + foreach (var ban in await _db.GetServerBansAsync(null, userId, null, null)) { SharedServerUnban? unban = null; if (ban.Unban is { } unbanDef) @@ -74,7 +74,7 @@ public sealed class BanListEui : BaseEui ? (address.address.ToString(), address.cidrMask) : null; - hwid = ban.HWId == null ? null : Convert.ToBase64String(ban.HWId.Value.AsSpan()); + hwid = ban.HWId?.ToString(); } Bans.Add(new SharedServerBan( @@ -95,7 +95,7 @@ public sealed class BanListEui : BaseEui private async Task LoadRoleBans(NetUserId userId) { - foreach (var ban in await _db.GetServerRoleBansAsync(null, userId, null)) + foreach (var ban in await _db.GetServerRoleBansAsync(null, userId, null, null)) { SharedServerUnban? unban = null; if (ban.Unban is { } unbanDef) @@ -115,7 +115,7 @@ public sealed class BanListEui : BaseEui ? (address.address.ToString(), address.cidrMask) : null; - hwid = ban.HWId == null ? null : Convert.ToBase64String(ban.HWId.Value.AsSpan()); + hwid = ban.HWId?.ToString(); } RoleBans.Add(new SharedServerRoleBan( ban.Id, diff --git a/Content.Server/Administration/BanPanelEui.cs b/Content.Server/Administration/BanPanelEui.cs index e746e9c725..3eedad3ed5 100644 --- a/Content.Server/Administration/BanPanelEui.cs +++ b/Content.Server/Administration/BanPanelEui.cs @@ -1,4 +1,3 @@ -using System.Collections.Immutable; using System.Net; using System.Net.Sockets; using Content.Server.Administration.Managers; @@ -8,7 +7,6 @@ using Content.Server.EUI; using Content.Shared.Administration; using Content.Shared.Database; using Content.Shared.Eui; -using Robust.Server.Player; using Robust.Shared.Network; namespace Content.Server.Administration; @@ -27,7 +25,7 @@ public sealed class BanPanelEui : BaseEui private NetUserId? PlayerId { get; set; } private string PlayerName { get; set; } = string.Empty; private IPAddress? LastAddress { get; set; } - private ImmutableArray? LastHwid { get; set; } + private ImmutableTypedHwid? LastHwid { get; set; } private const int Ipv4_CIDR = 32; private const int Ipv6_CIDR = 64; @@ -51,7 +49,7 @@ public sealed class BanPanelEui : BaseEui switch (msg) { case BanPanelEuiStateMsg.CreateBanRequest r: - BanPlayer(r.Player, r.IpAddress, r.UseLastIp, r.Hwid?.ToImmutableArray(), r.UseLastHwid, r.Minutes, r.Severity, r.Reason, r.Roles, r.Erase); + BanPlayer(r.Player, r.IpAddress, r.UseLastIp, r.Hwid, r.UseLastHwid, r.Minutes, r.Severity, r.Reason, r.Roles, r.Erase); break; case BanPanelEuiStateMsg.GetPlayerInfoRequest r: ChangePlayer(r.PlayerUsername); @@ -59,7 +57,7 @@ public sealed class BanPanelEui : BaseEui } } - private async void BanPlayer(string? target, string? ipAddressString, bool useLastIp, ImmutableArray? hwid, bool useLastHwid, uint minutes, NoteSeverity severity, string reason, IReadOnlyCollection? roles, bool erase) + private async void BanPlayer(string? target, string? ipAddressString, bool useLastIp, ImmutableTypedHwid? hwid, bool useLastHwid, uint minutes, NoteSeverity severity, string reason, IReadOnlyCollection? roles, bool erase) { if (!_admins.HasAdminFlag(Player, AdminFlags.Ban)) { @@ -155,7 +153,7 @@ public sealed class BanPanelEui : BaseEui ChangePlayer(located?.UserId, located?.Username ?? string.Empty, located?.LastAddress, located?.LastHWId); } - public void ChangePlayer(NetUserId? playerId, string playerName, IPAddress? lastAddress, ImmutableArray? lastHwid) + public void ChangePlayer(NetUserId? playerId, string playerName, IPAddress? lastAddress, ImmutableTypedHwid? lastHwid) { PlayerId = playerId; PlayerName = playerName; diff --git a/Content.Server/Administration/Commands/BanListCommand.cs b/Content.Server/Administration/Commands/BanListCommand.cs index a5bc97dce3..2f7093ae1d 100644 --- a/Content.Server/Administration/Commands/BanListCommand.cs +++ b/Content.Server/Administration/Commands/BanListCommand.cs @@ -38,7 +38,7 @@ public sealed class BanListCommand : LocalizedCommands if (shell.Player is not { } player) { - var bans = await _dbManager.GetServerBansAsync(data.LastAddress, data.UserId, data.LastHWId, false); + var bans = await _dbManager.GetServerBansAsync(data.LastAddress, data.UserId, data.LastLegacyHWId, data.LastModernHWIds, false); if (bans.Count == 0) { diff --git a/Content.Server/Administration/Commands/RoleBanListCommand.cs b/Content.Server/Administration/Commands/RoleBanListCommand.cs index 30bb3073ad..8244ded3b2 100644 --- a/Content.Server/Administration/Commands/RoleBanListCommand.cs +++ b/Content.Server/Administration/Commands/RoleBanListCommand.cs @@ -48,7 +48,7 @@ public sealed class RoleBanListCommand : IConsoleCommand if (shell.Player is not { } player) { - var bans = await _dbManager.GetServerRoleBansAsync(data.LastAddress, data.UserId, data.LastHWId, includeUnbanned); + var bans = await _dbManager.GetServerRoleBansAsync(data.LastAddress, data.UserId, data.LastLegacyHWId, data.LastModernHWIds, includeUnbanned); if (bans.Count == 0) { diff --git a/Content.Server/Administration/Managers/BanManager.cs b/Content.Server/Administration/Managers/BanManager.cs index 1cdfb82224..2e21710e51 100644 --- a/Content.Server/Administration/Managers/BanManager.cs +++ b/Content.Server/Administration/Managers/BanManager.cs @@ -65,7 +65,8 @@ public sealed partial class BanManager : IBanManager, IPostInjectInit var netChannel = player.Channel; ImmutableArray? hwId = netChannel.UserData.HWId.Length == 0 ? null : netChannel.UserData.HWId; - var roleBans = await _db.GetServerRoleBansAsync(netChannel.RemoteEndPoint.Address, player.UserId, hwId, false); + var modernHwids = netChannel.UserData.ModernHWIds; + var roleBans = await _db.GetServerRoleBansAsync(netChannel.RemoteEndPoint.Address, player.UserId, hwId, modernHwids, false); var userRoleBans = new List(); foreach (var ban in roleBans) @@ -132,7 +133,7 @@ public sealed partial class BanManager : IBanManager, IPostInjectInit } #region Server Bans - public async void CreateServerBan(NetUserId? target, string? targetUsername, NetUserId? banningAdmin, (IPAddress, int)? addressRange, ImmutableArray? hwid, uint? minutes, NoteSeverity severity, string reason) + public async void CreateServerBan(NetUserId? target, string? targetUsername, NetUserId? banningAdmin, (IPAddress, int)? addressRange, ImmutableTypedHwid? hwid, uint? minutes, NoteSeverity severity, string reason) { DateTimeOffset? expires = null; if (minutes > 0) @@ -166,9 +167,7 @@ public sealed partial class BanManager : IBanManager, IPostInjectInit var addressRangeString = addressRange != null ? $"{addressRange.Value.Item1}/{addressRange.Value.Item2}" : "null"; - var hwidString = hwid != null - ? string.Concat(hwid.Value.Select(x => x.ToString("x2"))) - : "null"; + var hwidString = hwid?.ToString() ?? "null"; var expiresString = expires == null ? Loc.GetString("server-ban-string-never") : $"{expires}"; var key = _cfg.GetCVar(CCVars.AdminShowPIIOnBan) ? "server-ban-string" : "server-ban-string-no-pii"; @@ -208,6 +207,7 @@ public sealed partial class BanManager : IBanManager, IPostInjectInit UserId = player.UserId, Address = player.Channel.RemoteEndPoint.Address, HWId = player.Channel.UserData.HWId, + ModernHWIds = player.Channel.UserData.ModernHWIds, // It's possible for the player to not have cached data loading yet due to coincidental timing. // If this is the case, we assume they have all flags to avoid false-positives. ExemptFlags = _cachedBanExemptions.GetValueOrDefault(player, ServerBanExemptFlags.All), @@ -228,7 +228,7 @@ public sealed partial class BanManager : IBanManager, IPostInjectInit #region Job Bans // If you are trying to remove timeOfBan, please don't. It's there because the note system groups role bans by time, reason and banning admin. // Removing it will clutter the note list. Please also make sure that department bans are applied to roles with the same DateTimeOffset. - public async void CreateRoleBan(NetUserId? target, string? targetUsername, NetUserId? banningAdmin, (IPAddress, int)? addressRange, ImmutableArray? hwid, string role, uint? minutes, NoteSeverity severity, string reason, DateTimeOffset timeOfBan) + public async void CreateRoleBan(NetUserId? target, string? targetUsername, NetUserId? banningAdmin, (IPAddress, int)? addressRange, ImmutableTypedHwid? hwid, string role, uint? minutes, NoteSeverity severity, string reason, DateTimeOffset timeOfBan) { if (!_prototypeManager.TryIndex(role, out JobPrototype? _)) { diff --git a/Content.Server/Administration/Managers/IBanManager.cs b/Content.Server/Administration/Managers/IBanManager.cs index c11e310a82..fc192cc306 100644 --- a/Content.Server/Administration/Managers/IBanManager.cs +++ b/Content.Server/Administration/Managers/IBanManager.cs @@ -24,7 +24,7 @@ public interface IBanManager /// Number of minutes to ban for. 0 and null mean permanent /// Severity of the resulting ban note /// Reason for the ban - public void CreateServerBan(NetUserId? target, string? targetUsername, NetUserId? banningAdmin, (IPAddress, int)? addressRange, ImmutableArray? hwid, uint? minutes, NoteSeverity severity, string reason); + public void CreateServerBan(NetUserId? target, string? targetUsername, NetUserId? banningAdmin, (IPAddress, int)? addressRange, ImmutableTypedHwid? hwid, uint? minutes, NoteSeverity severity, string reason); public HashSet? GetRoleBans(NetUserId playerUserId); public HashSet>? GetJobBans(NetUserId playerUserId); @@ -37,7 +37,7 @@ public interface IBanManager /// Reason for the ban /// Number of minutes to ban for. 0 and null mean permanent /// Time when the ban was applied, used for grouping role bans - public void CreateRoleBan(NetUserId? target, string? targetUsername, NetUserId? banningAdmin, (IPAddress, int)? addressRange, ImmutableArray? hwid, string role, uint? minutes, NoteSeverity severity, string reason, DateTimeOffset timeOfBan); + public void CreateRoleBan(NetUserId? target, string? targetUsername, NetUserId? banningAdmin, (IPAddress, int)? addressRange, ImmutableTypedHwid? hwid, string role, uint? minutes, NoteSeverity severity, string reason, DateTimeOffset timeOfBan); /// /// Pardons a role ban for the specified target, username or GUID diff --git a/Content.Server/Administration/PlayerLocator.cs b/Content.Server/Administration/PlayerLocator.cs index 64a85f19ad..25cc771468 100644 --- a/Content.Server/Administration/PlayerLocator.cs +++ b/Content.Server/Administration/PlayerLocator.cs @@ -5,16 +5,42 @@ using System.Net.Http.Headers; using System.Net.Http.Json; using System.Threading; using System.Threading.Tasks; +using Content.Server.Connection; using Content.Server.Database; +using Content.Shared.Database; using JetBrains.Annotations; using Robust.Server.Player; using Robust.Shared; using Robust.Shared.Configuration; using Robust.Shared.Network; +using Robust.Shared.Player; namespace Content.Server.Administration { - public sealed record LocatedPlayerData(NetUserId UserId, IPAddress? LastAddress, ImmutableArray? LastHWId, string Username); + /// + /// Contains data resolved via . + /// + /// The ID of the located user. + /// The last known IP address that the user connected with. + /// + /// The last known HWID that the user connected with. + /// This should be used for placing new records involving HWIDs, such as bans. + /// For looking up data based on HWID, use combined and . + /// + /// The last known username for the user connected with. + /// + /// The last known legacy HWID value this user connected with. Only use for old lookups! + /// + /// + /// The set of last known modern HWIDs the user connected with. + /// + public sealed record LocatedPlayerData( + NetUserId UserId, + IPAddress? LastAddress, + ImmutableTypedHwid? LastHWId, + string Username, + ImmutableArray? LastLegacyHWId, + ImmutableArray> LastModernHWIds); /// /// Utilities for finding user IDs that extend to more than the server database. @@ -67,63 +93,42 @@ namespace Content.Server.Administration { // Check people currently on the server, the easiest case. if (_playerManager.TryGetSessionByUsername(playerName, out var session)) - { - var userId = session.UserId; - var address = session.Channel.RemoteEndPoint.Address; - var hwId = session.Channel.UserData.HWId; - return new LocatedPlayerData(userId, address, hwId, session.Name); - } + return ReturnForSession(session); // Check database for past players. var record = await _db.GetPlayerRecordByUserName(playerName, cancel); if (record != null) - return new LocatedPlayerData(record.UserId, record.LastSeenAddress, record.HWId, record.LastSeenUserName); + return ReturnForPlayerRecord(record); // If all else fails, ask the auth server. var authServer = _configurationManager.GetCVar(CVars.AuthServer); var requestUri = $"{authServer}api/query/name?name={WebUtility.UrlEncode(playerName)}"; using var resp = await _httpClient.GetAsync(requestUri, cancel); - if (resp.StatusCode == HttpStatusCode.NotFound) - return null; - - if (!resp.IsSuccessStatusCode) - { - _sawmill.Error("Auth server returned bad response {StatusCode}!", resp.StatusCode); - return null; - } - - var responseData = await resp.Content.ReadFromJsonAsync(cancellationToken: cancel); - - if (responseData == null) - { - _sawmill.Error("Auth server returned null response!"); - return null; - } - - return new LocatedPlayerData(new NetUserId(responseData.UserId), null, null, responseData.UserName); + return await HandleAuthServerResponse(resp, cancel); } public async Task LookupIdAsync(NetUserId userId, CancellationToken cancel = default) { // Check people currently on the server, the easiest case. if (_playerManager.TryGetSessionById(userId, out var session)) - { - var address = session.Channel.RemoteEndPoint.Address; - var hwId = session.Channel.UserData.HWId; - return new LocatedPlayerData(userId, address, hwId, session.Name); - } + return ReturnForSession(session); // Check database for past players. var record = await _db.GetPlayerRecordByUserId(userId, cancel); if (record != null) - return new LocatedPlayerData(record.UserId, record.LastSeenAddress, record.HWId, record.LastSeenUserName); + return ReturnForPlayerRecord(record); // If all else fails, ask the auth server. var authServer = _configurationManager.GetCVar(CVars.AuthServer); var requestUri = $"{authServer}api/query/userid?userid={WebUtility.UrlEncode(userId.UserId.ToString())}"; using var resp = await _httpClient.GetAsync(requestUri, cancel); + return await HandleAuthServerResponse(resp, cancel); + } + + private async Task HandleAuthServerResponse(HttpResponseMessage resp, CancellationToken cancel) + { if (resp.StatusCode == HttpStatusCode.NotFound) return null; @@ -134,14 +139,40 @@ namespace Content.Server.Administration } var responseData = await resp.Content.ReadFromJsonAsync(cancellationToken: cancel); - if (responseData == null) { _sawmill.Error("Auth server returned null response!"); return null; } - return new LocatedPlayerData(new NetUserId(responseData.UserId), null, null, responseData.UserName); + return new LocatedPlayerData(new NetUserId(responseData.UserId), null, null, responseData.UserName, null, []); + } + + private static LocatedPlayerData ReturnForSession(ICommonSession session) + { + var userId = session.UserId; + var address = session.Channel.RemoteEndPoint.Address; + var hwId = session.Channel.UserData.GetModernHwid(); + return new LocatedPlayerData( + userId, + address, + hwId, + session.Name, + session.Channel.UserData.HWId, + session.Channel.UserData.ModernHWIds); + } + + private static LocatedPlayerData ReturnForPlayerRecord(PlayerRecord record) + { + var hwid = record.HWId; + + return new LocatedPlayerData( + record.UserId, + record.LastSeenAddress, + hwid, + record.LastSeenUserName, + hwid is { Type: HwidType.Legacy } ? hwid.Hwid : null, + hwid is { Type: HwidType.Modern } ? [hwid.Hwid] : []); } public async Task LookupIdByNameOrIdAsync(string playerName, CancellationToken cancel = default) diff --git a/Content.Server/Administration/PlayerPanelEui.cs b/Content.Server/Administration/PlayerPanelEui.cs index 4c0df80601..6c30488886 100644 --- a/Content.Server/Administration/PlayerPanelEui.cs +++ b/Content.Server/Administration/PlayerPanelEui.cs @@ -173,11 +173,11 @@ public sealed class PlayerPanelEui : BaseEui { _whitelisted = await _db.GetWhitelistStatusAsync(_targetPlayer.UserId); // This won't get associated ip or hwid bans but they were not placed on this account anyways - _bans = (await _db.GetServerBansAsync(null, _targetPlayer.UserId, null)).Count; + _bans = (await _db.GetServerBansAsync(null, _targetPlayer.UserId, null, null)).Count; // Unfortunately role bans for departments and stuff are issued individually. This means that a single role ban can have many individual role bans internally // The only way to distinguish whether a role ban is the same is to compare the ban time. // This is horrible and I would love to just erase the database and start from scratch instead but that's what I can do for now. - _roleBans = (await _db.GetServerRoleBansAsync(null, _targetPlayer.UserId, null)).DistinctBy(rb => rb.BanTime).Count(); + _roleBans = (await _db.GetServerRoleBansAsync(null, _targetPlayer.UserId, null, null)).DistinctBy(rb => rb.BanTime).Count(); } else { diff --git a/Content.Server/Administration/Systems/BwoinkSystem.cs b/Content.Server/Administration/Systems/BwoinkSystem.cs index 7a47755db9..4358b7e387 100644 --- a/Content.Server/Administration/Systems/BwoinkSystem.cs +++ b/Content.Server/Administration/Systems/BwoinkSystem.cs @@ -172,7 +172,7 @@ namespace Content.Server.Administration.Systems } // Check if the user has been banned - var ban = await _dbManager.GetServerBanAsync(null, e.Session.UserId, null); + var ban = await _dbManager.GetServerBanAsync(null, e.Session.UserId, null, null); if (ban != null) { var banMessage = Loc.GetString("bwoink-system-player-banned", ("banReason", ban.Reason)); diff --git a/Content.Server/Connection/ConnectionManager.cs b/Content.Server/Connection/ConnectionManager.cs index 2c1f9fb36f..e4c7cf0be2 100644 --- a/Content.Server/Connection/ConnectionManager.cs +++ b/Content.Server/Connection/ConnectionManager.cs @@ -111,11 +111,14 @@ namespace Content.Server.Connection var serverId = (await _serverDbEntry.ServerEntity).Id; + var hwid = e.UserData.GetModernHwid(); + var trust = e.UserData.Trust; + if (deny != null) { var (reason, msg, banHits) = deny.Value; - var id = await _db.AddConnectionLogAsync(userId, e.UserName, addr, e.UserData.HWId, reason, serverId); + var id = await _db.AddConnectionLogAsync(userId, e.UserName, addr, hwid, trust, reason, serverId); if (banHits is { Count: > 0 }) await _db.AddServerBanHitsAsync(id, banHits); @@ -127,12 +130,12 @@ namespace Content.Server.Connection } else { - await _db.AddConnectionLogAsync(userId, e.UserName, addr, e.UserData.HWId, null, serverId); + await _db.AddConnectionLogAsync(userId, e.UserName, addr, hwid, trust, null, serverId); if (!ServerPreferencesManager.ShouldStorePrefs(e.AuthType)) return; - await _db.UpdatePlayerRecordAsync(userId, e.UserName, addr, e.UserData.HWId); + await _db.UpdatePlayerRecordAsync(userId, e.UserName, addr, hwid); } } @@ -190,7 +193,9 @@ namespace Content.Server.Connection hwId = null; } - var bans = await _db.GetServerBansAsync(addr, userId, hwId, includeUnbanned: false); + var modernHwid = e.UserData.ModernHWIds; + + var bans = await _db.GetServerBansAsync(addr, userId, hwId, modernHwid, includeUnbanned: false); if (bans.Count > 0) { var firstBan = bans[0]; diff --git a/Content.Server/Connection/UserDataExt.cs b/Content.Server/Connection/UserDataExt.cs new file mode 100644 index 0000000000..a409f79a75 --- /dev/null +++ b/Content.Server/Connection/UserDataExt.cs @@ -0,0 +1,24 @@ +using Content.Shared.Database; +using Robust.Shared.Network; + +namespace Content.Server.Connection; + +/// +/// Helper functions for working with . +/// +public static class UserDataExt +{ + /// + /// Get the preferred HWID that should be used for new records related to a player. + /// + /// + /// Players can have zero or more HWIDs, but for logging things like connection logs we generally + /// only want a single one. This method returns a nullable method. + /// + public static ImmutableTypedHwid? GetModernHwid(this NetUserData userData) + { + return userData.ModernHWIds.Length == 0 + ? null + : new ImmutableTypedHwid(userData.ModernHWIds[0], HwidType.Modern); + } +} diff --git a/Content.Server/Database/BanMatcher.cs b/Content.Server/Database/BanMatcher.cs index e58e5b0b5f..f477ccd822 100644 --- a/Content.Server/Database/BanMatcher.cs +++ b/Content.Server/Database/BanMatcher.cs @@ -1,6 +1,7 @@ using System.Collections.Immutable; using System.Net; using Content.Server.IP; +using Content.Shared.Database; using Robust.Shared.Network; namespace Content.Server.Database; @@ -52,9 +53,28 @@ public static class BanMatcher return true; } - return player.HWId is { Length: > 0 } hwIdVar - && ban.HWId != null - && hwIdVar.AsSpan().SequenceEqual(ban.HWId.Value.AsSpan()); + switch (ban.HWId?.Type) + { + case HwidType.Legacy: + if (player.HWId is { Length: > 0 } hwIdVar + && hwIdVar.AsSpan().SequenceEqual(ban.HWId.Hwid.AsSpan())) + { + return true; + } + break; + case HwidType.Modern: + if (player.ModernHWIds is { Length: > 0 } modernHwIdVar) + { + foreach (var hwid in modernHwIdVar) + { + if (hwid.AsSpan().SequenceEqual(ban.HWId.Hwid.AsSpan())) + return true; + } + } + break; + } + + return false; } /// @@ -73,10 +93,15 @@ public static class BanMatcher public IPAddress? Address; /// - /// The hardware ID of the player. + /// The LEGACY hardware ID of the player. Corresponds with . /// public ImmutableArray? HWId; + /// + /// The modern hardware IDs of the player. Corresponds with . + /// + public ImmutableArray>? ModernHWIds; + /// /// Exemption flags the player has been granted. /// diff --git a/Content.Server/Database/DatabaseRecords.cs b/Content.Server/Database/DatabaseRecords.cs index c0d81147bb..30fba3434b 100644 --- a/Content.Server/Database/DatabaseRecords.cs +++ b/Content.Server/Database/DatabaseRecords.cs @@ -1,4 +1,3 @@ -using System.Collections.Immutable; using System.Net; using Content.Shared.Database; using Robust.Shared.Network; @@ -121,7 +120,7 @@ public sealed record PlayerRecord( string LastSeenUserName, DateTimeOffset LastSeenTime, IPAddress LastSeenAddress, - ImmutableArray? HWId); + ImmutableTypedHwid? HWId); public sealed record RoundRecord(int Id, DateTimeOffset? StartDate, ServerRecord Server); diff --git a/Content.Server/Database/ServerBanDef.cs b/Content.Server/Database/ServerBanDef.cs index 09a960e9a6..a09f9e959c 100644 --- a/Content.Server/Database/ServerBanDef.cs +++ b/Content.Server/Database/ServerBanDef.cs @@ -1,4 +1,3 @@ -using System.Collections.Immutable; using System.Net; using Content.Shared.CCVar; using Content.Shared.Database; @@ -13,7 +12,7 @@ namespace Content.Server.Database public int? Id { get; } public NetUserId? UserId { get; } public (IPAddress address, int cidrMask)? Address { get; } - public ImmutableArray? HWId { get; } + public ImmutableTypedHwid? HWId { get; } public DateTimeOffset BanTime { get; } public DateTimeOffset? ExpirationTime { get; } @@ -28,7 +27,7 @@ namespace Content.Server.Database public ServerBanDef(int? id, NetUserId? userId, (IPAddress, int)? address, - ImmutableArray? hwId, + TypedHwid? hwId, DateTimeOffset banTime, DateTimeOffset? expirationTime, int? roundId, diff --git a/Content.Server/Database/ServerDbBase.cs b/Content.Server/Database/ServerDbBase.cs index c85b774e38..723092bdc4 100644 --- a/Content.Server/Database/ServerDbBase.cs +++ b/Content.Server/Database/ServerDbBase.cs @@ -388,12 +388,14 @@ namespace Content.Server.Database /// /// The ip address of the user. /// The id of the user. - /// The HWId of the user. + /// The legacy HWId of the user. + /// The modern HWIDs of the user. /// The user's latest received un-pardoned ban, or null if none exist. public abstract Task GetServerBanAsync( IPAddress? address, NetUserId? userId, - ImmutableArray? hwId); + ImmutableArray? hwId, + ImmutableArray>? modernHWIds); /// /// Looks up an user's ban history. @@ -402,13 +404,15 @@ namespace Content.Server.Database /// /// The ip address of the user. /// The id of the user. - /// The HWId of the user. + /// The legacy HWId of the user. + /// The modern HWIDs of the user. /// Include pardoned and expired bans. /// The user's ban history. public abstract Task> GetServerBansAsync( IPAddress? address, NetUserId? userId, ImmutableArray? hwId, + ImmutableArray>? modernHWIds, bool includeUnbanned); public abstract Task AddServerBanAsync(ServerBanDef serverBan); @@ -499,11 +503,13 @@ namespace Content.Server.Database /// The IP address of the user. /// The NetUserId of the user. /// The Hardware Id of the user. + /// The modern HWIDs of the user. /// Whether expired and pardoned bans are included. /// The user's role ban history. public abstract Task> GetServerRoleBansAsync(IPAddress? address, NetUserId? userId, ImmutableArray? hwId, + ImmutableArray>? modernHWIds, bool includeUnbanned); public abstract Task AddServerRoleBanAsync(ServerRoleBanDef serverRoleBan); @@ -586,7 +592,7 @@ namespace Content.Server.Database NetUserId userId, string userName, IPAddress address, - ImmutableArray hwId) + ImmutableTypedHwid? hwId) { await using var db = await GetDb(); @@ -603,7 +609,7 @@ namespace Content.Server.Database record.LastSeenTime = DateTime.UtcNow; record.LastSeenAddress = address; record.LastSeenUserName = userName; - record.LastSeenHWId = hwId.ToArray(); + record.LastSeenHWId = hwId; await db.DbContext.SaveChangesAsync(); } @@ -649,7 +655,7 @@ namespace Content.Server.Database player.LastSeenUserName, new DateTimeOffset(NormalizeDatabaseTime(player.LastSeenTime)), player.LastSeenAddress, - player.LastSeenHWId?.ToImmutableArray()); + player.LastSeenHWId); } #endregion @@ -658,11 +664,11 @@ namespace Content.Server.Database /* * CONNECTION LOG */ - public abstract Task AddConnectionLogAsync( - NetUserId userId, + public abstract Task AddConnectionLogAsync(NetUserId userId, string userName, IPAddress address, - ImmutableArray hwId, + ImmutableTypedHwid? hwId, + float trust, ConnectionDenyReason? denied, int serverId); diff --git a/Content.Server/Database/ServerDbManager.cs b/Content.Server/Database/ServerDbManager.cs index 216b1ec159..be32b43595 100644 --- a/Content.Server/Database/ServerDbManager.cs +++ b/Content.Server/Database/ServerDbManager.cs @@ -69,12 +69,14 @@ namespace Content.Server.Database /// /// The ip address of the user. /// The id of the user. - /// The hardware ID of the user. + /// The legacy HWID of the user. + /// The modern HWIDs of the user. /// The user's latest received un-pardoned ban, or null if none exist. Task GetServerBanAsync( IPAddress? address, NetUserId? userId, - ImmutableArray? hwId); + ImmutableArray? hwId, + ImmutableArray>? modernHWIds); /// /// Looks up an user's ban history. @@ -82,13 +84,15 @@ namespace Content.Server.Database /// /// The ip address of the user. /// The id of the user. - /// The HWId of the user. + /// The legacy HWId of the user. + /// The modern HWIDs of the user. /// If true, bans that have been expired or pardoned are also included. /// The user's ban history. Task> GetServerBansAsync( IPAddress? address, NetUserId? userId, ImmutableArray? hwId, + ImmutableArray>? modernHWIds, bool includeUnbanned=true); Task AddServerBanAsync(ServerBanDef serverBan); @@ -137,12 +141,14 @@ namespace Content.Server.Database /// The IP address of the user. /// The NetUserId of the user. /// The Hardware Id of the user. + /// The modern HWIDs of the user. /// Whether expired and pardoned bans are included. /// The user's role ban history. Task> GetServerRoleBansAsync( IPAddress? address, NetUserId? userId, ImmutableArray? hwId, + ImmutableArray>? modernHWIds, bool includeUnbanned = true); Task AddServerRoleBanAsync(ServerRoleBanDef serverBan); @@ -180,7 +186,7 @@ namespace Content.Server.Database NetUserId userId, string userName, IPAddress address, - ImmutableArray hwId); + ImmutableTypedHwid? hwId); Task GetPlayerRecordByUserName(string userName, CancellationToken cancel = default); Task GetPlayerRecordByUserId(NetUserId userId, CancellationToken cancel = default); #endregion @@ -191,7 +197,8 @@ namespace Content.Server.Database NetUserId userId, string userName, IPAddress address, - ImmutableArray hwId, + ImmutableTypedHwid? hwId, + float trust, ConnectionDenyReason? denied, int serverId); @@ -480,20 +487,22 @@ namespace Content.Server.Database public Task GetServerBanAsync( IPAddress? address, NetUserId? userId, - ImmutableArray? hwId) + ImmutableArray? hwId, + ImmutableArray>? modernHWIds) { DbReadOpsMetric.Inc(); - return RunDbCommand(() => _db.GetServerBanAsync(address, userId, hwId)); + return RunDbCommand(() => _db.GetServerBanAsync(address, userId, hwId, modernHWIds)); } public Task> GetServerBansAsync( IPAddress? address, NetUserId? userId, ImmutableArray? hwId, + ImmutableArray>? modernHWIds, bool includeUnbanned=true) { DbReadOpsMetric.Inc(); - return RunDbCommand(() => _db.GetServerBansAsync(address, userId, hwId, includeUnbanned)); + return RunDbCommand(() => _db.GetServerBansAsync(address, userId, hwId, modernHWIds, includeUnbanned)); } public Task AddServerBanAsync(ServerBanDef serverBan) @@ -537,10 +546,11 @@ namespace Content.Server.Database IPAddress? address, NetUserId? userId, ImmutableArray? hwId, + ImmutableArray>? modernHWIds, bool includeUnbanned = true) { DbReadOpsMetric.Inc(); - return RunDbCommand(() => _db.GetServerRoleBansAsync(address, userId, hwId, includeUnbanned)); + return RunDbCommand(() => _db.GetServerRoleBansAsync(address, userId, hwId, modernHWIds, includeUnbanned)); } public Task AddServerRoleBanAsync(ServerRoleBanDef serverRoleBan) @@ -582,7 +592,7 @@ namespace Content.Server.Database NetUserId userId, string userName, IPAddress address, - ImmutableArray hwId) + ImmutableTypedHwid? hwId) { DbWriteOpsMetric.Inc(); return RunDbCommand(() => _db.UpdatePlayerRecord(userId, userName, address, hwId)); @@ -604,12 +614,13 @@ namespace Content.Server.Database NetUserId userId, string userName, IPAddress address, - ImmutableArray hwId, + ImmutableTypedHwid? hwId, + float trust, ConnectionDenyReason? denied, int serverId) { DbWriteOpsMetric.Inc(); - return RunDbCommand(() => _db.AddConnectionLogAsync(userId, userName, address, hwId, denied, serverId)); + return RunDbCommand(() => _db.AddConnectionLogAsync(userId, userName, address, hwId, trust, denied, serverId)); } public Task AddServerBanHitsAsync(int connection, IEnumerable bans) diff --git a/Content.Server/Database/ServerDbPostgres.cs b/Content.Server/Database/ServerDbPostgres.cs index 7d131f70dc..c034670837 100644 --- a/Content.Server/Database/ServerDbPostgres.cs +++ b/Content.Server/Database/ServerDbPostgres.cs @@ -9,6 +9,7 @@ using System.Threading.Tasks; using Content.Server.Administration.Logs; using Content.Server.IP; using Content.Shared.CCVar; +using Content.Shared.Database; using Microsoft.EntityFrameworkCore; using Robust.Shared.Configuration; using Robust.Shared.Network; @@ -73,7 +74,8 @@ namespace Content.Server.Database public override async Task GetServerBanAsync( IPAddress? address, NetUserId? userId, - ImmutableArray? hwId) + ImmutableArray? hwId, + ImmutableArray>? modernHWIds) { if (address == null && userId == null && hwId == null) { @@ -84,7 +86,7 @@ namespace Content.Server.Database var exempt = await GetBanExemptionCore(db, userId); var newPlayer = userId == null || !await PlayerRecordExists(db, userId.Value); - var query = MakeBanLookupQuery(address, userId, hwId, db, includeUnbanned: false, exempt, newPlayer) + var query = MakeBanLookupQuery(address, userId, hwId, modernHWIds, db, includeUnbanned: false, exempt, newPlayer) .OrderByDescending(b => b.BanTime); var ban = await query.FirstOrDefaultAsync(); @@ -94,7 +96,9 @@ namespace Content.Server.Database public override async Task> GetServerBansAsync(IPAddress? address, NetUserId? userId, - ImmutableArray? hwId, bool includeUnbanned) + ImmutableArray? hwId, + ImmutableArray>? modernHWIds, + bool includeUnbanned) { if (address == null && userId == null && hwId == null) { @@ -105,7 +109,7 @@ namespace Content.Server.Database var exempt = await GetBanExemptionCore(db, userId); var newPlayer = !await db.PgDbContext.Player.AnyAsync(p => p.UserId == userId); - var query = MakeBanLookupQuery(address, userId, hwId, db, includeUnbanned, exempt, newPlayer); + var query = MakeBanLookupQuery(address, userId, hwId, modernHWIds, db, includeUnbanned, exempt, newPlayer); var queryBans = await query.ToArrayAsync(); var bans = new List(queryBans.Length); @@ -127,6 +131,7 @@ namespace Content.Server.Database IPAddress? address, NetUserId? userId, ImmutableArray? hwId, + ImmutableArray>? modernHWIds, DbGuardImpl db, bool includeUnbanned, ServerBanExemptFlags? exemptFlags, @@ -134,16 +139,11 @@ namespace Content.Server.Database { DebugTools.Assert(!(address == null && userId == null && hwId == null)); - IQueryable? query = null; - - if (userId is { } uid) - { - var newQ = db.PgDbContext.Ban - .Include(p => p.Unban) - .Where(b => b.PlayerUserId == uid.UserId); - - query = query == null ? newQ : query.Union(newQ); - } + var query = MakeBanLookupQualityShared( + userId, + hwId, + modernHWIds, + db.PgDbContext.Ban); if (address != null && !exemptFlags.GetValueOrDefault(ServerBanExemptFlags.None).HasFlag(ServerBanExemptFlags.IP)) { @@ -156,15 +156,6 @@ namespace Content.Server.Database query = query == null ? newQ : query.Union(newQ); } - if (hwId != null && hwId.Value.Length > 0) - { - var newQ = db.PgDbContext.Ban - .Include(p => p.Unban) - .Where(b => b.HWId!.SequenceEqual(hwId.Value.ToArray())); - - query = query == null ? newQ : query.Union(newQ); - } - DebugTools.Assert( query != null, "At least one filter item (IP/UserID/HWID) must have been given to make query not null."); @@ -186,6 +177,49 @@ namespace Content.Server.Database return query.Distinct(); } + private static IQueryable? MakeBanLookupQualityShared( + NetUserId? userId, + ImmutableArray? hwId, + ImmutableArray>? modernHWIds, + DbSet set) + where TBan : class, IBanCommon + where TUnban : class, IUnbanCommon + { + IQueryable? query = null; + + if (userId is { } uid) + { + var newQ = set + .Include(p => p.Unban) + .Where(b => b.PlayerUserId == uid.UserId); + + query = query == null ? newQ : query.Union(newQ); + } + + if (hwId != null && hwId.Value.Length > 0) + { + var newQ = set + .Include(p => p.Unban) + .Where(b => b.HWId!.Type == HwidType.Legacy && b.HWId!.Hwid.SequenceEqual(hwId.Value.ToArray())); + + query = query == null ? newQ : query.Union(newQ); + } + + if (modernHWIds != null) + { + foreach (var modernHwid in modernHWIds) + { + var newQ = set + .Include(p => p.Unban) + .Where(b => b.HWId!.Type == HwidType.Modern && b.HWId!.Hwid.SequenceEqual(modernHwid.ToArray())); + + query = query == null ? newQ : query.Union(newQ); + } + } + + return query; + } + private static ServerBanDef? ConvertBan(ServerBan? ban) { if (ban == null) @@ -211,7 +245,7 @@ namespace Content.Server.Database ban.Id, uid, ban.Address.ToTuple(), - ban.HWId == null ? null : ImmutableArray.Create(ban.HWId), + ban.HWId, ban.BanTime, ban.ExpirationTime, ban.RoundId, @@ -249,7 +283,7 @@ namespace Content.Server.Database db.PgDbContext.Ban.Add(new ServerBan { Address = serverBan.Address.ToNpgsqlInet(), - HWId = serverBan.HWId?.ToArray(), + HWId = serverBan.HWId, Reason = serverBan.Reason, Severity = serverBan.Severity, BanningAdmin = serverBan.BanningAdmin?.UserId, @@ -297,6 +331,7 @@ namespace Content.Server.Database public override async Task> GetServerRoleBansAsync(IPAddress? address, NetUserId? userId, ImmutableArray? hwId, + ImmutableArray>? modernHWIds, bool includeUnbanned) { if (address == null && userId == null && hwId == null) @@ -306,7 +341,7 @@ namespace Content.Server.Database await using var db = await GetDbImpl(); - var query = MakeRoleBanLookupQuery(address, userId, hwId, db, includeUnbanned) + var query = MakeRoleBanLookupQuery(address, userId, hwId, modernHWIds, db, includeUnbanned) .OrderByDescending(b => b.BanTime); return await QueryRoleBans(query); @@ -334,19 +369,15 @@ namespace Content.Server.Database IPAddress? address, NetUserId? userId, ImmutableArray? hwId, + ImmutableArray>? modernHWIds, DbGuardImpl db, bool includeUnbanned) { - IQueryable? query = null; - - if (userId is { } uid) - { - var newQ = db.PgDbContext.RoleBan - .Include(p => p.Unban) - .Where(b => b.PlayerUserId == uid.UserId); - - query = query == null ? newQ : query.Union(newQ); - } + var query = MakeBanLookupQualityShared( + userId, + hwId, + modernHWIds, + db.PgDbContext.RoleBan); if (address != null) { @@ -357,15 +388,6 @@ namespace Content.Server.Database query = query == null ? newQ : query.Union(newQ); } - if (hwId != null && hwId.Value.Length > 0) - { - var newQ = db.PgDbContext.RoleBan - .Include(p => p.Unban) - .Where(b => b.HWId!.SequenceEqual(hwId.Value.ToArray())); - - query = query == null ? newQ : query.Union(newQ); - } - if (!includeUnbanned) { query = query?.Where(p => @@ -402,7 +424,7 @@ namespace Content.Server.Database ban.Id, uid, ban.Address.ToTuple(), - ban.HWId == null ? null : ImmutableArray.Create(ban.HWId), + ban.HWId, ban.BanTime, ban.ExpirationTime, ban.RoundId, @@ -440,7 +462,7 @@ namespace Content.Server.Database var ban = new ServerRoleBan { Address = serverRoleBan.Address.ToNpgsqlInet(), - HWId = serverRoleBan.HWId?.ToArray(), + HWId = serverRoleBan.HWId, Reason = serverRoleBan.Reason, Severity = serverRoleBan.Severity, BanningAdmin = serverRoleBan.BanningAdmin?.UserId, @@ -476,7 +498,8 @@ namespace Content.Server.Database NetUserId userId, string userName, IPAddress address, - ImmutableArray hwId, + ImmutableTypedHwid? hwId, + float trust, ConnectionDenyReason? denied, int serverId) { @@ -488,9 +511,10 @@ namespace Content.Server.Database Time = DateTime.UtcNow, UserId = userId.UserId, UserName = userName, - HWId = hwId.ToArray(), + HWId = hwId, Denied = denied, - ServerId = serverId + ServerId = serverId, + Trust = trust, }; db.PgDbContext.ConnectionLog.Add(connectionLog); diff --git a/Content.Server/Database/ServerDbSqlite.cs b/Content.Server/Database/ServerDbSqlite.cs index af4bc2cf8d..6ec90c3332 100644 --- a/Content.Server/Database/ServerDbSqlite.cs +++ b/Content.Server/Database/ServerDbSqlite.cs @@ -9,6 +9,7 @@ using Content.Server.Administration.Logs; using Content.Server.IP; using Content.Server.Preferences.Managers; using Content.Shared.CCVar; +using Content.Shared.Database; using Microsoft.EntityFrameworkCore; using Robust.Shared.Configuration; using Robust.Shared.Network; @@ -80,22 +81,24 @@ namespace Content.Server.Database public override async Task GetServerBanAsync( IPAddress? address, NetUserId? userId, - ImmutableArray? hwId) + ImmutableArray? hwId, + ImmutableArray>? modernHWIds) { await using var db = await GetDbImpl(); - return (await GetServerBanQueryAsync(db, address, userId, hwId, includeUnbanned: false)).FirstOrDefault(); + return (await GetServerBanQueryAsync(db, address, userId, hwId, modernHWIds, includeUnbanned: false)).FirstOrDefault(); } public override async Task> GetServerBansAsync( IPAddress? address, NetUserId? userId, ImmutableArray? hwId, + ImmutableArray>? modernHWIds, bool includeUnbanned) { await using var db = await GetDbImpl(); - return (await GetServerBanQueryAsync(db, address, userId, hwId, includeUnbanned)).ToList(); + return (await GetServerBanQueryAsync(db, address, userId, hwId, modernHWIds, includeUnbanned)).ToList(); } private async Task> GetServerBanQueryAsync( @@ -103,6 +106,7 @@ namespace Content.Server.Database IPAddress? address, NetUserId? userId, ImmutableArray? hwId, + ImmutableArray>? modernHWIds, bool includeUnbanned) { var exempt = await GetBanExemptionCore(db, userId); @@ -119,6 +123,7 @@ namespace Content.Server.Database UserId = userId, ExemptFlags = exempt ?? default, HWId = hwId, + ModernHWIds = modernHWIds, IsNewPlayer = newPlayer, }; @@ -161,7 +166,7 @@ namespace Content.Server.Database Reason = serverBan.Reason, Severity = serverBan.Severity, BanningAdmin = serverBan.BanningAdmin?.UserId, - HWId = serverBan.HWId?.ToArray(), + HWId = serverBan.HWId, BanTime = serverBan.BanTime.UtcDateTime, ExpirationTime = serverBan.ExpirationTime?.UtcDateTime, RoundId = serverBan.RoundId, @@ -205,6 +210,7 @@ namespace Content.Server.Database IPAddress? address, NetUserId? userId, ImmutableArray? hwId, + ImmutableArray>? modernHWIds, bool includeUnbanned) { await using var db = await GetDbImpl(); @@ -214,7 +220,7 @@ namespace Content.Server.Database var queryBans = await GetAllRoleBans(db.SqliteDbContext, includeUnbanned); return queryBans - .Where(b => RoleBanMatches(b, address, userId, hwId)) + .Where(b => RoleBanMatches(b, address, userId, hwId, modernHWIds)) .Select(ConvertRoleBan) .ToList()!; } @@ -237,7 +243,8 @@ namespace Content.Server.Database ServerRoleBan ban, IPAddress? address, NetUserId? userId, - ImmutableArray? hwId) + ImmutableArray? hwId, + ImmutableArray>? modernHWIds) { if (address != null && ban.Address is not null && address.IsInSubnet(ban.Address.ToTuple().Value)) { @@ -249,7 +256,27 @@ namespace Content.Server.Database return true; } - return hwId is { Length: > 0 } hwIdVar && hwIdVar.AsSpan().SequenceEqual(ban.HWId); + switch (ban.HWId?.Type) + { + case HwidType.Legacy: + if (hwId is { Length: > 0 } hwIdVar && hwIdVar.AsSpan().SequenceEqual(ban.HWId.Hwid)) + return true; + break; + + case HwidType.Modern: + if (modernHWIds != null) + { + foreach (var modernHWId in modernHWIds) + { + if (modernHWId.AsSpan().SequenceEqual(ban.HWId.Hwid)) + return true; + } + } + + break; + } + + return false; } public override async Task AddServerRoleBanAsync(ServerRoleBanDef serverBan) @@ -262,7 +289,7 @@ namespace Content.Server.Database Reason = serverBan.Reason, Severity = serverBan.Severity, BanningAdmin = serverBan.BanningAdmin?.UserId, - HWId = serverBan.HWId?.ToArray(), + HWId = serverBan.HWId, BanTime = serverBan.BanTime.UtcDateTime, ExpirationTime = serverBan.ExpirationTime?.UtcDateTime, RoundId = serverBan.RoundId, @@ -316,7 +343,7 @@ namespace Content.Server.Database ban.Id, uid, ban.Address.ToTuple(), - ban.HWId == null ? null : ImmutableArray.Create(ban.HWId), + ban.HWId, // SQLite apparently always reads DateTime as unspecified, but we always write as UTC. DateTime.SpecifyKind(ban.BanTime, DateTimeKind.Utc), ban.ExpirationTime == null ? null : DateTime.SpecifyKind(ban.ExpirationTime.Value, DateTimeKind.Utc), @@ -376,7 +403,7 @@ namespace Content.Server.Database ban.Id, uid, ban.Address.ToTuple(), - ban.HWId == null ? null : ImmutableArray.Create(ban.HWId), + ban.HWId, // SQLite apparently always reads DateTime as unspecified, but we always write as UTC. DateTime.SpecifyKind(ban.BanTime, DateTimeKind.Utc), ban.ExpirationTime == null ? null : DateTime.SpecifyKind(ban.ExpirationTime.Value, DateTimeKind.Utc), @@ -412,7 +439,8 @@ namespace Content.Server.Database NetUserId userId, string userName, IPAddress address, - ImmutableArray hwId, + ImmutableTypedHwid? hwId, + float trust, ConnectionDenyReason? denied, int serverId) { @@ -424,9 +452,10 @@ namespace Content.Server.Database Time = DateTime.UtcNow, UserId = userId.UserId, UserName = userName, - HWId = hwId.ToArray(), + HWId = hwId, Denied = denied, - ServerId = serverId + ServerId = serverId, + Trust = trust, }; db.SqliteDbContext.ConnectionLog.Add(connectionLog); diff --git a/Content.Server/Database/ServerRoleBanDef.cs b/Content.Server/Database/ServerRoleBanDef.cs index f615d5da4d..dda3a82237 100644 --- a/Content.Server/Database/ServerRoleBanDef.cs +++ b/Content.Server/Database/ServerRoleBanDef.cs @@ -1,4 +1,3 @@ -using System.Collections.Immutable; using System.Net; using Content.Shared.Database; using Robust.Shared.Network; @@ -10,7 +9,7 @@ public sealed class ServerRoleBanDef public int? Id { get; } public NetUserId? UserId { get; } public (IPAddress address, int cidrMask)? Address { get; } - public ImmutableArray? HWId { get; } + public ImmutableTypedHwid? HWId { get; } public DateTimeOffset BanTime { get; } public DateTimeOffset? ExpirationTime { get; } @@ -26,7 +25,7 @@ public sealed class ServerRoleBanDef int? id, NetUserId? userId, (IPAddress, int)? address, - ImmutableArray? hwId, + ImmutableTypedHwid? hwId, DateTimeOffset banTime, DateTimeOffset? expirationTime, int? roundId, diff --git a/Content.Shared.Database/TypedHwid.cs b/Content.Shared.Database/TypedHwid.cs new file mode 100644 index 0000000000..6e4a7763b3 --- /dev/null +++ b/Content.Shared.Database/TypedHwid.cs @@ -0,0 +1,62 @@ +using System.Collections.Immutable; +using System.Diagnostics.CodeAnalysis; + +namespace Content.Shared.Database; + +/// +/// Represents a raw HWID value together with its type. +/// +[Serializable] +public sealed class ImmutableTypedHwid(ImmutableArray hwid, HwidType type) +{ + public readonly ImmutableArray Hwid = hwid; + public readonly HwidType Type = type; + + public override string ToString() + { + var b64 = Convert.ToBase64String(Hwid.AsSpan()); + return Type == HwidType.Modern ? $"V2-{b64}" : b64; + } + + public static bool TryParse(string value, [NotNullWhen(true)] out ImmutableTypedHwid? hwid) + { + var type = HwidType.Legacy; + if (value.StartsWith("V2-", StringComparison.Ordinal)) + { + value = value["V2-".Length..]; + type = HwidType.Modern; + } + + var array = new byte[GetBase64ByteLength(value)]; + if (!Convert.TryFromBase64String(value, array, out _)) + { + hwid = null; + return false; + } + + hwid = new ImmutableTypedHwid([..array], type); + return true; + } + + private static int GetBase64ByteLength(string value) + { + // Why is .NET like this man wtf. + return 3 * (value.Length / 4) - value.TakeLast(2).Count(c => c == '='); + } +} + +/// +/// Represents different types of HWIDs as exposed by the engine. +/// +public enum HwidType +{ + /// + /// The legacy HWID system. Should only be used for checking old existing database bans. + /// + Legacy = 0, + + /// + /// The modern HWID system. + /// + Modern = 1, +} diff --git a/Content.Shared/Administration/BanPanelEuiState.cs b/Content.Shared/Administration/BanPanelEuiState.cs index dd10068e5d..74c340566b 100644 --- a/Content.Shared/Administration/BanPanelEuiState.cs +++ b/Content.Shared/Administration/BanPanelEuiState.cs @@ -25,7 +25,7 @@ public static class BanPanelEuiStateMsg { public string? Player { get; set; } public string? IpAddress { get; set; } - public byte[]? Hwid { get; set; } + public ImmutableTypedHwid? Hwid { get; set; } public uint Minutes { get; set; } public string Reason { get; set; } public NoteSeverity Severity { get; set; } @@ -34,7 +34,7 @@ public static class BanPanelEuiStateMsg public bool UseLastHwid { get; set; } public bool Erase { get; set; } - public CreateBanRequest(string? player, (IPAddress, int)? ipAddress, bool useLastIp, byte[]? hwid, bool useLastHwid, uint minutes, string reason, NoteSeverity severity, string[]? roles, bool erase) + public CreateBanRequest(string? player, (IPAddress, int)? ipAddress, bool useLastIp, ImmutableTypedHwid? hwid, bool useLastHwid, uint minutes, string reason, NoteSeverity severity, string[]? roles, bool erase) { Player = player; IpAddress = ipAddress == null ? null : $"{ipAddress.Value.Item1}/{ipAddress.Value.Item2}"; From 693e5f1fad8e375aff317bb246382865d71fa9d4 Mon Sep 17 00:00:00 2001 From: MissKay1994 <15877268+MissKay1994@users.noreply.github.com> Date: Wed, 20 Nov 2024 03:40:54 -0500 Subject: [PATCH 03/59] Update salvage.yml --- .../Catalog/VendingMachines/Inventories/salvage.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Resources/Prototypes/Catalog/VendingMachines/Inventories/salvage.yml b/Resources/Prototypes/Catalog/VendingMachines/Inventories/salvage.yml index 9e5549e249..48994a7162 100644 --- a/Resources/Prototypes/Catalog/VendingMachines/Inventories/salvage.yml +++ b/Resources/Prototypes/Catalog/VendingMachines/Inventories/salvage.yml @@ -3,10 +3,10 @@ startingInventory: Crowbar: 2 Pickaxe: 4 - OreBag: 2 + OreBag: 4 Flare: 4 FlashlightLantern: 2 - HandheldGPSBasic: 2 - RadioHandheld: 2 - WeaponGrapplingGun: 2 + HandheldGPSBasic: 4 + RadioHandheld: 4 + WeaponGrapplingGun: 4 WeaponProtoKineticAccelerator: 4 From f23b6522b2b25d029a189041624096c72efbb6a5 Mon Sep 17 00:00:00 2001 From: MissKay1994 <15877268+MissKay1994@users.noreply.github.com> Date: Wed, 20 Nov 2024 04:44:33 -0500 Subject: [PATCH 04/59] Update cargo_vending.yml --- Resources/Prototypes/Catalog/Cargo/cargo_vending.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Resources/Prototypes/Catalog/Cargo/cargo_vending.yml b/Resources/Prototypes/Catalog/Cargo/cargo_vending.yml index 86da8fb940..b8dd035e4f 100644 --- a/Resources/Prototypes/Catalog/Cargo/cargo_vending.yml +++ b/Resources/Prototypes/Catalog/Cargo/cargo_vending.yml @@ -154,7 +154,7 @@ sprite: Objects/Specific/Service/vending_machine_restock.rsi state: base product: CrateVendingMachineRestockSalvageEquipmentFilled - cost: 1000 + cost: 1500 category: cargoproduct-category-name-engineering group: market From e96e80bc955af1c709b5dfac298761bc26243d45 Mon Sep 17 00:00:00 2001 From: MissKay1994 <15877268+MissKay1994@users.noreply.github.com> Date: Wed, 20 Nov 2024 18:05:01 -0500 Subject: [PATCH 05/59] Update salvage.yml --- .../Catalog/VendingMachines/Inventories/salvage.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Resources/Prototypes/Catalog/VendingMachines/Inventories/salvage.yml b/Resources/Prototypes/Catalog/VendingMachines/Inventories/salvage.yml index 48994a7162..8a9e4bb342 100644 --- a/Resources/Prototypes/Catalog/VendingMachines/Inventories/salvage.yml +++ b/Resources/Prototypes/Catalog/VendingMachines/Inventories/salvage.yml @@ -2,11 +2,11 @@ id: SalvageEquipmentInventory startingInventory: Crowbar: 2 - Pickaxe: 4 + Pickaxe: 2 OreBag: 4 Flare: 4 FlashlightLantern: 2 - HandheldGPSBasic: 4 - RadioHandheld: 4 + HandheldGPSBasic: 2 + RadioHandheld: 2 WeaponGrapplingGun: 4 WeaponProtoKineticAccelerator: 4 From c02a027cf14f9f2c0c603a7a8035e1cd6868dddd Mon Sep 17 00:00:00 2001 From: MissKay1994 <15877268+MissKay1994@users.noreply.github.com> Date: Wed, 20 Nov 2024 18:06:19 -0500 Subject: [PATCH 06/59] Update salvage.yml --- .../Prototypes/Catalog/VendingMachines/Inventories/salvage.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Resources/Prototypes/Catalog/VendingMachines/Inventories/salvage.yml b/Resources/Prototypes/Catalog/VendingMachines/Inventories/salvage.yml index 8a9e4bb342..7761453327 100644 --- a/Resources/Prototypes/Catalog/VendingMachines/Inventories/salvage.yml +++ b/Resources/Prototypes/Catalog/VendingMachines/Inventories/salvage.yml @@ -2,7 +2,7 @@ id: SalvageEquipmentInventory startingInventory: Crowbar: 2 - Pickaxe: 2 + Pickaxe: 4 OreBag: 4 Flare: 4 FlashlightLantern: 2 From 3758715bdc8cd0209d3de3714b69897182546a20 Mon Sep 17 00:00:00 2001 From: slarticodefast <161409025+slarticodefast@users.noreply.github.com> Date: Fri, 22 Nov 2024 00:43:02 +0100 Subject: [PATCH 07/59] electrification hud --- .../ElectrocutionOverlaySystem.cs | 101 ++++++++++++++++++ .../Electrocution/ElectrocutionSystem.cs | 15 +-- Content.Server/Power/PowerWireAction.cs | 10 +- .../ElectrocutionOverlayComponent.cs | 9 ++ .../Electrocution/SharedElectrocution.cs | 6 +- .../SharedElectrocutionSystem.cs | 15 +++ .../Entities/Mobs/Player/observer.yml | 1 + .../Entities/Mobs/Player/silicon.yml | 1 + .../Doors/Airlocks/base_structureairlocks.yml | 5 + .../Entities/Structures/Walls/fence_metal.yml | 14 +-- .../Entities/Structures/Walls/grille.yml | 10 +- .../Interface/Misc/ai_hud.rsi/apc_hacked.png | Bin 0 -> 561 bytes .../Interface/Misc/ai_hud.rsi/electrified.png | Bin 0 -> 812 bytes .../Interface/Misc/ai_hud.rsi/meta.json | 37 +++++++ 14 files changed, 192 insertions(+), 32 deletions(-) create mode 100644 Content.Client/Electrocution/ElectrocutionOverlaySystem.cs create mode 100644 Content.Shared/Electrocution/Components/ElectrocutionOverlayComponent.cs create mode 100644 Resources/Textures/Interface/Misc/ai_hud.rsi/apc_hacked.png create mode 100644 Resources/Textures/Interface/Misc/ai_hud.rsi/electrified.png create mode 100644 Resources/Textures/Interface/Misc/ai_hud.rsi/meta.json diff --git a/Content.Client/Electrocution/ElectrocutionOverlaySystem.cs b/Content.Client/Electrocution/ElectrocutionOverlaySystem.cs new file mode 100644 index 0000000000..2751c498de --- /dev/null +++ b/Content.Client/Electrocution/ElectrocutionOverlaySystem.cs @@ -0,0 +1,101 @@ +using Content.Shared.Electrocution; +using Robust.Client.GameObjects; +using Robust.Client.Player; +using Robust.Shared.Player; + +namespace Content.Client.Electrocution; + +/// +/// Shows the ElectrocutionOverlay to entities with the ElectrocutionOverlayComponent. +/// +public sealed class ElectrocutionOverlaySystem : EntitySystem +{ + + [Dependency] private readonly AppearanceSystem _appearance = default!; + [Dependency] private readonly IPlayerManager _playerMan = default!; + + /// + public override void Initialize() + { + SubscribeLocalEvent(OnInit); + SubscribeLocalEvent(OnShutdown); + SubscribeLocalEvent(OnPlayerAttached); + SubscribeLocalEvent(OnPlayerDetached); + + SubscribeLocalEvent(OnAppearanceChange); + } + + private void OnPlayerAttached(Entity ent, ref LocalPlayerAttachedEvent args) + { + ShowOverlay(); + } + + private void OnPlayerDetached(Entity ent, ref LocalPlayerDetachedEvent args) + { + RemoveOverlay(); + } + + private void OnInit(Entity ent, ref ComponentInit args) + { + if (_playerMan.LocalEntity == ent) + { + ShowOverlay(); + } + } + + private void OnShutdown(Entity ent, ref ComponentShutdown args) + { + if (_playerMan.LocalEntity == ent) + { + RemoveOverlay(); + } + } + + private void ShowOverlay() + { + var electrifiedQuery = AllEntityQuery(); + while (electrifiedQuery.MoveNext(out var uid, out var _, out var appearanceComp, out var spriteComp)) + { + if (!_appearance.TryGetData(uid, ElectrifiedVisuals.IsElectrified, out var electrified, appearanceComp)) + continue; + + if (!spriteComp.LayerMapTryGet(ElectrifiedLayers.Overlay, out var layer)) + continue; + + if (electrified) + spriteComp.LayerSetVisible(ElectrifiedLayers.Overlay, true); + else + spriteComp.LayerSetVisible(ElectrifiedLayers.Overlay, false); + } + } + + private void RemoveOverlay() + { + var electrifiedQuery = AllEntityQuery(); + while (electrifiedQuery.MoveNext(out var uid, out var _, out var appearanceComp, out var spriteComp)) + { + if (!spriteComp.LayerMapTryGet(ElectrifiedLayers.Overlay, out var layer)) + continue; + + spriteComp.LayerSetVisible(layer, false); + } + } + + private void OnAppearanceChange(Entity ent, ref AppearanceChangeEvent args) + { + if (args.Sprite == null) + return; + + if (!_appearance.TryGetData(ent.Owner, ElectrifiedVisuals.IsElectrified, out var electrified, args.Component)) + return; + + if (!args.Sprite.LayerMapTryGet(ElectrifiedLayers.Overlay, out var layer)) + return; + + var player = _playerMan.LocalEntity; + if (electrified && HasComp(player)) + args.Sprite.LayerSetVisible(layer, true); + else + args.Sprite.LayerSetVisible(layer, false); + } +} diff --git a/Content.Server/Electrocution/ElectrocutionSystem.cs b/Content.Server/Electrocution/ElectrocutionSystem.cs index 88404c4aa9..eb10f8d280 100644 --- a/Content.Server/Electrocution/ElectrocutionSystem.cs +++ b/Content.Server/Electrocution/ElectrocutionSystem.cs @@ -121,7 +121,7 @@ public sealed class ElectrocutionSystem : SharedElectrocutionSystem activated.TimeLeft -= frameTime; if (activated.TimeLeft <= 0 || !IsPowered(uid, electrified, transform)) { - _appearance.SetData(uid, ElectrifiedVisuals.IsPowered, false); + _appearance.SetData(uid, ElectrifiedVisuals.ShowSparks, false); RemComp(uid); } } @@ -217,7 +217,7 @@ public sealed class ElectrocutionSystem : SharedElectrocutionSystem return false; EnsureComp(uid); - _appearance.SetData(uid, ElectrifiedVisuals.IsPowered, true); + _appearance.SetData(uid, ElectrifiedVisuals.ShowSparks, true); siemens *= electrified.SiemensCoefficient; if (!DoCommonElectrocutionAttempt(targetUid, uid, ref siemens) || siemens <= 0) @@ -488,15 +488,4 @@ public sealed class ElectrocutionSystem : SharedElectrocutionSystem } _audio.PlayPvs(electrified.ShockNoises, targetUid, AudioParams.Default.WithVolume(electrified.ShockVolume)); } - - public void SetElectrifiedWireCut(Entity ent, bool value) - { - if (ent.Comp.IsWireCut == value) - { - return; - } - - ent.Comp.IsWireCut = value; - Dirty(ent); - } } diff --git a/Content.Server/Power/PowerWireAction.cs b/Content.Server/Power/PowerWireAction.cs index cebb7de8ec..9e4e6a6086 100644 --- a/Content.Server/Power/PowerWireAction.cs +++ b/Content.Server/Power/PowerWireAction.cs @@ -17,7 +17,7 @@ public sealed partial class PowerWireAction : BaseWireAction [DataField("pulseTimeout")] private int _pulseTimeout = 30; - private ElectrocutionSystem _electrocutionSystem = default!; + private ElectrocutionSystem _electrocution = default!; public override object StatusKey { get; } = PowerWireActionKey.Status; @@ -105,8 +105,8 @@ public sealed partial class PowerWireAction : BaseWireAction && !EntityManager.TryGetComponent(used, out electrified)) return; - _electrocutionSystem.SetElectrifiedWireCut((used, electrified), setting); - electrified.Enabled = setting; + _electrocution.SetElectrifiedWireCut((used, electrified), setting); + _electrocution.SetElectrified((used, electrified), setting); } /// false if failed, true otherwise, or if the entity cannot be electrified @@ -120,7 +120,7 @@ public sealed partial class PowerWireAction : BaseWireAction // always set this to true SetElectrified(wire.Owner, true, electrified); - var electrifiedAttempt = _electrocutionSystem.TryDoElectrifiedAct(wire.Owner, user); + var electrifiedAttempt = _electrocution.TryDoElectrifiedAct(wire.Owner, user); // if we were electrified, then return false return !electrifiedAttempt; @@ -161,7 +161,7 @@ public sealed partial class PowerWireAction : BaseWireAction { base.Initialize(); - _electrocutionSystem = EntityManager.System(); + _electrocution = EntityManager.System(); } // This should add a wire into the entity's state, whether it be diff --git a/Content.Shared/Electrocution/Components/ElectrocutionOverlayComponent.cs b/Content.Shared/Electrocution/Components/ElectrocutionOverlayComponent.cs new file mode 100644 index 0000000000..e03e8cb934 --- /dev/null +++ b/Content.Shared/Electrocution/Components/ElectrocutionOverlayComponent.cs @@ -0,0 +1,9 @@ +using Robust.Shared.GameStates; + +namespace Content.Shared.Electrocution; + +/// +/// Allow an entity to see the ElectrocutionOverlay showing electrocuted doors. +/// +[RegisterComponent, NetworkedComponent] +public sealed partial class ElectrocutionOverlayComponent : Component; diff --git a/Content.Shared/Electrocution/SharedElectrocution.cs b/Content.Shared/Electrocution/SharedElectrocution.cs index 4060856d4d..b00fb1afdb 100644 --- a/Content.Shared/Electrocution/SharedElectrocution.cs +++ b/Content.Shared/Electrocution/SharedElectrocution.cs @@ -5,11 +5,13 @@ namespace Content.Shared.Electrocution; [Serializable, NetSerializable] public enum ElectrifiedLayers : byte { - Powered + Sparks, + Overlay, } [Serializable, NetSerializable] public enum ElectrifiedVisuals : byte { - IsPowered + ShowSparks, // only shown when zapping someone, deactivated after a short time + IsElectrified, // if the entity is electrified or not, used for the AI HUD } diff --git a/Content.Shared/Electrocution/SharedElectrocutionSystem.cs b/Content.Shared/Electrocution/SharedElectrocutionSystem.cs index e36e4a804b..5da344e023 100644 --- a/Content.Shared/Electrocution/SharedElectrocutionSystem.cs +++ b/Content.Shared/Electrocution/SharedElectrocutionSystem.cs @@ -5,6 +5,8 @@ namespace Content.Shared.Electrocution { public abstract class SharedElectrocutionSystem : EntitySystem { + [Dependency] private readonly SharedAppearanceSystem _appearance = default!; + public override void Initialize() { base.Initialize(); @@ -35,6 +37,19 @@ namespace Content.Shared.Electrocution ent.Comp.Enabled = value; Dirty(ent, ent.Comp); + + _appearance.SetData(ent.Owner, ElectrifiedVisuals.IsElectrified, value); + } + + public void SetElectrifiedWireCut(Entity ent, bool value) + { + if (ent.Comp.IsWireCut == value) + { + return; + } + + ent.Comp.IsWireCut = value; + Dirty(ent); } /// Entity being electrocuted. diff --git a/Resources/Prototypes/Entities/Mobs/Player/observer.yml b/Resources/Prototypes/Entities/Mobs/Player/observer.yml index d7c5dfe97b..dc89e635bf 100644 --- a/Resources/Prototypes/Entities/Mobs/Player/observer.yml +++ b/Resources/Prototypes/Entities/Mobs/Player/observer.yml @@ -55,6 +55,7 @@ skipChecks: true - type: Ghost - type: GhostHearing + - type: ElectrocutionOverlay - type: IntrinsicRadioReceiver - type: ActiveRadio receiveAllChannels: true diff --git a/Resources/Prototypes/Entities/Mobs/Player/silicon.yml b/Resources/Prototypes/Entities/Mobs/Player/silicon.yml index bcac46ed84..3b2b65e679 100644 --- a/Resources/Prototypes/Entities/Mobs/Player/silicon.yml +++ b/Resources/Prototypes/Entities/Mobs/Player/silicon.yml @@ -30,6 +30,7 @@ - type: IgnoreUIRange - type: StationAiHeld - type: StationAiOverlay + - type: ElectrocutionOverlay - type: ActionGrant actions: - ActionJumpToCore diff --git a/Resources/Prototypes/Entities/Structures/Doors/Airlocks/base_structureairlocks.yml b/Resources/Prototypes/Entities/Structures/Doors/Airlocks/base_structureairlocks.yml index fe725b0684..27f4973d05 100644 --- a/Resources/Prototypes/Entities/Structures/Doors/Airlocks/base_structureairlocks.yml +++ b/Resources/Prototypes/Entities/Structures/Doors/Airlocks/base_structureairlocks.yml @@ -30,6 +30,11 @@ shader: unshaded - state: panel_open map: ["enum.WiresVisualLayers.MaintenancePanel"] + - state: electrified + sprite: Interface/Misc/ai_hud.rsi + shader: unshaded + visible: false + map: ["enum.ElectrifiedLayers.Overlay"] - type: AnimationPlayer - type: Physics - type: Fixtures diff --git a/Resources/Prototypes/Entities/Structures/Walls/fence_metal.yml b/Resources/Prototypes/Entities/Structures/Walls/fence_metal.yml index 2d0c55af5a..b5fa7d9190 100644 --- a/Resources/Prototypes/Entities/Structures/Walls/fence_metal.yml +++ b/Resources/Prototypes/Entities/Structures/Walls/fence_metal.yml @@ -70,8 +70,8 @@ - type: Appearance - type: GenericVisualizer visuals: - enum.ElectrifiedVisuals.IsPowered: - enum.ElectrifiedLayers.Powered: + enum.ElectrifiedVisuals.ShowSparks: + enum.ElectrifiedLayers.Sparks: True: { visible: True } False: { visible: False } - type: AnimationPlayer @@ -91,7 +91,7 @@ - state: straight_broken - state: electrified sprite: Effects/electricity.rsi - map: ["enum.ElectrifiedLayers.Powered"] + map: ["enum.ElectrifiedLayers.Sparks"] shader: unshaded visible: false - type: Physics @@ -151,7 +151,7 @@ - state: straight - state: electrified sprite: Effects/electricity.rsi - map: ["enum.ElectrifiedLayers.Powered"] + map: ["enum.ElectrifiedLayers.Sparks"] shader: unshaded visible: false - type: Fixtures @@ -209,7 +209,7 @@ - state: corner - state: electrified sprite: Effects/electricity.rsi - map: ["enum.ElectrifiedLayers.Powered"] + map: ["enum.ElectrifiedLayers.Sparks"] shader: unshaded visible: false - type: Fixtures @@ -256,7 +256,7 @@ - state: end - state: electrified sprite: Effects/electricity.rsi - map: ["enum.ElectrifiedLayers.Powered"] + map: ["enum.ElectrifiedLayers.Sparks"] shader: unshaded visible: false - type: Fixtures @@ -292,7 +292,7 @@ map: ["enum.DoorVisualLayers.Base"] - state: electrified sprite: Effects/electricity.rsi - map: [ "enum.ElectrifiedLayers.Powered" ] + map: [ "enum.ElectrifiedLayers.Sparks" ] shader: unshaded visible: false - type: Fixtures diff --git a/Resources/Prototypes/Entities/Structures/Walls/grille.yml b/Resources/Prototypes/Entities/Structures/Walls/grille.yml index 2b65528d22..3433ffc366 100644 --- a/Resources/Prototypes/Entities/Structures/Walls/grille.yml +++ b/Resources/Prototypes/Entities/Structures/Walls/grille.yml @@ -21,7 +21,7 @@ - state: grille - state: electrified sprite: Effects/electricity.rsi - map: ["enum.ElectrifiedLayers.Powered"] + map: ["enum.ElectrifiedLayers.Sparks"] shader: unshaded visible: false - type: Icon @@ -82,8 +82,8 @@ - type: Appearance - type: GenericVisualizer visuals: - enum.ElectrifiedVisuals.IsPowered: - enum.ElectrifiedLayers.Powered: + enum.ElectrifiedVisuals.ShowSparks: + enum.ElectrifiedLayers.Sparks: True: { visible: True } False: { visible: False } - type: AnimationPlayer @@ -176,7 +176,7 @@ - state: grille_diagonal - state: electrified_diagonal sprite: Effects/electricity.rsi - map: ["enum.ElectrifiedLayers.Powered"] + map: ["enum.ElectrifiedLayers.Sparks"] shader: unshaded visible: false - type: Icon @@ -211,7 +211,7 @@ - state: ratvargrille_diagonal - state: electrified_diagonal sprite: Effects/electricity.rsi - map: ["enum.ElectrifiedLayers.Powered"] + map: ["enum.ElectrifiedLayers.Sparks"] shader: unshaded visible: false - type: Icon diff --git a/Resources/Textures/Interface/Misc/ai_hud.rsi/apc_hacked.png b/Resources/Textures/Interface/Misc/ai_hud.rsi/apc_hacked.png new file mode 100644 index 0000000000000000000000000000000000000000..72e111edac559c01afecad417d4e79eb6e953d80 GIT binary patch literal 561 zcmeAS@N?(olHy`uVBq!ia0vp^4nUm1!3HGP9xZtRq&N#aB8wRq_>O=u<5X=vX$A(y z$DS^ZAr*7p&JN5wY{27eso;L|Vc8Pdyz-k9_!vX3d!?vuEcTB)o5Vj03`d{1&yJo6>KO1N;cl0e$; z*HR2coD3&a85E{7G{i6=I9v4Bd_O(2`qTUK|9`((FaLk<#1@ZZ_K)8F)W3IxrzMy1 zbF|yGZA9*$1*K-tnKPdlko%Z@wqB{(z|Z{qCF1AIknRme1MKd)MiL zDacO~ycrzy7#ScQgm5zAPh5Mh{QV=)T_#~_ZW@Z4vP2FA=GJvf_D*jsxT0b>MJU?z zmiz@{`^)kP;xdgFUkiTlyXAGA!5V1c4l8*Hpydef-f(oS-FGYA`hc~;YPtpXGnkjxjOZghtrdu`eiQrDums|E=r~Q|Lgfb@B6&{ zzeOchp0ECYU;Zrfys!DsSK2EqP-hVR`ZKHkEyILvxdZY=GS8}w)^a8T(*T2~tDnm{ Hr-UW|fzIqt literal 0 HcmV?d00001 diff --git a/Resources/Textures/Interface/Misc/ai_hud.rsi/electrified.png b/Resources/Textures/Interface/Misc/ai_hud.rsi/electrified.png new file mode 100644 index 0000000000000000000000000000000000000000..046a307d09f964825068522b4fe5790b0eb5eb7c GIT binary patch literal 812 zcmV+{1JnG8P)t3m`bd7309&o=J$TLpk^JmiVDGT3 z$u5dNjX9AR(SBcRsd4w8{Ar9)NatF0uVFbV4ej~r@#i&EPx(7L46A# zmwgY_FogEp?+7;mxUHjveD4i!eSdrNABm;j3uu(@ml4*?NnbxMLbhK2M*!~<>(Ai~ zG@kq;cYl75wHu^M)`!|2PbL4V0JUu4aAyJ-f52WaDHR|^_0mK&4QepMx58BZfYe!F zmTqtge?V$0OqgK`Y=H9zcm_{^^#^zaPk{0VXrKEXAJJ#t%Jc_}=j;u1Yd1)jx zH<)Ju)G4sRGz*{yPf*_i$YtL{H4LFW_d9~vAD|&0x4xPFfUS+QdM_X$ABnU50llCl q{s8X(???0B^Czs`AYIPv5BLEgD;PVJ8F0k_0000>qx literal 0 HcmV?d00001 diff --git a/Resources/Textures/Interface/Misc/ai_hud.rsi/meta.json b/Resources/Textures/Interface/Misc/ai_hud.rsi/meta.json new file mode 100644 index 0000000000..7f1e67ac4d --- /dev/null +++ b/Resources/Textures/Interface/Misc/ai_hud.rsi/meta.json @@ -0,0 +1,37 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "taken from tgstation at commit https://github.com/tgstation/tgstation/commit/d170a410d40eec4fc19fe5eb8d561d58a0902082", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "electrified", + "delays": [ + [ + 0.2, + 0.2, + 0.2, + 0.2, + 0.2, + 0.2 + ] + ] + }, + { + "name": "apc_hacked", + "delays": [ + [ + 0.2, + 0.2, + 0.2, + 0.2, + 0.2, + 0.2 + ] + ] + } + ] +} \ No newline at end of file From 403528cbf344531fedd3b5038f6463ba12eea41a Mon Sep 17 00:00:00 2001 From: chromiumboy <50505512+chromiumboy@users.noreply.github.com> Date: Thu, 21 Nov 2024 21:46:10 -0600 Subject: [PATCH 08/59] Gas pipe sensors (#33128) * Initial commit * Monitored pipe node is now referenced by name * Review changes * Simplified construction * Tweaked deconstruction to match other binary atmos devices * Helper function removal * Updated attribution --- .../Components/AtmosMonitorComponent.cs | 19 +++- .../Monitor/Systems/AtmosMonitoringSystem.cs | 17 +++- .../Locale/en-US/atmos/gas-pipe-sensor.ftl | 5 ++ .../Piping/Atmospherics/gas_pipe_sensor.yml | 84 ++++++++++++++++++ .../Graphs/utilities/gas_pipe_sensor.yml | 29 ++++++ .../Recipes/Construction/utilities.yml | 15 ++++ .../Atmospherics/gas_pipe_sensor.rsi/base.png | Bin 0 -> 248 bytes .../gas_pipe_sensor.rsi/blank.png | Bin 0 -> 83 bytes .../Atmospherics/gas_pipe_sensor.rsi/icon.png | Bin 0 -> 523 bytes .../gas_pipe_sensor.rsi/lights.png | Bin 0 -> 183 bytes .../gas_pipe_sensor.rsi/meta.json | 29 ++++++ 11 files changed, 196 insertions(+), 2 deletions(-) create mode 100644 Resources/Locale/en-US/atmos/gas-pipe-sensor.ftl create mode 100644 Resources/Prototypes/Entities/Structures/Piping/Atmospherics/gas_pipe_sensor.yml create mode 100644 Resources/Prototypes/Recipes/Construction/Graphs/utilities/gas_pipe_sensor.yml create mode 100644 Resources/Textures/Structures/Piping/Atmospherics/gas_pipe_sensor.rsi/base.png create mode 100644 Resources/Textures/Structures/Piping/Atmospherics/gas_pipe_sensor.rsi/blank.png create mode 100644 Resources/Textures/Structures/Piping/Atmospherics/gas_pipe_sensor.rsi/icon.png create mode 100644 Resources/Textures/Structures/Piping/Atmospherics/gas_pipe_sensor.rsi/lights.png create mode 100644 Resources/Textures/Structures/Piping/Atmospherics/gas_pipe_sensor.rsi/meta.json diff --git a/Content.Server/Atmos/Monitor/Components/AtmosMonitorComponent.cs b/Content.Server/Atmos/Monitor/Components/AtmosMonitorComponent.cs index cb6d4d1630..830479561d 100644 --- a/Content.Server/Atmos/Monitor/Components/AtmosMonitorComponent.cs +++ b/Content.Server/Atmos/Monitor/Components/AtmosMonitorComponent.cs @@ -48,7 +48,9 @@ public sealed partial class AtmosMonitorComponent : Component [DataField("gasThresholds")] public Dictionary? GasThresholds; - // Stores a reference to the gas on the tile this is on. + /// + /// Stores a reference to the gas on the tile this entity is on (or the pipe network it monitors; see ). + /// [ViewVariables] public GasMixture? TileGas; @@ -65,4 +67,19 @@ public sealed partial class AtmosMonitorComponent : Component /// [DataField("registeredDevices")] public HashSet RegisteredDevices = new(); + + /// + /// Specifies whether this device monitors its own internal pipe network rather than the surrounding atmosphere. + /// + /// + /// If 'true', the entity will require a NodeContainerComponent with one or more PipeNodes to function. + /// + [DataField] + public bool MonitorsPipeNet = false; + + /// + /// Specifies the name of the pipe node that this device is monitoring. + /// + [DataField] + public string NodeNameMonitoredPipe = "monitored"; } diff --git a/Content.Server/Atmos/Monitor/Systems/AtmosMonitoringSystem.cs b/Content.Server/Atmos/Monitor/Systems/AtmosMonitoringSystem.cs index fbe74cbab7..17a24b1b0c 100644 --- a/Content.Server/Atmos/Monitor/Systems/AtmosMonitoringSystem.cs +++ b/Content.Server/Atmos/Monitor/Systems/AtmosMonitoringSystem.cs @@ -4,6 +4,9 @@ using Content.Server.Atmos.Piping.Components; using Content.Server.Atmos.Piping.EntitySystems; using Content.Server.DeviceNetwork; using Content.Server.DeviceNetwork.Systems; +using Content.Server.NodeContainer; +using Content.Server.NodeContainer.EntitySystems; +using Content.Server.NodeContainer.Nodes; using Content.Server.Power.Components; using Content.Server.Power.EntitySystems; using Content.Shared.Atmos; @@ -25,6 +28,7 @@ public sealed class AtmosMonitorSystem : EntitySystem [Dependency] private readonly AtmosDeviceSystem _atmosDeviceSystem = default!; [Dependency] private readonly DeviceNetworkSystem _deviceNetSystem = default!; [Dependency] private readonly IPrototypeManager _prototypeManager = default!; + [Dependency] private readonly NodeContainerSystem _nodeContainerSystem = default!; // Commands public const string AtmosMonitorSetThresholdCmd = "atmos_monitor_set_threshold"; @@ -56,8 +60,15 @@ public sealed class AtmosMonitorSystem : EntitySystem private void OnAtmosDeviceEnterAtmosphere(EntityUid uid, AtmosMonitorComponent atmosMonitor, ref AtmosDeviceEnabledEvent args) { + if (atmosMonitor.MonitorsPipeNet && _nodeContainerSystem.TryGetNode(uid, atmosMonitor.NodeNameMonitoredPipe, out var pipeNode)) + { + atmosMonitor.TileGas = pipeNode.Air; + return; + } + atmosMonitor.TileGas = _atmosphereSystem.GetContainingMixture(uid, true); } + private void OnMapInit(EntityUid uid, AtmosMonitorComponent component, MapInitEvent args) { if (component.TemperatureThresholdId != null) @@ -206,7 +217,7 @@ public sealed class AtmosMonitorSystem : EntitySystem if (!this.IsPowered(uid, EntityManager)) return; - if (args.Grid == null) + if (args.Grid == null) return; // if we're not monitoring atmos, don't bother @@ -215,6 +226,10 @@ public sealed class AtmosMonitorSystem : EntitySystem && component.GasThresholds == null) return; + // If monitoring a pipe network, get its most recent gas mixture + if (component.MonitorsPipeNet && _nodeContainerSystem.TryGetNode(uid, component.NodeNameMonitoredPipe, out var pipeNode)) + component.TileGas = pipeNode.Air; + UpdateState(uid, component.TileGas, component); } diff --git a/Resources/Locale/en-US/atmos/gas-pipe-sensor.ftl b/Resources/Locale/en-US/atmos/gas-pipe-sensor.ftl new file mode 100644 index 0000000000..8c3b8962e3 --- /dev/null +++ b/Resources/Locale/en-US/atmos/gas-pipe-sensor.ftl @@ -0,0 +1,5 @@ +gas-pipe-sensor-distribution-loop = Distribution loop +gas-pipe-sensor-waste-loop = Waste loop +gas-pipe-sensor-mixed-air = Mixed air +gas-pipe-sensor-teg-hot-loop = TEG hot loop +gas-pipe-sensor-teg-cold-loop = TEG cold loop diff --git a/Resources/Prototypes/Entities/Structures/Piping/Atmospherics/gas_pipe_sensor.yml b/Resources/Prototypes/Entities/Structures/Piping/Atmospherics/gas_pipe_sensor.yml new file mode 100644 index 0000000000..08015abe7d --- /dev/null +++ b/Resources/Prototypes/Entities/Structures/Piping/Atmospherics/gas_pipe_sensor.yml @@ -0,0 +1,84 @@ +- type: entity + parent: [AirSensorBase, GasPipeBase] + id: GasPipeSensor + name: gas pipe sensor + description: Reports on the status of the gas in the attached pipe network. + placement: + mode: SnapgridCenter + components: + - type: Sprite + sprite: Structures/Piping/Atmospherics/gas_pipe_sensor.rsi + drawdepth: BelowFloor + layers: + - sprite: Structures/Piping/Atmospherics/pipe.rsi + map: [ "enum.PipeVisualLayers.Pipe" ] + state: pipeStraight + - map: ["base"] + state: base + - map: [ "enum.PowerDeviceVisualLayers.Powered" ] + state: lights + shader: unshaded + - type: Appearance + - type: GenericVisualizer + visuals: + enum.PowerDeviceVisuals.Powered: + enum.PowerDeviceVisualLayers.Powered: + False: { state: blank } + True: { state: lights } + - type: AtmosMonitor + monitorsPipeNet: true + - type: ApcPowerReceiver + - type: ExtensionCableReceiver + - type: Construction + graph: GasPipeSensor + node: sensor + - type: NodeContainer + nodes: + monitored: + !type:PipeNode + nodeGroupID: Pipe + pipeDirection: Longitudinal + - type: Tag + tags: + - AirSensor + - Unstackable + +- type: entity + parent: GasPipeSensor + id: GasPipeSensorDistribution + suffix: Distribution + components: + - type: Label + currentLabel: gas-pipe-sensor-distribution-loop + +- type: entity + parent: GasPipeSensor + id: GasPipeSensorWaste + suffix: Waste + components: + - type: Label + currentLabel: gas-pipe-sensor-waste-loop + +- type: entity + parent: GasPipeSensor + id: GasPipeSensorMixedAir + suffix: Mixed air + components: + - type: Label + currentLabel: gas-pipe-sensor-mixed-air + +- type: entity + parent: GasPipeSensor + id: GasPipeSensorTEGHot + suffix: TEG hot + components: + - type: Label + currentLabel: gas-pipe-sensor-teg-hot-loop + +- type: entity + parent: GasPipeSensor + id: GasPipeSensorTEGCold + suffix: TEG cold + components: + - type: Label + currentLabel: gas-pipe-sensor-teg-cold-loop \ No newline at end of file diff --git a/Resources/Prototypes/Recipes/Construction/Graphs/utilities/gas_pipe_sensor.yml b/Resources/Prototypes/Recipes/Construction/Graphs/utilities/gas_pipe_sensor.yml new file mode 100644 index 0000000000..bda6d036e9 --- /dev/null +++ b/Resources/Prototypes/Recipes/Construction/Graphs/utilities/gas_pipe_sensor.yml @@ -0,0 +1,29 @@ +- type: constructionGraph + id: GasPipeSensor + start: start + graph: + - node: start + edges: + - to: sensor + steps: + - material: Steel + amount: 2 + doAfter: 1 + + - node: sensor + entity: GasPipeSensor + actions: + - !type:SetAnchor + edges: + - to: start + completed: + - !type:SpawnPrototype + prototype: SheetSteel1 + amount: 2 + - !type:DeleteEntity + conditions: + - !type:EntityAnchored + anchored: false + steps: + - tool: Welding + doAfter: 1 \ No newline at end of file diff --git a/Resources/Prototypes/Recipes/Construction/utilities.yml b/Resources/Prototypes/Recipes/Construction/utilities.yml index 5dc0168fd3..2dec0e4a7d 100644 --- a/Resources/Prototypes/Recipes/Construction/utilities.yml +++ b/Resources/Prototypes/Recipes/Construction/utilities.yml @@ -366,6 +366,21 @@ objectType: Structure canRotate: true +- type: construction + name: gas pipe sensor + id: GasPipeSensor + graph: GasPipeSensor + startNode: start + targetNode: sensor + category: construction-category-structures + description: Reports on the status of the gas within the attached pipe network. + icon: + sprite: Structures/Piping/Atmospherics/gas_pipe_sensor.rsi + state: icon + placementMode: SnapgridCenter + objectType: Structure + canRotate: true + # ATMOS PIPES - type: construction name: gas pipe half diff --git a/Resources/Textures/Structures/Piping/Atmospherics/gas_pipe_sensor.rsi/base.png b/Resources/Textures/Structures/Piping/Atmospherics/gas_pipe_sensor.rsi/base.png new file mode 100644 index 0000000000000000000000000000000000000000..4a9a8f6f2069490a67965a5fdf60019008341678 GIT binary patch literal 248 zcmVuMTL$ yH{Ahdj(Z-x$LRe>F*Ot^?|}CAhG7_n0RRt>*hN^}z=Wm%0000B?Wc})uc*XMaS cfSB*u1QZw;r+*K>4&*R+y85}Sb4q9e0KdKysQ>@~ literal 0 HcmV?d00001 diff --git a/Resources/Textures/Structures/Piping/Atmospherics/gas_pipe_sensor.rsi/icon.png b/Resources/Textures/Structures/Piping/Atmospherics/gas_pipe_sensor.rsi/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..4ac9e76480361a744196e09cbc3edcfaa05f737d GIT binary patch literal 523 zcmV+m0`&cfP)4QFfKyZoFJf(g^&|8Oe4&~^=#%085CT*bCFYwkP}FRIzbjfqyss? zpdlL<4S}TSs#$0PPK2?mwfilrdG-JGzrWvm;1E(u8%2=?h@!|!DJ_n%=bG5-^#E+U z-6l`?u8Bej`u#q6!vZQgw}nfl`X&pTC|7{h2V0V`LDZ zlqzNz$spiibPd46Kj-%^YJB=M{2Kjur9hr=BJh?1o4CKbd$$3d2t3Z`TLT^*9li1f zkO|zW4}@X3t@AXFnZ_|nDZ(&xD#3^Lfvm50Qs5~`yhf|V_tR5;4~LvxT+li=a01WO ziZ^4ql!c^TucNi5*=&}x4`{6sLSU^ehrmYm)oNAVMg+V$jte2M0nTecX9B+Ovs^Bz z)oSH>z!2ZKR*f5CV>W;7aki^U=rfxil~y+@Q(CfWc1 N002ovPDHLkV1lGg_D%o* literal 0 HcmV?d00001 diff --git a/Resources/Textures/Structures/Piping/Atmospherics/gas_pipe_sensor.rsi/lights.png b/Resources/Textures/Structures/Piping/Atmospherics/gas_pipe_sensor.rsi/lights.png new file mode 100644 index 0000000000000000000000000000000000000000..6108d2b99492134bbeeb0d5f7bfc64256627e5a9 GIT binary patch literal 183 zcmeAS@N?(olHy`uVBq!ia0vp^4nVBH!3HE3&8=$zQgxm#jv*QM-d^6w+n^xQ^6+xR zZ7W7;i<#UTnTvNc3g6hpAm-(ybA_$*L;YE9(VgWAj0~@?P7z9(SmoK=x6?D~tYLmB z>r}}@+Ozt(GlWeZ8tW>w%+r6KFP`wJcJ+mCKeqi<;XaYk>y-ao(j#%xIsa=vqu#UY d11$!EKR5Zp#g)Ie6~!okxSp Date: Fri, 22 Nov 2024 03:47:17 +0000 Subject: [PATCH 09/59] Automatic changelog update --- Resources/Changelog/Changelog.yml | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index 6bc25079ce..70963d8ba2 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,11 +1,4 @@ Entries: -- author: EmoGarbage404 - changes: - - message: Legends tell of horrifying Goliaths that roam the mining asteroid. - type: Add - id: 7137 - time: '2024-08-18T16:22:36.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/30839 - author: Beck Thompson changes: - message: Cutting food now moves the sliced pieces a small amount! @@ -3933,3 +3926,12 @@ id: 7636 time: '2024-11-22T02:56:05.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/31076 +- author: chromiumboy + changes: + - message: Added the gas pipe sensor. These sensors monitor the mixture of gases + passing through their pipe sub-network and report this information to any connected + air alarms + type: Add + id: 7637 + time: '2024-11-22T03:46:10.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/33128 From 646d41d3a7824168053349ce6159bac5acec2eb9 Mon Sep 17 00:00:00 2001 From: c4llv07e Date: Fri, 22 Nov 2024 15:38:41 +0000 Subject: [PATCH 10/59] Add telegram to the server info-links (#33459) --- Content.Client/Info/LinkBanner.cs | 1 + Content.Server/ServerInfo/ServerInfoManager.cs | 11 ++++++----- Content.Shared/CCVar/CCVars.Game.Infolinks.cs | 6 ++++++ Resources/Locale/en-US/info/server-info.ftl | 1 + Resources/Locale/en-US/server-info/info-links.ftl | 1 + 5 files changed, 15 insertions(+), 5 deletions(-) diff --git a/Content.Client/Info/LinkBanner.cs b/Content.Client/Info/LinkBanner.cs index a30aa41376..7366a8f856 100644 --- a/Content.Client/Info/LinkBanner.cs +++ b/Content.Client/Info/LinkBanner.cs @@ -34,6 +34,7 @@ namespace Content.Client.Info AddInfoButton("server-info-website-button", CCVars.InfoLinksWebsite); AddInfoButton("server-info-wiki-button", CCVars.InfoLinksWiki); AddInfoButton("server-info-forum-button", CCVars.InfoLinksForum); + AddInfoButton("server-info-telegram-button", CCVars.InfoLinksTelegram); var guidebookController = UserInterfaceManager.GetUIController(); var guidebookButton = new Button() { Text = Loc.GetString("server-info-guidebook-button") }; diff --git a/Content.Server/ServerInfo/ServerInfoManager.cs b/Content.Server/ServerInfo/ServerInfoManager.cs index d2e35e9663..673a33a941 100644 --- a/Content.Server/ServerInfo/ServerInfoManager.cs +++ b/Content.Server/ServerInfo/ServerInfoManager.cs @@ -13,11 +13,12 @@ public sealed class ServerInfoManager private static readonly (CVarDef cVar, string icon, string name)[] Vars = { // @formatter:off - (CCVars.InfoLinksDiscord, "discord", "info-link-discord"), - (CCVars.InfoLinksForum, "forum", "info-link-forum"), - (CCVars.InfoLinksGithub, "github", "info-link-github"), - (CCVars.InfoLinksWebsite, "web", "info-link-website"), - (CCVars.InfoLinksWiki, "wiki", "info-link-wiki") + (CCVars.InfoLinksDiscord, "discord", "info-link-discord"), + (CCVars.InfoLinksForum, "forum", "info-link-forum"), + (CCVars.InfoLinksGithub, "github", "info-link-github"), + (CCVars.InfoLinksWebsite, "web", "info-link-website"), + (CCVars.InfoLinksWiki, "wiki", "info-link-wiki"), + (CCVars.InfoLinksTelegram, "telegram", "info-link-telegram") // @formatter:on }; diff --git a/Content.Shared/CCVar/CCVars.Game.Infolinks.cs b/Content.Shared/CCVar/CCVars.Game.Infolinks.cs index fa8332b497..5544953a0d 100644 --- a/Content.Shared/CCVar/CCVars.Game.Infolinks.cs +++ b/Content.Shared/CCVar/CCVars.Game.Infolinks.cs @@ -51,4 +51,10 @@ public sealed partial class CCVars /// public static readonly CVarDef InfoLinksAppeal = CVarDef.Create("infolinks.appeal", "", CVar.SERVER | CVar.REPLICATED); + + /// + /// Link to Telegram channel to show in the launcher. + /// + public static readonly CVarDef InfoLinksTelegram = + CVarDef.Create("infolinks.telegram", "", CVar.SERVER | CVar.REPLICATED); } diff --git a/Resources/Locale/en-US/info/server-info.ftl b/Resources/Locale/en-US/info/server-info.ftl index 3039f4cb17..ff183d80ef 100644 --- a/Resources/Locale/en-US/info/server-info.ftl +++ b/Resources/Locale/en-US/info/server-info.ftl @@ -4,5 +4,6 @@ server-info-discord-button = Discord server-info-website-button = Website server-info-wiki-button = Wiki server-info-forum-button = Forum +server-info-telegram-button = Telegram server-info-report-button = Report Bugs server-info-credits-button = Credits diff --git a/Resources/Locale/en-US/server-info/info-links.ftl b/Resources/Locale/en-US/server-info/info-links.ftl index 0f8f9eb7d9..51b6b51ecb 100644 --- a/Resources/Locale/en-US/server-info/info-links.ftl +++ b/Resources/Locale/en-US/server-info/info-links.ftl @@ -5,3 +5,4 @@ info-link-forum = Forum info-link-github = GitHub info-link-website = Website info-link-wiki = Wiki +info-link-telegram = Telegram From b4ec946bd9f5af7bbc27dd676f294c0c5f4c6847 Mon Sep 17 00:00:00 2001 From: Pieter-Jan Briers Date: Fri, 22 Nov 2024 18:14:46 +0100 Subject: [PATCH 11/59] Fix sandbox error with new HWID code. (#33461) Oops --- Content.Shared.Database/TypedHwid.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Content.Shared.Database/TypedHwid.cs b/Content.Shared.Database/TypedHwid.cs index 6e4a7763b3..253375e9db 100644 --- a/Content.Shared.Database/TypedHwid.cs +++ b/Content.Shared.Database/TypedHwid.cs @@ -34,7 +34,9 @@ public sealed class ImmutableTypedHwid(ImmutableArray hwid, HwidType type) return false; } - hwid = new ImmutableTypedHwid([..array], type); + // ReSharper disable once UseCollectionExpression + // Do not use collection expression, C# compiler is weird and it fails sandbox. + hwid = new ImmutableTypedHwid(ImmutableArray.Create(array), type); return true; } From 08bfb43febe7bcf145e32e2e61146a5aedea454f Mon Sep 17 00:00:00 2001 From: slarticodefast <161409025+slarticodefast@users.noreply.github.com> Date: Fri, 22 Nov 2024 23:02:59 +0100 Subject: [PATCH 12/59] cleanup --- .../ElectrocutionOverlaySystem.cs | 72 +++++++++---------- .../ElectrocutionHUDVisualsComponent.cs | 7 ++ ...nt.cs => ShowElectrocutionHUDComponent.cs} | 4 +- .../Electrocution/SharedElectrocution.cs | 2 +- .../Entities/Mobs/Player/observer.yml | 2 +- .../Entities/Mobs/Player/silicon.yml | 2 +- .../Doors/Airlocks/base_structureairlocks.yml | 3 +- .../Structures/Doors/Airlocks/shuttle.yml | 18 ----- 8 files changed, 47 insertions(+), 63 deletions(-) create mode 100644 Content.Shared/Electrocution/Components/ElectrocutionHUDVisualsComponent.cs rename Content.Shared/Electrocution/Components/{ElectrocutionOverlayComponent.cs => ShowElectrocutionHUDComponent.cs} (51%) diff --git a/Content.Client/Electrocution/ElectrocutionOverlaySystem.cs b/Content.Client/Electrocution/ElectrocutionOverlaySystem.cs index 2751c498de..bcfc51acc1 100644 --- a/Content.Client/Electrocution/ElectrocutionOverlaySystem.cs +++ b/Content.Client/Electrocution/ElectrocutionOverlaySystem.cs @@ -6,96 +6,90 @@ using Robust.Shared.Player; namespace Content.Client.Electrocution; /// -/// Shows the ElectrocutionOverlay to entities with the ElectrocutionOverlayComponent. +/// Shows the Electrocution HUD to entities with the ShowElectrocutionHUDComponent. /// -public sealed class ElectrocutionOverlaySystem : EntitySystem +public sealed class ElectrifiedVisualizerSystem : VisualizerSystem { - - [Dependency] private readonly AppearanceSystem _appearance = default!; [Dependency] private readonly IPlayerManager _playerMan = default!; - /// public override void Initialize() { - SubscribeLocalEvent(OnInit); - SubscribeLocalEvent(OnShutdown); - SubscribeLocalEvent(OnPlayerAttached); - SubscribeLocalEvent(OnPlayerDetached); + base.Initialize(); - SubscribeLocalEvent(OnAppearanceChange); + SubscribeLocalEvent(OnInit); + SubscribeLocalEvent(OnShutdown); + SubscribeLocalEvent(OnPlayerAttached); + SubscribeLocalEvent(OnPlayerDetached); } - private void OnPlayerAttached(Entity ent, ref LocalPlayerAttachedEvent args) + private void OnPlayerAttached(Entity ent, ref LocalPlayerAttachedEvent args) { - ShowOverlay(); + ShowHUD(); } - private void OnPlayerDetached(Entity ent, ref LocalPlayerDetachedEvent args) + private void OnPlayerDetached(Entity ent, ref LocalPlayerDetachedEvent args) { - RemoveOverlay(); + RemoveHUD(); } - private void OnInit(Entity ent, ref ComponentInit args) + private void OnInit(Entity ent, ref ComponentInit args) { if (_playerMan.LocalEntity == ent) { - ShowOverlay(); + ShowHUD(); } } - private void OnShutdown(Entity ent, ref ComponentShutdown args) + private void OnShutdown(Entity ent, ref ComponentShutdown args) { if (_playerMan.LocalEntity == ent) { - RemoveOverlay(); + RemoveHUD(); } } - private void ShowOverlay() + // Show the HUD to the client. + // We have to look for all current entities that can be electrified and toggle the HUD layer on if they are. + private void ShowHUD() { - var electrifiedQuery = AllEntityQuery(); + var electrifiedQuery = AllEntityQuery(); while (electrifiedQuery.MoveNext(out var uid, out var _, out var appearanceComp, out var spriteComp)) { - if (!_appearance.TryGetData(uid, ElectrifiedVisuals.IsElectrified, out var electrified, appearanceComp)) - continue; - - if (!spriteComp.LayerMapTryGet(ElectrifiedLayers.Overlay, out var layer)) + if (!AppearanceSystem.TryGetData(uid, ElectrifiedVisuals.IsElectrified, out var electrified, appearanceComp)) continue; if (electrified) - spriteComp.LayerSetVisible(ElectrifiedLayers.Overlay, true); + spriteComp.LayerSetVisible(ElectrifiedLayers.HUD, true); else - spriteComp.LayerSetVisible(ElectrifiedLayers.Overlay, false); + spriteComp.LayerSetVisible(ElectrifiedLayers.HUD, false); } } - private void RemoveOverlay() + // Remove the HUD from the client. + // Find all current entities that can be electrified and hide the HUD layer. + private void RemoveHUD() { - var electrifiedQuery = AllEntityQuery(); + var electrifiedQuery = AllEntityQuery(); while (electrifiedQuery.MoveNext(out var uid, out var _, out var appearanceComp, out var spriteComp)) { - if (!spriteComp.LayerMapTryGet(ElectrifiedLayers.Overlay, out var layer)) - continue; - spriteComp.LayerSetVisible(layer, false); + spriteComp.LayerSetVisible(ElectrifiedLayers.HUD, false); } } - private void OnAppearanceChange(Entity ent, ref AppearanceChangeEvent args) + // Toggle the HUD layer if an entity becomes (de-)electrified + protected override void OnAppearanceChange(EntityUid uid, ElectrocutionHUDVisualsComponent comp, ref AppearanceChangeEvent args) { if (args.Sprite == null) return; - if (!_appearance.TryGetData(ent.Owner, ElectrifiedVisuals.IsElectrified, out var electrified, args.Component)) - return; - - if (!args.Sprite.LayerMapTryGet(ElectrifiedLayers.Overlay, out var layer)) + if (!AppearanceSystem.TryGetData(uid, ElectrifiedVisuals.IsElectrified, out var electrified, args.Component)) return; var player = _playerMan.LocalEntity; - if (electrified && HasComp(player)) - args.Sprite.LayerSetVisible(layer, true); + if (electrified && HasComp(player)) + args.Sprite.LayerSetVisible(ElectrifiedLayers.HUD, true); else - args.Sprite.LayerSetVisible(layer, false); + args.Sprite.LayerSetVisible(ElectrifiedLayers.HUD, false); } } diff --git a/Content.Shared/Electrocution/Components/ElectrocutionHUDVisualsComponent.cs b/Content.Shared/Electrocution/Components/ElectrocutionHUDVisualsComponent.cs new file mode 100644 index 0000000000..a48b1e3e5a --- /dev/null +++ b/Content.Shared/Electrocution/Components/ElectrocutionHUDVisualsComponent.cs @@ -0,0 +1,7 @@ +namespace Content.Shared.Electrocution; + +/// +/// Handles toggling sprite layers for the electrocution HUD to show if an entity with the ElectrifiedComponent is electrified. +/// +[RegisterComponent] +public sealed partial class ElectrocutionHUDVisualsComponent : Component; diff --git a/Content.Shared/Electrocution/Components/ElectrocutionOverlayComponent.cs b/Content.Shared/Electrocution/Components/ShowElectrocutionHUDComponent.cs similarity index 51% rename from Content.Shared/Electrocution/Components/ElectrocutionOverlayComponent.cs rename to Content.Shared/Electrocution/Components/ShowElectrocutionHUDComponent.cs index e03e8cb934..a6d9f380da 100644 --- a/Content.Shared/Electrocution/Components/ElectrocutionOverlayComponent.cs +++ b/Content.Shared/Electrocution/Components/ShowElectrocutionHUDComponent.cs @@ -3,7 +3,7 @@ using Robust.Shared.GameStates; namespace Content.Shared.Electrocution; /// -/// Allow an entity to see the ElectrocutionOverlay showing electrocuted doors. +/// Allow an entity to see the Electrocution HUD showing electrocuted doors. /// [RegisterComponent, NetworkedComponent] -public sealed partial class ElectrocutionOverlayComponent : Component; +public sealed partial class ShowElectrocutionHUDComponent : Component; diff --git a/Content.Shared/Electrocution/SharedElectrocution.cs b/Content.Shared/Electrocution/SharedElectrocution.cs index b00fb1afdb..5422049874 100644 --- a/Content.Shared/Electrocution/SharedElectrocution.cs +++ b/Content.Shared/Electrocution/SharedElectrocution.cs @@ -6,7 +6,7 @@ namespace Content.Shared.Electrocution; public enum ElectrifiedLayers : byte { Sparks, - Overlay, + HUD, } [Serializable, NetSerializable] diff --git a/Resources/Prototypes/Entities/Mobs/Player/observer.yml b/Resources/Prototypes/Entities/Mobs/Player/observer.yml index dc89e635bf..32a481491c 100644 --- a/Resources/Prototypes/Entities/Mobs/Player/observer.yml +++ b/Resources/Prototypes/Entities/Mobs/Player/observer.yml @@ -55,7 +55,7 @@ skipChecks: true - type: Ghost - type: GhostHearing - - type: ElectrocutionOverlay + - type: ShowElectrocutionHUD - type: IntrinsicRadioReceiver - type: ActiveRadio receiveAllChannels: true diff --git a/Resources/Prototypes/Entities/Mobs/Player/silicon.yml b/Resources/Prototypes/Entities/Mobs/Player/silicon.yml index dee11f0451..b694b245b2 100644 --- a/Resources/Prototypes/Entities/Mobs/Player/silicon.yml +++ b/Resources/Prototypes/Entities/Mobs/Player/silicon.yml @@ -30,7 +30,7 @@ - type: IgnoreUIRange - type: StationAiHeld - type: StationAiOverlay - - type: ElectrocutionOverlay + - type: ShowElectrocutionHUD - type: ActionGrant actions: - ActionJumpToCore diff --git a/Resources/Prototypes/Entities/Structures/Doors/Airlocks/base_structureairlocks.yml b/Resources/Prototypes/Entities/Structures/Doors/Airlocks/base_structureairlocks.yml index 8d8c69c6ad..90224d3136 100644 --- a/Resources/Prototypes/Entities/Structures/Doors/Airlocks/base_structureairlocks.yml +++ b/Resources/Prototypes/Entities/Structures/Doors/Airlocks/base_structureairlocks.yml @@ -35,7 +35,7 @@ sprite: Interface/Misc/ai_hud.rsi shader: unshaded visible: false - map: ["enum.ElectrifiedLayers.Overlay"] + map: ["enum.ElectrifiedLayers.HUD"] - type: AnimationPlayer - type: Physics - type: Fixtures @@ -78,6 +78,7 @@ - type: DoorBolt - type: Appearance - type: WiresVisuals + - type: ElectrocutionHUDVisuals - type: ApcPowerReceiver powerLoad: 20 - type: ExtensionCableReceiver diff --git a/Resources/Prototypes/Entities/Structures/Doors/Airlocks/shuttle.yml b/Resources/Prototypes/Entities/Structures/Doors/Airlocks/shuttle.yml index e6905d61cc..630027384c 100644 --- a/Resources/Prototypes/Entities/Structures/Doors/Airlocks/shuttle.yml +++ b/Resources/Prototypes/Entities/Structures/Doors/Airlocks/shuttle.yml @@ -30,24 +30,6 @@ hard: false - type: Sprite sprite: Structures/Doors/Airlocks/Standard/shuttle.rsi - snapCardinals: false - layers: - - state: closed - map: ["enum.DoorVisualLayers.Base"] - - state: closed_unlit - shader: unshaded - map: ["enum.DoorVisualLayers.BaseUnlit"] - visible: false - - state: welded - map: ["enum.WeldableLayers.BaseWelded"] - - state: bolted_unlit - shader: unshaded - map: ["enum.DoorVisualLayers.BaseBolted"] - - state: emergency_unlit - shader: unshaded - map: ["enum.DoorVisualLayers.BaseEmergencyAccess"] - - state: panel_open - map: ["enum.WiresVisualLayers.MaintenancePanel"] - type: Wires layoutId: Docking - type: Door From 306277afe0a08cf2713309ffa57299f52d4b40d5 Mon Sep 17 00:00:00 2001 From: slarticodefast <161409025+slarticodefast@users.noreply.github.com> Date: Fri, 22 Nov 2024 23:05:36 +0100 Subject: [PATCH 13/59] rename --- ...ectrocutionOverlaySystem.cs => ElectrifiedVisualizerSystem.cs} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename Content.Client/Electrocution/{ElectrocutionOverlaySystem.cs => ElectrifiedVisualizerSystem.cs} (100%) diff --git a/Content.Client/Electrocution/ElectrocutionOverlaySystem.cs b/Content.Client/Electrocution/ElectrifiedVisualizerSystem.cs similarity index 100% rename from Content.Client/Electrocution/ElectrocutionOverlaySystem.cs rename to Content.Client/Electrocution/ElectrifiedVisualizerSystem.cs From de516905f0dd65864523da671e3cb04dd394d6e2 Mon Sep 17 00:00:00 2001 From: slarticodefast <161409025+slarticodefast@users.noreply.github.com> Date: Fri, 22 Nov 2024 23:39:05 +0100 Subject: [PATCH 14/59] another rename --- ...dVisualizerSystem.cs => ElectrocutionHUDVisualizerSystem.cs} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename Content.Client/Electrocution/{ElectrifiedVisualizerSystem.cs => ElectrocutionHUDVisualizerSystem.cs} (97%) diff --git a/Content.Client/Electrocution/ElectrifiedVisualizerSystem.cs b/Content.Client/Electrocution/ElectrocutionHUDVisualizerSystem.cs similarity index 97% rename from Content.Client/Electrocution/ElectrifiedVisualizerSystem.cs rename to Content.Client/Electrocution/ElectrocutionHUDVisualizerSystem.cs index bcfc51acc1..b95c0d585d 100644 --- a/Content.Client/Electrocution/ElectrifiedVisualizerSystem.cs +++ b/Content.Client/Electrocution/ElectrocutionHUDVisualizerSystem.cs @@ -8,7 +8,7 @@ namespace Content.Client.Electrocution; /// /// Shows the Electrocution HUD to entities with the ShowElectrocutionHUDComponent. /// -public sealed class ElectrifiedVisualizerSystem : VisualizerSystem +public sealed class ElectrocutionHUDVisualizerSystem : VisualizerSystem { [Dependency] private readonly IPlayerManager _playerMan = default!; From a28adf4ae4be77ded0dd17cacf58e69e1f9c85b0 Mon Sep 17 00:00:00 2001 From: IProduceWidgets <107586145+IProduceWidgets@users.noreply.github.com> Date: Fri, 22 Nov 2024 17:50:41 -0500 Subject: [PATCH 15/59] baby proof the terminal (#33281) * baby proof the terminal * Make a couple exceptions for items that you might take with you. * alwayspoweredlights * Uncuttable cables since cablecomp is a snowflake construction system * chairs and vendors * rerun heisentests * rerun tests again --- .../Power/Components/CableComponent.cs | 5 +- .../Power/EntitySystems/CableSystem.cs | 5 +- Resources/Maps/Misc/terminal.yml | 4583 +++++++++++++++-- .../Structures/Power/cable_terminal.yml | 8 + .../Entities/Structures/Power/cables.yml | 24 + 5 files changed, 4130 insertions(+), 495 deletions(-) diff --git a/Content.Server/Power/Components/CableComponent.cs b/Content.Server/Power/Components/CableComponent.cs index 7398bc0616..63899735b5 100644 --- a/Content.Server/Power/Components/CableComponent.cs +++ b/Content.Server/Power/Components/CableComponent.cs @@ -18,8 +18,11 @@ public sealed partial class CableComponent : Component [DataField] public EntProtoId CableDroppedOnCutPrototype = "CableHVStack1"; + /// + /// The tool quality needed to cut the cable. Setting to null prevents cutting. + /// [DataField] - public ProtoId CuttingQuality = SharedToolSystem.CutQuality; + public ProtoId? CuttingQuality = SharedToolSystem.CutQuality; /// /// Checked by to determine if there is diff --git a/Content.Server/Power/EntitySystems/CableSystem.cs b/Content.Server/Power/EntitySystems/CableSystem.cs index d0f45b54fc..db44323007 100644 --- a/Content.Server/Power/EntitySystems/CableSystem.cs +++ b/Content.Server/Power/EntitySystems/CableSystem.cs @@ -35,7 +35,10 @@ public sealed partial class CableSystem : EntitySystem if (args.Handled) return; - args.Handled = _toolSystem.UseTool(args.Used, args.User, uid, cable.CuttingDelay, cable.CuttingQuality, new CableCuttingFinishedEvent()); + if (cable.CuttingQuality != null) + { + args.Handled = _toolSystem.UseTool(args.Used, args.User, uid, cable.CuttingDelay, cable.CuttingQuality, new CableCuttingFinishedEvent()); + } } private void OnCableCut(EntityUid uid, CableComponent cable, DoAfterEvent args) diff --git a/Resources/Maps/Misc/terminal.yml b/Resources/Maps/Misc/terminal.yml index d32a53856e..8ca17b4ebc 100644 --- a/Resources/Maps/Misc/terminal.yml +++ b/Resources/Maps/Misc/terminal.yml @@ -948,6 +948,7 @@ entities: - type: RadiationGridResistance - type: SpreaderGrid - type: GridPathfinding + - type: Godmode - proto: AirlockExternalGlass entities: - uid: 2 @@ -955,87 +956,86 @@ entities: - type: Transform pos: 6.5,-10.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 3 components: - type: Transform pos: -7.5,-17.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 4 components: - type: Transform pos: -7.5,-10.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 5 components: - type: Transform pos: 6.5,-17.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 11 components: - type: Transform rot: -1.5707963267948966 rad pos: 12.5,-10.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 12 components: - type: Transform rot: -1.5707963267948966 rad pos: 12.5,-17.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 13 components: - type: Transform rot: -1.5707963267948966 rad pos: -13.5,-17.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 14 components: - type: Transform rot: -1.5707963267948966 rad pos: -13.5,-10.5 parent: 818 -- proto: AirlockExternalLocked - entities: - - uid: 589 - components: - - type: MetaData - flags: PvsPriority - - type: Transform - pos: 4.5,8.5 - parent: 818 -- proto: AirlockGlass - entities: - - uid: 252 - components: - - type: Transform - pos: -9.5,-4.5 - parent: 818 - - uid: 253 - components: - - type: Transform - pos: -10.5,-4.5 - parent: 818 - - uid: 254 - components: - - type: Transform - pos: -11.5,-4.5 - parent: 818 - - uid: 255 - components: - - type: Transform - pos: 8.5,-4.5 - parent: 818 - - uid: 256 - components: - - type: Transform - pos: 9.5,-4.5 - parent: 818 - - uid: 257 - components: - - type: Transform - pos: 10.5,-4.5 - parent: 818 -- proto: AirlockGlassShuttleEasyPryLocked + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction +- proto: AirlockExternalGlassShuttleLocked entities: - uid: 1 components: @@ -1043,57 +1043,338 @@ entities: rot: -1.5707963267948966 rad pos: -15.5,-10.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 6 components: - type: Transform rot: -1.5707963267948966 rad pos: -15.5,-17.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 7 components: - type: Transform rot: 1.5707963267948966 rad pos: 14.5,-10.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 8 components: - type: Transform rot: 1.5707963267948966 rad pos: 14.5,-17.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 9 components: - type: Transform rot: -1.5707963267948966 rad pos: 4.5,-10.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 15 components: - type: Transform rot: -1.5707963267948966 rad pos: 4.5,-17.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 16 components: - type: Transform rot: 1.5707963267948966 rad pos: -5.5,-10.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 17 components: - type: Transform rot: 1.5707963267948966 rad pos: -5.5,-17.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible +- proto: AirlockExternalLocked + entities: + - uid: 589 + components: + - type: Transform + pos: 4.5,8.5 + parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction +- proto: AirlockGlass + entities: + - uid: 252 + components: + - type: Transform + pos: -9.5,-4.5 + parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible + - uid: 253 + components: + - type: Transform + pos: -10.5,-4.5 + parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible + - uid: 254 + components: + - type: Transform + pos: -11.5,-4.5 + parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible + - uid: 255 + components: + - type: Transform + pos: 8.5,-4.5 + parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible + - uid: 256 + components: + - type: Transform + pos: 9.5,-4.5 + parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible + - uid: 257 + components: + - type: Transform + pos: 10.5,-4.5 + parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - proto: AirlockMaint entities: - uid: 146 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: 3.5,3.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction +- proto: AlwaysPoweredWallLight + entities: + - uid: 150 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: -8.5,-5.5 + parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible + - uid: 188 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 11.5,2.5 + parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible + - uid: 195 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: -2.5,-1.5 + parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible + - uid: 209 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 7.5,-5.5 + parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible + - uid: 341 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 1.5,-1.5 + parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible + - uid: 634 + components: + - type: Transform + pos: 9.5,-16.5 + parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible + - uid: 636 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 9.5,-11.5 + parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible + - uid: 649 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: -10.5,-11.5 + parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible + - uid: 650 + components: + - type: Transform + pos: -10.5,-16.5 + parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible + - uid: 687 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -13.5,1.5 + parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible + - uid: 701 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: -6.5,3.5 + parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible + - uid: 702 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 5.5,3.5 + parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible + - uid: 715 + components: + - type: Transform + pos: -0.5,5.5 + parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible + - uid: 717 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: -7.5,-3.5 + parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible + - uid: 742 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 6.5,-3.5 + parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - proto: APCBasic entities: - uid: 205 @@ -1101,32 +1382,92 @@ entities: - type: Transform pos: 6.5,2.5 parent: 818 + - type: AccessReader + access: + - - CentralCommand + - type: Godmode + - type: BatterySelfRecharger + autoRechargeRate: 50000 + autoRecharge: True + missingComponents: + - Construction + - Destructible - uid: 206 components: - type: Transform pos: -13.5,2.5 parent: 818 + - type: AccessReader + access: + - - CentralCommand + - type: Godmode + - type: BatterySelfRecharger + autoRechargeRate: 50000 + autoRecharge: True + missingComponents: + - Construction + - Destructible - uid: 211 components: - type: Transform pos: -13.5,-11.5 parent: 818 + - type: AccessReader + access: + - - CentralCommand + - type: Godmode + - type: BatterySelfRecharger + autoRechargeRate: 50000 + autoRecharge: True + missingComponents: + - Construction + - Destructible - uid: 212 components: - type: Transform pos: 6.5,-11.5 parent: 818 + - type: AccessReader + access: + - - CentralCommand + - type: Godmode + - type: BatterySelfRecharger + autoRechargeRate: 50000 + autoRecharge: True + missingComponents: + - Construction + - Destructible - uid: 355 components: - type: Transform rot: 3.141592653589793 rad pos: 1.5,6.5 parent: 818 + - type: AccessReader + access: + - - CentralCommand + - type: Godmode + - type: BatterySelfRecharger + autoRechargeRate: 50000 + autoRecharge: True + missingComponents: + - Construction + - Destructible - uid: 846 components: - type: Transform pos: 2.5,3.5 parent: 818 + - type: AccessReader + access: + - - CentralCommand + - type: Godmode + - type: BatterySelfRecharger + autoRechargeRate: 50000 + autoRecharge: True + missingComponents: + - Construction + - Destructible - proto: ArrivalsShuttleTimer entities: - uid: 597 @@ -1134,21 +1475,33 @@ entities: - type: Transform pos: -7.5,-5.5 parent: 818 + - type: Godmode + missingComponents: + - Construction - uid: 633 components: - type: Transform pos: 6.5,-5.5 parent: 818 + - type: Godmode + missingComponents: + - Construction - uid: 928 components: - type: Transform pos: -6.5,-14.5 parent: 818 + - type: Godmode + missingComponents: + - Construction - uid: 929 components: - type: Transform pos: 5.5,-14.5 parent: 818 + - type: Godmode + missingComponents: + - Construction - proto: AtmosDeviceFanTiny entities: - uid: 296 @@ -1156,46 +1509,55 @@ entities: - type: Transform pos: -6.5,-10.5 parent: 818 + - type: Godmode - uid: 297 components: - type: Transform pos: -14.5,-10.5 parent: 818 + - type: Godmode - uid: 298 components: - type: Transform pos: -14.5,-17.5 parent: 818 + - type: Godmode - uid: 299 components: - type: Transform pos: -6.5,-17.5 parent: 818 + - type: Godmode - uid: 300 components: - type: Transform pos: 5.5,-17.5 parent: 818 + - type: Godmode - uid: 301 components: - type: Transform pos: 5.5,-10.5 parent: 818 + - type: Godmode - uid: 302 components: - type: Transform pos: 13.5,-10.5 parent: 818 + - type: Godmode - uid: 303 components: - type: Transform pos: 13.5,-17.5 parent: 818 + - type: Godmode - uid: 809 components: - type: Transform pos: 4.5,8.5 parent: 818 + - type: Godmode - proto: BarSignEngineChange entities: - uid: 215 @@ -1203,6 +1565,10 @@ entities: - type: Transform pos: -10.5,5.5 parent: 818 + - type: Godmode + missingComponents: + - ApcPowerReceiver + - Destructible - proto: BlockGameArcade entities: - uid: 727 @@ -1211,28 +1577,46 @@ entities: rot: 1.5707963267948966 rad pos: -13.5,-1.5 parent: 818 + - type: Godmode + missingComponents: + - ApcPowerReceiver + - Anchorable + - Construction + - Destructible - uid: 728 components: - type: Transform rot: 1.5707963267948966 rad pos: -13.5,0.5 parent: 818 + - type: Godmode + missingComponents: + - ApcPowerReceiver + - Anchorable + - Construction + - Destructible - proto: BookshelfFilled entities: - uid: 442 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: 7.5,3.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - Anchorable + - Construction - uid: 752 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: 11.5,3.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - Anchorable + - Construction - proto: BoozeDispenser entities: - uid: 710 @@ -1240,1198 +1624,2152 @@ entities: - type: Transform pos: -11.5,4.5 parent: 818 -- proto: CableApcExtension + - type: Godmode + missingComponents: + - ApcPowerReceiver + - Anchorable + - Destructible + - Construction +- proto: CableApcExtensionUncuttable entities: - uid: 203 components: - type: Transform pos: 1.5,6.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 208 components: - type: Transform pos: -3.5,7.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 218 components: - type: Transform pos: -4.5,4.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 402 components: - type: Transform pos: -4.5,7.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 404 components: - type: Transform pos: 2.5,1.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 410 components: - type: Transform pos: 2.5,2.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 411 components: - type: Transform pos: 3.5,5.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 412 components: - type: Transform pos: 3.5,4.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 426 components: - type: Transform pos: -2.5,7.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 427 components: - type: Transform pos: -1.5,7.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 428 components: - type: Transform pos: -0.5,7.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 429 components: - type: Transform pos: 0.5,7.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 430 components: - type: Transform pos: 1.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 431 components: - type: Transform pos: 1.5,-1.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 434 components: - type: Transform pos: 0.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 435 components: - type: Transform pos: -0.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 436 components: - type: Transform pos: -1.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 437 components: - type: Transform pos: -2.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 438 components: - type: Transform pos: -3.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 439 components: - type: Transform pos: -4.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 440 components: - type: Transform pos: -2.5,-1.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 443 components: - type: Transform pos: 2.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 444 components: - type: Transform pos: 3.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 445 components: - type: Transform pos: 4.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 446 components: - type: Transform pos: -5.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 447 components: - type: Transform pos: -13.5,2.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 448 components: - type: Transform pos: -13.5,1.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 449 components: - type: Transform pos: -13.5,0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 450 components: - type: Transform pos: -13.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 451 components: - type: Transform pos: -12.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 452 components: - type: Transform pos: -11.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 453 components: - type: Transform pos: -10.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 454 components: - type: Transform pos: -9.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 455 components: - type: Transform pos: -8.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 456 components: - type: Transform pos: -7.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 457 components: - type: Transform pos: -10.5,-1.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 458 components: - type: Transform pos: -10.5,-2.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 459 components: - type: Transform pos: -10.5,-3.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 460 components: - type: Transform pos: -10.5,0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 461 components: - type: Transform pos: -10.5,1.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 462 components: - type: Transform pos: -10.5,2.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 463 components: - type: Transform pos: -10.5,3.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 464 components: - type: Transform pos: -11.5,-3.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 465 components: - type: Transform pos: -9.5,-3.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 466 components: - type: Transform pos: -11.5,3.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 467 components: - type: Transform pos: -9.5,3.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 468 components: - type: Transform pos: -13.5,-11.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 469 components: - type: Transform pos: -12.5,-11.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 470 components: - type: Transform pos: -11.5,-11.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 471 components: - type: Transform pos: -11.5,-10.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 472 components: - type: Transform pos: 10.5,-16.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 473 components: - type: Transform pos: 10.5,-15.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 474 components: - type: Transform pos: 10.5,-14.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 475 components: - type: Transform pos: 10.5,-12.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 476 components: - type: Transform pos: -11.5,-13.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 477 components: - type: Transform pos: -10.5,-17.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 478 components: - type: Transform pos: -10.5,-18.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 479 components: - type: Transform pos: -10.5,-19.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 480 components: - type: Transform pos: -10.5,-20.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 481 components: - type: Transform pos: -11.5,-17.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 482 components: - type: Transform pos: -12.5,-17.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 483 components: - type: Transform pos: -13.5,-17.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 484 components: - type: Transform pos: -14.5,-17.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 485 components: - type: Transform pos: -9.5,-17.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 486 components: - type: Transform pos: -8.5,-17.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 487 components: - type: Transform pos: -7.5,-17.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 488 components: - type: Transform pos: -6.5,-17.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 489 components: - type: Transform pos: -10.5,-10.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 490 components: - type: Transform pos: -9.5,-10.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 491 components: - type: Transform pos: -8.5,-10.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 492 components: - type: Transform pos: -7.5,-10.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 493 components: - type: Transform pos: -6.5,-10.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 494 components: - type: Transform pos: -12.5,-10.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 495 components: - type: Transform pos: -13.5,-10.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 496 components: - type: Transform pos: -14.5,-10.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 497 components: - type: Transform pos: -11.5,-14.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 498 components: - type: Transform pos: -12.5,-14.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 499 components: - type: Transform pos: -9.5,-13.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 500 components: - type: Transform pos: -8.5,-13.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 501 components: - type: Transform pos: -10.5,-9.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 502 components: - type: Transform pos: -10.5,-8.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 503 components: - type: Transform pos: -10.5,-7.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 504 components: - type: Transform pos: -10.5,-6.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 505 components: - type: Transform pos: 6.5,-11.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 506 components: - type: Transform pos: 7.5,-11.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 507 components: - type: Transform pos: 7.5,-10.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 508 components: - type: Transform pos: 6.5,-10.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 509 components: - type: Transform pos: 5.5,-10.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 510 components: - type: Transform pos: 8.5,-11.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 511 components: - type: Transform pos: 8.5,-10.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 512 components: - type: Transform pos: 9.5,-10.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 513 components: - type: Transform pos: 10.5,-10.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 514 components: - type: Transform pos: 11.5,-10.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 515 components: - type: Transform pos: 12.5,-10.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 516 components: - type: Transform pos: 13.5,-10.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 517 components: - type: Transform pos: 8.5,-16.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 518 components: - type: Transform pos: 8.5,-15.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 519 components: - type: Transform pos: 8.5,-13.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 520 components: - type: Transform pos: 8.5,-12.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 521 components: - type: Transform pos: -11.5,-12.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 522 components: - type: Transform pos: 9.5,-17.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 523 components: - type: Transform pos: 9.5,-18.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 524 components: - type: Transform pos: 9.5,-19.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 525 components: - type: Transform pos: 9.5,-20.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 526 components: - type: Transform pos: 8.5,-17.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 527 components: - type: Transform pos: 7.5,-17.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 528 components: - type: Transform pos: 6.5,-17.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 529 components: - type: Transform pos: 5.5,-17.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 530 components: - type: Transform pos: 10.5,-17.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 531 components: - type: Transform pos: 11.5,-17.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 532 components: - type: Transform pos: 12.5,-17.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 533 components: - type: Transform pos: 13.5,-17.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 534 components: - type: Transform pos: 8.5,-14.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 535 components: - type: Transform pos: 7.5,-14.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 536 components: - type: Transform pos: 10.5,-13.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 537 components: - type: Transform pos: 11.5,-13.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 538 components: - type: Transform pos: 9.5,-9.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 539 components: - type: Transform pos: 9.5,-8.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 540 components: - type: Transform pos: 9.5,-7.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 541 components: - type: Transform pos: 9.5,-6.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 542 components: - type: Transform pos: 6.5,2.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 543 components: - type: Transform pos: 6.5,1.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 544 components: - type: Transform pos: 6.5,0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 545 components: - type: Transform pos: 6.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 546 components: - type: Transform pos: 7.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 547 components: - type: Transform pos: 8.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 548 components: - type: Transform pos: 9.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 549 components: - type: Transform pos: 9.5,0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 550 components: - type: Transform pos: 9.5,1.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 551 components: - type: Transform pos: 9.5,2.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 552 components: - type: Transform pos: 9.5,3.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 553 components: - type: Transform pos: 10.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 554 components: - type: Transform pos: 8.5,3.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 555 components: - type: Transform pos: 10.5,3.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 556 components: - type: Transform pos: 11.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 557 components: - type: Transform pos: 12.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 558 components: - type: Transform pos: 9.5,-1.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 559 components: - type: Transform pos: 9.5,-2.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 560 components: - type: Transform pos: 9.5,-3.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 561 components: - type: Transform pos: 8.5,-3.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 562 components: - type: Transform pos: 10.5,-3.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 563 components: - type: Transform pos: 1.5,7.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 564 components: - type: Transform pos: 2.5,7.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 565 components: - type: Transform pos: 3.5,7.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 566 components: - type: Transform pos: 3.5,6.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 579 components: - type: Transform pos: 2.5,0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 599 components: - type: Transform pos: -4.5,6.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 601 components: - type: Transform pos: -4.5,5.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 651 components: - type: Transform pos: 10.5,-11.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 652 components: - type: Transform pos: -11.5,-16.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 653 components: - type: Transform pos: -11.5,-15.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 654 components: - type: Transform pos: -9.5,-16.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 655 components: - type: Transform pos: -9.5,-15.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 656 components: - type: Transform pos: -9.5,-14.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 657 components: - type: Transform pos: -9.5,-12.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 658 components: - type: Transform pos: -9.5,-11.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 842 components: - type: Transform pos: -4.5,0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 843 components: - type: Transform pos: -4.5,1.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 844 components: - type: Transform pos: 2.5,3.5 parent: 818 -- proto: CableHV + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable +- proto: CableHVUncuttable entities: - uid: 413 components: - type: Transform pos: -3.5,8.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 415 components: - type: Transform pos: -4.5,8.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 416 components: - type: Transform pos: -2.5,8.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 734 components: - type: Transform pos: -0.5,8.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 735 components: - type: Transform pos: -1.5,8.5 parent: 818 -- proto: CableMV + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable +- proto: CableMVUncuttable entities: - uid: 177 components: - type: Transform pos: 3.5,3.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 201 components: - type: Transform pos: 6.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 210 components: - type: Transform pos: 6.5,1.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 214 components: - type: Transform pos: 6.5,0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 219 components: - type: Transform pos: 7.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 221 components: - type: Transform pos: 3.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 224 components: - type: Transform pos: 1.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 226 components: - type: Transform pos: 6.5,2.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 227 components: - type: Transform pos: 8.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 228 components: - type: Transform pos: 9.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 349 components: - type: Transform pos: 9.5,-1.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 350 components: - type: Transform pos: 5.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 352 components: - type: Transform pos: 2.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 353 components: - type: Transform pos: 4.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 354 components: - type: Transform pos: 1.5,6.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 356 components: - type: Transform pos: 9.5,-7.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 357 components: - type: Transform pos: 9.5,-6.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 358 components: - type: Transform pos: 9.5,-5.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 359 components: - type: Transform pos: 9.5,-3.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 360 components: - type: Transform pos: 9.5,-4.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 361 components: - type: Transform pos: 9.5,-2.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 362 components: - type: Transform pos: 9.5,-8.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 363 components: - type: Transform pos: 9.5,-9.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 364 components: - type: Transform pos: 9.5,-10.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 365 components: - type: Transform pos: 9.5,-11.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 366 components: - type: Transform pos: 8.5,-11.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 367 components: - type: Transform pos: 7.5,-11.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 368 components: - type: Transform pos: 6.5,-11.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 369 components: - type: Transform pos: 0.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 370 components: - type: Transform pos: -0.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 371 components: - type: Transform pos: -1.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 372 components: - type: Transform pos: -2.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 373 components: - type: Transform pos: -3.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 374 components: - type: Transform pos: -4.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 375 components: - type: Transform pos: -5.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 376 components: - type: Transform pos: -6.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 377 components: - type: Transform pos: -7.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 378 components: - type: Transform pos: -8.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 379 components: - type: Transform pos: -9.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 380 components: - type: Transform pos: -10.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 381 components: - type: Transform pos: -11.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 382 components: - type: Transform pos: -12.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 383 components: - type: Transform pos: -13.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 384 components: - type: Transform pos: -13.5,0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 385 components: - type: Transform pos: -13.5,1.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 386 components: - type: Transform pos: -13.5,2.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 387 components: - type: Transform pos: -10.5,-1.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 388 components: - type: Transform pos: -10.5,-2.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 389 components: - type: Transform pos: -10.5,-3.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 390 components: - type: Transform pos: -10.5,-4.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 391 components: - type: Transform pos: -10.5,-5.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 392 components: - type: Transform pos: -10.5,-6.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 393 components: - type: Transform pos: -10.5,-7.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 394 components: - type: Transform pos: -10.5,-8.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 395 components: - type: Transform pos: -10.5,-9.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 396 components: - type: Transform pos: -10.5,-10.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 397 components: - type: Transform pos: -10.5,-11.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 398 components: - type: Transform pos: -11.5,-11.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 399 components: - type: Transform pos: -12.5,-11.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 400 components: - type: Transform pos: -13.5,-11.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 418 components: - type: Transform pos: 3.5,1.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 419 components: - type: Transform pos: 3.5,2.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 421 components: - type: Transform pos: -0.5,7.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 422 components: - type: Transform pos: 0.5,7.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 423 components: - type: Transform pos: 1.5,7.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 424 components: - type: Transform pos: 2.5,7.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 425 components: - type: Transform pos: 3.5,7.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 567 components: - type: Transform pos: 3.5,4.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 568 components: - type: Transform pos: 3.5,5.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 569 components: - type: Transform pos: 3.5,6.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 570 components: - type: Transform pos: -0.5,8.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 803 components: - type: Transform pos: 3.5,0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 845 components: - type: Transform pos: 2.5,3.5 parent: 818 -- proto: CableTerminal + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable +- proto: CableTerminalUncuttable entities: - uid: 417 components: @@ -2439,6 +3777,11 @@ entities: rot: 1.5707963267948966 rad pos: -3.5,8.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - proto: Catwalk entities: - uid: 580 @@ -2446,56 +3789,111 @@ entities: - type: Transform pos: 3.5,6.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Destructible + - RCDDeconstructable - uid: 584 components: - type: Transform pos: 2.5,7.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Destructible + - RCDDeconstructable - uid: 590 components: - type: Transform pos: 3.5,5.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Destructible + - RCDDeconstructable - uid: 596 components: - type: Transform pos: 1.5,7.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Destructible + - RCDDeconstructable - uid: 747 components: - type: Transform pos: 3.5,4.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Destructible + - RCDDeconstructable - uid: 810 components: - type: Transform pos: 0.5,7.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Destructible + - RCDDeconstructable - uid: 811 components: - type: Transform pos: -0.5,7.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Destructible + - RCDDeconstructable - uid: 812 components: - type: Transform pos: -1.5,7.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Destructible + - RCDDeconstructable - uid: 813 components: - type: Transform pos: -2.5,7.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Destructible + - RCDDeconstructable - uid: 814 components: - type: Transform pos: -3.5,7.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Destructible + - RCDDeconstructable - uid: 815 components: - type: Transform pos: -4.5,7.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Destructible + - RCDDeconstructable - proto: Chair entities: - uid: 592 @@ -2504,254 +3902,475 @@ entities: rot: -1.5707963267948966 rad pos: -7.5,-14.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 593 components: - type: Transform rot: -1.5707963267948966 rad pos: -7.5,-15.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 603 components: - type: Transform rot: -1.5707963267948966 rad pos: -7.5,-13.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 604 components: - type: Transform rot: -1.5707963267948966 rad pos: -7.5,-12.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 605 components: - type: Transform rot: -1.5707963267948966 rad pos: -11.5,-15.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 606 components: - type: Transform rot: -1.5707963267948966 rad pos: -11.5,-14.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 607 components: - type: Transform rot: -1.5707963267948966 rad pos: -11.5,-13.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 608 components: - type: Transform rot: -1.5707963267948966 rad pos: -11.5,-12.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 609 components: - type: Transform rot: 1.5707963267948966 rad pos: -13.5,-15.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 610 components: - type: Transform rot: 1.5707963267948966 rad pos: -13.5,-14.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 611 components: - type: Transform rot: 1.5707963267948966 rad pos: -13.5,-13.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 612 components: - type: Transform rot: 1.5707963267948966 rad pos: -13.5,-12.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 613 components: - type: Transform rot: 1.5707963267948966 rad pos: -9.5,-15.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 614 components: - type: Transform rot: 1.5707963267948966 rad pos: -9.5,-14.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 615 components: - type: Transform rot: 1.5707963267948966 rad pos: -9.5,-13.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 616 components: - type: Transform rot: 1.5707963267948966 rad pos: -9.5,-12.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 617 components: - type: Transform rot: 1.5707963267948966 rad pos: 6.5,-15.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 618 components: - type: Transform rot: 1.5707963267948966 rad pos: 6.5,-14.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 619 components: - type: Transform rot: 1.5707963267948966 rad pos: 6.5,-13.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 620 components: - type: Transform rot: 1.5707963267948966 rad pos: 6.5,-12.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 621 components: - type: Transform rot: 1.5707963267948966 rad pos: 10.5,-15.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 622 components: - type: Transform rot: 1.5707963267948966 rad pos: 10.5,-14.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 623 components: - type: Transform rot: 1.5707963267948966 rad pos: 10.5,-13.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 624 components: - type: Transform rot: 1.5707963267948966 rad pos: 10.5,-12.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 625 components: - type: Transform rot: -1.5707963267948966 rad pos: 8.5,-15.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 626 components: - type: Transform rot: -1.5707963267948966 rad pos: 8.5,-14.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 627 components: - type: Transform rot: -1.5707963267948966 rad pos: 8.5,-13.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 628 components: - type: Transform rot: -1.5707963267948966 rad pos: 8.5,-12.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 629 components: - type: Transform rot: -1.5707963267948966 rad pos: 12.5,-15.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 630 components: - type: Transform rot: -1.5707963267948966 rad pos: 12.5,-14.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 631 components: - type: Transform rot: -1.5707963267948966 rad pos: 12.5,-13.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 632 components: - type: Transform rot: -1.5707963267948966 rad pos: 12.5,-12.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 847 components: - type: Transform rot: 1.5707963267948966 rad pos: -12.5,-8.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 848 components: - type: Transform rot: -1.5707963267948966 rad pos: -8.5,-8.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 849 components: - type: Transform rot: -1.5707963267948966 rad pos: -8.5,-7.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 850 components: - type: Transform rot: -1.5707963267948966 rad pos: -8.5,-6.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - proto: ChairOfficeDark entities: - - uid: 591 + - uid: 18 components: - type: Transform + anchored: True rot: 3.141592653589793 rad pos: 9.5,3.5 parent: 818 + - type: Physics + bodyType: Static + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - proto: ChairWood entities: - uid: 577 components: - type: Transform + anchored: True pos: 10.5,1.5 parent: 818 - - uid: 703 + - type: Physics + bodyType: Static + - type: Godmode + missingComponents: + - Construction + - Destructible + - Anchorable + - uid: 591 components: - type: Transform + anchored: True rot: 1.5707963267948966 rad pos: 8.5,0.5 parent: 818 + - type: Physics + bodyType: Static + - type: Godmode + missingComponents: + - Construction + - Destructible + - Anchorable + - uid: 703 + components: + - type: Transform + anchored: True + pos: 9.5,1.5 + parent: 818 + - type: Physics + bodyType: Static + - type: Godmode + missingComponents: + - Construction + - Destructible + - Anchorable - uid: 704 components: - type: Transform - pos: 9.5,1.5 - parent: 818 - - uid: 714 - components: - - type: Transform + anchored: True rot: 1.5707963267948966 rad pos: 8.5,-0.5 parent: 818 + - type: Physics + bodyType: Static + - type: Godmode + missingComponents: + - Construction + - Destructible + - Anchorable - proto: ChessBoard entities: - - uid: 918 + - uid: 714 components: - type: Transform - pos: 12.503689,-2.3981738 + rot: 3.141592653589793 rad + pos: 12.5093775,-2.403601 parent: 818 - proto: ClosetWallEmergencyFilledRandom entities: @@ -2760,6 +4379,10 @@ entities: - type: Transform pos: -5.5,2.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - Construction - proto: ClosetWallFireFilledRandom entities: - uid: 432 @@ -2767,6 +4390,10 @@ entities: - type: Transform pos: 4.5,2.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - Construction - proto: ComfyChair entities: - uid: 595 @@ -2775,28 +4402,53 @@ entities: rot: 3.141592653589793 rad pos: 6.5,-3.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 718 components: - type: Transform pos: 12.5,-1.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 749 components: - type: Transform pos: 12.5,1.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 759 components: - type: Transform rot: 3.141592653589793 rad pos: 12.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 760 components: - type: Transform rot: 3.141592653589793 rad pos: 12.5,-3.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - proto: DisposalBend entities: - uid: 853 @@ -2805,40 +4457,75 @@ entities: rot: -1.5707963267948966 rad pos: -10.5,-7.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 862 components: - type: Transform rot: 1.5707963267948966 rad pos: -10.5,0.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 891 components: - type: Transform pos: 3.5,7.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 893 components: - type: Transform rot: 1.5707963267948966 rad pos: -4.5,7.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 898 components: - type: Transform rot: 3.141592653589793 rad pos: 9.5,-7.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 899 components: - type: Transform pos: 9.5,-1.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 900 components: - type: Transform rot: 3.141592653589793 rad pos: 3.5,-1.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - proto: DisposalJunctionFlipped entities: - uid: 892 @@ -2847,6 +4534,11 @@ entities: rot: 3.141592653589793 rad pos: 3.5,0.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - proto: DisposalPipe entities: - uid: 854 @@ -2855,277 +4547,517 @@ entities: rot: -1.5707963267948966 rad pos: -11.5,-7.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 855 components: - type: Transform rot: 3.141592653589793 rad pos: -10.5,-6.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 856 components: - type: Transform rot: 3.141592653589793 rad pos: -10.5,-5.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 857 components: - type: Transform rot: 3.141592653589793 rad pos: -10.5,-4.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 858 components: - type: Transform rot: 3.141592653589793 rad pos: -10.5,-3.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 859 components: - type: Transform rot: 3.141592653589793 rad pos: -10.5,-2.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 860 components: - type: Transform rot: 3.141592653589793 rad pos: -10.5,-1.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 861 components: - type: Transform rot: 3.141592653589793 rad pos: -10.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 863 components: - type: Transform rot: 1.5707963267948966 rad pos: -9.5,0.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 864 components: - type: Transform rot: 1.5707963267948966 rad pos: -8.5,0.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 865 components: - type: Transform rot: 1.5707963267948966 rad pos: -7.5,0.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 866 components: - type: Transform rot: 1.5707963267948966 rad pos: -6.5,0.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 867 components: - type: Transform rot: 1.5707963267948966 rad pos: -5.5,0.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 868 components: - type: Transform rot: 1.5707963267948966 rad pos: -4.5,0.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 869 components: - type: Transform rot: 1.5707963267948966 rad pos: -3.5,0.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 870 components: - type: Transform rot: 1.5707963267948966 rad pos: -2.5,0.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 871 components: - type: Transform rot: 1.5707963267948966 rad pos: -1.5,0.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 872 components: - type: Transform rot: 1.5707963267948966 rad pos: -0.5,0.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 873 components: - type: Transform rot: 1.5707963267948966 rad pos: 0.5,0.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 874 components: - type: Transform rot: 1.5707963267948966 rad pos: 1.5,0.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 875 components: - type: Transform rot: 1.5707963267948966 rad pos: 2.5,0.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 876 components: - type: Transform pos: 3.5,1.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 877 components: - type: Transform pos: 3.5,2.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 878 components: - type: Transform pos: 3.5,3.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 879 components: - type: Transform pos: 3.5,4.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 880 components: - type: Transform pos: 3.5,5.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 881 components: - type: Transform pos: 3.5,6.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 882 components: - type: Transform rot: -1.5707963267948966 rad pos: 2.5,7.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 883 components: - type: Transform rot: -1.5707963267948966 rad pos: 1.5,7.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 884 components: - type: Transform rot: -1.5707963267948966 rad pos: 0.5,7.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 885 components: - type: Transform rot: -1.5707963267948966 rad pos: -0.5,7.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 886 components: - type: Transform rot: -1.5707963267948966 rad pos: -1.5,7.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 887 components: - type: Transform rot: -1.5707963267948966 rad pos: -2.5,7.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 888 components: - type: Transform rot: -1.5707963267948966 rad pos: -3.5,7.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 889 components: - type: Transform rot: 3.141592653589793 rad pos: -4.5,6.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 890 components: - type: Transform rot: 3.141592653589793 rad pos: -4.5,5.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 901 components: - type: Transform rot: 1.5707963267948966 rad pos: 10.5,-7.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 902 components: - type: Transform pos: 9.5,-6.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 903 components: - type: Transform pos: 9.5,-5.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 904 components: - type: Transform pos: 9.5,-4.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 905 components: - type: Transform pos: 9.5,-3.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 906 components: - type: Transform pos: 9.5,-2.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 907 components: - type: Transform rot: -1.5707963267948966 rad pos: 8.5,-1.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 908 components: - type: Transform rot: -1.5707963267948966 rad pos: 7.5,-1.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 909 components: - type: Transform rot: -1.5707963267948966 rad pos: 6.5,-1.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 910 components: - type: Transform rot: -1.5707963267948966 rad pos: 5.5,-1.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 911 components: - type: Transform rot: -1.5707963267948966 rad pos: 4.5,-1.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 912 components: - type: Transform rot: 3.141592653589793 rad pos: 3.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - proto: DisposalTrunk entities: - uid: 852 @@ -3134,18 +5066,33 @@ entities: rot: 1.5707963267948966 rad pos: -12.5,-7.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 894 components: - type: Transform rot: 3.141592653589793 rad pos: -4.5,4.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 897 components: - type: Transform rot: -1.5707963267948966 rad pos: 11.5,-7.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - proto: DisposalUnit entities: - uid: 851 @@ -3153,29 +5100,39 @@ entities: - type: Transform pos: -12.5,-7.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Destructible + - Anchorable - uid: 896 components: - type: Transform pos: 11.5,-7.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Destructible + - Anchorable - proto: DrinkGlass entities: + - uid: 723 + components: + - type: Transform + pos: -12.618602,2.5336328 + parent: 818 - uid: 915 components: - type: Transform - pos: -12.587411,2.5765429 - parent: 818 - - uid: 916 - components: - - type: Transform - pos: -12.321786,2.7171679 + pos: -12.399852,2.6273828 parent: 818 - proto: DrinkShaker entities: - - uid: 914 + - uid: 724 components: - type: Transform - pos: -12.649911,2.7640429 + pos: -12.722768,2.7627993 parent: 818 - proto: ExtinguisherCabinetFilled entities: @@ -3184,11 +5141,17 @@ entities: - type: Transform pos: -6.5,-2.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 816 components: - type: Transform pos: 5.5,-2.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - proto: FirelockEdge entities: - uid: 690 @@ -3196,111 +5159,211 @@ entities: - type: Transform pos: -8.5,-11.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 694 components: - type: Transform pos: -12.5,-11.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 695 components: - type: Transform rot: 3.141592653589793 rad pos: -8.5,-16.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 696 components: - type: Transform rot: 3.141592653589793 rad pos: -12.5,-16.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 697 components: - type: Transform rot: 3.141592653589793 rad pos: 7.5,-16.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 698 components: - type: Transform rot: 3.141592653589793 rad pos: 11.5,-16.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 699 components: - type: Transform pos: 11.5,-11.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 700 components: - type: Transform pos: 7.5,-11.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 822 components: - type: Transform pos: 10.5,-3.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 823 components: - type: Transform pos: 9.5,-3.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 824 components: - type: Transform pos: 8.5,-3.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 825 components: - type: Transform rot: 3.141592653589793 rad pos: 8.5,-5.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 826 components: - type: Transform rot: 3.141592653589793 rad pos: 9.5,-5.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 827 components: - type: Transform rot: 3.141592653589793 rad pos: 10.5,-5.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 828 components: - type: Transform pos: -9.5,-3.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 829 components: - type: Transform pos: -10.5,-3.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 830 components: - type: Transform pos: -11.5,-3.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 831 components: - type: Transform rot: 3.141592653589793 rad pos: -11.5,-5.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 832 components: - type: Transform rot: 3.141592653589793 rad pos: -10.5,-5.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 833 components: - type: Transform rot: 3.141592653589793 rad pos: -9.5,-5.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - proto: FirelockGlass entities: - uid: 194 @@ -3308,51 +5371,101 @@ entities: - type: Transform pos: 5.5,0.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 216 components: - type: Transform pos: -10.5,2.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 220 components: - type: Transform pos: -9.5,2.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 305 components: - type: Transform pos: -6.5,0.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 345 components: - type: Transform pos: 5.5,-1.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 346 components: - type: Transform pos: 5.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 347 components: - type: Transform pos: -6.5,-1.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 348 components: - type: Transform pos: -6.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 586 components: - type: Transform pos: -11.5,2.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 716 components: - type: Transform pos: -12.5,2.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - proto: GeneratorBasic15kW entities: - uid: 124 @@ -3360,6 +5473,10 @@ entities: - type: Transform pos: -4.5,8.5 parent: 818 + - type: Godmode + missingComponents: + - Anchorable + - Destructible - proto: GravityGeneratorMini entities: - uid: 808 @@ -3367,6 +5484,11 @@ entities: - type: Transform pos: 1.5,8.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - Anchorable + - Construction - proto: Grille entities: - uid: 96 @@ -3374,479 +5496,918 @@ entities: - type: Transform pos: -14.5,-15.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 97 components: - type: Transform pos: -14.5,-14.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 98 components: - type: Transform pos: -14.5,-13.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 99 components: - type: Transform pos: -6.5,-13.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 101 components: - type: Transform pos: 5.5,-15.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 102 components: - type: Transform pos: 5.5,-14.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 103 components: - type: Transform pos: 13.5,-15.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 104 components: - type: Transform pos: 13.5,-14.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 125 components: - type: Transform rot: 1.5707963267948966 rad pos: -7.5,-19.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 126 components: - type: Transform rot: 1.5707963267948966 rad pos: -7.5,-20.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 127 components: - type: Transform rot: 1.5707963267948966 rad pos: -8.5,-20.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 128 components: - type: Transform rot: 1.5707963267948966 rad pos: -8.5,-21.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 129 components: - type: Transform rot: 1.5707963267948966 rad pos: -9.5,-21.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 130 components: - type: Transform rot: 1.5707963267948966 rad pos: -11.5,-21.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 131 components: - type: Transform rot: 1.5707963267948966 rad pos: -12.5,-21.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 132 components: - type: Transform rot: 1.5707963267948966 rad pos: -12.5,-20.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 133 components: - type: Transform rot: 1.5707963267948966 rad pos: -13.5,-20.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 134 components: - type: Transform rot: 1.5707963267948966 rad pos: -13.5,-19.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 135 components: - type: Transform pos: 5.5,-13.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 136 components: - type: Transform pos: 5.5,-12.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 137 components: - type: Transform pos: 13.5,-13.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 138 components: - type: Transform pos: 13.5,-12.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 139 components: - type: Transform pos: -14.5,-12.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 140 components: - type: Transform pos: -6.5,-15.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 141 components: - type: Transform pos: -6.5,-12.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 142 components: - type: Transform pos: -6.5,-14.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 143 components: - type: Transform rot: 1.5707963267948966 rad pos: -7.5,-8.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 144 components: - type: Transform rot: 1.5707963267948966 rad pos: -7.5,-7.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 145 components: - type: Transform rot: 1.5707963267948966 rad pos: -7.5,-6.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 147 components: - type: Transform rot: 1.5707963267948966 rad pos: -13.5,-8.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 148 components: - type: Transform rot: 1.5707963267948966 rad pos: -13.5,-7.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 149 components: - type: Transform rot: 1.5707963267948966 rad pos: -13.5,-6.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 151 components: - type: Transform rot: 1.5707963267948966 rad pos: 12.5,-8.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 152 components: - type: Transform rot: 1.5707963267948966 rad pos: 12.5,-7.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 153 components: - type: Transform rot: 1.5707963267948966 rad pos: 12.5,-6.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 155 components: - type: Transform rot: 1.5707963267948966 rad pos: 6.5,-8.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 156 components: - type: Transform rot: 1.5707963267948966 rad pos: 6.5,-7.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 157 components: - type: Transform rot: 1.5707963267948966 rad pos: 6.5,-6.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 167 components: - type: Transform rot: 1.5707963267948966 rad pos: 12.5,-19.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 168 components: - type: Transform rot: 1.5707963267948966 rad pos: 12.5,-20.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 169 components: - type: Transform rot: 1.5707963267948966 rad pos: 11.5,-20.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 170 components: - type: Transform rot: 1.5707963267948966 rad pos: 11.5,-21.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 171 components: - type: Transform rot: 1.5707963267948966 rad pos: 10.5,-21.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 172 components: - type: Transform rot: 1.5707963267948966 rad pos: 8.5,-21.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 173 components: - type: Transform rot: 1.5707963267948966 rad pos: 7.5,-21.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 174 components: - type: Transform rot: 1.5707963267948966 rad pos: 7.5,-20.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 175 components: - type: Transform rot: 1.5707963267948966 rad pos: 6.5,-20.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 176 components: - type: Transform rot: 1.5707963267948966 rad pos: 6.5,-19.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 178 components: - type: Transform pos: 3.5,-2.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 183 components: - type: Transform pos: -3.5,-2.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 184 components: - type: Transform pos: 4.5,-2.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 191 components: - type: Transform pos: -5.5,-2.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 197 components: - type: Transform pos: -4.5,-2.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 229 components: - type: Transform pos: 2.5,-2.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 233 components: - type: Transform pos: -8.5,-4.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 234 components: - type: Transform pos: 11.5,-4.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 235 components: - type: Transform pos: 7.5,-4.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 244 components: - type: Transform pos: -12.5,-4.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 276 components: - type: Transform pos: 13.5,-2.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 277 components: - type: Transform pos: 13.5,-1.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 278 components: - type: Transform pos: 13.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 279 components: - type: Transform pos: 13.5,0.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 280 components: - type: Transform pos: -14.5,-2.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 281 components: - type: Transform pos: -14.5,-1.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 282 components: - type: Transform pos: -14.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 283 components: - type: Transform pos: -14.5,0.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 318 components: - type: Transform pos: -13.5,3.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 319 components: - type: Transform pos: -13.5,4.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 320 components: - type: Transform pos: -12.5,4.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 321 components: - type: Transform pos: -12.5,5.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 322 components: - type: Transform pos: -11.5,5.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 323 components: - type: Transform pos: -10.5,5.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 324 components: - type: Transform pos: -9.5,5.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 325 components: - type: Transform pos: -8.5,5.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 326 components: - type: Transform pos: -8.5,4.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 327 components: - type: Transform pos: -7.5,4.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 328 components: - type: Transform pos: -7.5,3.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 329 components: - type: Transform pos: 6.5,3.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 330 components: - type: Transform pos: 6.5,4.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 331 components: - type: Transform pos: 7.5,4.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 332 components: - type: Transform pos: 7.5,5.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 333 components: - type: Transform pos: 8.5,5.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 334 components: - type: Transform pos: 9.5,5.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 335 components: - type: Transform pos: 10.5,5.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 336 components: - type: Transform pos: 11.5,5.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 337 components: - type: Transform pos: 11.5,4.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 338 components: - type: Transform pos: 12.5,4.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 339 components: - type: Transform pos: 12.5,3.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - proto: PaperBin10 entities: - - uid: 737 + - uid: 729 components: - type: Transform - rot: 3.141592653589793 rad pos: 8.5,4.5 parent: 818 - proto: PosterLegitCohibaRobustoAd @@ -3856,6 +6417,9 @@ entities: - type: Transform pos: -6.5,1.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - proto: PosterLegitEnlist entities: - uid: 926 @@ -3863,6 +6427,9 @@ entities: - type: Transform pos: -14.5,1.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - proto: PosterLegitHighClassMartini entities: - uid: 925 @@ -3870,6 +6437,9 @@ entities: - type: Transform pos: -6.5,-3.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - proto: PosterLegitJustAWeekAway entities: - uid: 821 @@ -3877,6 +6447,9 @@ entities: - type: Transform pos: 5.5,1.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - proto: PosterLegitNanomichiAd entities: - uid: 820 @@ -3884,6 +6457,9 @@ entities: - type: Transform pos: -4.5,3.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - proto: PosterLegitNanotrasenLogo entities: - uid: 246 @@ -3891,36 +6467,57 @@ entities: - type: Transform pos: -7.5,-11.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 247 components: - type: Transform pos: -13.5,-4.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 248 components: - type: Transform pos: 12.5,-4.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 249 components: - type: Transform pos: 6.5,-16.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 250 components: - type: Transform pos: -13.5,-16.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 251 components: - type: Transform pos: 12.5,-11.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 922 components: - type: Transform pos: -0.5,6.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - proto: PosterLegitNTTGC entities: - uid: 924 @@ -3928,6 +6525,9 @@ entities: - type: Transform pos: 5.5,-3.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - proto: PosterLegitPDAAd entities: - uid: 920 @@ -3935,6 +6535,9 @@ entities: - type: Transform pos: 12.5,-16.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - proto: PosterLegitVacation entities: - uid: 921 @@ -3942,6 +6545,9 @@ entities: - type: Transform pos: -7.5,-16.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - proto: PosterLegitWorkForAFuture entities: - uid: 923 @@ -3949,6 +6555,9 @@ entities: - type: Transform pos: 12.5,2.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - proto: PottedPlantRandom entities: - uid: 236 @@ -3956,31 +6565,37 @@ entities: - type: Transform pos: 7.5,-19.5 parent: 818 + - type: Godmode - uid: 237 components: - type: Transform pos: -12.5,-19.5 parent: 818 + - type: Godmode - uid: 238 components: - type: Transform pos: 11.5,-19.5 parent: 818 + - type: Godmode - uid: 239 components: - type: Transform pos: -8.5,-19.5 parent: 818 + - type: Godmode - uid: 733 components: - type: Transform pos: -8.5,-5.5 parent: 818 + - type: Godmode - uid: 741 components: - type: Transform pos: -7.5,-3.5 parent: 818 + - type: Godmode - proto: PottedPlantRandomPlastic entities: - uid: 708 @@ -3988,130 +6603,13 @@ entities: - type: Transform pos: -13.5,1.5 parent: 818 + - type: Godmode - uid: 755 components: - type: Transform pos: -13.5,-3.5 parent: 818 -- proto: Poweredlight - entities: - - uid: 150 - components: - - type: MetaData - flags: PvsPriority - - type: Transform - rot: -1.5707963267948966 rad - pos: -8.5,-5.5 - parent: 818 - - uid: 188 - components: - - type: MetaData - flags: PvsPriority - - type: Transform - rot: -1.5707963267948966 rad - pos: 11.5,2.5 - parent: 818 - - uid: 195 - components: - - type: MetaData - flags: PvsPriority - - type: Transform - rot: 3.141592653589793 rad - pos: -2.5,-1.5 - parent: 818 - - uid: 209 - components: - - type: MetaData - flags: PvsPriority - - type: Transform - rot: 1.5707963267948966 rad - pos: 7.5,-5.5 - parent: 818 - - uid: 341 - components: - - type: MetaData - flags: PvsPriority - - type: Transform - rot: 3.141592653589793 rad - pos: 1.5,-1.5 - parent: 818 - - uid: 634 - components: - - type: MetaData - flags: PvsPriority - - type: Transform - pos: 9.5,-16.5 - parent: 818 - - uid: 636 - components: - - type: MetaData - flags: PvsPriority - - type: Transform - rot: 3.141592653589793 rad - pos: 9.5,-11.5 - parent: 818 - - uid: 649 - components: - - type: MetaData - flags: PvsPriority - - type: Transform - rot: 3.141592653589793 rad - pos: -10.5,-11.5 - parent: 818 - - uid: 650 - components: - - type: MetaData - flags: PvsPriority - - type: Transform - pos: -10.5,-16.5 - parent: 818 - - uid: 687 - components: - - type: MetaData - flags: PvsPriority - - type: Transform - rot: 1.5707963267948966 rad - pos: -13.5,1.5 - parent: 818 - - uid: 701 - components: - - type: MetaData - flags: PvsPriority - - type: Transform - rot: 3.141592653589793 rad - pos: -6.5,3.5 - parent: 818 - - uid: 702 - components: - - type: MetaData - flags: PvsPriority - - type: Transform - rot: 3.141592653589793 rad - pos: 5.5,3.5 - parent: 818 - - uid: 715 - components: - - type: MetaData - flags: PvsPriority - - type: Transform - pos: -0.5,5.5 - parent: 818 - - uid: 717 - components: - - type: MetaData - flags: PvsPriority - - type: Transform - rot: -1.5707963267948966 rad - pos: -7.5,-3.5 - parent: 818 - - uid: 742 - components: - - type: MetaData - flags: PvsPriority - - type: Transform - rot: 1.5707963267948966 rad - pos: 6.5,-3.5 - parent: 818 + - type: Godmode - proto: RandomSpawner entities: - uid: 895 @@ -4119,32 +6617,7 @@ entities: - type: Transform pos: -4.5,4.5 parent: 818 -- proto: RandomVending - entities: - - uid: 835 - components: - - type: Transform - pos: 9.5,-20.5 - parent: 818 - - uid: 836 - components: - - type: Transform - pos: -10.5,-20.5 - parent: 818 -- proto: RandomVendingDrinks - entities: - - uid: 692 - components: - - type: Transform - pos: 11.5,-5.5 - parent: 818 -- proto: RandomVendingSnacks - entities: - - uid: 834 - components: - - type: Transform - pos: 11.5,-6.5 - parent: 818 + - type: Godmode - proto: ReinforcedWindow entities: - uid: 19 @@ -4153,472 +6626,912 @@ entities: rot: 1.5707963267948966 rad pos: -7.5,-20.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 20 components: - type: Transform rot: 1.5707963267948966 rad pos: -8.5,-20.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 21 components: - type: Transform rot: 1.5707963267948966 rad pos: -8.5,-21.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 22 components: - type: Transform rot: 1.5707963267948966 rad pos: -9.5,-21.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 24 components: - type: Transform rot: 1.5707963267948966 rad pos: -7.5,-19.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 25 components: - type: Transform rot: 1.5707963267948966 rad pos: -11.5,-21.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 26 components: - type: Transform rot: 1.5707963267948966 rad pos: -12.5,-21.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 27 components: - type: Transform rot: 1.5707963267948966 rad pos: -12.5,-20.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 28 components: - type: Transform rot: 1.5707963267948966 rad pos: -13.5,-20.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 29 components: - type: Transform rot: 1.5707963267948966 rad pos: -13.5,-19.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 30 components: - type: Transform rot: 1.5707963267948966 rad pos: 8.5,-21.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 31 components: - type: Transform rot: 1.5707963267948966 rad pos: 7.5,-21.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 32 components: - type: Transform rot: 1.5707963267948966 rad pos: 7.5,-20.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 33 components: - type: Transform rot: 1.5707963267948966 rad pos: 6.5,-20.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 34 components: - type: Transform rot: 1.5707963267948966 rad pos: 6.5,-19.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 35 components: - type: Transform rot: 1.5707963267948966 rad pos: 10.5,-21.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 36 components: - type: Transform rot: 1.5707963267948966 rad pos: 11.5,-21.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 37 components: - type: Transform rot: 1.5707963267948966 rad pos: 11.5,-20.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 38 components: - type: Transform rot: 1.5707963267948966 rad pos: 12.5,-20.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 39 components: - type: Transform rot: 1.5707963267948966 rad pos: 12.5,-19.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 91 components: - type: Transform pos: -14.5,-12.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 93 components: - type: Transform pos: -14.5,-14.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 94 components: - type: Transform pos: -6.5,-13.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 95 components: - type: Transform pos: -6.5,-12.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 100 components: - type: Transform rot: 1.5707963267948966 rad pos: -7.5,-8.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 105 components: - type: Transform pos: 5.5,-12.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 106 components: - type: Transform pos: 5.5,-14.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 107 components: - type: Transform pos: 13.5,-12.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 108 components: - type: Transform pos: 13.5,-13.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 109 components: - type: Transform rot: 1.5707963267948966 rad pos: 12.5,-8.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 110 components: - type: Transform rot: 1.5707963267948966 rad pos: 12.5,-7.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 111 components: - type: Transform rot: 1.5707963267948966 rad pos: 12.5,-6.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 113 components: - type: Transform rot: 1.5707963267948966 rad pos: 6.5,-6.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 115 components: - type: Transform rot: 1.5707963267948966 rad pos: 6.5,-7.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 116 components: - type: Transform rot: 1.5707963267948966 rad pos: 6.5,-8.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 117 components: - type: Transform rot: 1.5707963267948966 rad pos: -7.5,-7.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 118 components: - type: Transform rot: 1.5707963267948966 rad pos: -7.5,-6.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 121 components: - type: Transform rot: 1.5707963267948966 rad pos: -13.5,-8.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 122 components: - type: Transform rot: 1.5707963267948966 rad pos: -13.5,-7.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 123 components: - type: Transform rot: 1.5707963267948966 rad pos: -13.5,-6.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 159 components: - type: Transform pos: -14.5,-13.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 160 components: - type: Transform pos: -14.5,-15.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 161 components: - type: Transform pos: -6.5,-14.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 162 components: - type: Transform pos: -6.5,-15.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 163 components: - type: Transform pos: 5.5,-13.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 164 components: - type: Transform pos: 13.5,-15.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 165 components: - type: Transform pos: 5.5,-15.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 166 components: - type: Transform pos: 13.5,-14.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 185 components: - type: Transform pos: -5.5,-2.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 186 components: - type: Transform pos: 2.5,-2.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 192 components: - type: Transform pos: 4.5,-2.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 196 components: - type: Transform pos: 3.5,-2.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 198 components: - type: Transform pos: -3.5,-2.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 232 components: - type: Transform pos: -4.5,-2.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 240 components: - type: Transform pos: -12.5,-4.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 241 components: - type: Transform pos: 11.5,-4.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 242 components: - type: Transform pos: 7.5,-4.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 243 components: - type: Transform pos: -8.5,-4.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 268 components: - type: Transform pos: -14.5,-2.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 269 components: - type: Transform pos: -14.5,-1.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 270 components: - type: Transform pos: -14.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 271 components: - type: Transform pos: -14.5,0.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 272 components: - type: Transform pos: 13.5,-2.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 273 components: - type: Transform pos: 13.5,-1.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 274 components: - type: Transform pos: 13.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 275 components: - type: Transform pos: 13.5,0.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 284 components: - type: Transform pos: -13.5,4.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 285 components: - type: Transform pos: -12.5,4.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 286 components: - type: Transform pos: -10.5,5.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 287 components: - type: Transform pos: -11.5,5.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 288 components: - type: Transform pos: -8.5,4.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 289 components: - type: Transform pos: -8.5,5.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 290 components: - type: Transform pos: -12.5,5.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 291 components: - type: Transform pos: -13.5,3.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 292 components: - type: Transform pos: -9.5,5.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 293 components: - type: Transform pos: 6.5,3.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 294 components: - type: Transform pos: -7.5,3.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 295 components: - type: Transform pos: -7.5,4.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 308 components: - type: Transform pos: 6.5,4.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 309 components: - type: Transform pos: 7.5,4.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 310 components: - type: Transform pos: 7.5,5.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 311 components: - type: Transform pos: 8.5,5.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 312 components: - type: Transform pos: 9.5,5.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 313 components: - type: Transform pos: 10.5,5.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 314 components: - type: Transform pos: 11.5,5.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 315 components: - type: Transform pos: 11.5,4.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 316 components: - type: Transform pos: 12.5,4.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 317 components: - type: Transform pos: 12.5,3.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - proto: SignNanotrasen1 entities: - uid: 721 @@ -4626,6 +7539,9 @@ entities: - type: Transform pos: -2.5,-2.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - proto: SignNanotrasen2 entities: - uid: 722 @@ -4633,6 +7549,9 @@ entities: - type: Transform pos: -1.5,-2.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - proto: SignNanotrasen3 entities: - uid: 719 @@ -4640,6 +7559,9 @@ entities: - type: Transform pos: -0.5,-2.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - proto: SignNanotrasen4 entities: - uid: 801 @@ -4647,6 +7569,9 @@ entities: - type: Transform pos: 0.5,-2.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - proto: SignNanotrasen5 entities: - uid: 802 @@ -4654,6 +7579,9 @@ entities: - type: Transform pos: 1.5,-2.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - proto: SignNosmoking entities: - uid: 720 @@ -4661,6 +7589,9 @@ entities: - type: Transform pos: -7.5,2.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - proto: SignShipDock entities: - uid: 200 @@ -4668,11 +7599,17 @@ entities: - type: Transform pos: 6.5,-4.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 245 components: - type: Transform pos: -7.5,-4.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - proto: SignSpace entities: - uid: 571 @@ -4680,46 +7617,73 @@ entities: - type: Transform pos: 12.5,-18.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 640 components: - type: Transform pos: -7.5,-18.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 688 components: - type: Transform pos: -13.5,-18.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 689 components: - type: Transform pos: -7.5,-9.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 691 components: - type: Transform pos: -13.5,-9.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 705 components: - type: Transform pos: 12.5,-9.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 709 components: - type: Transform pos: 6.5,-9.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 817 components: - type: Transform pos: 6.5,-18.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 819 components: - type: Transform pos: 4.5,7.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - proto: SinkWide entities: - uid: 913 @@ -4728,6 +7692,9 @@ entities: rot: 1.5707963267948966 rad pos: -12.5,3.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - proto: SmallLight entities: - uid: 598 @@ -4736,52 +7703,102 @@ entities: rot: -1.5707963267948966 rad pos: -8.5,2.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - Construction + - RCDDeconstructable - uid: 641 components: - type: Transform pos: -14.5,-17.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - Construction + - RCDDeconstructable - uid: 642 components: - type: Transform pos: -6.5,-17.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - Construction + - RCDDeconstructable - uid: 643 components: - type: Transform pos: -14.5,-10.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - Construction + - RCDDeconstructable - uid: 644 components: - type: Transform pos: -6.5,-10.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - Construction + - RCDDeconstructable - uid: 645 components: - type: Transform pos: 5.5,-10.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - Construction + - RCDDeconstructable - uid: 646 components: - type: Transform pos: 13.5,-10.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - Construction + - RCDDeconstructable - uid: 647 components: - type: Transform pos: 13.5,-17.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - Construction + - RCDDeconstructable - uid: 648 components: - type: Transform pos: 5.5,-17.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - Construction + - RCDDeconstructable - uid: 917 components: - type: Transform rot: 3.141592653589793 rad pos: -0.5,7.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - Construction + - RCDDeconstructable - proto: SMESBasic entities: - uid: 805 @@ -4789,13 +7806,24 @@ entities: - type: Transform pos: -2.5,8.5 parent: 818 -- proto: soda_dispenser + - type: Godmode + missingComponents: + - Anchorable + - Destructible + - Construction +- proto: SodaDispenser entities: - uid: 795 components: - type: Transform pos: -10.5,4.5 parent: 818 + - type: Godmode + missingComponents: + - ApcPowerReceiver + - Anchorable + - Destructible + - Construction - proto: SpaceVillainArcadeFilled entities: - uid: 731 @@ -4804,12 +7832,24 @@ entities: rot: 1.5707963267948966 rad pos: -13.5,-2.5 parent: 818 + - type: Godmode + missingComponents: + - ApcPowerReceiver + - Anchorable + - Construction + - Destructible - uid: 732 components: - type: Transform rot: 1.5707963267948966 rad pos: -13.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - ApcPowerReceiver + - Anchorable + - Construction + - Destructible - proto: SpawnPointLatejoin entities: - uid: 763 @@ -4817,161 +7857,193 @@ entities: - type: Transform pos: -7.5,-15.5 parent: 818 + - type: Godmode - uid: 764 components: - type: Transform pos: -7.5,-14.5 parent: 818 + - type: Godmode - uid: 765 components: - type: Transform pos: -7.5,-13.5 parent: 818 + - type: Godmode - uid: 766 components: - type: Transform pos: -7.5,-12.5 parent: 818 + - type: Godmode - uid: 767 components: - type: Transform pos: -9.5,-15.5 parent: 818 + - type: Godmode - uid: 768 components: - type: Transform pos: -9.5,-14.5 parent: 818 + - type: Godmode - uid: 769 components: - type: Transform pos: -9.5,-13.5 parent: 818 + - type: Godmode - uid: 770 components: - type: Transform pos: -9.5,-12.5 parent: 818 + - type: Godmode - uid: 771 components: - type: Transform pos: -11.5,-15.5 parent: 818 + - type: Godmode - uid: 772 components: - type: Transform pos: -11.5,-14.5 parent: 818 + - type: Godmode - uid: 773 components: - type: Transform pos: -11.5,-13.5 parent: 818 + - type: Godmode - uid: 774 components: - type: Transform pos: -11.5,-12.5 parent: 818 + - type: Godmode - uid: 775 components: - type: Transform pos: -13.5,-15.5 parent: 818 + - type: Godmode - uid: 776 components: - type: Transform pos: -13.5,-14.5 parent: 818 + - type: Godmode - uid: 777 components: - type: Transform pos: -13.5,-13.5 parent: 818 + - type: Godmode - uid: 778 components: - type: Transform pos: -13.5,-12.5 parent: 818 + - type: Godmode - uid: 779 components: - type: Transform pos: 6.5,-15.5 parent: 818 + - type: Godmode - uid: 780 components: - type: Transform pos: 6.5,-14.5 parent: 818 + - type: Godmode - uid: 781 components: - type: Transform pos: 6.5,-13.5 parent: 818 + - type: Godmode - uid: 782 components: - type: Transform pos: 6.5,-12.5 parent: 818 + - type: Godmode - uid: 783 components: - type: Transform pos: 8.5,-15.5 parent: 818 + - type: Godmode - uid: 784 components: - type: Transform pos: 8.5,-14.5 parent: 818 + - type: Godmode - uid: 785 components: - type: Transform pos: 8.5,-13.5 parent: 818 + - type: Godmode - uid: 786 components: - type: Transform pos: 8.5,-12.5 parent: 818 + - type: Godmode - uid: 787 components: - type: Transform pos: 10.5,-15.5 parent: 818 + - type: Godmode - uid: 788 components: - type: Transform pos: 10.5,-14.5 parent: 818 + - type: Godmode - uid: 789 components: - type: Transform pos: 10.5,-13.5 parent: 818 + - type: Godmode - uid: 790 components: - type: Transform pos: 10.5,-12.5 parent: 818 + - type: Godmode - uid: 791 components: - type: Transform pos: 12.5,-15.5 parent: 818 + - type: Godmode - uid: 792 components: - type: Transform pos: 12.5,-14.5 parent: 818 + - type: Godmode - uid: 793 components: - type: Transform pos: 12.5,-13.5 parent: 818 + - type: Godmode - uid: 794 components: - type: Transform pos: 12.5,-12.5 parent: 818 + - type: Godmode - proto: SS13Memorial entities: - uid: 594 @@ -4979,56 +8051,121 @@ entities: - type: Transform pos: -0.5,4.5 parent: 818 + - type: Godmode - proto: Stool entities: - uid: 119 components: - type: Transform + anchored: True rot: 3.141592653589793 rad pos: -11.5,-20.5 parent: 818 + - type: Physics + bodyType: Static + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 639 components: - type: Transform + anchored: True rot: 3.141592653589793 rad pos: -9.5,-20.5 parent: 818 - - uid: 723 - components: - - type: Transform - rot: 3.141592653589793 rad - pos: 10.5,-20.5 - parent: 818 - - uid: 724 - components: - - type: Transform - rot: 3.141592653589793 rad - pos: 8.5,-20.5 - parent: 818 - - uid: 729 - components: - - type: Transform - rot: -1.5707963267948966 rad - pos: -12.5,-1.5 - parent: 818 + - type: Physics + bodyType: Static + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 730 components: - type: Transform - rot: -1.5707963267948966 rad - pos: -12.5,-2.5 + anchored: True + rot: 3.141592653589793 rad + pos: 8.5,-20.5 parent: 818 + - type: Physics + bodyType: Static + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible + - uid: 737 + components: + - type: Transform + anchored: True + rot: 3.141592653589793 rad + pos: 10.5,-20.5 + parent: 818 + - type: Physics + bodyType: Static + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 738 components: - type: Transform + anchored: True rot: -1.5707963267948966 rad pos: -12.5,-0.5 parent: 818 + - type: Physics + bodyType: Static + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 740 components: - type: Transform + anchored: True rot: -1.5707963267948966 rad pos: -12.5,0.5 parent: 818 + - type: Physics + bodyType: Static + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible + - uid: 761 + components: + - type: Transform + anchored: True + rot: -1.5707963267948966 rad + pos: -12.5,-1.5 + parent: 818 + - type: Physics + bodyType: Static + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible + - uid: 914 + components: + - type: Transform + anchored: True + rot: -1.5707963267948966 rad + pos: -12.5,-2.5 + parent: 818 + - type: Physics + bodyType: Static + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - proto: StoolBar entities: - uid: 230 @@ -5037,18 +8174,33 @@ entities: rot: 3.141592653589793 rad pos: -9.5,1.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 342 components: - type: Transform rot: 3.141592653589793 rad pos: -11.5,1.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 433 components: - type: Transform rot: 3.141592653589793 rad pos: -10.5,1.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - proto: SubstationBasic entities: - uid: 807 @@ -5056,6 +8208,11 @@ entities: - type: Transform pos: -0.5,8.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - Anchorable + - Construction - proto: TableCarpet entities: - uid: 572 @@ -5063,21 +8220,37 @@ entities: - type: Transform pos: 9.5,0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - Construction - uid: 573 components: - type: Transform pos: 9.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - Construction - uid: 574 components: - type: Transform pos: 10.5,-0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - Construction - uid: 576 components: - type: Transform pos: 10.5,0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - Construction - proto: TableReinforced entities: - uid: 585 @@ -5086,36 +8259,60 @@ entities: rot: 1.5707963267948966 rad pos: -9.5,2.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - Construction - uid: 707 components: - type: Transform rot: -1.5707963267948966 rad pos: -10.5,4.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - Construction - uid: 751 components: - type: Transform rot: -1.5707963267948966 rad pos: -11.5,4.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - Construction - uid: 796 components: - type: Transform rot: -1.5707963267948966 rad pos: -10.5,2.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - Construction - uid: 797 components: - type: Transform rot: -1.5707963267948966 rad pos: -12.5,2.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - Construction - uid: 798 components: - type: Transform rot: -1.5707963267948966 rad pos: -11.5,2.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - Construction - proto: TableWood entities: - uid: 441 @@ -5123,31 +8320,55 @@ entities: - type: Transform pos: 12.5,0.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - Construction - uid: 575 components: - type: Transform pos: 6.5,-2.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - Construction - uid: 587 components: - type: Transform pos: 12.5,-2.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - Construction - uid: 706 components: - type: Transform pos: 9.5,4.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - Construction - uid: 750 components: - type: Transform pos: 10.5,4.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - Construction - uid: 756 components: - type: Transform pos: 8.5,4.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - Construction - proto: TelecomServerFilled entities: - uid: 919 @@ -5155,972 +8376,1162 @@ entities: - type: Transform pos: -1.5,8.5 parent: 818 + - type: EncryptionKeyHolder + keysUnlocked: False + - type: Godmode + missingComponents: + - Destructible + - ApcPowerReceiver + - Anchorable + - Construction - proto: VendingMachineBooze entities: - uid: 753 components: - - type: MetaData - flags: SessionSpecific - type: Transform pos: -9.5,4.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - Anchorable + - ApcPowerReceiver +- proto: VendingMachineChang + entities: + - uid: 692 + components: + - type: Transform + pos: 9.5,-20.5 + parent: 818 + - type: Godmode + missingComponents: + - Destructible + - Anchorable - proto: VendingMachineCigs entities: - uid: 744 components: - - type: MetaData - flags: SessionSpecific - type: Transform pos: -7.5,1.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - Anchorable + - ApcPowerReceiver - proto: VendingMachineCola entities: - uid: 635 components: - - type: MetaData - flags: SessionSpecific - type: Transform pos: -12.5,-5.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - Anchorable + - ApcPowerReceiver +- proto: VendingMachineColaBlack + entities: + - uid: 834 + components: + - type: Transform + pos: -10.5,-20.5 + parent: 818 + - type: Godmode + missingComponents: + - Destructible + - Anchorable +- proto: VendingMachineDiscount + entities: + - uid: 836 + components: + - type: Transform + pos: 11.5,-6.5 + parent: 818 + - type: Godmode + missingComponents: + - Destructible + - Anchorable +- proto: VendingMachineDrGibb + entities: + - uid: 835 + components: + - type: Transform + pos: 11.5,-5.5 + parent: 818 + - type: Godmode + missingComponents: + - Destructible + - Anchorable - proto: VendingMachineGames entities: - uid: 748 components: - - type: MetaData - flags: SessionSpecific - type: Transform pos: 6.5,1.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - Anchorable + - ApcPowerReceiver - proto: VendingMachineSnack entities: - uid: 637 components: - - type: MetaData - flags: SessionSpecific - type: Transform pos: -12.5,-6.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible + - Anchorable + - ApcPowerReceiver - proto: WallRiveted entities: - uid: 10 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: 1.5707963267948966 rad pos: 6.5,-4.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 23 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: 1.5707963267948966 rad pos: -10.5,-21.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 40 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: 1.5707963267948966 rad pos: 9.5,-21.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 41 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: 1.5707963267948966 rad pos: 6.5,-18.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 42 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: 1.5707963267948966 rad pos: 5.5,-18.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 43 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: 1.5707963267948966 rad pos: 4.5,-18.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 44 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: 1.5707963267948966 rad pos: 12.5,-18.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 45 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: 1.5707963267948966 rad pos: 13.5,-18.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 46 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: 1.5707963267948966 rad pos: 14.5,-18.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 47 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: 1.5707963267948966 rad pos: -5.5,-18.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 48 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: 1.5707963267948966 rad pos: -6.5,-18.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 49 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: 1.5707963267948966 rad pos: -7.5,-18.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 50 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: 1.5707963267948966 rad pos: -13.5,-18.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 51 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: 1.5707963267948966 rad pos: -14.5,-18.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 52 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: 1.5707963267948966 rad pos: -15.5,-18.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 53 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: 1.5707963267948966 rad pos: -13.5,-9.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 54 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: 1.5707963267948966 rad pos: -14.5,-9.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 55 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: 1.5707963267948966 rad pos: -15.5,-9.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 56 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: 1.5707963267948966 rad pos: -7.5,-9.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 57 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: 1.5707963267948966 rad pos: -6.5,-9.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 58 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: 1.5707963267948966 rad pos: -5.5,-9.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 59 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: 1.5707963267948966 rad pos: -5.5,-11.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 60 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: 1.5707963267948966 rad pos: -6.5,-11.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 61 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: 1.5707963267948966 rad pos: -7.5,-11.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 62 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: 1.5707963267948966 rad pos: -13.5,-11.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 63 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: 1.5707963267948966 rad pos: -14.5,-11.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 64 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: 1.5707963267948966 rad pos: -15.5,-11.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 65 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: 1.5707963267948966 rad pos: -13.5,-16.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 66 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: 1.5707963267948966 rad pos: -14.5,-16.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 67 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: 1.5707963267948966 rad pos: -15.5,-16.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 68 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: 1.5707963267948966 rad pos: -7.5,-16.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 69 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: 1.5707963267948966 rad pos: -6.5,-16.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 70 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: 1.5707963267948966 rad pos: -5.5,-16.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 71 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: 1.5707963267948966 rad pos: 12.5,-16.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 72 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: 1.5707963267948966 rad pos: 13.5,-16.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 73 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: 1.5707963267948966 rad pos: 14.5,-16.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 74 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: 1.5707963267948966 rad pos: 14.5,-11.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 75 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: 1.5707963267948966 rad pos: 13.5,-11.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 76 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: 1.5707963267948966 rad pos: 12.5,-11.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 77 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: 1.5707963267948966 rad pos: 14.5,-9.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 78 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: 1.5707963267948966 rad pos: 13.5,-9.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 79 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: 1.5707963267948966 rad pos: 12.5,-9.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 80 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: 1.5707963267948966 rad pos: 6.5,-9.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 81 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: 1.5707963267948966 rad pos: 5.5,-9.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 82 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: 1.5707963267948966 rad pos: 4.5,-9.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 83 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: 1.5707963267948966 rad pos: 6.5,-11.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 84 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: 1.5707963267948966 rad pos: 5.5,-11.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 85 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: 1.5707963267948966 rad pos: 4.5,-11.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 86 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: 1.5707963267948966 rad pos: 6.5,-16.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 87 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: 1.5707963267948966 rad pos: 5.5,-16.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 88 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: 1.5707963267948966 rad pos: 4.5,-16.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 89 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: 1.5707963267948966 rad pos: -7.5,-4.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 90 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: 1.5707963267948966 rad pos: -13.5,-4.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 92 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: 1.5707963267948966 rad pos: 12.5,-4.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 112 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: -1.5707963267948966 rad pos: 6.5,-5.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 114 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: -1.5707963267948966 rad pos: -13.5,-5.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 120 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: 5.5,1.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 154 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: -1.5707963267948966 rad pos: 12.5,-5.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 158 components: - - type: MetaData - flags: PvsPriority - type: Transform rot: -1.5707963267948966 rad pos: -7.5,-5.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 179 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: -2.5,-2.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 180 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: 5.5,-3.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 182 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: 1.5,-2.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 187 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: -6.5,-2.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 189 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: 5.5,-4.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 190 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: 1.5,9.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 193 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: 5.5,-2.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 199 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: -6.5,-4.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 202 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: -6.5,1.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 207 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: -6.5,-3.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 217 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: -4.5,3.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 222 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: -2.5,9.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 223 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: -0.5,9.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 225 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: -1.5,9.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 231 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: -4.5,9.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 258 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: -14.5,-4.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 259 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: 13.5,-3.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 260 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: 13.5,-4.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 261 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: -14.5,-3.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 262 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: 13.5,1.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 263 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: 13.5,2.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 264 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: 12.5,2.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 265 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: -14.5,1.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 266 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: -14.5,2.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 267 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: -13.5,2.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 304 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: -7.5,2.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 306 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: -6.5,2.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 307 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: 6.5,2.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 340 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: 5.5,2.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 343 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: 0.5,9.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 351 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: -3.5,9.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 401 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: -5.5,2.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 403 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: 4.5,9.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 405 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: -1.5,6.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 406 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: 4.5,2.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 407 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: 2.5,6.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 408 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: 2.5,4.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 409 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: 2.5,5.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 414 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: 3.5,9.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 420 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: 2.5,3.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 578 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: -3.5,3.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 581 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: -3.5,5.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 582 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: -3.5,4.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 583 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: -3.5,6.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 588 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: -2.5,6.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 602 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: 0.5,6.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 693 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: 1.5,6.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 711 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: -1.5,-2.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 712 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: -0.5,-2.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 713 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: 0.5,-2.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 725 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: -5.5,4.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 726 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: -5.5,3.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 736 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: -5.5,5.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 739 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: -5.5,6.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 743 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: -5.5,7.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 745 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: -5.5,8.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 746 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: 2.5,9.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 754 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: 4.5,7.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 757 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: 4.5,3.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 758 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: 4.5,6.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 762 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: 4.5,5.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 799 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: 4.5,4.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 800 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: -5.5,9.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - uid: 804 components: - - type: MetaData - flags: PvsPriority - type: Transform pos: -0.5,6.5 parent: 818 + - type: Godmode + missingComponents: + - Destructible - proto: WarpPoint entities: - uid: 638 @@ -6130,6 +9541,7 @@ entities: parent: 818 - type: WarpPoint location: Terminal + - type: Godmode - proto: Windoor entities: - uid: 806 @@ -6137,11 +9549,21 @@ entities: - type: Transform pos: -8.5,2.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - uid: 841 components: - type: Transform pos: -2.5,3.5 parent: 818 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - proto: WindowReinforcedDirectional entities: - uid: 181 @@ -6150,198 +9572,373 @@ entities: rot: 1.5707963267948966 rad pos: -9.5,2.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 204 components: - type: Transform rot: 1.5707963267948966 rad pos: 0.5,8.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 600 components: - type: Transform rot: -1.5707963267948966 rad pos: 2.5,8.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 659 components: - type: Transform pos: 9.5,-15.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 660 components: - type: Transform rot: 3.141592653589793 rad pos: 9.5,-12.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 661 components: - type: Transform rot: 1.5707963267948966 rad pos: 9.5,-12.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 662 components: - type: Transform rot: 1.5707963267948966 rad pos: 9.5,-13.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 663 components: - type: Transform rot: 1.5707963267948966 rad pos: 9.5,-14.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 664 components: - type: Transform rot: 1.5707963267948966 rad pos: 9.5,-15.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 665 components: - type: Transform rot: -1.5707963267948966 rad pos: 9.5,-15.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 666 components: - type: Transform rot: -1.5707963267948966 rad pos: 9.5,-14.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 667 components: - type: Transform rot: -1.5707963267948966 rad pos: 9.5,-13.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 668 components: - type: Transform rot: -1.5707963267948966 rad pos: 9.5,-12.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 669 components: - type: Transform rot: 3.141592653589793 rad pos: -10.5,-12.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 670 components: - type: Transform pos: -10.5,-15.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 671 components: - type: Transform rot: -1.5707963267948966 rad pos: -10.5,-15.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 672 components: - type: Transform rot: -1.5707963267948966 rad pos: -10.5,-14.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 673 components: - type: Transform rot: -1.5707963267948966 rad pos: -10.5,-13.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 674 components: - type: Transform rot: -1.5707963267948966 rad pos: -10.5,-12.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 675 components: - type: Transform rot: 1.5707963267948966 rad pos: -10.5,-12.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 676 components: - type: Transform rot: 1.5707963267948966 rad pos: -10.5,-13.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 677 components: - type: Transform rot: 1.5707963267948966 rad pos: -10.5,-14.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 678 components: - type: Transform rot: 1.5707963267948966 rad pos: -10.5,-15.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 679 components: - type: Transform rot: 3.141592653589793 rad pos: -9.5,-16.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 680 components: - type: Transform rot: 3.141592653589793 rad pos: -11.5,-16.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 681 components: - type: Transform pos: -11.5,-11.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 682 components: - type: Transform pos: -9.5,-11.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 683 components: - type: Transform pos: 10.5,-11.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 684 components: - type: Transform pos: 8.5,-11.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 685 components: - type: Transform rot: 3.141592653589793 rad pos: 8.5,-16.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 686 components: - type: Transform rot: 3.141592653589793 rad pos: 10.5,-16.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 837 components: - type: Transform pos: 1.5,3.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 838 components: - type: Transform pos: 0.5,3.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 839 components: - type: Transform pos: -0.5,3.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 840 components: - type: Transform pos: -1.5,3.5 parent: 818 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible ... diff --git a/Resources/Prototypes/Entities/Structures/Power/cable_terminal.yml b/Resources/Prototypes/Entities/Structures/Power/cable_terminal.yml index 8c7ee9e219..cc6abce25e 100644 --- a/Resources/Prototypes/Entities/Structures/Power/cable_terminal.yml +++ b/Resources/Prototypes/Entities/Structures/Power/cable_terminal.yml @@ -45,3 +45,11 @@ powerMV: !type:CableTerminalNode nodeGroupID: MVPower + +- type: entity + id: CableTerminalUncuttable + parent: CableTerminal + suffix: uncuttable + components: + - type: Cable + cuttingQuality: null \ No newline at end of file diff --git a/Resources/Prototypes/Entities/Structures/Power/cables.yml b/Resources/Prototypes/Entities/Structures/Power/cables.yml index ac855a5460..f1ae038bc1 100644 --- a/Resources/Prototypes/Entities/Structures/Power/cables.yml +++ b/Resources/Prototypes/Entities/Structures/Power/cables.yml @@ -98,6 +98,14 @@ sound: path: /Audio/Ambience/Objects/emf_buzz.ogg +- type: entity + id: CableHVUncuttable + parent: CableHV + suffix: uncuttable + components: + - type: Cable + cuttingQuality: null + - type: entity parent: CableBase id: CableMV @@ -142,6 +150,14 @@ - type: CableVisualizer statePrefix: mvcable_ +- type: entity + id: CableMVUncuttable + parent: CableMV + suffix: uncuttable + components: + - type: Cable + cuttingQuality: null + - type: entity parent: CableBase id: CableApcExtension @@ -188,3 +204,11 @@ acts: [ "Destruction" ] - type: CableVisualizer statePrefix: lvcable_ + +- type: entity + id: CableApcExtensionUncuttable + parent: CableApcExtension + suffix: uncuttable + components: + - type: Cable + cuttingQuality: null From 6bc205484f5c2523c478f93b00326ac13988afac Mon Sep 17 00:00:00 2001 From: PJBot Date: Fri, 22 Nov 2024 22:51:50 +0000 Subject: [PATCH 16/59] Automatic changelog update --- Resources/Changelog/Changelog.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index 70963d8ba2..ec9b0d4057 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,11 +1,4 @@ Entries: -- author: Beck Thompson - changes: - - message: Cutting food now moves the sliced pieces a small amount! - type: Tweak - id: 7138 - time: '2024-08-18T21:18:20.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/31166 - author: lzk228 changes: - message: Pizza and pizza box now have 3x2 size in inventory. @@ -3935,3 +3928,10 @@ id: 7637 time: '2024-11-22T03:46:10.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/33128 +- author: IProduceWidgets + changes: + - message: The terminal is more tamper proof. + type: Fix + id: 7638 + time: '2024-11-22T22:50:41.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/33281 From d8ecf12fcaf4ce8e296a0dd2953149b662dbcd21 Mon Sep 17 00:00:00 2001 From: PJBot Date: Sat, 23 Nov 2024 02:54:55 +0000 Subject: [PATCH 17/59] Automatic changelog update --- Resources/Changelog/Changelog.yml | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index ec9b0d4057..c08c82af8a 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,15 +1,4 @@ Entries: -- author: lzk228 - changes: - - message: Pizza and pizza box now have 3x2 size in inventory. - type: Tweak - - message: Pizze box is 4x2 inside and always will have a pizza with a knife inside. - type: Tweak - - message: Pizza box have whitelist for utensils and pizza. - type: Tweak - id: 7139 - time: '2024-08-18T21:55:42.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/31171 - author: Deatherd changes: - message: Sharks Go RAWR! @@ -3935,3 +3924,10 @@ id: 7638 time: '2024-11-22T22:50:41.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/33281 +- author: MissKay1994 + changes: + - message: The salvage vendor now has enough equipment for everyone + type: Tweak + id: 7639 + time: '2024-11-23T02:53:48.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/33437 From 7feafcbe95b13daa0f3d69b85655221da8633e99 Mon Sep 17 00:00:00 2001 From: PJBot Date: Sat, 23 Nov 2024 06:38:21 +0000 Subject: [PATCH 18/59] Automatic changelog update --- Resources/Changelog/Changelog.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index c08c82af8a..be5f714bc3 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,11 +1,4 @@ Entries: -- author: Deatherd - changes: - - message: Sharks Go RAWR! - type: Tweak - id: 7140 - time: '2024-08-18T22:18:07.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/31142 - author: slarticodefast changes: - message: Fixed the radiation collector warning light thresholds. @@ -3931,3 +3924,10 @@ id: 7639 time: '2024-11-23T02:53:48.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/33437 +- author: slarticodefast + changes: + - message: The AI and observers can now see if doors are electrified. + type: Add + id: 7640 + time: '2024-11-23T06:37:15.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/33466 From 0a587c9ccc4ae70e21f71ea74b509911aa03041c Mon Sep 17 00:00:00 2001 From: Winkarst <74284083+Winkarst-cpu@users.noreply.github.com> Date: Sat, 23 Nov 2024 09:41:28 +0300 Subject: [PATCH 19/59] Disable submit admin note button on switch to note (#33456) Co-authored-by: Winkarst <74284083+Winkarst-cpu@users.noreply.github.co> --- Content.Client/Administration/UI/Notes/NoteEdit.xaml.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/Content.Client/Administration/UI/Notes/NoteEdit.xaml.cs b/Content.Client/Administration/UI/Notes/NoteEdit.xaml.cs index a412e47396..c8e3afeb22 100644 --- a/Content.Client/Administration/UI/Notes/NoteEdit.xaml.cs +++ b/Content.Client/Administration/UI/Notes/NoteEdit.xaml.cs @@ -159,6 +159,7 @@ public sealed partial class NoteEdit : FancyWindow SecretCheckBox.Pressed = false; SeverityOption.Disabled = false; PermanentCheckBox.Pressed = true; + SubmitButton.Disabled = true; UpdatePermanentCheckboxFields(); break; case (int) NoteType.Message: // Message: these are shown to the player when they log on From 1e93e123306144fabcf2f47d39b8b87adc3c0513 Mon Sep 17 00:00:00 2001 From: PJBot Date: Sat, 23 Nov 2024 06:42:34 +0000 Subject: [PATCH 20/59] Automatic changelog update --- Resources/Changelog/Changelog.yml | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index be5f714bc3..e28f46c1c1 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,11 +1,4 @@ Entries: -- author: slarticodefast - changes: - - message: Fixed the radiation collector warning light thresholds. - type: Fix - id: 7141 - time: '2024-08-18T22:25:02.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/31175 - author: Potato1234_x changes: - message: Added tea plants that can be dried and ground to make tea powder which @@ -3931,3 +3924,11 @@ id: 7640 time: '2024-11-23T06:37:15.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/33466 +- author: Winkarst-cpu + changes: + - message: Now submit button in admin notes becomes disabled on switching type back + to note. + type: Fix + id: 7641 + time: '2024-11-23T06:41:28.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/33456 From a42bacd3a94b515ee594b2ee39e331b3e6f0b318 Mon Sep 17 00:00:00 2001 From: MetalSage <74924875+MetalSage@users.noreply.github.com> Date: Sat, 23 Nov 2024 09:54:35 +0300 Subject: [PATCH 21/59] Fix startingGear storage (#33394) * fix starting gear storage * removal of unused --------- Co-authored-by: MetalSage --- .../Station/SharedStationSpawningSystem.cs | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/Content.Shared/Station/SharedStationSpawningSystem.cs b/Content.Shared/Station/SharedStationSpawningSystem.cs index ad264cd22a..a23ee30940 100644 --- a/Content.Shared/Station/SharedStationSpawningSystem.cs +++ b/Content.Shared/Station/SharedStationSpawningSystem.cs @@ -2,6 +2,7 @@ using System.Linq; using Content.Shared.Hands.Components; using Content.Shared.Hands.EntitySystems; using Content.Shared.Inventory; +using Content.Shared.Item; using Content.Shared.Preferences.Loadouts; using Content.Shared.Roles; using Content.Shared.Storage; @@ -145,27 +146,23 @@ public abstract class SharedStationSpawningSystem : EntitySystem if (startingGear.Storage.Count > 0) { var coords = _xformSystem.GetMapCoordinates(entity); - var ents = new ValueList(); _inventoryQuery.TryComp(entity, out var inventoryComp); - foreach (var (slot, entProtos) in startingGear.Storage) + foreach (var (slotName, entProtos) in startingGear.Storage) { - ents.Clear(); - if (entProtos.Count == 0) + if (entProtos == null || entProtos.Count == 0) continue; if (inventoryComp != null && - InventorySystem.TryGetSlotEntity(entity, slot, out var slotEnt, inventoryComponent: inventoryComp) && + InventorySystem.TryGetSlotEntity(entity, slotName, out var slotEnt, inventoryComponent: inventoryComp) && _storageQuery.TryComp(slotEnt, out var storage)) { - foreach (var ent in entProtos) - { - ents.Add(Spawn(ent, coords)); - } - foreach (var ent in ents) + foreach (var entProto in entProtos) { - _storage.Insert(slotEnt.Value, ent, out _, storageComp: storage, playSound: false); + var spawnedEntity = Spawn(entProto, coords); + + _storage.Insert(slotEnt.Value, spawnedEntity, out _, storageComp: storage, playSound: false); } } } From bdf4a46edf6dc0f457f0aebafdfbd181e3f2efb2 Mon Sep 17 00:00:00 2001 From: eoineoineoin Date: Sat, 23 Nov 2024 06:55:09 +0000 Subject: [PATCH 22/59] Minor improvements & fixes to Shuttle Console UI (#31623) * Fix grids and docks being culled from display prematurely * Fix inconsistent disabling of "Undock" buttons * Add a radar icon to indicate where the controlling console is * Tidy up math Remove lots of sketchy transforms-of-transforms, which should have been as single matrix multiply. Assign proper names to matrices. Remove some redundant calculations. * Feedback --- .../Shuttles/UI/BaseShuttleControl.xaml.cs | 13 +-- Content.Client/Shuttles/UI/NavScreen.xaml.cs | 7 ++ .../Shuttles/UI/ShuttleConsoleWindow.xaml.cs | 1 + .../Shuttles/UI/ShuttleDockControl.xaml.cs | 74 ++++++------- .../Shuttles/UI/ShuttleNavControl.xaml.cs | 100 ++++++++++-------- 5 files changed, 104 insertions(+), 91 deletions(-) diff --git a/Content.Client/Shuttles/UI/BaseShuttleControl.xaml.cs b/Content.Client/Shuttles/UI/BaseShuttleControl.xaml.cs index b50d8fa6b2..a541100539 100644 --- a/Content.Client/Shuttles/UI/BaseShuttleControl.xaml.cs +++ b/Content.Client/Shuttles/UI/BaseShuttleControl.xaml.cs @@ -116,7 +116,7 @@ public partial class BaseShuttleControl : MapGridControl } } - protected void DrawGrid(DrawingHandleScreen handle, Matrix3x2 matrix, Entity grid, Color color, float alpha = 0.01f) + protected void DrawGrid(DrawingHandleScreen handle, Matrix3x2 gridToView, Entity grid, Color color, float alpha = 0.01f) { var rator = Maps.GetAllTilesEnumerator(grid.Owner, grid.Comp); var minimapScale = MinimapScale; @@ -264,7 +264,7 @@ public partial class BaseShuttleControl : MapGridControl Extensions.EnsureLength(ref _allVertices, totalData); _drawJob.MidPoint = midpoint; - _drawJob.Matrix = matrix; + _drawJob.Matrix = gridToView; _drawJob.MinimapScale = minimapScale; _drawJob.Vertices = gridData.Vertices; _drawJob.ScaledVertices = _allVertices; @@ -286,7 +286,7 @@ public partial class BaseShuttleControl : MapGridControl private record struct GridDrawJob : IParallelRobustJob { - public int BatchSize => 16; + public int BatchSize => 64; public float MinimapScale; public Vector2 MidPoint; @@ -297,12 +297,7 @@ public partial class BaseShuttleControl : MapGridControl public void Execute(int index) { - var vert = Vertices[index]; - var adjustedVert = Vector2.Transform(vert, Matrix); - adjustedVert = adjustedVert with { Y = -adjustedVert.Y }; - - var scaledVert = ScalePosition(adjustedVert, MinimapScale, MidPoint); - ScaledVertices[index] = scaledVert; + ScaledVertices[index] = Vector2.Transform(Vertices[index], Matrix); } } } diff --git a/Content.Client/Shuttles/UI/NavScreen.xaml.cs b/Content.Client/Shuttles/UI/NavScreen.xaml.cs index 91d95aaa04..7236714ef2 100644 --- a/Content.Client/Shuttles/UI/NavScreen.xaml.cs +++ b/Content.Client/Shuttles/UI/NavScreen.xaml.cs @@ -15,6 +15,7 @@ public sealed partial class NavScreen : BoxContainer [Dependency] private readonly IEntityManager _entManager = default!; private SharedTransformSystem _xformSystem; + private EntityUid? _consoleEntity; // Entity of controlling console private EntityUid? _shuttleEntity; public NavScreen() @@ -35,6 +36,12 @@ public sealed partial class NavScreen : BoxContainer _shuttleEntity = shuttle; } + public void SetConsole(EntityUid? console) + { + _consoleEntity = console; + NavRadar.SetConsole(console); + } + private void OnIFFTogglePressed(BaseButton.ButtonEventArgs args) { NavRadar.ShowIFF ^= true; diff --git a/Content.Client/Shuttles/UI/ShuttleConsoleWindow.xaml.cs b/Content.Client/Shuttles/UI/ShuttleConsoleWindow.xaml.cs index a4b42fb672..d0e6f9ebf7 100644 --- a/Content.Client/Shuttles/UI/ShuttleConsoleWindow.xaml.cs +++ b/Content.Client/Shuttles/UI/ShuttleConsoleWindow.xaml.cs @@ -138,6 +138,7 @@ public sealed partial class ShuttleConsoleWindow : FancyWindow, { var coordinates = _entManager.GetCoordinates(cState.NavState.Coordinates); NavContainer.SetShuttle(coordinates?.EntityId); + NavContainer.SetConsole(owner); MapContainer.SetShuttle(coordinates?.EntityId); MapContainer.SetConsole(owner); diff --git a/Content.Client/Shuttles/UI/ShuttleDockControl.xaml.cs b/Content.Client/Shuttles/UI/ShuttleDockControl.xaml.cs index 61ae069926..2b575b4805 100644 --- a/Content.Client/Shuttles/UI/ShuttleDockControl.xaml.cs +++ b/Content.Client/Shuttles/UI/ShuttleDockControl.xaml.cs @@ -107,16 +107,19 @@ public sealed partial class ShuttleDockControl : BaseShuttleControl DrawCircles(handle); var gridNent = EntManager.GetNetEntity(GridEntity); var mapPos = _xformSystem.ToMapCoordinates(_coordinates.Value); - var ourGridMatrix = _xformSystem.GetWorldMatrix(GridEntity.Value); - var dockMatrix = Matrix3Helpers.CreateTransform(_coordinates.Value.Position, Angle.Zero); - var worldFromDock = Matrix3x2.Multiply(dockMatrix, ourGridMatrix); + var ourGridToWorld = _xformSystem.GetWorldMatrix(GridEntity.Value); + var selectedDockToOurGrid = Matrix3Helpers.CreateTransform(_coordinates.Value.Position, Angle.Zero); + var selectedDockToWorld = Matrix3x2.Multiply(selectedDockToOurGrid, ourGridToWorld); - Matrix3x2.Invert(worldFromDock, out var offsetMatrix); + Box2 viewBoundsWorld = Matrix3Helpers.TransformBox(selectedDockToWorld, new Box2(-WorldRangeVector, WorldRangeVector)); + + Matrix3x2.Invert(selectedDockToWorld, out var worldToSelectedDock); + var selectedDockToView = Matrix3x2.CreateScale(new Vector2(MinimapScale, -MinimapScale)) * Matrix3x2.CreateTranslation(MidPointVector); // Draw nearby grids var controlBounds = PixelSizeBox; _grids.Clear(); - _mapManager.FindGridsIntersecting(gridXform.MapID, new Box2(mapPos.Position - WorldRangeVector, mapPos.Position + WorldRangeVector), ref _grids); + _mapManager.FindGridsIntersecting(gridXform.MapID, viewBoundsWorld, ref _grids); // offset the dotted-line position to the bounds. Vector2? viewedDockPos = _viewedState != null ? MidPointVector : null; @@ -136,11 +139,11 @@ public sealed partial class ShuttleDockControl : BaseShuttleControl if (grid.Owner != GridEntity && !_shuttles.CanDraw(grid.Owner, iffComp: iffComp)) continue; - var gridMatrix = _xformSystem.GetWorldMatrix(grid.Owner); - var matty = Matrix3x2.Multiply(gridMatrix, offsetMatrix); + var curGridToWorld = _xformSystem.GetWorldMatrix(grid.Owner); + var curGridToView = curGridToWorld * worldToSelectedDock * selectedDockToView; var color = _shuttles.GetIFFColor(grid.Owner, grid.Owner == GridEntity, component: iffComp); - DrawGrid(handle, matty, grid, color); + DrawGrid(handle, curGridToView, grid, color); // Draw any docks on that grid if (!DockState.Docks.TryGetValue(EntManager.GetNetEntity(grid), out var gridDocks)) @@ -151,23 +154,24 @@ public sealed partial class ShuttleDockControl : BaseShuttleControl if (ViewedDock == dock.Entity) continue; - var position = Vector2.Transform(dock.Coordinates.Position, matty); - var otherDockRotation = Matrix3Helpers.CreateRotation(dock.Angle); - var scaledPos = ScalePosition(position with {Y = -position.Y}); - if (!controlBounds.Contains(scaledPos.Floored())) + // This box is the AABB of all the vertices we draw below. + var dockRenderBoundsLocal = new Box2(-0.5f, -0.7f, 0.5f, 0.5f); + var currentDockToCurGrid = Matrix3Helpers.CreateTransform(dock.Coordinates.Position, dock.Angle); + var currentDockToWorld = Matrix3x2.Multiply(currentDockToCurGrid, curGridToWorld); + var dockRenderBoundsWorld = Matrix3Helpers.TransformBox(currentDockToWorld, dockRenderBoundsLocal); + if (!viewBoundsWorld.Intersects(dockRenderBoundsWorld)) continue; - // Draw the dock's collision var collisionBL = Vector2.Transform(dock.Coordinates.Position + - Vector2.Transform(new Vector2(-0.2f, -0.7f), otherDockRotation), matty); + Vector2.Transform(new Vector2(-0.2f, -0.7f), otherDockRotation), curGridToView); var collisionBR = Vector2.Transform(dock.Coordinates.Position + - Vector2.Transform(new Vector2(0.2f, -0.7f), otherDockRotation), matty); + Vector2.Transform(new Vector2(0.2f, -0.7f), otherDockRotation), curGridToView); var collisionTR = Vector2.Transform(dock.Coordinates.Position + - Vector2.Transform(new Vector2(0.2f, -0.5f), otherDockRotation), matty); + Vector2.Transform(new Vector2(0.2f, -0.5f), otherDockRotation), curGridToView); var collisionTL = Vector2.Transform(dock.Coordinates.Position + - Vector2.Transform(new Vector2(-0.2f, -0.5f), otherDockRotation), matty); + Vector2.Transform(new Vector2(-0.2f, -0.5f), otherDockRotation), curGridToView); var verts = new[] { @@ -181,13 +185,6 @@ public sealed partial class ShuttleDockControl : BaseShuttleControl collisionBL, }; - for (var i = 0; i < verts.Length; i++) - { - var vert = verts[i]; - vert.Y = -vert.Y; - verts[i] = ScalePosition(vert); - } - var collisionCenter = verts[0] + verts[1] + verts[3] + verts[5]; var otherDockConnection = Color.ToSrgb(Color.Pink); @@ -195,10 +192,10 @@ public sealed partial class ShuttleDockControl : BaseShuttleControl handle.DrawPrimitives(DrawPrimitiveTopology.LineList, verts, otherDockConnection); // Draw the dock itself - var dockBL = Vector2.Transform(dock.Coordinates.Position + new Vector2(-0.5f, -0.5f), matty); - var dockBR = Vector2.Transform(dock.Coordinates.Position + new Vector2(0.5f, -0.5f), matty); - var dockTR = Vector2.Transform(dock.Coordinates.Position + new Vector2(0.5f, 0.5f), matty); - var dockTL = Vector2.Transform(dock.Coordinates.Position + new Vector2(-0.5f, 0.5f), matty); + var dockBL = Vector2.Transform(dock.Coordinates.Position + new Vector2(-0.5f, -0.5f), curGridToView); + var dockBR = Vector2.Transform(dock.Coordinates.Position + new Vector2(0.5f, -0.5f), curGridToView); + var dockTR = Vector2.Transform(dock.Coordinates.Position + new Vector2(0.5f, 0.5f), curGridToView); + var dockTL = Vector2.Transform(dock.Coordinates.Position + new Vector2(-0.5f, 0.5f), curGridToView); verts = new[] { @@ -212,13 +209,6 @@ public sealed partial class ShuttleDockControl : BaseShuttleControl dockBL }; - for (var i = 0; i < verts.Length; i++) - { - var vert = verts[i]; - vert.Y = -vert.Y; - verts[i] = ScalePosition(vert); - } - Color otherDockColor; if (HighlightedDock == dock.Entity) @@ -253,9 +243,11 @@ public sealed partial class ShuttleDockControl : BaseShuttleControl collisionCenter /= 4; var range = viewedDockPos.Value - collisionCenter; - if (range.Length() < SharedDockingSystem.DockingHiglightRange * MinimapScale) + var maxRange = SharedDockingSystem.DockingHiglightRange * MinimapScale; + var maxRangeSq = maxRange * maxRange; + if (range.LengthSquared() < maxRangeSq) { - if (_viewedState?.GridDockedWith == null) + if (dock.GridDockedWith == null) { var coordsOne = EntManager.GetCoordinates(_viewedState!.Coordinates); var coordsTwo = EntManager.GetCoordinates(dock.Coordinates); @@ -265,10 +257,11 @@ public sealed partial class ShuttleDockControl : BaseShuttleControl var rotA = _xformSystem.GetWorldRotation(coordsOne.EntityId) + _viewedState!.Angle; var rotB = _xformSystem.GetWorldRotation(coordsTwo.EntityId) + dock.Angle; - var distance = (mapOne.Position - mapTwo.Position).Length(); + var distanceSq = (mapOne.Position - mapTwo.Position).LengthSquared(); var inAlignment = _dockSystem.InAlignment(mapOne, rotA, mapTwo, rotB); - var canDock = distance < SharedDockingSystem.DockRange && inAlignment; + var maxDockDistSq = SharedDockingSystem.DockRange * SharedDockingSystem.DockRange; + var canDock = distanceSq < maxDockDistSq && inAlignment; if (dockButton != null) dockButton.Disabled = !canDock || !canDockChange; @@ -297,7 +290,8 @@ public sealed partial class ShuttleDockControl : BaseShuttleControl { // Because it's being layed out top-down we have to arrange for first frame. container.Arrange(PixelRect); - var containerPos = scaledPos / UIScale - container.DesiredSize / 2 - new Vector2(0f, 0.75f) * MinimapScale; + var dockPositionInView = Vector2.Transform(dock.Coordinates.Position, curGridToView); + var containerPos = dockPositionInView / UIScale - container.DesiredSize / 2 - new Vector2(0f, 0.75f) * MinimapScale; SetPosition(container, containerPos); } diff --git a/Content.Client/Shuttles/UI/ShuttleNavControl.xaml.cs b/Content.Client/Shuttles/UI/ShuttleNavControl.xaml.cs index 2674343e05..805608c9a5 100644 --- a/Content.Client/Shuttles/UI/ShuttleNavControl.xaml.cs +++ b/Content.Client/Shuttles/UI/ShuttleNavControl.xaml.cs @@ -29,6 +29,11 @@ public sealed partial class ShuttleNavControl : BaseShuttleControl /// private EntityCoordinates? _coordinates; + /// + /// Entity of controlling console + /// + private EntityUid? _consoleEntity; + private Angle? _rotation; private Dictionary> _docks = new(); @@ -57,6 +62,11 @@ public sealed partial class ShuttleNavControl : BaseShuttleControl _rotation = angle; } + public void SetConsole(EntityUid? consoleEntity) + { + _consoleEntity = consoleEntity; + } + protected override void KeyBindUp(GUIBoundKeyEventArgs args) { base.KeyBindUp(args); @@ -139,40 +149,35 @@ public sealed partial class ShuttleNavControl : BaseShuttleControl } var mapPos = _transform.ToMapCoordinates(_coordinates.Value); - var offset = _coordinates.Value.Position; - var posMatrix = Matrix3Helpers.CreateTransform(offset, _rotation.Value); + var posMatrix = Matrix3Helpers.CreateTransform(_coordinates.Value.Position, _rotation.Value); var ourEntRot = RotateWithEntity ? _transform.GetWorldRotation(xform) : _rotation.Value; var ourEntMatrix = Matrix3Helpers.CreateTransform(_transform.GetWorldPosition(xform), ourEntRot); - var ourWorldMatrix = Matrix3x2.Multiply(posMatrix, ourEntMatrix); - Matrix3x2.Invert(ourWorldMatrix, out var ourWorldMatrixInvert); + var shuttleToWorld = Matrix3x2.Multiply(posMatrix, ourEntMatrix); + Matrix3x2.Invert(shuttleToWorld, out var worldToShuttle); + var shuttleToView = Matrix3x2.CreateScale(new Vector2(MinimapScale, -MinimapScale)) * Matrix3x2.CreateTranslation(MidPointVector); // Draw our grid in detail var ourGridId = xform.GridUid; if (EntManager.TryGetComponent(ourGridId, out var ourGrid) && fixturesQuery.HasComponent(ourGridId.Value)) { - var ourGridMatrix = _transform.GetWorldMatrix(ourGridId.Value); - var matrix = Matrix3x2.Multiply(ourGridMatrix, ourWorldMatrixInvert); + var ourGridToWorld = _transform.GetWorldMatrix(ourGridId.Value); + var ourGridToShuttle = Matrix3x2.Multiply(ourGridToWorld, worldToShuttle); + var ourGridToView = ourGridToShuttle * shuttleToView; var color = _shuttles.GetIFFColor(ourGridId.Value, self: true); - DrawGrid(handle, matrix, (ourGridId.Value, ourGrid), color); - DrawDocks(handle, ourGridId.Value, matrix); + DrawGrid(handle, ourGridToView, (ourGridId.Value, ourGrid), color); + DrawDocks(handle, ourGridId.Value, ourGridToView); } - var invertedPosition = _coordinates.Value.Position - offset; - invertedPosition.Y = -invertedPosition.Y; - // Don't need to transform the InvWorldMatrix again as it's already offset to its position. - // Draw radar position on the station - var radarPos = invertedPosition; const float radarVertRadius = 2f; - var radarPosVerts = new Vector2[] { - ScalePosition(radarPos + new Vector2(0f, -radarVertRadius)), - ScalePosition(radarPos + new Vector2(radarVertRadius / 2f, 0f)), - ScalePosition(radarPos + new Vector2(0f, radarVertRadius)), - ScalePosition(radarPos + new Vector2(radarVertRadius / -2f, 0f)), + ScalePosition(new Vector2(0f, -radarVertRadius)), + ScalePosition(new Vector2(radarVertRadius / 2f, 0f)), + ScalePosition(new Vector2(0f, radarVertRadius)), + ScalePosition(new Vector2(radarVertRadius / -2f, 0f)), }; handle.DrawPrimitives(DrawPrimitiveTopology.TriangleFan, radarPosVerts, Color.Lime); @@ -197,8 +202,8 @@ public sealed partial class ShuttleNavControl : BaseShuttleControl if (!_shuttles.CanDraw(gUid, gridBody, iff)) continue; - var gridMatrix = _transform.GetWorldMatrix(gUid); - var matty = Matrix3x2.Multiply(gridMatrix, ourWorldMatrixInvert); + var curGridToWorld = _transform.GetWorldMatrix(gUid); + var curGridToView = curGridToWorld * worldToShuttle * shuttleToView; var labelColor = _shuttles.GetIFFColor(grid, self: false, iff); var coordColor = new Color(labelColor.R * 0.8f, labelColor.G * 0.8f, labelColor.B * 0.8f, 0.5f); @@ -213,8 +218,7 @@ public sealed partial class ShuttleNavControl : BaseShuttleControl { var gridBounds = grid.Comp.LocalAABB; - var gridCentre = Vector2.Transform(gridBody.LocalCenter, matty); - gridCentre.Y = -gridCentre.Y; + var gridCentre = Vector2.Transform(gridBody.LocalCenter, curGridToView); var distance = gridCentre.Length(); var labelText = Loc.GetString("shuttle-console-iff-label", ("name", labelName), @@ -230,9 +234,8 @@ public sealed partial class ShuttleNavControl : BaseShuttleControl // y-offset the control to always render below the grid (vertically) var yOffset = Math.Max(gridBounds.Height, gridBounds.Width) * MinimapScale / 1.8f; - // The actual position in the UI. We centre the label by offsetting the matrix position - // by half the label's width, plus the y-offset - var gridScaledPosition = ScalePosition(gridCentre) - new Vector2(0, -yOffset); + // The actual position in the UI. + var gridScaledPosition = gridCentre - new Vector2(0, -yOffset); // Normalize the grid position if it exceeds the viewport bounds // normalizing it instead of clamping it preserves the direction of the vector and prevents corner-hugging @@ -264,18 +267,32 @@ public sealed partial class ShuttleNavControl : BaseShuttleControl } // Detailed view - var gridAABB = gridMatrix.TransformBox(grid.Comp.LocalAABB); + var gridAABB = curGridToWorld.TransformBox(grid.Comp.LocalAABB); // Skip drawing if it's out of range. if (!gridAABB.Intersects(viewAABB)) continue; - DrawGrid(handle, matty, grid, labelColor); - DrawDocks(handle, gUid, matty); + DrawGrid(handle, curGridToView, grid, labelColor); + DrawDocks(handle, gUid, curGridToView); } + + // If we've set the controlling console, and it's on a different grid + // to the shuttle itself, then draw an additional marker to help the + // player determine where they are relative to the shuttle. + if (_consoleEntity != null && xformQuery.TryGetComponent(_consoleEntity, out var consoleXform)) + { + if (consoleXform.ParentUid != _coordinates.Value.EntityId) + { + var consolePositionWorld = _transform.GetWorldPosition((EntityUid)_consoleEntity); + var p = Vector2.Transform(consolePositionWorld, worldToShuttle * shuttleToView); + handle.DrawCircle(p, 5, Color.ToSrgb(Color.Cyan), true); + } + } + } - private void DrawDocks(DrawingHandleScreen handle, EntityUid uid, Matrix3x2 matrix) + private void DrawDocks(DrawingHandleScreen handle, EntityUid uid, Matrix3x2 gridToView) { if (!ShowDocks) return; @@ -283,33 +300,32 @@ public sealed partial class ShuttleNavControl : BaseShuttleControl const float DockScale = 0.6f; var nent = EntManager.GetNetEntity(uid); + const float sqrt2 = 1.41421356f; + const float dockRadius = DockScale * sqrt2; + // Worst-case bounds used to cull a dock: + Box2 viewBounds = new Box2(-dockRadius, -dockRadius, Size.X + dockRadius, Size.Y + dockRadius); if (_docks.TryGetValue(nent, out var docks)) { foreach (var state in docks) { var position = state.Coordinates.Position; - var uiPosition = Vector2.Transform(position, matrix); - if (uiPosition.Length() > (WorldRange * 2f) - DockScale) + var positionInView = Vector2.Transform(position, gridToView); + if (!viewBounds.Contains(positionInView)) + { continue; + } var color = Color.ToSrgb(Color.Magenta); var verts = new[] { - Vector2.Transform(position + new Vector2(-DockScale, -DockScale), matrix), - Vector2.Transform(position + new Vector2(DockScale, -DockScale), matrix), - Vector2.Transform(position + new Vector2(DockScale, DockScale), matrix), - Vector2.Transform(position + new Vector2(-DockScale, DockScale), matrix), + Vector2.Transform(position + new Vector2(-DockScale, -DockScale), gridToView), + Vector2.Transform(position + new Vector2(DockScale, -DockScale), gridToView), + Vector2.Transform(position + new Vector2(DockScale, DockScale), gridToView), + Vector2.Transform(position + new Vector2(-DockScale, DockScale), gridToView), }; - for (var i = 0; i < verts.Length; i++) - { - var vert = verts[i]; - vert.Y = -vert.Y; - verts[i] = ScalePosition(vert); - } - handle.DrawPrimitives(DrawPrimitiveTopology.TriangleFan, verts, color.WithAlpha(0.8f)); handle.DrawPrimitives(DrawPrimitiveTopology.LineStrip, verts, color); } From c3786a56dcbb03d53eb8a42d69105936398d5eff Mon Sep 17 00:00:00 2001 From: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com> Date: Sat, 23 Nov 2024 20:31:07 +1100 Subject: [PATCH 23/59] Fix door animations mispredicting if closing is interrupted (#33481) * Fix door animations mispredicting if closing is interrupted On master it will flicker states a little bit partially due to it not being predicted. Instead we'll just set it straight back to opening (no animation is ever played anyway). * no log --- Content.Shared/Doors/Systems/SharedDoorSystem.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Content.Shared/Doors/Systems/SharedDoorSystem.cs b/Content.Shared/Doors/Systems/SharedDoorSystem.cs index 80e7ff9669..7fd5d61db7 100644 --- a/Content.Shared/Doors/Systems/SharedDoorSystem.cs +++ b/Content.Shared/Doors/Systems/SharedDoorSystem.cs @@ -461,17 +461,17 @@ public abstract partial class SharedDoorSystem : EntitySystem if (!Resolve(uid, ref door, ref physics)) return false; - door.Partial = true; - // Make sure no entity walked into the airlock when it started closing. if (!CanClose(uid, door)) { door.NextStateChange = GameTiming.CurTime + door.OpenTimeTwo; - door.State = DoorState.Opening; - AppearanceSystem.SetData(uid, DoorVisuals.State, DoorState.Opening); + door.State = DoorState.Open; + AppearanceSystem.SetData(uid, DoorVisuals.State, DoorState.Open); + Dirty(uid, door); return false; } + door.Partial = true; SetCollidable(uid, true, door, physics); door.NextStateChange = GameTiming.CurTime + door.CloseTimeTwo; Dirty(uid, door); From bde85858a39903a8127fe48dd24ca8ecf3b1ed40 Mon Sep 17 00:00:00 2001 From: PJBot Date: Sat, 23 Nov 2024 09:32:14 +0000 Subject: [PATCH 24/59] Automatic changelog update --- Resources/Changelog/Changelog.yml | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index e28f46c1c1..f6d02fcadd 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,14 +1,4 @@ Entries: -- author: Potato1234_x - changes: - - message: Added tea plants that can be dried and ground to make tea powder which - can then be used to make tea. - type: Add - - message: Added blue pumpkins. Currently useless but recipe uses are coming soon. - type: Add - id: 7142 - time: '2024-08-18T22:28:18.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/25092 - author: deltanedas changes: - message: Added Memory Cells for storing logic signals persistently. @@ -3932,3 +3922,11 @@ id: 7641 time: '2024-11-23T06:41:28.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/33456 +- author: metalgearsloth + changes: + - message: Fix airlock animations mispredicting if the closing animation is interrupted, + e.g. via walking into it. + type: Fix + id: 7642 + time: '2024-11-23T09:31:08.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/33481 From 11dae2ff93ebecb6187e21db15fb52f5cb02e152 Mon Sep 17 00:00:00 2001 From: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com> Date: Sat, 23 Nov 2024 22:19:59 +1100 Subject: [PATCH 25/59] Don't show drag-drop outline if climbing (#33477) It won't actually do anything. --- Content.Shared/Climbing/Systems/ClimbSystem.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Content.Shared/Climbing/Systems/ClimbSystem.cs b/Content.Shared/Climbing/Systems/ClimbSystem.cs index 9bf481002a..467d96187e 100644 --- a/Content.Shared/Climbing/Systems/ClimbSystem.cs +++ b/Content.Shared/Climbing/Systems/ClimbSystem.cs @@ -151,6 +151,10 @@ public sealed partial class ClimbSystem : VirtualController if (args.Handled) return; + // If already climbing then don't show outlines. + if (TryComp(args.Dragged, out ClimbingComponent? climbing) && climbing.IsClimbing) + return; + var canVault = args.User == args.Dragged ? CanVault(component, args.User, uid, out _) : CanVault(component, args.User, args.Dragged, uid, out _); From 45af6a13fcba1e07b76ee5d692067047f0786aa3 Mon Sep 17 00:00:00 2001 From: PJBot Date: Sat, 23 Nov 2024 11:21:05 +0000 Subject: [PATCH 26/59] Automatic changelog update --- Resources/Changelog/Changelog.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index f6d02fcadd..5f474eceb2 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,11 +1,4 @@ Entries: -- author: deltanedas - changes: - - message: Added Memory Cells for storing logic signals persistently. - type: Add - id: 7143 - time: '2024-08-18T22:34:43.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/24983 - author: Psychpsyo changes: - message: The random sentience event is back and can no longer pick things that @@ -3930,3 +3923,10 @@ id: 7642 time: '2024-11-23T09:31:08.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/33481 +- author: metalgearsloth + changes: + - message: Drag-drop outline no longer shows the vaulting outlines if you're vaulting. + type: Tweak + id: 7643 + time: '2024-11-23T11:19:59.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/33477 From 855547a2d4ea6f95f1b1db7d62a586a57a54f712 Mon Sep 17 00:00:00 2001 From: goet <6637097+goet@users.noreply.github.com> Date: Sat, 23 Nov 2024 12:41:37 +0100 Subject: [PATCH 27/59] Ensure wires can always be cut (#32447) ensure wires are always cut --- Content.Server/Wires/ComponentWireAction.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Content.Server/Wires/ComponentWireAction.cs b/Content.Server/Wires/ComponentWireAction.cs index 2407068056..90c8a7594d 100644 --- a/Content.Server/Wires/ComponentWireAction.cs +++ b/Content.Server/Wires/ComponentWireAction.cs @@ -22,13 +22,14 @@ public abstract partial class ComponentWireAction : BaseWireAction w public override bool Cut(EntityUid user, Wire wire) { base.Cut(user, wire); - return EntityManager.TryGetComponent(wire.Owner, out TComponent? component) && Cut(user, wire, component); + // if the entity doesn't exist, we need to return true otherwise the wire sprite is never updated + return EntityManager.TryGetComponent(wire.Owner, out TComponent? component) ? Cut(user, wire, component) : true; } public override bool Mend(EntityUid user, Wire wire) { base.Mend(user, wire); - return EntityManager.TryGetComponent(wire.Owner, out TComponent? component) && Mend(user, wire, component); + return EntityManager.TryGetComponent(wire.Owner, out TComponent? component) ? Mend(user, wire, component) : true; } public override void Pulse(EntityUid user, Wire wire) From 4cecf99e65c1fafc1e82cfae9dbae88d62b18566 Mon Sep 17 00:00:00 2001 From: PJBot Date: Sat, 23 Nov 2024 11:42:43 +0000 Subject: [PATCH 28/59] Automatic changelog update --- Resources/Changelog/Changelog.yml | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index 5f474eceb2..8146476b3e 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,12 +1,4 @@ Entries: -- author: Psychpsyo - changes: - - message: The random sentience event is back and can no longer pick things that - aren't even on the station. - type: Add - id: 7144 - time: '2024-08-18T23:41:12.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/29123 - author: EmoGarbage404 changes: - message: Ore can no longer be destroyed by explosions. Happy blast mining. @@ -3930,3 +3922,10 @@ id: 7643 time: '2024-11-23T11:19:59.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/33477 +- author: goet + changes: + - message: Useless wires some vending machines have can be cut now. + type: Fix + id: 7644 + time: '2024-11-23T11:41:37.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/32447 From fab9993a3b75a05c8c1d573132e45f396d760b72 Mon Sep 17 00:00:00 2001 From: IProduceWidgets <107586145+IProduceWidgets@users.noreply.github.com> Date: Sat, 23 Nov 2024 10:14:13 -0500 Subject: [PATCH 29/59] babyproof arrivals shuttle (#33284) * babyproof arrivals shuttle * always powered lights * uncuttable cables from terminal PR. --------- Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com> --- Resources/Maps/Shuttles/arrivals.yml | 1363 ++++++++++++++++++++++++-- 1 file changed, 1260 insertions(+), 103 deletions(-) diff --git a/Resources/Maps/Shuttles/arrivals.yml b/Resources/Maps/Shuttles/arrivals.yml index b4609e1b0a..3c853ef739 100644 --- a/Resources/Maps/Shuttles/arrivals.yml +++ b/Resources/Maps/Shuttles/arrivals.yml @@ -192,13 +192,17 @@ entities: - type: RadiationGridResistance - type: SpreaderGrid - type: GridPathfinding + - type: Godmode - proto: AirCanister entities: - uid: 214 components: - type: Transform + anchored: True pos: -1.5,7.5 parent: 292 + - type: Physics + bodyType: Static - proto: AirlockCommandGlassLocked entities: - uid: 278 @@ -208,6 +212,11 @@ entities: - type: Transform pos: -0.5,6.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - proto: AirlockGlassShuttle entities: - uid: 177 @@ -217,11 +226,16 @@ entities: pos: 3.5,-2.5 parent: 292 - type: Door - secondsUntilStateChange: -336.60016 + secondsUntilStateChange: -623.03485 state: Opening - type: DeviceLinkSource lastSignals: DoorStatus: True + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 178 components: - type: Transform @@ -229,11 +243,16 @@ entities: pos: 3.5,4.5 parent: 292 - type: Door - secondsUntilStateChange: -338.3335 + secondsUntilStateChange: -624.7682 state: Opening - type: DeviceLinkSource lastSignals: DoorStatus: True + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 179 components: - type: Transform @@ -241,11 +260,16 @@ entities: pos: -4.5,4.5 parent: 292 - type: Door - secondsUntilStateChange: -332.80017 + secondsUntilStateChange: -619.23486 state: Opening - type: DeviceLinkSource lastSignals: DoorStatus: True + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 180 components: - type: Transform @@ -253,11 +277,16 @@ entities: pos: -4.5,-2.5 parent: 292 - type: Door - secondsUntilStateChange: -334.70016 + secondsUntilStateChange: -621.1349 state: Opening - type: DeviceLinkSource lastSignals: DoorStatus: True + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - proto: APCBasic entities: - uid: 116 @@ -266,6 +295,13 @@ entities: rot: 3.141592653589793 rad pos: -0.5,3.5 parent: 292 + - type: BatterySelfRecharger + autoRechargeRate: 50000 + autoRecharge: True + - type: Godmode + missingComponents: + - Construction + - Destructible - proto: ArrivalsShuttleTimer entities: - uid: 294 @@ -273,11 +309,17 @@ entities: - type: Transform pos: -4.5,3.5 parent: 292 + - type: Godmode + missingComponents: + - Construction - uid: 295 components: - type: Transform pos: 3.5,3.5 parent: 292 + - type: Godmode + missingComponents: + - Construction - proto: AtmosDeviceFanDirectional entities: - uid: 164 @@ -286,24 +328,28 @@ entities: rot: -1.5707963267948966 rad pos: -4.5,4.5 parent: 292 + - type: Godmode - uid: 165 components: - type: Transform rot: 1.5707963267948966 rad pos: 3.5,4.5 parent: 292 + - type: Godmode - uid: 166 components: - type: Transform rot: 1.5707963267948966 rad pos: 3.5,-2.5 parent: 292 + - type: Godmode - uid: 167 components: - type: Transform rot: -1.5707963267948966 rad pos: -4.5,-2.5 parent: 292 + - type: Godmode - proto: BlockGameArcade entities: - uid: 258 @@ -312,418 +358,747 @@ entities: rot: -1.5707963267948966 rad pos: -1.5,-1.5 parent: 292 -- proto: CableApcExtension + - type: Godmode + missingComponents: + - Anchorable + - Construction + - Destructible +- proto: CableApcExtensionUncuttable entities: - uid: 123 components: - type: Transform pos: -0.5,3.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 124 components: - type: Transform pos: -0.5,4.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 125 components: - type: Transform pos: -1.5,4.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 126 components: - type: Transform pos: -2.5,4.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 127 components: - type: Transform pos: -2.5,3.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 128 components: - type: Transform pos: -2.5,2.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 129 components: - type: Transform pos: -2.5,1.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 130 components: - type: Transform pos: -2.5,0.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 131 components: - type: Transform pos: -2.5,-0.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 132 components: - type: Transform pos: -2.5,-1.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 133 components: - type: Transform pos: -2.5,-2.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 134 components: - type: Transform pos: -1.5,-2.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 135 components: - type: Transform pos: -0.5,-2.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 136 components: - type: Transform pos: 0.5,-2.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 137 components: - type: Transform pos: 1.5,-2.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 138 components: - type: Transform pos: 1.5,-1.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 139 components: - type: Transform pos: 1.5,-0.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 140 components: - type: Transform pos: 1.5,0.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 141 components: - type: Transform pos: 1.5,1.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 142 components: - type: Transform pos: 1.5,2.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 143 components: - type: Transform pos: 1.5,3.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 144 components: - type: Transform pos: 1.5,4.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 145 components: - type: Transform pos: 0.5,4.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 146 components: - type: Transform pos: -0.5,5.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 147 components: - type: Transform pos: -0.5,6.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 148 components: - type: Transform pos: -0.5,7.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 149 components: - type: Transform pos: -0.5,8.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 150 components: - type: Transform pos: -1.5,-3.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 151 components: - type: Transform pos: 0.5,-3.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 152 components: - type: Transform pos: 0.5,-4.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 153 components: - type: Transform pos: 1.5,-4.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 154 components: - type: Transform pos: -1.5,-4.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 155 components: - type: Transform pos: -2.5,-4.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 156 components: - type: Transform pos: -2.5,-5.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 157 components: - type: Transform pos: 1.5,-5.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 158 components: - type: Transform pos: -1.5,8.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 159 components: - type: Transform pos: 0.5,8.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 160 components: - type: Transform pos: -3.5,4.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 161 components: - type: Transform pos: 2.5,4.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 162 components: - type: Transform pos: 2.5,-2.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 163 components: - type: Transform pos: -3.5,-2.5 parent: 292 -- proto: CableHV + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable +- proto: CableHVUncuttable entities: - uid: 79 components: - type: Transform pos: 0.5,7.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 80 components: - type: Transform pos: 1.5,7.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 81 components: - type: Transform pos: 1.5,6.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 82 components: - type: Transform pos: -0.5,7.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 83 components: - type: Transform pos: -0.5,6.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 85 components: - type: Transform pos: -0.5,5.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 86 components: - type: Transform pos: -0.5,4.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 87 components: - type: Transform pos: -1.5,4.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 88 components: - type: Transform pos: -2.5,4.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 89 components: - type: Transform pos: -2.5,3.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 90 components: - type: Transform pos: -2.5,2.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 91 components: - type: Transform pos: -2.5,1.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 92 components: - type: Transform pos: -2.5,0.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 93 components: - type: Transform pos: -2.5,-0.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 94 components: - type: Transform pos: -2.5,-1.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 95 components: - type: Transform pos: -2.5,-2.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 96 components: - type: Transform pos: -1.5,-2.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 97 components: - type: Transform pos: -0.5,-2.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 98 components: - type: Transform pos: 0.5,-2.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 99 components: - type: Transform pos: 1.5,-2.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 100 components: - type: Transform pos: 1.5,-1.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 101 components: - type: Transform pos: 1.5,-0.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 102 components: - type: Transform pos: 1.5,0.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 103 components: - type: Transform pos: 1.5,1.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 104 components: - type: Transform pos: 1.5,2.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 105 components: - type: Transform pos: 1.5,3.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 106 components: - type: Transform pos: 1.5,4.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 107 components: - type: Transform pos: 0.5,4.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 108 components: - type: Transform pos: -1.5,-3.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 109 components: - type: Transform pos: -1.5,-4.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 110 components: - type: Transform pos: -1.5,-5.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 111 components: - type: Transform pos: 0.5,-5.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 112 components: - type: Transform pos: 0.5,-4.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 113 components: - type: Transform pos: 0.5,-3.5 parent: 292 -- proto: CableMV + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable +- proto: CableMVUncuttable entities: - uid: 117 components: - type: Transform pos: 1.5,6.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 118 components: - type: Transform pos: 1.5,5.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 119 components: - type: Transform pos: 1.5,4.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 120 components: - type: Transform pos: 0.5,4.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 121 components: - type: Transform pos: -0.5,4.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable - uid: 122 components: - type: Transform pos: -0.5,3.5 parent: 292 -- proto: CableTerminal + - type: Godmode + missingComponents: + - Destructible + - RCDDeconstructable +- proto: CableTerminalUncuttable entities: - uid: 84 components: @@ -731,6 +1106,11 @@ entities: rot: 1.5707963267948966 rad pos: -0.5,7.5 parent: 292 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Destructible + - Construction - proto: ChairPilotSeat entities: - uid: 223 @@ -739,112 +1119,207 @@ entities: rot: -1.5707963267948966 rad pos: 2.5,-0.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 224 components: - type: Transform rot: -1.5707963267948966 rad pos: 2.5,0.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 225 components: - type: Transform rot: -1.5707963267948966 rad pos: 2.5,1.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 226 components: - type: Transform rot: -1.5707963267948966 rad pos: 2.5,2.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 227 components: - type: Transform rot: -1.5707963267948966 rad pos: -1.5,-0.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 228 components: - type: Transform rot: -1.5707963267948966 rad pos: -1.5,0.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 229 components: - type: Transform rot: -1.5707963267948966 rad pos: -1.5,1.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 230 components: - type: Transform rot: -1.5707963267948966 rad pos: -1.5,2.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 231 components: - type: Transform rot: 1.5707963267948966 rad pos: 0.5,-0.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 232 components: - type: Transform rot: 1.5707963267948966 rad pos: 0.5,0.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 233 components: - type: Transform rot: 1.5707963267948966 rad pos: 0.5,1.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 234 components: - type: Transform rot: 1.5707963267948966 rad pos: 0.5,2.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 235 components: - type: Transform rot: 1.5707963267948966 rad pos: -3.5,-0.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 236 components: - type: Transform rot: 1.5707963267948966 rad pos: -3.5,0.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 237 components: - type: Transform rot: 1.5707963267948966 rad pos: -3.5,1.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 238 components: - type: Transform rot: 1.5707963267948966 rad pos: -3.5,2.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 239 components: - type: Transform pos: 1.5,5.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 240 components: - type: Transform pos: -2.5,5.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 241 components: - type: Transform rot: 3.141592653589793 rad pos: -0.5,8.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - proto: ClosetEmergencyFilledRandom entities: - uid: 252 @@ -852,72 +1327,18 @@ entities: - type: Transform pos: 0.5,5.5 parent: 292 - - type: EntityStorage - air: - volume: 200 - immutable: False - temperature: 293.14963 - moles: - - 1.7459903 - - 6.568249 - - 0 - - 0 - - 0 - - 0 - - 0 - - 0 - - 0 - - 0 - - 0 - - 0 - - uid: 260 + - uid: 253 components: - type: Transform pos: -2.5,-3.5 parent: 292 - - type: EntityStorage - air: - volume: 200 - immutable: False - temperature: 293.14963 - moles: - - 1.7459903 - - 6.568249 - - 0 - - 0 - - 0 - - 0 - - 0 - - 0 - - 0 - - 0 - - 0 - - 0 - proto: ClosetFireFilled entities: - - uid: 253 + - uid: 260 components: - type: Transform pos: -1.5,5.5 parent: 292 - - type: EntityStorage - air: - volume: 200 - immutable: False - temperature: 293.14963 - moles: - - 1.7459903 - - 6.568249 - - 0 - - 0 - - 0 - - 0 - - 0 - - 0 - - 0 - - 0 - - 0 - - 0 - proto: ClosetWallEmergencyFilledRandom entities: - uid: 288 @@ -944,6 +1365,10 @@ entities: - 0 - 0 - 0 + - type: Godmode + missingComponents: + - Destructible + - Construction - uid: 289 components: - type: Transform @@ -967,6 +1392,10 @@ entities: - 0 - 0 - 0 + - type: Godmode + missingComponents: + - Destructible + - Construction - proto: ClosetWallFireFilledRandom entities: - uid: 286 @@ -992,6 +1421,10 @@ entities: - 0 - 0 - 0 + - type: Godmode + missingComponents: + - Destructible + - Construction - uid: 287 components: - type: Transform @@ -1016,40 +1449,28 @@ entities: - 0 - 0 - 0 + - type: Godmode + missingComponents: + - Destructible + - Construction - proto: ClothingBackpack entities: - - uid: 275 + - uid: 266 components: - type: Transform - pos: 2.5,5.5 + pos: 2.5277145,5.600461 parent: 292 - - type: GroupExamine - group: - - hoverMessage: "" - contextText: verb-examine-group-other - icon: /Textures/Interface/examine-star.png - components: - - Armor - - ClothingSpeedModifier - entries: - - message: >- - It provides the following protection: - - - [color=orange]Explosion[/color] damage [color=white]to contents[/color] reduced by [color=lightblue]10%[/color]. - priority: 0 - component: Armor - title: null - proto: ClothingMaskBreath entities: - - uid: 272 + - uid: 267 components: - type: Transform - pos: 2.5,-3.5 + pos: 2.4086668,-3.4828715 parent: 292 - - uid: 273 + - uid: 274 components: - type: Transform - pos: -3.5,-3.5 + pos: -3.6032372,-3.4947772 parent: 292 - proto: ComputerShuttle entities: @@ -1058,24 +1479,29 @@ entities: - type: Transform pos: -0.5,9.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - proto: CrowbarRed entities: - - uid: 274 + - uid: 293 components: - type: Transform - pos: 0.5,-3.5 + pos: 0.45628688,-3.5066814 parent: 292 - proto: EmergencyOxygenTankFilled entities: - - uid: 270 + - uid: 268 components: - type: Transform - pos: 2.5708976,-3.5851696 + pos: -3.2460945,-3.6614437 parent: 292 - - uid: 271 + - uid: 269 components: - type: Transform - pos: -3.4291024,-3.5851696 + pos: 2.7300956,-3.6138248 parent: 292 - proto: ExtinguisherCabinetFilled entities: @@ -1084,6 +1510,9 @@ entities: - type: Transform pos: -0.5,-4.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible - proto: GasPassiveGate entities: - uid: 184 @@ -1091,6 +1520,11 @@ entities: - type: Transform pos: -0.5,7.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - proto: GasPipeBend entities: - uid: 182 @@ -1099,34 +1533,64 @@ entities: rot: 1.5707963267948966 rad pos: -1.5,8.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 183 components: - type: Transform pos: -0.5,8.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 187 components: - type: Transform rot: 1.5707963267948966 rad pos: -2.5,5.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 188 components: - type: Transform pos: 1.5,5.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 189 components: - type: Transform rot: -1.5707963267948966 rad pos: 1.5,-3.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 190 components: - type: Transform rot: 3.141592653589793 rad pos: -2.5,-3.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - proto: GasPipeFourway entities: - uid: 186 @@ -1134,6 +1598,11 @@ entities: - type: Transform pos: -0.5,5.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - proto: GasPipeStraight entities: - uid: 185 @@ -1141,110 +1610,215 @@ entities: - type: Transform pos: -0.5,6.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 192 components: - type: Transform rot: 1.5707963267948966 rad pos: 0.5,5.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 193 components: - type: Transform rot: 1.5707963267948966 rad pos: -1.5,5.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 194 components: - type: Transform rot: 1.5707963267948966 rad pos: -1.5,-3.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 195 components: - type: Transform rot: 1.5707963267948966 rad pos: 0.5,-3.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 196 components: - type: Transform pos: 1.5,-2.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 197 components: - type: Transform pos: 1.5,-1.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 198 components: - type: Transform pos: 1.5,-0.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 199 components: - type: Transform pos: 1.5,0.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 200 components: - type: Transform pos: 1.5,1.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 201 components: - type: Transform pos: 1.5,2.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 202 components: - type: Transform pos: 1.5,3.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 203 components: - type: Transform pos: 1.5,4.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 204 components: - type: Transform pos: -2.5,-2.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 205 components: - type: Transform pos: -2.5,-1.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 206 components: - type: Transform pos: -2.5,-0.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 207 components: - type: Transform pos: -2.5,0.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 208 components: - type: Transform pos: -2.5,1.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 209 components: - type: Transform pos: -2.5,2.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 210 components: - type: Transform pos: -2.5,3.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 211 components: - type: Transform pos: -2.5,4.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - proto: GasPipeTJunction entities: - uid: 191 @@ -1253,6 +1827,11 @@ entities: rot: 3.141592653589793 rad pos: -0.5,-3.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - proto: GasPort entities: - uid: 181 @@ -1261,6 +1840,11 @@ entities: rot: 3.141592653589793 rad pos: -1.5,7.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - proto: GasVentPump entities: - uid: 212 @@ -1268,12 +1852,22 @@ entities: - type: Transform pos: -0.5,-2.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 213 components: - type: Transform rot: 3.141592653589793 rad pos: -0.5,4.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - proto: GeneratorBasic15kW entities: - uid: 114 @@ -1281,11 +1875,19 @@ entities: - type: Transform pos: -1.5,-5.5 parent: 292 + - type: Godmode + missingComponents: + - Anchorable + - Destructible - uid: 115 components: - type: Transform pos: 0.5,-5.5 parent: 292 + - type: Godmode + missingComponents: + - Anchorable + - Destructible - proto: GeneratorWallmountAPU entities: - uid: 78 @@ -1293,6 +1895,11 @@ entities: - type: Transform pos: 1.5,7.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - proto: GravityGeneratorMini entities: - uid: 291 @@ -1300,6 +1907,11 @@ entities: - type: Transform pos: -2.5,-5.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Anchorable + - Construction - proto: Grille entities: - uid: 44 @@ -1307,116 +1919,231 @@ entities: - type: Transform pos: 3.5,-0.5 parent: 292 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 52 components: - type: Transform pos: 3.5,0.5 parent: 292 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 53 components: - type: Transform pos: 3.5,1.5 parent: 292 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 54 components: - type: Transform pos: 3.5,2.5 parent: 292 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 55 components: - type: Transform pos: -4.5,-0.5 parent: 292 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 56 components: - type: Transform pos: -4.5,0.5 parent: 292 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 57 components: - type: Transform pos: -4.5,1.5 parent: 292 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 58 components: - type: Transform pos: -4.5,2.5 parent: 292 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 59 components: - type: Transform pos: -1.5,-4.5 parent: 292 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 60 components: - type: Transform pos: -2.5,-4.5 parent: 292 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 61 components: - type: Transform pos: 1.5,-4.5 parent: 292 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 62 components: - type: Transform pos: 0.5,-4.5 parent: 292 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 63 components: - type: Transform pos: 0.5,6.5 parent: 292 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 64 components: - type: Transform pos: -1.5,6.5 parent: 292 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 65 components: - type: Transform pos: -2.5,8.5 parent: 292 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 66 components: - type: Transform pos: -2.5,9.5 parent: 292 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 67 components: - type: Transform pos: -1.5,9.5 parent: 292 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 68 components: - type: Transform pos: -1.5,10.5 parent: 292 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 69 components: - type: Transform pos: -0.5,10.5 parent: 292 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 70 components: - type: Transform pos: 0.5,10.5 parent: 292 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 71 components: - type: Transform pos: 0.5,9.5 parent: 292 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 72 components: - type: Transform pos: 1.5,9.5 parent: 292 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - uid: 73 components: - type: Transform pos: 1.5,8.5 parent: 292 + - type: Godmode + missingComponents: + - RCDDeconstructable + - Construction + - Destructible - proto: Gyroscope entities: - uid: 168 @@ -1424,6 +2151,11 @@ entities: - type: Transform pos: 1.5,-5.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Anchorable + - Construction - proto: IntercomCommon entities: - uid: 264 @@ -1431,6 +2163,12 @@ entities: - type: Transform pos: -0.5,-1.5 parent: 292 + - type: EncryptionKeyHolder + keysUnlocked: False + - type: Godmode + missingComponents: + - Construction + - Destructible - proto: MaintenanceFluffSpawner entities: - uid: 284 @@ -1438,29 +2176,31 @@ entities: - type: Transform pos: 0.5,3.5 parent: 292 + - type: Godmode - uid: 285 components: - type: Transform pos: -1.5,3.5 parent: 292 + - type: Godmode - proto: MedkitFilled entities: - - uid: 266 + - uid: 276 components: - type: Transform - pos: -0.5,-3.5 + pos: -0.4960943,-3.4828715 parent: 292 - proto: NitrogenTankFilled entities: - - uid: 268 + - uid: 271 components: - type: Transform - pos: -3.5,-3.5 + pos: -3.4365704,-3.590015 parent: 292 - - uid: 269 + - uid: 273 components: - type: Transform - pos: 2.5,-3.5 + pos: 2.563429,-3.566205 parent: 292 - proto: PosterLegitNanotrasenLogo entities: @@ -1469,6 +2209,9 @@ entities: - type: Transform pos: -2.5,6.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible - proto: PottedPlantRandom entities: - uid: 254 @@ -1476,21 +2219,25 @@ entities: - type: Transform pos: 2.5,-1.5 parent: 292 + - type: Godmode - uid: 255 components: - type: Transform pos: 2.5,3.5 parent: 292 + - type: Godmode - uid: 256 components: - type: Transform pos: -3.5,3.5 parent: 292 + - type: Godmode - uid: 257 components: - type: Transform pos: -3.5,-1.5 parent: 292 + - type: Godmode - proto: PowerCellRecharger entities: - uid: 265 @@ -1498,7 +2245,12 @@ entities: - type: Transform pos: 0.5,-3.5 parent: 292 -- proto: Poweredlight + - type: Godmode + missingComponents: + - Anchorable + - Destructible + - Construction +- proto: AlwaysPoweredWallLight entities: - uid: 279 components: @@ -1508,6 +2260,11 @@ entities: parent: 292 - type: ApcPowerReceiver powerLoad: 0 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 280 components: - type: Transform @@ -1516,6 +2273,11 @@ entities: parent: 292 - type: ApcPowerReceiver powerLoad: 0 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 281 components: - type: Transform @@ -1524,6 +2286,11 @@ entities: parent: 292 - type: ApcPowerReceiver powerLoad: 0 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 282 components: - type: Transform @@ -1532,6 +2299,11 @@ entities: parent: 292 - type: ApcPowerReceiver powerLoad: 0 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 283 components: - type: Transform @@ -1540,6 +2312,11 @@ entities: parent: 292 - type: ApcPowerReceiver powerLoad: 0 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - proto: Rack entities: - uid: 262 @@ -1547,11 +2324,21 @@ entities: - type: Transform pos: 2.5,-3.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - uid: 263 components: - type: Transform pos: -3.5,-3.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - Anchorable + - Destructible - proto: ShuttleWindow entities: - uid: 28 @@ -1559,116 +2346,231 @@ entities: - type: Transform pos: 3.5,-0.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction + - RCDDeconstructable - uid: 29 components: - type: Transform pos: 3.5,0.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction + - RCDDeconstructable - uid: 30 components: - type: Transform pos: 3.5,1.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction + - RCDDeconstructable - uid: 31 components: - type: Transform pos: 3.5,2.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction + - RCDDeconstructable - uid: 32 components: - type: Transform pos: -4.5,-0.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction + - RCDDeconstructable - uid: 33 components: - type: Transform pos: -4.5,0.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction + - RCDDeconstructable - uid: 34 components: - type: Transform pos: -4.5,1.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction + - RCDDeconstructable - uid: 35 components: - type: Transform pos: -4.5,2.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction + - RCDDeconstructable - uid: 36 components: - type: Transform pos: -1.5,-4.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction + - RCDDeconstructable - uid: 37 components: - type: Transform pos: -2.5,-4.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction + - RCDDeconstructable - uid: 38 components: - type: Transform pos: 0.5,-4.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction + - RCDDeconstructable - uid: 39 components: - type: Transform pos: 1.5,-4.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction + - RCDDeconstructable - uid: 40 components: - type: Transform pos: 0.5,6.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction + - RCDDeconstructable - uid: 41 components: - type: Transform pos: -1.5,6.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction + - RCDDeconstructable - uid: 42 components: - type: Transform pos: -2.5,8.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction + - RCDDeconstructable - uid: 43 components: - type: Transform pos: -1.5,9.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction + - RCDDeconstructable - uid: 45 components: - type: Transform pos: -2.5,9.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction + - RCDDeconstructable - uid: 46 components: - type: Transform pos: -1.5,10.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction + - RCDDeconstructable - uid: 47 components: - type: Transform pos: -0.5,10.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction + - RCDDeconstructable - uid: 48 components: - type: Transform pos: 0.5,10.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction + - RCDDeconstructable - uid: 49 components: - type: Transform pos: 0.5,9.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction + - RCDDeconstructable - uid: 50 components: - type: Transform pos: 1.5,9.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction + - RCDDeconstructable - uid: 51 components: - type: Transform pos: 1.5,8.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction + - RCDDeconstructable - proto: SMESBasic entities: - uid: 76 @@ -1676,6 +2578,11 @@ entities: - type: Transform pos: 0.5,7.5 parent: 292 + - type: Godmode + missingComponents: + - Anchorable + - Destructible + - Construction - proto: SpaceVillainArcadeFilled entities: - uid: 259 @@ -1684,6 +2591,11 @@ entities: rot: 1.5707963267948966 rad pos: 0.5,-1.5 parent: 292 + - type: Godmode + missingComponents: + - Anchorable + - Construction + - Destructible - proto: SubstationWallBasic entities: - uid: 77 @@ -1691,6 +2603,10 @@ entities: - type: Transform pos: 1.5,6.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction - proto: TableReinforced entities: - uid: 243 @@ -1698,46 +2614,82 @@ entities: - type: Transform pos: 0.5,-3.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction - uid: 244 components: - type: Transform pos: -1.5,8.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction - uid: 245 components: - type: Transform pos: 0.5,8.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction - uid: 246 components: - type: Transform pos: -0.5,-3.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction - uid: 247 components: - type: Transform pos: -1.5,-3.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction - uid: 248 components: - type: Transform pos: 0.5,3.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction - uid: 249 components: - type: Transform pos: -1.5,3.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction - uid: 250 components: - type: Transform pos: 2.5,5.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction - uid: 251 components: - type: Transform pos: -3.5,5.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction - proto: Thruster entities: - uid: 169 @@ -1745,58 +2697,103 @@ entities: - type: Transform pos: 2.5,7.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Anchorable + - Construction - uid: 170 components: - type: Transform pos: -3.5,7.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Anchorable + - Construction - uid: 171 components: - type: Transform rot: 3.141592653589793 rad pos: -1.5,-6.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Anchorable + - Construction - uid: 172 components: - type: Transform rot: 3.141592653589793 rad pos: -2.5,-6.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Anchorable + - Construction - uid: 173 components: - type: Transform rot: 3.141592653589793 rad pos: 1.5,-6.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Anchorable + - Construction - uid: 174 components: - type: Transform rot: 3.141592653589793 rad pos: 0.5,-6.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Anchorable + - Construction - uid: 175 components: - type: Transform rot: -1.5707963267948966 rad pos: 2.5,-6.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Anchorable + - Construction - uid: 176 components: - type: Transform rot: 1.5707963267948966 rad pos: -3.5,-6.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Anchorable + - Construction - proto: ToolboxEmergencyFilled entities: - - uid: 267 + - uid: 270 components: - type: Transform - pos: -1.5,-3.5 + pos: -1.4722855,-3.4471583 parent: 292 - - uid: 276 + - uid: 272 components: - type: Transform - pos: -3.5,5.5 + pos: -1.4722855,-3.4471583 + parent: 292 + - uid: 275 + components: + - type: Transform + pos: -3.5079994,5.600461 parent: 292 - proto: VendingMachineClothing entities: @@ -1805,6 +2802,10 @@ entities: - type: Transform pos: 1.5,-3.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Anchorable - proto: WallShuttle entities: - uid: 1 @@ -1812,146 +2813,262 @@ entities: - type: Transform pos: 3.5,-3.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction - uid: 2 components: - type: Transform pos: 3.5,-1.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction - uid: 3 components: - type: Transform pos: -4.5,-3.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction - uid: 4 components: - type: Transform pos: -4.5,-1.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction - uid: 5 components: - type: Transform pos: -4.5,3.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction - uid: 6 components: - type: Transform pos: -4.5,5.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction - uid: 7 components: - type: Transform pos: 3.5,3.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction - uid: 8 components: - type: Transform pos: 3.5,5.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction - uid: 9 components: - type: Transform pos: 3.5,6.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction - uid: 10 components: - type: Transform pos: 2.5,6.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction - uid: 11 components: - type: Transform pos: -4.5,6.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction - uid: 12 components: - type: Transform pos: -3.5,6.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction - uid: 13 components: - type: Transform pos: -2.5,6.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction - uid: 14 components: - type: Transform pos: -2.5,7.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction - uid: 15 components: - type: Transform pos: 1.5,6.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction - uid: 16 components: - type: Transform pos: 1.5,7.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction - uid: 17 components: - type: Transform pos: 3.5,-4.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction - uid: 18 components: - type: Transform pos: 2.5,-4.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction - uid: 19 components: - type: Transform pos: -4.5,-4.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction - uid: 20 components: - type: Transform pos: -3.5,-4.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction - uid: 21 components: - type: Transform pos: -0.5,-4.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction - uid: 22 components: - type: Transform pos: 2.5,-5.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction - uid: 23 components: - type: Transform pos: 3.5,-5.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction - uid: 24 components: - type: Transform pos: -3.5,-5.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction - uid: 25 components: - type: Transform pos: -4.5,-5.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction - uid: 26 components: - type: Transform pos: -0.5,-6.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction - uid: 27 components: - type: Transform pos: -0.5,-5.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction - uid: 74 components: - type: Transform pos: -0.5,-1.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction - uid: 75 components: - type: Transform pos: -0.5,3.5 parent: 292 + - type: Godmode + missingComponents: + - Destructible + - Construction - proto: WindowReinforcedDirectional entities: - uid: 215 @@ -1960,46 +3077,86 @@ entities: rot: -1.5707963267948966 rad pos: -0.5,-0.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 216 components: - type: Transform rot: -1.5707963267948966 rad pos: -0.5,0.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 217 components: - type: Transform rot: -1.5707963267948966 rad pos: -0.5,1.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 218 components: - type: Transform rot: -1.5707963267948966 rad pos: -0.5,2.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 219 components: - type: Transform rot: 1.5707963267948966 rad pos: -0.5,2.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 220 components: - type: Transform rot: 1.5707963267948966 rad pos: -0.5,1.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 221 components: - type: Transform rot: 1.5707963267948966 rad pos: -0.5,0.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible - uid: 222 components: - type: Transform rot: 1.5707963267948966 rad pos: -0.5,-0.5 parent: 292 + - type: Godmode + missingComponents: + - Construction + - RCDDeconstructable + - Destructible ... From 8522ffe8ce17f5eaa761f32c8689114083581728 Mon Sep 17 00:00:00 2001 From: PJBot Date: Sat, 23 Nov 2024 15:15:19 +0000 Subject: [PATCH 30/59] Automatic changelog update --- Resources/Changelog/Changelog.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index 8146476b3e..89a03ee2a0 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,11 +1,4 @@ Entries: -- author: EmoGarbage404 - changes: - - message: Ore can no longer be destroyed by explosions. Happy blast mining. - type: Tweak - id: 7145 - time: '2024-08-19T01:55:49.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/31182 - author: slarticodefast changes: - message: Mobs without hands can no longer toggle other players' suit pieces. @@ -3929,3 +3922,10 @@ id: 7644 time: '2024-11-23T11:41:37.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/32447 +- author: IProduceWidgets + changes: + - message: Arrivals shuttle is more tamper proof. + type: Fix + id: 7645 + time: '2024-11-23T15:14:13.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/33284 From 11dbf50ed62040c832941f3c46fc159497eca525 Mon Sep 17 00:00:00 2001 From: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com> Date: Sun, 24 Nov 2024 03:52:58 +1100 Subject: [PATCH 31/59] Add delay to AutoOrient (#33479) It functions identically to how V1 of orientation worked and it's incredibly annoying. --- Content.Shared/CCVar/CCVars.Shuttle.cs | 6 +++ .../Components/AutoOrientComponent.cs | 5 +- .../Movement/Systems/AutoOrientSystem.cs | 51 +++++++++++++++++++ .../Systems/SharedMoverController.Input.cs | 7 --- 4 files changed, 60 insertions(+), 9 deletions(-) create mode 100644 Content.Shared/Movement/Systems/AutoOrientSystem.cs diff --git a/Content.Shared/CCVar/CCVars.Shuttle.cs b/Content.Shared/CCVar/CCVars.Shuttle.cs index f66fe9ca59..caf7f81b0e 100644 --- a/Content.Shared/CCVar/CCVars.Shuttle.cs +++ b/Content.Shared/CCVar/CCVars.Shuttle.cs @@ -4,6 +4,12 @@ namespace Content.Shared.CCVar; public sealed partial class CCVars { + /// + /// Delay for auto-orientation. Used for people arriving via arrivals. + /// + public static readonly CVarDef AutoOrientDelay = + CVarDef.Create("shuttle.auto_orient_delay", 2.0, CVar.SERVER | CVar.REPLICATED); + /// /// If true then the camera will match the grid / map and is unchangeable. /// - When traversing grids it will snap to 0 degrees rotation. diff --git a/Content.Shared/Movement/Components/AutoOrientComponent.cs b/Content.Shared/Movement/Components/AutoOrientComponent.cs index 4b89b0cbf4..1031425c71 100644 --- a/Content.Shared/Movement/Components/AutoOrientComponent.cs +++ b/Content.Shared/Movement/Components/AutoOrientComponent.cs @@ -5,8 +5,9 @@ namespace Content.Shared.Movement.Components; /// /// Automatically rotates eye upon grid traversals. /// -[RegisterComponent, NetworkedComponent] +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState, AutoGenerateComponentPause] public sealed partial class AutoOrientComponent : Component { - + [DataField, AutoNetworkedField, AutoPausedField] + public TimeSpan? NextChange; } diff --git a/Content.Shared/Movement/Systems/AutoOrientSystem.cs b/Content.Shared/Movement/Systems/AutoOrientSystem.cs new file mode 100644 index 0000000000..3bbd715df5 --- /dev/null +++ b/Content.Shared/Movement/Systems/AutoOrientSystem.cs @@ -0,0 +1,51 @@ +using Content.Shared.CCVar; +using Content.Shared.Movement.Components; +using Robust.Shared.Configuration; +using Robust.Shared.Timing; + +namespace Content.Shared.Movement.Systems; + +public sealed class AutoOrientSystem : EntitySystem +{ + [Dependency] private readonly IConfigurationManager _cfgManager = default!; + [Dependency] private readonly IGameTiming _timing = default!; + [Dependency] private readonly SharedMoverController _mover = default!; + + private TimeSpan _delay = TimeSpan.Zero; + + public override void Initialize() + { + base.Initialize(); + SubscribeLocalEvent(OnEntParentChanged); + + Subs.CVar(_cfgManager, CCVars.AutoOrientDelay, OnAutoOrient, true); + } + + private void OnAutoOrient(double obj) + { + _delay = TimeSpan.FromSeconds(obj); + } + + private void OnEntParentChanged(Entity ent, ref EntParentChangedMessage args) + { + ent.Comp.NextChange = _timing.CurTime + _delay; + Dirty(ent); + } + + public override void Update(float frameTime) + { + base.Update(frameTime); + + var query = EntityQueryEnumerator(); + + while (query.MoveNext(out var uid, out var comp)) + { + if (comp.NextChange <= _timing.CurTime) + { + comp.NextChange = null; + Dirty(uid, comp); + _mover.ResetCamera(uid); + } + } + } +} diff --git a/Content.Shared/Movement/Systems/SharedMoverController.Input.cs b/Content.Shared/Movement/Systems/SharedMoverController.Input.cs index c11df709f6..1fe38b6cdf 100644 --- a/Content.Shared/Movement/Systems/SharedMoverController.Input.cs +++ b/Content.Shared/Movement/Systems/SharedMoverController.Input.cs @@ -57,8 +57,6 @@ namespace Content.Shared.Movement.Systems SubscribeLocalEvent(OnMoverHandleState); SubscribeLocalEvent(OnInputParentChange); - SubscribeLocalEvent(OnAutoParentChange); - SubscribeLocalEvent(OnFollowedParentChange); Subs.CVar(_configManager, CCVars.CameraRotationLocked, obj => CameraRotationLocked = obj, true); @@ -146,11 +144,6 @@ namespace Content.Shared.Movement.Systems protected virtual void HandleShuttleInput(EntityUid uid, ShuttleButtons button, ushort subTick, bool state) {} - private void OnAutoParentChange(Entity entity, ref EntParentChangedMessage args) - { - ResetCamera(entity.Owner); - } - public void RotateCamera(EntityUid uid, Angle angle) { if (CameraRotationLocked || !MoverQuery.TryGetComponent(uid, out var mover)) From e958c0c9b0ece05a40efea3a962cd1fd1916000e Mon Sep 17 00:00:00 2001 From: PJBot Date: Sat, 23 Nov 2024 16:54:04 +0000 Subject: [PATCH 32/59] Automatic changelog update --- Resources/Changelog/Changelog.yml | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index 89a03ee2a0..e15f682297 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,11 +1,4 @@ Entries: -- author: slarticodefast - changes: - - message: Mobs without hands can no longer toggle other players' suit pieces. - type: Fix - id: 7146 - time: '2024-08-19T02:41:27.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/31152 - author: Goldminermac changes: - message: Chocolate-chip and blueberry pancakes can now be in stacks of up to nine @@ -3929,3 +3922,11 @@ id: 7645 time: '2024-11-23T15:14:13.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/33284 +- author: metalgearsloth + changes: + - message: The auto-orientation when showing up on the arrivals shuttle now has + a delay to it. + type: Tweak + id: 7646 + time: '2024-11-23T16:52:58.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/33479 From ef89d5cc21b4dcf147ccf3f10bdce21f9286b248 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 24 Nov 2024 12:56:18 +1100 Subject: [PATCH 33/59] Update Credits (#33503) Co-authored-by: PJBot --- Resources/Credits/GitHub.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Resources/Credits/GitHub.txt b/Resources/Credits/GitHub.txt index 53c4eb7ea0..326dc1945d 100644 --- a/Resources/Credits/GitHub.txt +++ b/Resources/Credits/GitHub.txt @@ -1 +1 @@ -0x6273, 12rabbits, 13spacemen, 2013HORSEMEATSCANDAL, 20kdc, 21Melkuu, 3nderall, 4310v343k, 4dplanner, 612git, 778b, Ablankmann, abregado, Absolute-Potato, achookh, Acruid, actioninja, actually-reb, ada-please, adamsong, Adeinitas, Admiral-Obvious-001, adrian, Adrian16199, Ady4ik, Aerocrux, Aeshus, Aexolott, Aexxie, africalimedrop, afrokada, AftrLite, Agoichi, Ahion, aiden, AJCM-git, AjexRose, Alekshhh, alexkar598, AlexMorgan3817, alexumandxgabriel08x, Alithsko, ALMv1, Alpha-Two, AlphaQwerty, Altoids1, amylizzle, ancientpower, Andre19926, AndrewEyeke, AndreyCamper, Anzarot121, Appiah, ar4ill, ArchPigeon, ArchRBX, areitpog, Arendian, arimah, Arkanic, ArkiveDev, armoks, Arteben, ArthurMousatov, ArtisticRoomba, artur, AruMoon, ArZarLordOfMango, as334, AsikKEsel, AsnDen, asperger-sind, aspiringLich, astriloqua, august-sun, AutoOtter, avghdev, Awlod, AzzyIsNotHere, BackeTako, BananaFlambe, Baptr0b0t, BasedUser, beck-thompson, bellwetherlogic, benev0, benjamin-burges, BGare, bhenrich, bhespiritu, bibbly, BIGZi0348, bingojohnson, BismarckShuffle, Bixkitts, Blackern5000, Blazeror, BlitzTheSquishy, bloodrizer, Bloody2372, blueDev2, Boaz1111, BobdaBiscuit, BobTheSleder, boiled-water-tsar, BombasterDS, Boolean-Buckeye, botanySupremist, brainfood1183, BramvanZijp, Brandon-Huu, BriBrooo, Bright0, brndd, bryce0110, BubblegumBlue, buletsponge, buntobaggins, bvelliquette, byondfuckery, c0rigin, c4llv07e, CaasGit, Caconym27, Calecute, Callmore, capnsockless, CaptainSqrBeard, Carbonhell, Carolyn3114, Carou02, carteblanche4me, Catofquestionableethics, CatTheSystem, Centronias, chairbender, Charlese2, charlie, ChaseFlorom, chavonadelal, Cheackraze, CheddaCheez, cheesePizza2, cheeseplated, Chief-Engineer, chillyconmor, christhirtle, chromiumboy, Chronophylos, Chubbicous, Chubbygummibear, Ciac32, civilCornball, Clement-O, clyf, Clyybber, CMDR-Piboy314, cohanna, Cohnway, Cojoke-dot, ColdAutumnRain, Colin-Tel, collinlunn, ComicIronic, CookieMasterT, coolboy911, coolmankid12345, Coolsurf6, corentt, CormosLemming, crazybrain23, creadth, CrigCrag, croilbird, Crotalus, CrudeWax, CrzyPotato, cutemoongod, Cyberboss, d34d10cc, d4kii, DadeKuma, Daemon, daerSeebaer, dahnte, dakamakat, DamianX, DangerRevolution, daniel-cr, DanSAussieITS, Daracke, Darkenson, DawBla, Daxxi3, dch-GH, de0rix, Deahaka, dean, DEATHB4DEFEAT, DeathCamel58, Deatherd, deathride58, DebugOk, Decappi, Decortex, Deeeeja, deepdarkdepths, degradka, Delete69, deltanedas, DenisShvalov, DerbyX, derek, dersheppard, Deserty0, Detintinto, DevilishMilk, dexlerxd, dffdff2423, DieselMohawk, digitalic, Dimastra, DinoWattz, DisposableCrewmember42, DjfjdfofdjfjD, doc-michael, docnite, Doctor-Cpu, DoctorBeard, DogZeroX, dolgovmi, dontbetank, Doomsdrayk, Doru991, DoubleRiceEddiedd, DoutorWhite, dragonryan06, drakewill-CRL, Drayff, dreamlyjack, DrEnzyme, dribblydrone, DrMelon, drongood12, DrSingh, DrSmugleaf, drteaspoon420, DTanxxx, DubiousDoggo, Duddino, dukevanity, duskyjay, Dutch-VanDerLinde, dvir001, Dynexust, Easypoller, echo, eclips_e, eden077, EEASAS, Efruit, efzapa, Ekkosangen, ElectroSR, elsie, elthundercloud, Elysium206, Emisse, emmafornash, EmoGarbage404, Endecc, eoineoineoin, eris, erohrs2, ERORR404V1, Errant-4, ertanic, esguard, estacaoespacialpirata, eugene, ewokswagger, exincore, exp111, f0x-n3rd, FacePluslll, Fahasor, FairlySadPanda, FATFSAAM2, Feluk6174, ficcialfaint, Fiftyllama, Fildrance, FillerVK, FinnishPaladin, firenamefn, FirinMaLazors, Fishfish458, FL-OZ, Flareguy, flashgnash, FluffiestFloof, FluffMe, FluidRock, foboscheshir, FoLoKe, fooberticus, ForestNoises, forgotmyotheraccount, forkeyboards, forthbridge, Fortune117, Fouin, foxhorn, freeman2651, freeze2222, Froffy025, Fromoriss, froozigiusz, FrostMando, FungiFellow, FunTust, Futuristic-OK, GalacticChimp, gamer3107, Gaxeer, gbasood, Geekyhobo, genderGeometries, GeneralGaws, Genkail, geraeumig, Ghagliiarghii, Git-Nivrak, githubuser508, gituhabu, GlassEclipse, GNF54, godisdeadLOL, goet, Goldminermac, Golinth, GoodWheatley, Gorox221, gradientvera, graevy, GraniteSidewalk, GreaseMonk, greenrock64, GreyMario, GTRsound, gusxyz, Gyrandola, h3half, hamurlik, Hanzdegloker, HappyRoach, Hardly3D, harikattar, he1acdvv, Hebi, Henry, HerCoyote23, hitomishirichan, hiucko, Hmeister-fake, Hmeister-real, Hobbitmax, hobnob, HoidC, Holinka4ever, holyssss, HoofedEar, Hoolny, hord-brayden, Hreno, hubismal, Hugal31, Huxellberger, Hyenh, hyphenationc, i-justuser-i, iacore, IamVelcroboy, Ian321, icekot8, icesickleone, iczero, iglov, IgorAnt028, igorsaux, ike709, illersaver, Illiux, Ilushkins33, Ilya246, IlyaElDunaev, imrenq, imweax, indeano, Injazz, Insineer, IntegerTempest, Interrobang01, IProduceWidgets, ItsMeThom, Itzbenz, iztokbajcar, Jackal298, Jackrost, jacksonzck, Jackw2As, jacob, jamessimo, janekvap, Jark255, Jarmer123, Jaskanbe, JasperJRoth, JerryImMouse, jerryimmouse, Jessetriesagain, jessicamaybe, Jezithyr, jicksaw, JiimBob, JimGamemaster, jimmy12or, JIPDawg, jjtParadox, jmcb, JoeHammad1844, JohnGinnane, johnku1, Jophire, joshepvodka, Jrpl, juliangiebel, JustArt1m, JustCone14, justdie12, justin, justintether, JustinTrotter, justtne, K-Dynamic, k3yw, Kadeo64, Kaga-404, KaiShibaa, kalane15, kalanosh, Kanashi-Panda, katzenminer, kbailey-git, Keelin, Keer-Sar, KEEYNy, keikiru, Kelrak, kerisargit, keronshb, KIBORG04, Killerqu00, Kimpes, KingFroozy, kira-er, Kirillcas, Kirus59, Kistras, Kit0vras, KittenColony, klaypexx, Kmc2000, Ko4ergaPunk, kognise, kokoc9n, komunre, KonstantinAngelov, kosticia, koteq, KrasnoshchekovPavel, Krunklehorn, Kupie, kxvvv, kyupolaris, kzhanik, lajolico, Lamrr, LankLTE, laok233, lapatison, larryrussian, lawdog4817, Lazzi0706, leander-0, leonardo-dabepis, leonidussaks, leonsfriedrich, LeoSantich, lettern, LetterN, Level10Cybermancer, LEVELcat, lever1209, Lgibb18, lgruthes, LightVillet, liltenhead, LinkUyx, LittleBuilderJane, LittleNorthStar, LittleNyanCat, lizelive, localcc, lokachop, Lomcastar, LordCarve, LordEclipse, LucasTheDrgn, luckyshotpictures, LudwigVonChesterfield, luizwritescode, Lukasz825700516, luminight, lunarcomets, luringens, lvvova1, Lyndomen, lyroth001, lzimann, lzk228, M3739, mac6na6na, MACMAN2003, Macoron, Magicalus, magmodius, MagnusCrowe, malchanceux, MaloTV, ManelNavola, Mangohydra, marboww, Markek1, Matz05, max, MaxNox7, maylokana, MehimoNemo, MeltedPixel, MemeProof, MendaxxDev, Menshin, Mephisto72, MerrytheManokit, Mervill, metalgearsloth, MetalSage, MFMessage, mhamsterr, michaelcu, micheel665, MilenVolf, MilonPL, Minemoder5000, Minty642, Mirino97, mirrorcult, misandrie, MishaUnity, MissKay1994, MisterMecky, Mith-randalf, MjrLandWhale, mkanke-real, MLGTASTICa, moderatelyaware, modern-nm, mokiros, Moneyl, Moomoobeef, moony, Morb0, MossyGreySlope, mr-bo-jangles, Mr0maks, MrFippik, mrrobdemo, muburu, MureixloI, musicmanvr, MWKane, Myakot, Myctai, N3X15, nails-n-tape, Nairodian, Naive817, NakataRin, namespace-Memory, Nannek, NazrinNya, neutrino-laser, NickPowers43, nikthechampiongr, Nimfar11, Nirnael, NIXC, NkoKirkto, nmajask, noctyrnal, noelkathegod, nok-ko, NonchalantNoob, NoobyLegion, Nopey, not-gavnaed, notafet, notquitehadouken, NotSoDana, noudoit, noverd, NuclearWinter, nukashimika, nuke-haus, NULL882, nullarmo, nyeogmi, Nylux, Nyranu, och-och, OctoRocket, OldDanceJacket, OliverOtter, OnyxTheBrave, OrangeMoronage9622, osjarw, Ostaf, othymer, OttoMaticode, Owai-Seek, packmore, paigemaeforrest, pali6, Pangogie, panzer-iv1, paolordls, partyaddict, patrikturi, PaulRitter, peccneck, Peptide90, peptron1, PeterFuto, PetMudstone, pewter-wiz, Pgriha, Phantom-Lily, pheenty, Phill101, phunnyguy, PilgrimViis, Pill-U, Pireax, Pissachu, pissdemon, PixeltheAertistContrib, PixelTheKermit, PJB3005, Plasmaguy, plinyvic, Plykiya, poeMota, pofitlo, pointer-to-null, pok27, PolterTzi, PoorMansDreams, PopGamer45, portfiend, potato1234x, PotentiallyTom, ProfanedBane, ProPandaBear, PrPleGoo, ps3moira, Pspritechologist, Psychpsyo, psykzz, PuceTint, PuroSlavKing, PursuitInAshes, Putnam3145, qrtDaniil, quatre, QueerNB, QuietlyWhisper, qwerltaz, RadioMull, Radosvik, Radrark, Rainbeon, Rainfey, Raitononai, Ramlik, RamZ, randy10122, Rane, Ranger6012, Rapidgame7, ravage123321, rbertoche, RedBookcase, Redfire1331, Redict, RedlineTriad, redmushie, RednoWCirabrab, RemberBM, RemieRichards, RemTim, rene-descartes2021, Renlou, retequizzle, rich-dunne, RieBi, riggleprime, RIKELOLDABOSS, rinary1, Rinkashikachi, riolume, RobbyTheFish, Rockdtben, Rohesie, rok-povsic, rolfero, RomanNovo, rosieposieeee, Roudenn, router, RumiTiger, S1rFl0, S1ss3l, Saakra, Sadie-silly, saga3152, saintmuntzer, Salex08, sam, samgithubaccount, SaphireLattice, SapphicOverload, Sarahon, sativaleanne, SaveliyM360, sBasalto, ScalyChimp, ScarKy0, scrato, Scribbles0, scrivoy, scruq445, scuffedjays, ScumbagDog, Segonist, sephtasm, Serkket, sewerpig, sh18rw, Shaddap1, ShadeAware, ShadowCommander, Shadowtheprotogen546, shaeone, shampunj, shariathotpatrol, SignalWalker, siigiil, Simyon264, sirdragooon, Sirionaut, Sk1tch, SkaldetSkaeg, Skarletto, Skrauz, Skyedra, SlamBamActionman, slarticodefast, Slava0135, Slyfox333, snebl, snicket, sniperchance, Snowni, snowsignal, SolidusSnek, SonicHDC, SoulFN, SoulSloth, Soundwavesghost, southbridge-fur, Soydium, spacelizard, SpaceLizardSky, SpaceManiac, SpaceRox1244, SpaceyLady, Spanky, spanky-spanky, spartak, SpartanKadence, SpeltIncorrectyl, Spessmann, SphiraI, SplinterGP, spoogemonster, sporekto, sporkyz, ssdaniel24, stalengd, stanberytrask, Stanislav4ix, StanTheCarpenter, Stealthbomber16, stellar-novas, stomf, stopbreaking, stopka-html, StrawberryMoses, Stray-Pyramid, strO0pwafel, Strol20, StStevens, Subversionary, sunbear-dev, superjj18, Supernorn, SweptWasTaken, Sybil, SYNCHRONIC, Szunti, Tainakov, takemysoult, TaralGit, Taran, taurie, Tayrtahn, tday93, teamaki, TekuNut, telyonok, TemporalOroboros, tentekal, terezi4real, Terraspark4941, texcruize, TGODiamond, TGRCdev, tgrkzus, ThatOneGoblin25, thatrandomcanadianguy, TheArturZh, theashtronaut, thecopbennet, TheCze, TheDarkElites, thedraccx, TheEmber, TheIntoxicatedCat, thekilk, themias, theomund, theOperand, TherapyGoth, TheShuEd, thetolbean, thevinter, TheWaffleJesus, Thinbug0, ThunderBear2006, timothyteakettle, TimrodDX, timurjavid, tin-man-tim, Titian3, tk-a369, tkdrg, tmtmtl30, TokenStyle, Tollhouse, Toly65, tom-leys, tomasalves8, Tomeno, Tonydatguy, topy, Tornado-Technology, tosatur, TotallyLemon, Tr1bute, tropicalhibi, truepaintgit, Truoizys, Tryded, TsjipTsjip, Tunguso4ka, TurboTrackerss14, TyAshley, Tyler-IN, Tyzemol, UbaserB, ubis1, UBlueberry, UKNOWH, UltimateJester, Unbelievable-Salmon, underscorex5, UnicornOnLSD, Unisol, Unkn0wnGh0st333, unusualcrow, Uriende, UristMcDorf, user424242420, Vaaankas, valentfingerov, Varen, VasilisThePikachu, veliebm, VelonacepsCalyxEggs, veprolet, veritable-calamity, Veritius, Vermidia, vero5123, Verslebas, VigersRay, violet754, Visne, VMSolidus, voidnull000, volotomite, volundr-, Voomra, Vordenburg, vorkathbruh, vulppine, wafehling, Warentan, WarMechanic, Watermelon914, waylon531, weaversam8, wertanchik, whateverusername0, Willhelm53, WilliamECrew, willicassi, Winkarst-cpu, wirdal, wixoaGit, WlarusFromDaSpace, wrexbe, wtcwr68, xkreksx, xprospero, xRiriq, YanehCheck, yathxyz, Ygg01, YotaXP, youarereadingthis, Yousifb26, youtissoum, YuriyKiss, zach-hill, Zadeon, zamp, Zandario, Zap527, Zealith-Gamer, ZelteHonor, zero, ZeroDiamond, zerorulez, ZeWaka, zionnBE, ZNixian, ZoldorfTheWizard, Zonespace27, Zylofan, Zymem, zzylex +0x6273, 12rabbits, 13spacemen, 2013HORSEMEATSCANDAL, 20kdc, 21Melkuu, 3nderall, 4310v343k, 4dplanner, 612git, 778b, Ablankmann, abregado, Absolute-Potato, achookh, Acruid, actioninja, ActiveMammmoth, actually-reb, ada-please, adamsong, Adeinitas, Admiral-Obvious-001, adrian, Adrian16199, Ady4ik, Aerocrux, Aeshus, Aexolott, Aexxie, africalimedrop, afrokada, AftrLite, Agoichi, Ahion, aiden, AJCM-git, AjexRose, Alekshhh, alexkar598, AlexMorgan3817, alexumandxgabriel08x, Alithsko, ALMv1, Alpha-Two, AlphaQwerty, Altoids1, amylizzle, ancientpower, Andre19926, AndrewEyeke, AndreyCamper, Anzarot121, Appiah, ar4ill, ArchPigeon, ArchRBX, areitpog, Arendian, arimah, Arkanic, ArkiveDev, armoks, Arteben, ArthurMousatov, ArtisticRoomba, artur, AruMoon, ArZarLordOfMango, as334, AsikKEsel, AsnDen, asperger-sind, aspiringLich, astriloqua, august-sun, AutoOtter, avghdev, Awlod, AzzyIsNotHere, BackeTako, BananaFlambe, Baptr0b0t, BasedUser, beck-thompson, bellwetherlogic, benev0, benjamin-burges, BGare, bhespiritu, bibbly, BIGZi0348, bingojohnson, BismarckShuffle, Bixkitts, Blackern5000, Blazeror, BlitzTheSquishy, bloodrizer, Bloody2372, blueDev2, Boaz1111, BobdaBiscuit, BobTheSleder, boiled-water-tsar, BombasterDS, Boolean-Buckeye, botanySupremist, brainfood1183, BramvanZijp, Brandon-Huu, BriBrooo, Bright0, brndd, bryce0110, BubblegumBlue, buletsponge, buntobaggins, bvelliquette, byondfuckery, c0rigin, c4llv07e, CaasGit, Caconym27, Calecute, Callmore, capnsockless, CaptainSqrBeard, Carbonhell, Carolyn3114, Carou02, carteblanche4me, Catofquestionableethics, CatTheSystem, Centronias, chairbender, Charlese2, charlie, ChaseFlorom, chavonadelal, Cheackraze, CheddaCheez, cheesePizza2, cheeseplated, Chief-Engineer, chillyconmor, christhirtle, chromiumboy, Chronophylos, Chubbicous, Chubbygummibear, Ciac32, civilCornball, Clement-O, clyf, Clyybber, CMDR-Piboy314, cohanna, Cohnway, Cojoke-dot, ColdAutumnRain, Colin-Tel, collinlunn, ComicIronic, CookieMasterT, coolboy911, coolmankid12345, Coolsurf6, corentt, CormosLemming, CrafterKolyan, crazybrain23, creadth, CrigCrag, croilbird, Crotalus, CrudeWax, CrzyPotato, cutemoongod, Cyberboss, d34d10cc, d4kii, DadeKuma, Daemon, daerSeebaer, dahnte, dakamakat, DamianX, DangerRevolution, daniel-cr, DanSAussieITS, Daracke, Darkenson, DawBla, Daxxi3, dch-GH, de0rix, Deahaka, dean, DEATHB4DEFEAT, DeathCamel58, Deatherd, deathride58, DebugOk, Decappi, Decortex, Deeeeja, deepdarkdepths, degradka, Delete69, deltanedas, DenisShvalov, DerbyX, derek, dersheppard, Deserty0, Detintinto, DevilishMilk, dexlerxd, dffdff2423, DieselMohawk, digitalic, Dimastra, DinoWattz, DisposableCrewmember42, DjfjdfofdjfjD, doc-michael, docnite, Doctor-Cpu, DoctorBeard, DogZeroX, dolgovmi, dontbetank, Doomsdrayk, Doru991, DoubleRiceEddiedd, DoutorWhite, dragonryan06, drakewill-CRL, Drayff, dreamlyjack, DrEnzyme, dribblydrone, DrMelon, drongood12, DrSingh, DrSmugleaf, drteaspoon420, DTanxxx, DubiousDoggo, Duddino, dukevanity, duskyjay, Dutch-VanDerLinde, dvir001, dylanstrategie, Dynexust, Easypoller, echo, eclips_e, eden077, EEASAS, Efruit, efzapa, Ekkosangen, ElectroSR, elsie, elthundercloud, Elysium206, Emisse, emmafornash, EmoGarbage404, Endecc, eoineoineoin, eris, erohrs2, ERORR404V1, Errant-4, ertanic, esguard, estacaoespacialpirata, eugene, ewokswagger, exincore, exp111, f0x-n3rd, FacePluslll, Fahasor, FairlySadPanda, FATFSAAM2, Feluk6174, ficcialfaint, Fiftyllama, Fildrance, FillerVK, FinnishPaladin, firenamefn, FirinMaLazors, Fishfish458, FL-OZ, Flareguy, flashgnash, FluffiestFloof, FluffMe, FluidRock, foboscheshir, FoLoKe, fooberticus, ForestNoises, forgotmyotheraccount, forkeyboards, forthbridge, Fortune117, Fouin, foxhorn, freeman2651, freeze2222, Froffy025, Fromoriss, froozigiusz, FrostMando, FungiFellow, FunTust, Futuristic-OK, GalacticChimp, gamer3107, Gaxeer, gbasood, Geekyhobo, genderGeometries, GeneralGaws, Genkail, geraeumig, Ghagliiarghii, Git-Nivrak, githubuser508, gituhabu, GlassEclipse, GNF54, godisdeadLOL, goet, GoldenCan, Goldminermac, Golinth, GoodWheatley, Gorox221, gradientvera, graevy, GraniteSidewalk, GreaseMonk, greenrock64, GreyMario, GTRsound, gusxyz, Gyrandola, h3half, hamurlik, Hanzdegloker, HappyRoach, Hardly3D, harikattar, he1acdvv, Hebi, Henry, HerCoyote23, hitomishirichan, hiucko, Hmeister-fake, Hmeister-real, Hobbitmax, hobnob, HoidC, Holinka4ever, holyssss, HoofedEar, Hoolny, hord-brayden, Hreno, hubismal, Hugal31, Huxellberger, Hyenh, hyphenationc, i-justuser-i, iacore, IamVelcroboy, Ian321, icekot8, icesickleone, iczero, iglov, IgorAnt028, igorsaux, ike709, illersaver, Illiux, Ilushkins33, Ilya246, IlyaElDunaev, imrenq, imweax, indeano, Injazz, Insineer, IntegerTempest, Interrobang01, IProduceWidgets, ItsMeThom, Itzbenz, iztokbajcar, Jackal298, Jackrost, jacksonzck, Jackw2As, jacob, jamessimo, janekvap, Jark255, Jarmer123, Jaskanbe, JasperJRoth, JerryImMouse, jerryimmouse, Jessetriesagain, jessicamaybe, Jezithyr, jicksaw, JiimBob, JimGamemaster, jimmy12or, JIPDawg, jjtParadox, jmcb, JoeHammad1844, JohnGinnane, johnku1, Jophire, joshepvodka, Jrpl, juliangiebel, JustArt1m, JustCone14, justdie12, justin, justintether, JustinTrotter, justtne, K-Dynamic, k3yw, Kadeo64, Kaga-404, KaiShibaa, kalane15, kalanosh, Kanashi-Panda, katzenminer, kbailey-git, Keelin, Keer-Sar, KEEYNy, keikiru, Kelrak, kerisargit, keronshb, KIBORG04, Killerqu00, Kimpes, KingFroozy, kira-er, Kirillcas, Kirus59, Kistras, Kit0vras, KittenColony, klaypexx, Kmc2000, Ko4ergaPunk, kognise, kokoc9n, komunre, KonstantinAngelov, kosticia, koteq, KrasnoshchekovPavel, Krunklehorn, Kupie, kxvvv, kyupolaris, kzhanik, lajolico, Lamrr, LankLTE, laok233, lapatison, larryrussian, lawdog4817, Lazzi0706, leander-0, leonardo-dabepis, leonidussaks, leonsfriedrich, LeoSantich, LetterN, lettern, Level10Cybermancer, LEVELcat, lever1209, Lgibb18, lgruthes, LightVillet, liltenhead, LinkUyx, LittleBuilderJane, LittleNorthStar, LittleNyanCat, lizelive, localcc, lokachop, Lomcastar, LordCarve, LordEclipse, LucasTheDrgn, luckyshotpictures, LudwigVonChesterfield, luizwritescode, Lukasz825700516, luminight, lunarcomets, luringens, lvvova1, Lyndomen, lyroth001, lzimann, lzk228, M3739, mac6na6na, MACMAN2003, Macoron, magicalus, magmodius, MagnusCrowe, malchanceux, MaloTV, ManelNavola, Mangohydra, marboww, Markek1, Matz05, max, MaxNox7, maylokana, MehimoNemo, MeltedPixel, MemeProof, MendaxxDev, Menshin, Mephisto72, MerrytheManokit, Mervill, metalgearsloth, MetalSage, MFMessage, mhamsterr, michaelcu, micheel665, MilenVolf, MilonPL, Minemoder5000, Minty642, Mirino97, mirrorcult, misandrie, MishaUnity, MissKay1994, MisterMecky, Mith-randalf, MjrLandWhale, mkanke-real, MLGTASTICa, moderatelyaware, modern-nm, mokiros, Moneyl, Moomoobeef, moony, Morb0, MossyGreySlope, mr-bo-jangles, Mr0maks, MrFippik, mrrobdemo, muburu, MureixloI, musicmanvr, MWKane, Myakot, Myctai, N3X15, nails-n-tape, Nairodian, Naive817, NakataRin, namespace-Memory, Nannek, NazrinNya, neutrino-laser, NickPowers43, nikthechampiongr, Nimfar11, Nirnael, NIXC, NkoKirkto, nmajask, noctyrnal, noelkathegod, nok-ko, NonchalantNoob, NoobyLegion, Nopey, not-gavnaed, notafet, notquitehadouken, NotSoDana, noudoit, noverd, NuclearWinter, nukashimika, nuke-haus, NULL882, nullarmo, nyeogmi, Nylux, Nyranu, och-och, OctoRocket, OldDanceJacket, OliverOtter, OnyxTheBrave, OrangeMoronage9622, osjarw, Ostaf, othymer, OttoMaticode, Owai-Seek, packmore, paigemaeforrest, pali6, Pangogie, panzer-iv1, paolordls, partyaddict, patrikturi, PaulRitter, peccneck, Peptide90, peptron1, PeterFuto, PetMudstone, pewter-wiz, Pgriha, Phantom-Lily, pheenty, Phill101, phunnyguy, PilgrimViis, Pill-U, Pireax, Pissachu, pissdemon, PixeltheAertistContrib, PixelTheKermit, PJB3005, Plasmaguy, plinyvic, Plykiya, poeMota, pofitlo, pointer-to-null, pok27, PolterTzi, PoorMansDreams, PopGamer45, portfiend, potato1234x, PotentiallyTom, ProfanedBane, ProPandaBear, PrPleGoo, ps3moira, Pspritechologist, Psychpsyo, psykzz, PuceTint, PuroSlavKing, PursuitInAshes, Putnam3145, qrtDaniil, quatre, QueerNB, QuietlyWhisper, qwerltaz, RadioMull, Radosvik, Radrark, Rainbeon, Rainfey, Raitononai, Ramlik, RamZ, randy10122, Rane, Ranger6012, Rapidgame7, ravage123321, rbertoche, RedBookcase, Redfire1331, Redict, RedlineTriad, redmushie, RednoWCirabrab, RemberBM, RemieRichards, RemTim, rene-descartes2021, Renlou, retequizzle, rich-dunne, RieBi, riggleprime, RIKELOLDABOSS, rinary1, Rinkashikachi, riolume, RobbyTheFish, Rockdtben, Rohesie, rok-povsic, rolfero, RomanNovo, rosieposieeee, Roudenn, router, RumiTiger, S1rFl0, S1ss3l, Saakra, Sadie-silly, saga3152, saintmuntzer, Salex08, sam, samgithubaccount, SaphireLattice, SapphicOverload, Sarahon, sativaleanne, SaveliyM360, sBasalto, ScalyChimp, ScarKy0, scrato, Scribbles0, scrivoy, scruq445, scuffedjays, ScumbagDog, Segonist, sephtasm, Serkket, sewerpig, sh18rw, Shaddap1, ShadeAware, ShadowCommander, Shadowtheprotogen546, shaeone, shampunj, shariathotpatrol, SignalWalker, siigiil, Simyon264, sirdragooon, Sirionaut, Sk1tch, SkaldetSkaeg, Skarletto, Skrauz, Skyedra, SlamBamActionman, slarticodefast, Slava0135, Slyfox333, snebl, snicket, sniperchance, Snowni, snowsignal, SolidusSnek, SonicHDC, SoulFN, SoulSloth, Soundwavesghost, southbridge-fur, Soydium, spacelizard, SpaceLizardSky, SpaceManiac, SpaceRox1244, SpaceyLady, spanky-spanky, spartak, SpartanKadence, SpeltIncorrectyl, Spessmann, SphiraI, SplinterGP, spoogemonster, sporekto, sporkyz, ssdaniel24, stalengd, stanberytrask, Stanislav4ix, StanTheCarpenter, Stealthbomber16, stellar-novas, stomf, stopbreaking, stopka-html, StrawberryMoses, Stray-Pyramid, strO0pwafel, Strol20, StStevens, Subversionary, sunbear-dev, superjj18, Supernorn, SweptWasTaken, Sybil, SYNCHRONIC, Szunti, Tainakov, takemysoult, TaralGit, Taran, taurie, Tayrtahn, tday93, teamaki, TekuNut, telyonok, TemporalOroboros, tentekal, terezi4real, Terraspark4941, texcruize, TGODiamond, TGRCdev, tgrkzus, ThatGuyUSA, ThatOneGoblin25, thatrandomcanadianguy, TheArturZh, theashtronaut, thecopbennet, TheCze, TheDarkElites, thedraccx, TheEmber, TheIntoxicatedCat, thekilk, themias, theomund, theOperand, TherapyGoth, TheShuEd, thetolbean, thevinter, TheWaffleJesus, Thinbug0, ThunderBear2006, timothyteakettle, TimrodDX, timurjavid, tin-man-tim, Titian3, tk-a369, tkdrg, tmtmtl30, TokenStyle, Tollhouse, Toly65, tom-leys, tomasalves8, Tomeno, Tonydatguy, topy, Tornado-Technology, tosatur, TotallyLemon, Tr1bute, tropicalhibi, truepaintgit, Truoizys, Tryded, TsjipTsjip, Tunguso4ka, TurboTrackerss14, TyAshley, Tyler-IN, Tyzemol, UbaserB, ubis1, UBlueberry, UKNOWH, UltimateJester, Unbelievable-Salmon, underscorex5, UnicornOnLSD, Unisol, Unkn0wnGh0st333, unusualcrow, Uriende, UristMcDorf, user424242420, Vaaankas, valentfingerov, Varen, Vasilis, VasilisThePikachu, veliebm, VelonacepsCalyxEggs, veprolet, veritable-calamity, Veritius, Vermidia, vero5123, Verslebas, VigersRay, violet754, Visne, VMSolidus, voidnull000, volotomite, volundr-, Voomra, Vordenburg, vorkathbruh, vulppine, wafehling, Warentan, WarMechanic, Watermelon914, weaversam8, wertanchik, whateverusername0, Willhelm53, WilliamECrew, willicassi, Winkarst-cpu, wirdal, wixoaGit, WlarusFromDaSpace, wrexbe, wtcwr68, xkreksx, xprospero, xRiriq, YanehCheck, yathxyz, Ygg01, YotaXP, youarereadingthis, Yousifb26, youtissoum, yunii, YuriyKiss, zach-hill, Zadeon, zamp, Zandario, Zap527, Zealith-Gamer, ZelteHonor, zero, ZeroDiamond, zerorulez, ZeWaka, zionnBE, ZNixian, ZoldorfTheWizard, zonespace27, Zylofan, Zymem, zzylex From f706170ee135c1b7e77034cdee51eda1146862bf Mon Sep 17 00:00:00 2001 From: Winkarst <74284083+Winkarst-cpu@users.noreply.github.com> Date: Sun, 24 Nov 2024 07:20:00 +0300 Subject: [PATCH 34/59] Draw muzzle flash below mobs (#33465) * Draw muzzle flash below mobs * Better naming --------- Co-authored-by: Winkarst <74284083+Winkarst-cpu@users.noreply.github.co> --- Content.Shared/DrawDepth/DrawDepth.cs | 23 +++++++++++-------- .../Weapons/Guns/Projectiles/projectiles.yml | 8 +++---- 2 files changed, 18 insertions(+), 13 deletions(-) diff --git a/Content.Shared/DrawDepth/DrawDepth.cs b/Content.Shared/DrawDepth/DrawDepth.cs index f7b1f3648a..d0d2daf5d9 100644 --- a/Content.Shared/DrawDepth/DrawDepth.cs +++ b/Content.Shared/DrawDepth/DrawDepth.cs @@ -74,33 +74,38 @@ namespace Content.Shared.DrawDepth /// Items = DrawDepthTag.Default + 3, - Mobs = DrawDepthTag.Default + 4, - - OverMobs = DrawDepthTag.Default + 5, + /// + /// Stuff that should be drawn below mobs, but on top of items. Like muzzle flash. + /// + BelowMobs = DrawDepthTag.Default + 4, - Doors = DrawDepthTag.Default + 6, + Mobs = DrawDepthTag.Default + 5, + + OverMobs = DrawDepthTag.Default + 6, + + Doors = DrawDepthTag.Default + 7, /// /// Blast doors and shutters which go over the usual doors. /// - BlastDoors = DrawDepthTag.Default + 7, + BlastDoors = DrawDepthTag.Default + 8, /// /// Stuff that needs to draw over most things, but not effects, like Kudzu. /// - Overdoors = DrawDepthTag.Default + 8, + Overdoors = DrawDepthTag.Default + 9, /// /// Explosions, fire, melee swings. Whatever. /// - Effects = DrawDepthTag.Default + 9, + Effects = DrawDepthTag.Default + 10, - Ghosts = DrawDepthTag.Default + 10, + Ghosts = DrawDepthTag.Default + 11, /// /// Use this selectively if it absolutely needs to be drawn above (almost) everything else. Examples include /// the pointing arrow, the drag & drop ghost-entity, and some debug tools. /// - Overlays = DrawDepthTag.Default + 11, + Overlays = DrawDepthTag.Default + 12, } } diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Projectiles/projectiles.yml b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Projectiles/projectiles.yml index 64af32883c..7d11dffbfa 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Projectiles/projectiles.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Projectiles/projectiles.yml @@ -5,7 +5,7 @@ - type: TimedDespawn lifetime: 0.4 - type: Sprite - drawdepth: Effects + drawdepth: BelowMobs layers: - shader: unshaded map: ["enum.EffectLayers.Unshaded"] @@ -983,7 +983,7 @@ - HideContextMenu - type: entity - name: laser bolt + name: laser bolt id: BulletLaser parent: BaseBullet categories: [ HideSpawnMenu ] @@ -1029,7 +1029,7 @@ - type: ProjectileSpread proto: BulletLaser count: 5 #65 heat damage if you hit all your shots, but wide spread - spread: 30 + spread: 30 - type: entity name: narrow laser barrage @@ -1051,4 +1051,4 @@ - type: ProjectileSpread proto: BulletDisablerSmg count: 3 #bit stronger than a disabler if you hit your shots you goober, still not a 2 hit stun though - spread: 9 \ No newline at end of file + spread: 9 \ No newline at end of file From 2229a6a04b75e9c2a30c334b06480fba866e4856 Mon Sep 17 00:00:00 2001 From: PJBot Date: Sun, 24 Nov 2024 04:21:08 +0000 Subject: [PATCH 35/59] Automatic changelog update --- Resources/Changelog/Changelog.yml | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index e15f682297..abda89f332 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,12 +1,4 @@ Entries: -- author: Goldminermac - changes: - - message: Chocolate-chip and blueberry pancakes can now be in stacks of up to nine - for consistency. - type: Fix - id: 7147 - time: '2024-08-19T02:42:58.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/31123 - author: tosatur changes: - message: Made hydroponics alert light more orange @@ -3930,3 +3922,10 @@ id: 7646 time: '2024-11-23T16:52:58.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/33479 +- author: Winkarst-cpu + changes: + - message: Now muzzle flashes are displayed below mobs. + type: Tweak + id: 7647 + time: '2024-11-24T04:20:00.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/33465 From aa80a88cc4c530178ab9971c87160c4d7b3c91ec Mon Sep 17 00:00:00 2001 From: MilenVolf <63782763+MilenVolf@users.noreply.github.com> Date: Sun, 24 Nov 2024 11:11:47 +0300 Subject: [PATCH 36/59] Allow shuttles on planets to make FTL jump (#33507) This check conflicts with an attempt to FTL from the planet before expedition ends --- .../Shuttles/Systems/ShuttleSystem.FasterThanLight.cs | 6 ------ Resources/Locale/en-US/shuttles/console.ftl | 1 - 2 files changed, 7 deletions(-) diff --git a/Content.Server/Shuttles/Systems/ShuttleSystem.FasterThanLight.cs b/Content.Server/Shuttles/Systems/ShuttleSystem.FasterThanLight.cs index d0aab9aad5..c02d2564a9 100644 --- a/Content.Server/Shuttles/Systems/ShuttleSystem.FasterThanLight.cs +++ b/Content.Server/Shuttles/Systems/ShuttleSystem.FasterThanLight.cs @@ -234,12 +234,6 @@ public sealed partial class ShuttleSystem if (TryComp(shuttleUid, out var shuttlePhysics)) { - // Static physics type is set when station anchor is enabled - if (shuttlePhysics.BodyType == BodyType.Static) - { - reason = Loc.GetString("shuttle-console-static"); - return false; - } // Too large to FTL if (FTLMassLimit > 0 && shuttlePhysics.Mass > FTLMassLimit) diff --git a/Resources/Locale/en-US/shuttles/console.ftl b/Resources/Locale/en-US/shuttles/console.ftl index 6143c99552..80e61a2812 100644 --- a/Resources/Locale/en-US/shuttles/console.ftl +++ b/Resources/Locale/en-US/shuttles/console.ftl @@ -4,7 +4,6 @@ shuttle-pilot-end = Stopped piloting shuttle-console-in-ftl = Currently in FTL shuttle-console-mass = Too large to FTL shuttle-console-prevent = You are unable to pilot this ship -shuttle-console-static = Grid is static # NAV From 84df2b857e7408c3e278103d47e1b683a0ef6426 Mon Sep 17 00:00:00 2001 From: PJBot Date: Sun, 24 Nov 2024 08:12:54 +0000 Subject: [PATCH 37/59] Automatic changelog update --- Resources/Changelog/Changelog.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index abda89f332..0f6cc4b696 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,11 +1,4 @@ Entries: -- author: tosatur - changes: - - message: Made hydroponics alert light more orange - type: Tweak - id: 7148 - time: '2024-08-19T02:48:47.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/31088 - author: redmushie changes: - message: News management console now checks for Service ID card access instead @@ -3929,3 +3922,10 @@ id: 7647 time: '2024-11-24T04:20:00.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/33465 +- author: MilenVolf + changes: + - message: Expeditions can now be completed prematurely again by making an FTL jump. + type: Fix + id: 7648 + time: '2024-11-24T08:11:47.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/33507 From e436a50c3653d423ad18bda8c953367470270758 Mon Sep 17 00:00:00 2001 From: deltanedas <39013340+deltanedas@users.noreply.github.com> Date: Sun, 24 Nov 2024 08:49:31 +0000 Subject: [PATCH 38/59] fix exped caves generation (#32890) Co-authored-by: deltanedas <@deltanedas:kde.org> --- .../Procedural/DungeonJob/DungeonJob.PostGenWallMount.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Content.Server/Procedural/DungeonJob/DungeonJob.PostGenWallMount.cs b/Content.Server/Procedural/DungeonJob/DungeonJob.PostGenWallMount.cs index afc7608d64..d5c8587ea9 100644 --- a/Content.Server/Procedural/DungeonJob/DungeonJob.PostGenWallMount.cs +++ b/Content.Server/Procedural/DungeonJob/DungeonJob.PostGenWallMount.cs @@ -20,7 +20,11 @@ public sealed partial class DungeonJob } var tileDef = _prototype.Index(tileProto); - data.SpawnGroups.TryGetValue(DungeonDataKey.WallMounts, out var spawnProto); + if (!data.SpawnGroups.TryGetValue(DungeonDataKey.WallMounts, out var spawnProto)) + { + // caves can have no walls + return; + } var checkedTiles = new HashSet(); var allExterior = new HashSet(dungeon.CorridorExteriorTiles); From 91b9d4a7f0aeb91ef54c1396785c0cd8e856d6ef Mon Sep 17 00:00:00 2001 From: PJBot Date: Sun, 24 Nov 2024 08:50:37 +0000 Subject: [PATCH 39/59] Automatic changelog update --- Resources/Changelog/Changelog.yml | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index 0f6cc4b696..1a6a2a8a46 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,12 +1,4 @@ Entries: -- author: redmushie - changes: - - message: News management console now checks for Service ID card access instead - of the manifest - type: Fix - id: 7149 - time: '2024-08-19T02:55:44.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/31160 - author: Moomoobeef changes: - message: Added pitchers for the chef who wants to serve beverages too. @@ -3929,3 +3921,10 @@ id: 7648 time: '2024-11-24T08:11:47.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/33507 +- author: deltanedas + changes: + - message: Fixed expeditions on cave planets not having any ore. + type: Fix + id: 7649 + time: '2024-11-24T08:49:31.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/32890 From cae49ae0d231994b523d4b11855904102544f0cf Mon Sep 17 00:00:00 2001 From: mubururu_ <139181059+muburu@users.noreply.github.com> Date: Sun, 24 Nov 2024 10:24:13 -0600 Subject: [PATCH 40/59] various material & ore inhands (#33342) * begin * bones + pyrotten + goliath hide inhands * Update Resources/Prototypes/Entities/Objects/Materials/materials.yml Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com> * Update Resources/Textures/Objects/Materials/materials.rsi/meta.json Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com> * Update Resources/Textures/Objects/Materials/materials.rsi/meta.json Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com> * Update Resources/Textures/Objects/Materials/materials.rsi/meta.json Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com> * pyrottOn --------- Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com> --- .../Entities/Objects/Materials/materials.yml | 22 ++++- .../Entities/Objects/Materials/ore.yml | 20 +++++ .../Entities/Objects/Materials/parts.yml | 2 +- .../hide.rsi/goliathhide-inhand-left.png | Bin 0 -> 525 bytes .../hide.rsi/goliathhide-inhand-right.png | Bin 0 -> 535 bytes .../Objects/Materials/hide.rsi/meta.json | 12 ++- .../materials.rsi/bananium-inhand-left.png | Bin 0 -> 345 bytes .../materials.rsi/bananium-inhand-right.png | Bin 0 -> 347 bytes .../materials.rsi/bones-inhand-left.png | Bin 0 -> 362 bytes .../materials.rsi/bones-inhand-right.png | Bin 0 -> 369 bytes .../materials.rsi/cardboard-inhand-left.png | Bin 0 -> 418 bytes .../materials.rsi/cardboard-inhand-right.png | Bin 0 -> 441 bytes .../materials.rsi/cloth-inhand-left.png | Bin 0 -> 393 bytes .../materials.rsi/cloth-inhand-right.png | Bin 0 -> 400 bytes .../materials.rsi/corgihide-inhand-left.png | Bin 0 -> 670 bytes .../materials.rsi/corgihide-inhand-right.png | Bin 0 -> 724 bytes .../materials.rsi/cotton-inhand-left.png | Bin 0 -> 262 bytes .../materials.rsi/cotton-inhand-right.png | Bin 0 -> 263 bytes .../materials.rsi/durathread-inhand-left.png | Bin 0 -> 381 bytes .../materials.rsi/durathread-inhand-right.png | Bin 0 -> 372 bytes .../Objects/Materials/materials.rsi/meta.json | 66 +++++++++++++- .../materials.rsi/pyrotton-inhand-left.png | Bin 0 -> 305 bytes .../materials.rsi/pyrotton-inhand-right.png | Bin 0 -> 303 bytes .../ore.rsi/bananium-inhand-left.png | Bin 0 -> 428 bytes .../ore.rsi/bananium-inhand-right.png | Bin 0 -> 435 bytes .../Materials/ore.rsi/coal-inhand-left.png | Bin 0 -> 320 bytes .../Materials/ore.rsi/coal-inhand-right.png | Bin 0 -> 326 bytes .../Materials/ore.rsi/diamond-inhand-left.png | Bin 0 -> 325 bytes .../ore.rsi/diamond-inhand-right.png | Bin 0 -> 334 bytes .../Materials/ore.rsi/gold-inhand-left.png | Bin 0 -> 472 bytes .../Materials/ore.rsi/gold-inhand-right.png | Bin 0 -> 449 bytes .../Materials/ore.rsi/iron-inhand-left.png | Bin 0 -> 321 bytes .../Materials/ore.rsi/iron-inhand-right.png | Bin 0 -> 340 bytes .../Objects/Materials/ore.rsi/meta.json | 82 +++++++++++++++++- .../Materials/ore.rsi/plasma-inhand-left.png | Bin 0 -> 395 bytes .../Materials/ore.rsi/plasma-inhand-right.png | Bin 0 -> 390 bytes .../Materials/ore.rsi/salt-inhand-left.png | Bin 0 -> 299 bytes .../Materials/ore.rsi/salt-inhand-right.png | Bin 0 -> 300 bytes .../Materials/ore.rsi/silver-inhand-left.png | Bin 0 -> 380 bytes .../Materials/ore.rsi/silver-inhand-right.png | Bin 0 -> 385 bytes .../ore.rsi/spacequartz-inhand-left.png | Bin 0 -> 509 bytes .../ore.rsi/spacequartz-inhand-right.png | Bin 0 -> 469 bytes .../Materials/ore.rsi/uranium-inhand-left.png | Bin 0 -> 453 bytes .../ore.rsi/uranium-inhand-right.png | Bin 0 -> 463 bytes .../Objects/Materials/parts.rsi/meta.json | 10 ++- .../Materials/parts.rsi/rods-inhand-left.png | Bin 0 -> 189 bytes .../Materials/parts.rsi/rods-inhand-right.png | Bin 0 -> 192 bytes .../Objects/Materials/silk.rsi/meta.json | 12 ++- .../Materials/silk.rsi/silk-inhand-left.png | Bin 0 -> 358 bytes .../Materials/silk.rsi/silk-inhand-right.png | Bin 0 -> 345 bytes 50 files changed, 216 insertions(+), 10 deletions(-) create mode 100644 Resources/Textures/Objects/Materials/hide.rsi/goliathhide-inhand-left.png create mode 100644 Resources/Textures/Objects/Materials/hide.rsi/goliathhide-inhand-right.png create mode 100644 Resources/Textures/Objects/Materials/materials.rsi/bananium-inhand-left.png create mode 100644 Resources/Textures/Objects/Materials/materials.rsi/bananium-inhand-right.png create mode 100644 Resources/Textures/Objects/Materials/materials.rsi/bones-inhand-left.png create mode 100644 Resources/Textures/Objects/Materials/materials.rsi/bones-inhand-right.png create mode 100644 Resources/Textures/Objects/Materials/materials.rsi/cardboard-inhand-left.png create mode 100644 Resources/Textures/Objects/Materials/materials.rsi/cardboard-inhand-right.png create mode 100644 Resources/Textures/Objects/Materials/materials.rsi/cloth-inhand-left.png create mode 100644 Resources/Textures/Objects/Materials/materials.rsi/cloth-inhand-right.png create mode 100644 Resources/Textures/Objects/Materials/materials.rsi/corgihide-inhand-left.png create mode 100644 Resources/Textures/Objects/Materials/materials.rsi/corgihide-inhand-right.png create mode 100644 Resources/Textures/Objects/Materials/materials.rsi/cotton-inhand-left.png create mode 100644 Resources/Textures/Objects/Materials/materials.rsi/cotton-inhand-right.png create mode 100644 Resources/Textures/Objects/Materials/materials.rsi/durathread-inhand-left.png create mode 100644 Resources/Textures/Objects/Materials/materials.rsi/durathread-inhand-right.png create mode 100644 Resources/Textures/Objects/Materials/materials.rsi/pyrotton-inhand-left.png create mode 100644 Resources/Textures/Objects/Materials/materials.rsi/pyrotton-inhand-right.png create mode 100644 Resources/Textures/Objects/Materials/ore.rsi/bananium-inhand-left.png create mode 100644 Resources/Textures/Objects/Materials/ore.rsi/bananium-inhand-right.png create mode 100644 Resources/Textures/Objects/Materials/ore.rsi/coal-inhand-left.png create mode 100644 Resources/Textures/Objects/Materials/ore.rsi/coal-inhand-right.png create mode 100644 Resources/Textures/Objects/Materials/ore.rsi/diamond-inhand-left.png create mode 100644 Resources/Textures/Objects/Materials/ore.rsi/diamond-inhand-right.png create mode 100644 Resources/Textures/Objects/Materials/ore.rsi/gold-inhand-left.png create mode 100644 Resources/Textures/Objects/Materials/ore.rsi/gold-inhand-right.png create mode 100644 Resources/Textures/Objects/Materials/ore.rsi/iron-inhand-left.png create mode 100644 Resources/Textures/Objects/Materials/ore.rsi/iron-inhand-right.png create mode 100644 Resources/Textures/Objects/Materials/ore.rsi/plasma-inhand-left.png create mode 100644 Resources/Textures/Objects/Materials/ore.rsi/plasma-inhand-right.png create mode 100644 Resources/Textures/Objects/Materials/ore.rsi/salt-inhand-left.png create mode 100644 Resources/Textures/Objects/Materials/ore.rsi/salt-inhand-right.png create mode 100644 Resources/Textures/Objects/Materials/ore.rsi/silver-inhand-left.png create mode 100644 Resources/Textures/Objects/Materials/ore.rsi/silver-inhand-right.png create mode 100644 Resources/Textures/Objects/Materials/ore.rsi/spacequartz-inhand-left.png create mode 100644 Resources/Textures/Objects/Materials/ore.rsi/spacequartz-inhand-right.png create mode 100644 Resources/Textures/Objects/Materials/ore.rsi/uranium-inhand-left.png create mode 100644 Resources/Textures/Objects/Materials/ore.rsi/uranium-inhand-right.png create mode 100644 Resources/Textures/Objects/Materials/parts.rsi/rods-inhand-left.png create mode 100644 Resources/Textures/Objects/Materials/parts.rsi/rods-inhand-right.png create mode 100644 Resources/Textures/Objects/Materials/silk.rsi/silk-inhand-left.png create mode 100644 Resources/Textures/Objects/Materials/silk.rsi/silk-inhand-right.png diff --git a/Resources/Prototypes/Entities/Objects/Materials/materials.yml b/Resources/Prototypes/Entities/Objects/Materials/materials.yml index 8371e21c65..e16044b282 100644 --- a/Resources/Prototypes/Entities/Objects/Materials/materials.yml +++ b/Resources/Prototypes/Entities/Objects/Materials/materials.yml @@ -54,6 +54,8 @@ reagents: - ReagentId: Cellulose Quantity: 6 + - type: Item + heldPrefix: cardboard - type: entity parent: MaterialCardboard @@ -135,6 +137,8 @@ - type: Construction graph: WebObjects # not sure if I should either keep this here or just make another prototype. Will keep it here just in case. node: cloth + - type: Item + heldPrefix: cloth - type: entity parent: MaterialCloth @@ -195,6 +199,8 @@ tags: - ClothMade - RawMaterial + - type: Item + heldPrefix: durathread - type: entity parent: MaterialDurathread @@ -334,8 +340,7 @@ sprite: Objects/Materials/materials.rsi state: corgihide - type: Item - sprite: Clothing/Head/Misc/hides.rsi - heldPrefix: corgi + heldPrefix: corgihide - type: Clothing sprite: Clothing/Head/Misc/hides.rsi equippedPrefix: corgi2 @@ -427,6 +432,8 @@ tags: - ClothMade - RawMaterial + - type: Item + heldPrefix: cotton - type: entity parent: MaterialCotton @@ -479,6 +486,8 @@ tags: - ClothMade - RawMaterial + - type: Item + heldPrefix: pyrotton - type: entity parent: MaterialPyrotton @@ -538,6 +547,8 @@ - ReagentId: Honk Quantity: 5 - type: Appearance + - type: Item + heldPrefix: bananium - type: entity parent: MaterialBananium @@ -588,6 +599,9 @@ tags: - ClothMade - RawMaterial + - type: Item + sprite: Objects/Materials/silk.rsi + heldPrefix: silk - type: entity parent: MaterialWebSilk @@ -710,6 +724,8 @@ reagents: - ReagentId: Vitamin Quantity: 3 + - type: Item + heldPrefix: bones - type: entity parent: MaterialBones @@ -764,6 +780,8 @@ - goliath_hide_3 - type: Item size: Large + heldPrefix: goliathhide + sprite: Objects/Materials/hide.rsi shape: - 0,0,2,2 diff --git a/Resources/Prototypes/Entities/Objects/Materials/ore.yml b/Resources/Prototypes/Entities/Objects/Materials/ore.yml index fd46fb40be..9d07aed853 100644 --- a/Resources/Prototypes/Entities/Objects/Materials/ore.yml +++ b/Resources/Prototypes/Entities/Objects/Materials/ore.yml @@ -46,6 +46,8 @@ reagents: - ReagentId: Gold Quantity: 10 + - type: Item + heldPrefix: gold - type: entity parent: GoldOre @@ -77,6 +79,8 @@ reagents: - ReagentId: Carbon Quantity: 20 + - type: Item + heldPrefix: diamond - type: entity parent: DiamondOre @@ -108,6 +112,8 @@ reagents: - ReagentId: Iron Quantity: 10 + - type: Item + heldPrefix: iron - type: entity id: SteelOre1 @@ -144,6 +150,8 @@ reagents: - ReagentId: Plasma Quantity: 10 + - type: Item + heldPrefix: plasma - type: entity parent: PlasmaOre @@ -175,6 +183,8 @@ reagents: - ReagentId: Silver Quantity: 10 + - type: Item + heldPrefix: silver - type: entity parent: SilverOre @@ -206,6 +216,8 @@ reagents: - ReagentId: Silicon Quantity: 10 + - type: Item + heldPrefix: spacequartz - type: entity parent: SpaceQuartz @@ -245,6 +257,8 @@ - ReagentId: Radium Quantity: 2 canReact: false + - type: Item + heldPrefix: uranium - type: entity parent: UraniumOre @@ -285,6 +299,8 @@ Quantity: 2 - ReagentId: Honk Quantity: 5 + - type: Item + heldPrefix: bananium - type: entity parent: BananiumOre @@ -324,6 +340,8 @@ - type: PhysicalComposition materialComposition: Coal: 100 + - type: Item + heldPrefix: coal - type: entity parent: Coal @@ -381,6 +399,8 @@ Quantity: 10 - ReagentId: Iodine Quantity: 5 + - type: Item + heldPrefix: salt - type: entity parent: SaltOre diff --git a/Resources/Prototypes/Entities/Objects/Materials/parts.yml b/Resources/Prototypes/Entities/Objects/Materials/parts.yml index 1db564c3b3..700c08e096 100644 --- a/Resources/Prototypes/Entities/Objects/Materials/parts.yml +++ b/Resources/Prototypes/Entities/Objects/Materials/parts.yml @@ -45,7 +45,7 @@ map: ["base"] - type: Item size: Normal -# heldPrefix: rods + heldPrefix: rods - type: Construction graph: MetalRod node: MetalRod diff --git a/Resources/Textures/Objects/Materials/hide.rsi/goliathhide-inhand-left.png b/Resources/Textures/Objects/Materials/hide.rsi/goliathhide-inhand-left.png new file mode 100644 index 0000000000000000000000000000000000000000..b9a381ea13a1d59a5c97c0ddc5a670135441439c GIT binary patch literal 525 zcmV+o0`mQdP)Px$$4Nv%RCt{2+CORnK@7J)1nVHAF_MUrVpt=hV0Pb_KYTw}W)Sx6_;yB%_W&XyA|fIpA|fK9n0yy{ zo6q9LvcZuIHktwL($~V5=W$#gl^6GSm9ml$u>=$x=({4|RTX>}x?O_yswz>;^5g}+ z3*E{?_XeTRN-Zfk&|Rgp@0#(p2%U5rN3o(&YOPij94x+cbVZAg6EC{IU4jm>$&Fcz;qa* znKQdUDqh_KF3ytupl-4!9dP-r_urGp_g(1G%*r*OTf;5KBOig|2(R z<-WZ--YT!E(CLS`@fF5%pwkaU%5kwoRoozJD!I0gfK)$%SbxCdbBJ2T9E0B5ZVH*w z{RoLfHT-tTUN^@oiGBpJwx?;cS_$@F$z{Smi^*$$~Oq$UYP!Z_14z;Q)hE2 zWn9#1Qd05RrJJ`{$kh1R+_aYe%z~vha_8>ni=FLfh)jRWqg)$F4|CZ*J+2W8J9_H2YSn#(nRwmJ?zXySXoj3ay<~S8Hc7 zJtL|ttg$(^bN0r(_SQ4^{-#>|V^I4$-{k%YVFre^LIqnE`a7@9P&;X2DlPQe?^6wT zq4=3^7ZOD3Yp)&J9jC45zRv{#>`xrcusc1M@p{v%oLT?Z-Z*)oJn{|C4zVi-tqOj! zZ8@FRZBWj*>6YY;sEf_#Uzcw#e6DpMq2t zVb9u`y46_VTm5dExqoJL*L; VA6D^QcL&BagQu&X%Q~loCIC;H^EChf literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Materials/hide.rsi/meta.json b/Resources/Textures/Objects/Materials/hide.rsi/meta.json index 0ec2b25480..9235e8e2e9 100644 --- a/Resources/Textures/Objects/Materials/hide.rsi/meta.json +++ b/Resources/Textures/Objects/Materials/hide.rsi/meta.json @@ -1,7 +1,7 @@ { "version": 1, "license": "CC-BY-SA-3.0", - "copyright": "Taken from Paradise at https://github.com/ParadiseSS13/Paradise/blob/88d236d5c91e9a57e103957555c2e9a8c63b68fa/icons/obj/stacks/organic.dmi", + "copyright": "Taken from Paradise at https://github.com/ParadiseSS13/Paradise/blob/88d236d5c91e9a57e103957555c2e9a8c63b68fa/icons/obj/stacks/organic.dmi. Inhands by mubururu_ (github).", "size": { "x": 32, "y": 32 @@ -10,6 +10,14 @@ { "name": "goliath_hide" }, + { + "name": "goliathhide-inhand-left", + "directions": 4 + }, + { + "name": "goliathhide-inhand-right", + "directions": 4 + }, { "name": "goliath_hide_2" }, @@ -17,4 +25,4 @@ "name": "goliath_hide_3" } ] -} \ No newline at end of file +} diff --git a/Resources/Textures/Objects/Materials/materials.rsi/bananium-inhand-left.png b/Resources/Textures/Objects/Materials/materials.rsi/bananium-inhand-left.png new file mode 100644 index 0000000000000000000000000000000000000000..b936e0fd78cb850e93fa00bcaea097a72d1cb597 GIT binary patch literal 345 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=jKx9jP7LeL$-D%zg*{yyLn`LH zy=BPP!LWAa3XM0{x>}^t!p#5NXH?sr zuO4uw185ouOpaM+{r|P`pO_xSH74DuH{CYJ2&`i4=-6{leX?GKN%iDion;4C>HR6& zJ#E|Drxh7#*Z1EoejlS1`+ef4KOy$(tJsgYnKnH9s%tTQ)|F81gqq5=-^2wq&!1oN z+D>Zeo6ypSt9KdvjJW%*vSfb*#7c$(Nk=R+!-OAws+TQTq1fie5y)zQpU6C!YG4Z_p?Nil!weu=hnIz)w?KD~CxGaj{v0>Q?0h4cnSHk_;x}(=@ l?umS>>~ge7o{>T9A-Bx$g6icW=X^jmdAjoUbVa~>#;fD z=f9w?MUxKOeXr9$+qbFalM~< n!n)UcpZ|;9vB{W$;m0FZl?w&aHpU3O09oYe>gTe~DWM4f8wis@ literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Materials/materials.rsi/bones-inhand-left.png b/Resources/Textures/Objects/Materials/materials.rsi/bones-inhand-left.png new file mode 100644 index 0000000000000000000000000000000000000000..07a339dc36426b5ae58d39c4139f544453778a89 GIT binary patch literal 362 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=jKx9jP7LeL$-D%zRXklBLn`LH zy=9ws$U&g(A>&h~6GAUDGQ^}-E#3TNp7jlPheu*E&DKji+g;d2d3T&-)DUpLA;K}G zL!@!;#-Ek*>yBryFQ1j~0yG#1ltgCoyFP0U&F$WmAJrQ4+^PP;1=0}x2Ct965pS^b7^eADQ$SJAHrFuUS&39dUw_&=c z9oOoo({)a5TDV~^x0O_BMjX7PW2N4h>cyz+JQzCAmy>@0Y_UV5__ z#1#w;T@h|i#I78^xa9J*e+$ArgVuc9cy+O%;Kcs(ODkt3+x81AUFGup>Ey-J|1*@Q zPU_F%G){glcx6^XtYO(3n?uRZ-qm-^bgz&)Bf`K?Fg1U!b>6A=ncb!!(>-1NT-G@y GGywq3S(?%S literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Materials/materials.rsi/bones-inhand-right.png b/Resources/Textures/Objects/Materials/materials.rsi/bones-inhand-right.png new file mode 100644 index 0000000000000000000000000000000000000000..5eb64901c0e50f12fe06932975f0131fff540391 GIT binary patch literal 369 zcmV-%0gnEOP)Px$D@jB_RCt{2+A(gzKoEuDA<6|JOHSt|%|JutbSt^%4)zg{xCO_^O(M~S3%E%` z6(U&_Il!igEsBt}!5h}*|7vSIvl?ylRs;Y50002sgd$6Ak)`(9eYkY(@viNMQ4-5+ zJ{6-H^dUq^?5}v}!=Iz|2H@5dS!&nIyjl67tp9PJ>t*h|xbIyBSNXzj-`-_YmXkgj z^lej?6QgR==O@`8D(CmV4pn5Soz17RKU6ZL;g8jaARa`wV3~vT5M&1qpz^Hr!o6>f(ezoA$ P00000NkvXXu0mjfxObtE literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Materials/materials.rsi/cardboard-inhand-left.png b/Resources/Textures/Objects/Materials/materials.rsi/cardboard-inhand-left.png new file mode 100644 index 0000000000000000000000000000000000000000..fd69f67e5f3c95eafeca74e4fea915b95703c864 GIT binary patch literal 418 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=jKx9jP7LeL$-D%zV?13PLn`LH zy=9nn*g=5x!hC@(`szB^GubEhfttkBQkwrcOEZO?FR~+10jI4S}%w zl$QUid%6;BXUR&ZF$luJ$?Z}4&i9`eAOCf_*Y(2m>sAa0-W8i$T-$b!g&|{hS-~2+ zEi6m&PyD{T{`vcS`EbjPyUtDayU`!T*xk;$$Nu0>NrnY$o)zRx3*}4=UG&kuQu zyLb6B-TxNm3Y9wP*)d+x7VzG?<{3l7wx6f^L}$n8{5|~7;zP;b49*VUysdF@gi zzDbV27Gaq1 zzWDXtV=OOb3P1Yr{MYHvua{&_h@BKPB|ZAgRM8FlqMSRJn-bUjdB4@{lIzHfyK(h~j^|^g9w!gYQxm68Ve0?xzxL0(VAh_}^anFG z&*t4_wUYgdZ*Ikop1rS&ybcIhGyhrd7gw=ym_z cOMAZZ+IaTm)I0wE3ycc}Pgg&ebxsLQ04-t2-~a#s literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Materials/materials.rsi/cloth-inhand-left.png b/Resources/Textures/Objects/Materials/materials.rsi/cloth-inhand-left.png new file mode 100644 index 0000000000000000000000000000000000000000..22b176f3d37b687733f171d5ef43267ede88698f GIT binary patch literal 393 zcmV;40e1e0P)Px$LrFwIRCt{2+COW;Kpe*LC#8eXK)Mv-AjM5P`~F{nyMm(*mJCfW@e~Z#K_WpN zF5%8r_Quwki_c>BcB`&Wy=v9<>C!fi6SWt_CvOX|T+Hoo_<8f(n5y&6O{TNR zm`cV}y%*5ctIuMC!JCRav&s8MB%K$f?`zw%d#ZoH^XF*`|86nRbl-6ytLuY#ZIXvT9q z>~H$Xf4*&zXU=1Aj>lb--q3lzbe{Zp{B_yww(WK;>5r1>N1W+t`Z*r~`TLKKukgob zr*Fl`&0;&XDfsb&?>?Hp=hRG_oAp^^wQhrXd{oqXt@Fz-PY)DvRPm2{JvU=-c1*3{ z#N*4@^7m~48G71NX6DH!FU2-~)AF7C`R~#r+-qg))>TY*WP~_?fx#dwwr}S9lle)x zHnMvB&n(ti^l2YITqoihaOz!5%QdEsj)<^(zOQqa=AM{)v2@)w<&Ue?{2rY+5bP0l+XkKwMMf- literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Materials/materials.rsi/corgihide-inhand-left.png b/Resources/Textures/Objects/Materials/materials.rsi/corgihide-inhand-left.png new file mode 100644 index 0000000000000000000000000000000000000000..28d69ddcd71f2737c4b2c0a8e5cea745358f4502 GIT binary patch literal 670 zcmV;P0%84$P)Px%SV=@dRCt{2+OcaBQ5*;G?@2KlV&rk8gGfctk`TnDATCmH5C?I{AP52f0>Qc9 zAE1N9*{M!~4oVv>fRLvrD+(c&e)s};VV<<}R=kN1AL z+&%9703sqHA|fIpA|fK1jI~yL-&M2jyr>X7^_06_AyC^qVFheb$}FIs%z z-JQ{Ah4=R~raDID3dp~@gkt$R&O%MRE7sBbbAiyXdb!t~YSlb*d z+EfxTtZhz|uYGe(Yib8leF})FAXi((?(L7r)m9;g;rrs`|)&yUW^){}WT_4XEwF`2*7)#yi1Er6VGN3rnXL8e96-;dCJc1|Wagi$+i zh#DCZjvIXcvY~$38}COzCm0;W&g6ldiyzmXBM1WgZBvHs;pjeDEFRG9N64jr4^CRwIKSDgFrQabkB*hDvJ_WS;5!4Fsbzvnj z{x<(mEA<%degsvX=SkK_+tCInwh>B<|7igZi&j6vFU`w$@M5d4`v3p{07*qoM6N<$ Ef&~;lsQ>@~ literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Materials/materials.rsi/corgihide-inhand-right.png b/Resources/Textures/Objects/Materials/materials.rsi/corgihide-inhand-right.png new file mode 100644 index 0000000000000000000000000000000000000000..a75f4f96e68a377cb12e2e06ea080c5ed69050d8 GIT binary patch literal 724 zcmV;_0xSKAP)Px%j!8s8RCt{2+QDnnP#g#FZ)92xwIjstB=evfEv2`j3{j+>c90!<5QKt%!N7y3 zfq#HIxIe&yOb~?iu-k?#NJT^#gt5y5m4TkdGn7e5Y`gOF(4{tO(zP>b>-c>xzrLhR z-g|k;3w=L;F~%5Uj4{R-V~jDzSc?#X+|N=<>MV~d!!XG2a}XtHhY*5vUB~2l4s;<7 zrC!Cs!Zs|+LMoLC{N1RTrb+P+j{yMHJFifwRFKc-1M7RvZ=>7zM7ao3rvLz?P9ae) zLf3VS^GI+T4*>D^520yV&yg_Uw^1!+kx1PKYSz)W)K;unNR*3k#8zk(j@s`xH*u-Q ze%}!=z0^?l0~)z6wlKZa7~5OG&)jlweSJH?}6KMs%NBT7Izdh9aQhVJ^ex4t1N_|wMVz8vm8z}qvc-pe%=NdV~jDz z7-Nhv#u#I4tQdwtrfEj<=jO>vW5*0TXTUHF(lia1-#x&W7qj&B`PER*H&6$-3nulK z*QmCdp~>}Jqzff(_PWm4J0000z#DPpGwCYMP{=C7+?Ocj)E2^W9h6DqMN*cV^n<`SKyA zp{CXE(~s`ST_v{f&T&SVaUcBkgj2gutSy?cD$l<#UinAp-Inb;tKZojdZ8rayX-f| zx{@PyItzaMNc2RYa8-ai2KCDvpQaJhcBswm{z^dcC5F* zULAj2!t`+Z!AVY&W4GqROk?=7_tK5($KPJ^-?nbN*;%;TJNCs--O$>5+-GcN0S$Tc zgZ0S=<9LT-_jdQoX~|R?7j)hDE#k|-u;DiIgA)@@SuzbP0l+XkKw2x^? literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Materials/materials.rsi/durathread-inhand-left.png b/Resources/Textures/Objects/Materials/materials.rsi/durathread-inhand-left.png new file mode 100644 index 0000000000000000000000000000000000000000..139c2a573e883282a4a19b445663920024d146dd GIT binary patch literal 381 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=jKx9jP7LeL$-D%z%{^TlLn`LH zy|vNnaDd3MkN$-o(zEz#`_5?g9i4tcZqCv?ziW;H;;nhRI-2z#JPHz!xf1$8*Tkcv zY`0(UO4TXLmb*UufBRi)^^Wfa+uwTtjR%2-s%_-fKfeB4w)nI5_j${z>MBAdj=p>PGA;R{RicQsr`NasSOFHPe)~1+wLEWa(YujR zb|s^%t90)1|8~zSb1UO+KPcOr6}!$$;^?}oS-x*mBg0m60yWI3qiE&doo+eto+qc76A&N3ZfGK7RP| z<*AzQv5g8nYgFdO-@DQ5=Pv(#{neBmshe-kex$PX^2?C({`y>pPV~9&ZF~LGHhjU4 zpv_l9H(yy@74IpUf1SY_>(`g1=U-e0jb4#=qvPhBe;@cc}J zph#D@tR{~xO#1AekbKjLr6T?Nr2pM| zRo2C~dec;ZMu5P9ze;6tZCdbI|;Qv0xv(2Sh_t!oM1DWaR>gTe~DWM4fc*lV# literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Materials/materials.rsi/pyrotton-inhand-right.png b/Resources/Textures/Objects/Materials/materials.rsi/pyrotton-inhand-right.png new file mode 100644 index 0000000000000000000000000000000000000000..3225dc089809c33619d5e9f65e8521334e4195c9 GIT binary patch literal 303 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=jKx9jP7LeL$-D$|UV6GXhE&XX zd&`io$w8p?VPrPH$u+aMgVqvzJ9s(JPx3yd&-}2X~+NU|GcmDZ?=C0`FNK3uEd;5RhBUO3Udt`-fG?e|Ap?=`g snKd1|U*>N;+#l$u9$2j|$i&caZ=FzSVb%;cAvKVRp00i_>zopr052hb;s5{u literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Materials/ore.rsi/bananium-inhand-left.png b/Resources/Textures/Objects/Materials/ore.rsi/bananium-inhand-left.png new file mode 100644 index 0000000000000000000000000000000000000000..01b00bc68f54f6a29879a951a1c86cebd53c1eac GIT binary patch literal 428 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=jKx9jP7LeL$-D%z(>z@qLn`LH zy`|`XI6#E;0rMiy-Dhn#FR6SrvvVig(RhW5FFY1T&Jj%tjb|7lJ=CUUUU>1B`N=fN zOA2BvDyG7wrumCz-i%;czg=48x$)YUFHh&*-N_&b2Rpf^Zn}T>y;b()+LIdsG_zlo zx*WT)-M>R-$HJ|>JsY22?{v8%b&-+bK!S2(cN+KEFQOxcS=AH38R7XaB1?`ngLkTlpj7ms`FvbNv_?4zJUjQd+a%;>+V6 zn|U&)dCKIUomcYUmHz*UD(Bu$IHQCF78y+mP5oav(XcGCH$R)hwVdO~>5G2$$4(|% zhJITWp!xg96a}MWW?RancHCfi_v@#V%lf-hy8cW&JVe1e}8+Yvx7^>0VW^uY=asB!3VDWwRc&z<|1UnY8& z$MOdcCivb`JZ-r}aH5%E(b}~&`!!Xj-+BCW+j~YAI4}tdKjpJKF3mMN?tJuzPi&7n zC01SyTg3Txv&6iP%#6Q_qteY5tediOhu*K)gv}v`-UgqKn_B#(KvhDG^Hg7R*Xw8h zwww`uP_8sbo||F8{jCvC=S-DlXZY|#=IOe#IS1~xvN6cWd@ZQml)Z4vPiZyIHqRyn znFUv`?0kKFlU$v>-TJ~gJL@FZB%Ou32*~(y^^(fvdPC!Y@KZ|+_o^qAp1j%}-g@AFXwbur z700H!F#!z#fhpVzx9)kjYwy|b@1K?2z4xrT|FdpwbzAF&TLv{Zj&Psb-e1P>j;}hriW%hdU_THI6 zJ^b7ETy4D|_WyTw8Y9FqAbHO2rPk}y#%td5ms!otmFW9#)^f|P>G#(iU#eX9srB16 z-DYsg(3O8swp-*o)4kB!?gi2g@7S(PQS!R~@~-<2ixLh7hSYhyyUGta$;?gy8SCll K=d#Wzp$PysMTR{9 literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Materials/ore.rsi/coal-inhand-right.png b/Resources/Textures/Objects/Materials/ore.rsi/coal-inhand-right.png new file mode 100644 index 0000000000000000000000000000000000000000..a8286cdebe2d22dce48510c1a4800d24185cb634 GIT binary patch literal 326 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=jKx9jP7LeL$-D%z89ZGaLn`LH zy|uCHkb_9;!_D1mb$HA+@o@fN$ke%fGcq@M_xT-D^ObWp#IhZ-Ik44mf|F#dTF(n%O@6na{%>&+*;7E#zHf*1>IeZxsF1d_L#fZ+UCE z`ujyJbGwSUL$97v(L84N^UqbLIq_GXedhNJ;!q4elF3_{{6_T9{2+OqN~Sigvb%~q zZz#Xm)jTKqN%V!^RzKx!XQiLvf!GEl=lEWIRkh#TrE@0Z`|R6!`?uV#jlP|?>D|mX zeDOg^X$h;o{fTAOFf}%K6CJ93^v3DmR?!##moj;s;o)(Wh@I~IUzXv6l;2K|+|+B* RPwYX)db;|#taD0e0stObhr$2= literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Materials/ore.rsi/diamond-inhand-left.png b/Resources/Textures/Objects/Materials/ore.rsi/diamond-inhand-left.png new file mode 100644 index 0000000000000000000000000000000000000000..837741af4345a598c1e8c1f9cb18a0ad541c5c78 GIT binary patch literal 325 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=jKx9jP7LeL$-D$|{(HJOhE&XX zd&}1Eu!BI`!^T-mEiFL?TXI^a-1C}v%)H?6*&5mTjGT<2DwC9)oR%&4AJn+*sN6Nq zJ?9zIj{km~W@ijE1q7V81eurePcHVKwX1!;Rj*#e)wAE#cBu32m0Ww}sr0Pty(L1S zE2i$M-hA~@THf{T<=;MT+kF1tU9;KG4`%OBpBo!<>*v)o+w}VvXNg|)iq$`9d(t*j zw|5ug>osBevd2H4vafj4Z@5VeVi^O&f%QMWJNMKb@p$8}VW?*Rf>&>*?y}vd$@?2>`txguMU& literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Materials/ore.rsi/diamond-inhand-right.png b/Resources/Textures/Objects/Materials/ore.rsi/diamond-inhand-right.png new file mode 100644 index 0000000000000000000000000000000000000000..0f97e2c9c9dde7c8e795c1692980997acff66df0 GIT binary patch literal 334 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=jKx9jP7LeL$-D%zIXqn)Ln`LH zy=Cvk>?m^lM`8H~m*Q5LH_4)tLh`gW42s9W7GK7{+v353l=eW~&OK!+^fu$k375gIi7X8Tb`@SGJ zKIh_=7jh+LGjIL)b7-EN`8Kt0z|t*tIcIG(e$Q#DzVPN**yp30E^qt!+-}0x@DsMi7rG}m{Ih0Y bs6WPjjAIGMbP0l+XkKhMkoX literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Materials/ore.rsi/gold-inhand-left.png b/Resources/Textures/Objects/Materials/ore.rsi/gold-inhand-left.png new file mode 100644 index 0000000000000000000000000000000000000000..62255bf46bfda5897f88ffcaf631338fa932c41b GIT binary patch literal 472 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=jKx9jP7LeL$-D%zCwaO!hE&XX zduzWpQ=$a>hxd0iO*Hu~X(S~?2T$DM)hxclyYat+jK!9fozcw+X59;RaKBR6?kXVK zINSN54BvB0(S`Yw15+A*{Zjr>w@v!qd)xPif8YBg&v$I;8h1=}(S$X`+SwpKq;B{Vks1=KbcKOj7b^zNv964!N(^tozNeO1ok89QTN6 zt-s40(^k%3Vy19cLaXq5^9H8nFTU8`$lIQF?$hnk7B(#d2CID{TIV;L7ODCi*4%Wm zrQ`UbV%gh0>pCmfUGz#V@%6g6si*@Ph$$@2EAo#|K-6W|#Nd=P|Dczy4Q0alyz6)5eJ#AnyXbXU!YspG zTi9l_1@GDSM$tq=VNQMgk7tYvLe^?_xUxq1megogFvwKT*6^LExR%k}Upb_TZ_29E zH~&Pej0*m&0ZbhsO$5zK@sw|8%jpi_7aL%recr7ZVPdZ2?9VgQu&X%Q~lo FCII9j)L8%k literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Materials/ore.rsi/gold-inhand-right.png b/Resources/Textures/Objects/Materials/ore.rsi/gold-inhand-right.png new file mode 100644 index 0000000000000000000000000000000000000000..50892832e0545205c2127385703c1d716d44540b GIT binary patch literal 449 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=jKx9jP7LeL$-D%zt36#DLn`LH zy=9wy$U%nfgL`h6s`E90 z0f*|RKc;dsFyy~uY0eRRTq1Wkj{odA6GiI{Ierm`D#Kh8L)aP4EV}u=J5)P0ac0|x zlBW;0|6BC)s`Di+WuI*v$F#MUc|2sJ5}_n##`kv&$`T&`Q>b77cI`ZuHRwf ztF*}!Xuy^CN23}Pio4w=v@h3ww76L3&pvK-os(xaUrA1%^QXMXLa#gn_}+)z4*}Q$iB}wF%62 literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Materials/ore.rsi/iron-inhand-left.png b/Resources/Textures/Objects/Materials/ore.rsi/iron-inhand-left.png new file mode 100644 index 0000000000000000000000000000000000000000..7d2f6abd5779e42c4260300f558016a80b5d8f76 GIT binary patch literal 321 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=jKx9jP7LeL$-D$|etWt&hE&XX zduwCXp#YI%9~XZSJ#w*(LxulgLd%4m!G_T%f-SgemtR`AKJef{H~o$u0?WObm6ja6 zQ_Q^Z|9!C&e?9nAPXBZPngj-SmsBou4b3W+Ro(cn?0@{a^Y-iG_H4Rk6TyCNp4`$E zUbdF%$A3MTYaXvxVl?-ceFXPsMw7m;j%D+2PxL=_{^tT_iD>p~zx6FG(`Qv$&iDP? zyN&_xaDpj?GT(MAo#PQ`n#6f9c35!!~mx+f(#7*kD4Dm8ag{>qxw{kp`NaO JF6*2UngG8cgTnv- literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Materials/ore.rsi/iron-inhand-right.png b/Resources/Textures/Objects/Materials/ore.rsi/iron-inhand-right.png new file mode 100644 index 0000000000000000000000000000000000000000..f616f48f95730357cd980df6b7631f127f57b8cc GIT binary patch literal 340 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=jKx9jP7LeL$-D%z`8-`5Ln`LH zy=9oi_Ipu2X zkN>N5?`@FJk2CjY0-6c}HLt%_pQ}GFR%|Z88yi_G+_QZ0{GR=v#Vh$ldEA_@dj{{_ zv-gzL=kpcc4d?mYF+E>uc{?FDleuhmuF}cUOIz0Elowk@&)*+Xz@)PE*|WXb^W3kq zNk3TbFzMRq&<%_GpSjyV`^E^dih-elZP(Sye}bIvI#sx5z0(XHcn^PfVt&y{EHYfkZgSYvqVTl=membKGYACX!dT$Xd}a{2cA g*+zopr0Ju7iod5s; literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Materials/ore.rsi/meta.json b/Resources/Textures/Objects/Materials/ore.rsi/meta.json index 8f1b4533f2..bf4d6e7745 100644 --- a/Resources/Textures/Objects/Materials/ore.rsi/meta.json +++ b/Resources/Textures/Objects/Materials/ore.rsi/meta.json @@ -1,7 +1,7 @@ { "version": 1, "license": "CC-BY-NC-SA-3.0", - "copyright": "silver, plasma taken from https://github.com/vgstation-coders/vgstation13 at commit f2ef221849675915a78fd92fe622c32ab740e085, spacequartz taken from https://github.com/goonstation/goonstation at commit b51daf824df46a3a1426475f982c09479818e522 and reshaded by Alekshhh, bananium; uranium; iron; gold; coal by Alekshhh, diamond at commit https://github.com/tgstation/tgstation/pull/78524, edited by TheShuEd", + "copyright": "silver, plasma taken from https://github.com/vgstation-coders/vgstation13 at commit f2ef221849675915a78fd92fe622c32ab740e085, spacequartz taken from https://github.com/goonstation/goonstation at commit b51daf824df46a3a1426475f982c09479818e522 and reshaded by Alekshhh, bananium; uranium; iron; gold; coal by Alekshhh, diamond at commit https://github.com/tgstation/tgstation/pull/78524, edited by TheShuEd. Inhands by mubururu_ (github).", "size": { "x": 32, "y": 32 @@ -10,32 +10,112 @@ { "name": "bananium" }, + { + "name": "bananium-inhand-left", + "directions": 4 + }, + { + "name": "bananium-inhand-right", + "directions": 4 + }, { "name": "gold" }, + { + "name": "gold-inhand-left", + "directions": 4 + }, + { + "name": "gold-inhand-right", + "directions": 4 + }, { "name": "iron" }, + { + "name": "iron-inhand-left", + "directions": 4 + }, + { + "name": "iron-inhand-right", + "directions": 4 + }, { "name": "uranium" }, + { + "name": "uranium-inhand-left", + "directions": 4 + }, + { + "name": "uranium-inhand-right", + "directions": 4 + }, { "name": "plasma" }, + { + "name": "plasma-inhand-left", + "directions": 4 + }, + { + "name": "plasma-inhand-right", + "directions": 4 + }, { "name": "spacequartz" }, + { + "name": "spacequartz-inhand-left", + "directions": 4 + }, + { + "name": "spacequartz-inhand-right", + "directions": 4 + }, { "name": "silver" }, + { + "name": "silver-inhand-left", + "directions": 4 + }, + { + "name": "silver-inhand-right", + "directions": 4 + }, { "name": "coal" }, + { + "name": "coal-inhand-left", + "directions": 4 + }, + { + "name": "coal-inhand-right", + "directions": 4 + }, { "name": "salt" }, + { + "name": "salt-inhand-left", + "directions": 4 + }, + { + "name": "salt-inhand-right", + "directions": 4 + }, { "name": "diamond" + }, + { + "name": "diamond-inhand-left", + "directions": 4 + }, + { + "name": "diamond-inhand-right", + "directions": 4 } ] } diff --git a/Resources/Textures/Objects/Materials/ore.rsi/plasma-inhand-left.png b/Resources/Textures/Objects/Materials/ore.rsi/plasma-inhand-left.png new file mode 100644 index 0000000000000000000000000000000000000000..6c41a2c1494179a4f590153234c56f5dfe475c84 GIT binary patch literal 395 zcmV;60d)R}P)Px$MM*?KRCt{2+OJCkaTv$(k760fg)2i2loc;o1j7&(EG`($!?r)cuz%*_U<(%p z*JQ;su$*N<27`r_OV<`2gKVf6w(q|42fknJzTxwIz7N-)M*;u<0000007vyk(|)>! zP3`*%syCW;H9Aoqq^l-$Ds79R$f+rD99ta6_Ws*Pou3`}3Yxy;dbp4@%4DsnJ*Q8) zJ-U}lx4g0}bzZ+#SglzxpD3)>r198SxhvipFq_TxBv}&XQt$1oEX(D&Q{G|zXs2hF zlB8lj@m1>XMN#DZ>+doP00000000000Pw6+Y5(t0Rvx7G9ZmRkjb1){o4tT_bt-Mk zgVd}w{jfu@>Al{@$YbbhAmwv-n|)H)|9)4;!`#fXBYcicSCgpu z@aod6hZ1*Egv|r)*97mI|3&Wm-Q(}&@~qvNfOY^ugXF8;WzXj-W@~R2J9EbR=(pdE zkBgqP^WXN4ZxLwnxAWgupO(g`^0Ml+U!i4DzG~giqQ$rOrmOlFhDC}m3R*8l@&q%8?vzVq*s%`5TG;3M$_b0k752j}MzLuU{)${)9`|tJBuAjMc zX4X(ZO5N#{AZeRGi3kW=+5I$Pl(61d|Y!#iEHDp zxxRCgZu?*FE2%40%)Dadzq!X$*Y~p1^{RY!`IO)9^}nAxd&Ya|B)>_`F==eaa^J^1 h7kROtnc;)}9;QRfvrmW@wx0so=jrO_vd$@?2>`zEtH=NV literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Materials/ore.rsi/salt-inhand-left.png b/Resources/Textures/Objects/Materials/ore.rsi/salt-inhand-left.png new file mode 100644 index 0000000000000000000000000000000000000000..fe4e9e2d5d1477142c2afe35d7f8b95aa6f3ceb9 GIT binary patch literal 299 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=jKx9jP7LeL$-D$|o_e}ChE&XX zd&`!u$w1=R$77dgG%Xfah>fsmEYGMGd(6wjUZ5^>prs|!jQ_#2Usk4xAC)5<4*lO= z`eL%VZerys5uhO;uwcH8@uUph#JL%|m1$4z&dc8{mwQ+H`Q*?u8@{TAPXFww8r8ks zuj{enTJy~JYaUeubY8m@vNWgs_l(7S$D`GKLr>{%w|BX=Vo&Ksw!WFH5JQ2a%d@r7 zWmCUqWY0XU=(6^>^W^Hicax9pd$M-&yWNc^qn})O+HdMo;c_u#X^U3vC4K$#XI_|J oux&Yd?L}o;+UN6(3=jHk7+DUK<#N24#0)ak)78&qol`;+00{Mbd;kCd literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Materials/ore.rsi/salt-inhand-right.png b/Resources/Textures/Objects/Materials/ore.rsi/salt-inhand-right.png new file mode 100644 index 0000000000000000000000000000000000000000..8330643546b49e1f8d8aa603cea234d86a785192 GIT binary patch literal 300 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=jKx9jP7LeL$-D$|o_V@BhE&XX zdut;nlcC75kL{N|{Jh0EGA~&)TC2=_x`X!!2rg5+BxfmI|f4b#=*4a;;f;;B^|D_av;?3IMGpC=gGc<-63nUA^ zT@MZC3e?Yj@4qX$|9;V4rPD|Q$1b%T-G@yGywq9{C_6^ literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Materials/ore.rsi/silver-inhand-left.png b/Resources/Textures/Objects/Materials/ore.rsi/silver-inhand-left.png new file mode 100644 index 0000000000000000000000000000000000000000..7f7005031355b3e3b84e4fa05cc6e5aa719a0bb0 GIT binary patch literal 380 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=jKx9jP7LeL$-D%z%{*NkLn`LH zy|vNnaDd3MkHH^BRT8|GT~dvlq}sgW*3pg02hJYU+jT0mm{xcPBNVvI`{bUbW1y{2^u#; zSLV;GV)lym*ejazgPxn==Fzw&4GW5jjM}96(vWhNe7(7znwKu{mdQJAu`^$SPSr`t~e`HF^ VjPulcoA3!_tEa1<%Q~loCIG#!s%`)P literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Materials/ore.rsi/silver-inhand-right.png b/Resources/Textures/Objects/Materials/ore.rsi/silver-inhand-right.png new file mode 100644 index 0000000000000000000000000000000000000000..ab4dcb98d690d38373b232996559b097d595f3d3 GIT binary patch literal 385 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=jKx9jP7LeL$-D%ztvy{FLn`LH zy=CZs$U)-R$K`eG&Ppwv8%_j?u|L-8R#xtu-K?`~hV)MbUm2f2N`879UL0v{+%mzf z=cDi(=8Gi)QC}2PfBs*_H~rho>hjCKy?_>gK*Q3it&jH2U%U0)lG-=d*6KHRf4)4w z=jNZ)GEa03j_rus9{fxG{HANWHeA)2Qkl!R%u~w7?vD4QMH-(3a(_p?HNG1Y|LX7K z;L9q!pRPTh$Kbij)ahv1m;WW!AB<{(jH*BXzErh!llb@eNr%ENi|+glu@p!;c;>D) z4PRk7YwFwGUw6%&`;F)QFWdB(^b literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Materials/ore.rsi/spacequartz-inhand-left.png b/Resources/Textures/Objects/Materials/ore.rsi/spacequartz-inhand-left.png new file mode 100644 index 0000000000000000000000000000000000000000..56837c96099e8bf50e5bcd3d3ab88324dcbee676 GIT binary patch literal 509 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=jKx9jP7LeL$-D%zw|lxchE&XX zd&}0F*-?P)!F7HSR_>#2u0b9OyLh=_3( z&GRw|wBQii=sDR*N>-d~oHx%1}Cy_~Jg0)jB`)icw-s`7gN8V#OX zTuZj7M_YR?k-6$=6VH{Bf8S8gEz^Hlvhj)OP3Ow*7UoKAlhiRY?EAP;aL3I#SF}xA z>O`Nq2`^WF*WfwlvT(UWroU5-*uFg*+je(L&tB=~oauij$1kXF(x`b{OC zOXaD?%Xe(E*OW0Zs9c+VAtf^qw!FR6Ty*<4zZhpMM{0N7=LCtnH2cG_%`f=B_K8Nb(r_)Om#h7!}%9lqrg&H>|-!PC{xWt~$(696WA-TeRn literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Materials/ore.rsi/spacequartz-inhand-right.png b/Resources/Textures/Objects/Materials/ore.rsi/spacequartz-inhand-right.png new file mode 100644 index 0000000000000000000000000000000000000000..45b370cb8e3cc750c524c0140da691e6a89cc425 GIT binary patch literal 469 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=jKx9jP7LeL$-D%z`#oJ8Ln`LH zy|pp>kb?y4hxC^rFBYU+Q9Fw_>YA%c5T&Re6IwfZ|KSK%YxMY6zcb*k-tp`3|%qd-Zw>UXgdz1Zx00~i-uRK6^lpSYbsQhOChjCRnBg2(h zg;p=wcz%^-ZH_uzRd=XppTokSLup%&U8uF)&-w5~DdU0&UFEqK1)l3#ykxjiD${Gb z#5n4Paly&6+Rgjs&f3>=Na@e)=r@uIN=jYdc&7y%k~+L)TN^N*7(8A5T-G@yGywqr CugpXM literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Materials/ore.rsi/uranium-inhand-left.png b/Resources/Textures/Objects/Materials/ore.rsi/uranium-inhand-left.png new file mode 100644 index 0000000000000000000000000000000000000000..422008998b45b0ecc22f15deab7dfcbc9f105d60 GIT binary patch literal 453 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=jKx9jP7LeL$-D%z>pfi@Ln`LH zy=CZqI6#2?L%pj^)WUr;{N5%kNKkC9Yz` zN=xvaf2Rop!x}f%NNuTR_glB}gLC@3+X|OjeZoDpCdgYYdwF%DUA@Cy z`2{6^I@-I1CaD}PDA`^h_jYI6{@tvr0~>c{DrFztVI$pj)ml~R0>A8MBaOq`bl;TS zo2Zr?GvEH{Im6sTuM@1xmBXE?*Ik^aZM3QGMaNMkWRUrK%UQwOeDznqyvo?lADAM% zHEqZeh&Mun>sG(4Z6D2{P6ybQlcq0Z{M+X znzvj%DnTG~vRd*Uo>Q&sH!TltxNWNu>UyoKcXTz<)Dj@ zkW9&r4Lm}tSA1N#S`PSyq7U8EG7NsoA zvdjqUTHRKioOD@%hga;mhjxRh%|) zxg7E)JnlmN*@D}9qjlp?n;bFf?fvyk_wtQh^GyX2;Nt%YPnM`(s`#Vr`JN|Ync~w= zf?dxXl|F{&Ib5=4{&`9S=&=7r^Id*q@cyU~eeLJllrZVVIfvzjK0ohCbWL*In(29W z<*SUpk%ZkNwk?1jZ19r>mdKI;Vst0L3!c A#Q*>R literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Materials/parts.rsi/meta.json b/Resources/Textures/Objects/Materials/parts.rsi/meta.json index 290b7dd91c..c2503bb393 100644 --- a/Resources/Textures/Objects/Materials/parts.rsi/meta.json +++ b/Resources/Textures/Objects/Materials/parts.rsi/meta.json @@ -1,7 +1,7 @@ { "version": 1, "license": "CC-BY-SA-3.0", - "copyright": "Taken from tgstation at commit https://github.com/tgstation/tgstation/commit/c6e3401f2e7e1e55c57060cdf956a98ef1fefc24", + "copyright": "Taken from tgstation at commit https://github.com/tgstation/tgstation/commit/c6e3401f2e7e1e55c57060cdf956a98ef1fefc24. Inhands by mubururu_ (github).", "size": { "x": 32, "y": 32 @@ -10,6 +10,14 @@ { "name": "rods" }, + { + "name": "rods-inhand-left", + "directions": 4 + }, + { + "name": "rods-inhand-right", + "directions": 4 + }, { "name": "rods_2" }, diff --git a/Resources/Textures/Objects/Materials/parts.rsi/rods-inhand-left.png b/Resources/Textures/Objects/Materials/parts.rsi/rods-inhand-left.png new file mode 100644 index 0000000000000000000000000000000000000000..b0e71052cdc8a7d1525155745d1c030fb6fcab8b GIT binary patch literal 189 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=jKx9jP7LeL$-D$|$~|2iLn`LH zy?Kzg#ej$9fUf#f*O&VnKRDcxf2VNLFt~B=q`x;=fC?Wh3G&L{`t4#dk7^5t;z_wf zFC-I$_W$5qdu`vB$Xek;pH9oK)B7lXni;5;;ehv@&>WqMPWSJ=@{vCzy!PA|MH|Oj jHu*ZImI+6aSsH}R{!FqFkEv}_1*!IQ^>bP0l+XkKu9QYA literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Materials/parts.rsi/rods-inhand-right.png b/Resources/Textures/Objects/Materials/parts.rsi/rods-inhand-right.png new file mode 100644 index 0000000000000000000000000000000000000000..01b42adce19e4856aa4c73ba7ef516a25ce687ba GIT binary patch literal 192 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=jKx9jP7LeL$-D$|sytmBLn`LH zy}6V3fPw(a0qy5n&hPd!%2;miIbdTf`eq)>NjIP}hCKySgN!%-oBLS&)chzrrAIG5 z&B=IbK7Zy{t*6!Brk=K+)wiMQ=W#t-kXnWWwY_aqp0%d8+|#~v#a+U5q3`YwKGHnD mZX}xhfAiv#pq&lFjWfKlTWrK1@@sm7ba=Y@xvX6^`3o|L6Fp?dE~NNz+mbms&GgR<8Xf*wuBz%xc^F^ryOa-3=_6za_uf y>~{0oZ;r@qXM6uXk3V0ldEWeA{%i&YOFM=ox-TB+xf?GA+2iTz=d#Wzp$PzcESKH@ literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Materials/silk.rsi/silk-inhand-right.png b/Resources/Textures/Objects/Materials/silk.rsi/silk-inhand-right.png new file mode 100644 index 0000000000000000000000000000000000000000..ee1b193af07732e9b94bb1354d8d2e4bba7b97c9 GIT binary patch literal 345 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=jKx9jP7LeL$-D%zg*{yyLn`LH zy=B{4*Pp$1bdQHu=B8_2yw(Szv^AG{rrfvA z{><1Sa6}^c*0!}tzq?O(?^kU3EVeH3clVXc>JTR|FdT@!&t+q_c%$t)ucT{+*NaQ) zSC&51UcAC)^MuQ Date: Mon, 25 Nov 2024 03:46:33 +0300 Subject: [PATCH 41/59] Delete HOS headset from warden's locker (#33234) * add headset * Add icons * Meta change * fix * Revert + delete headset from locker --- Resources/Prototypes/Catalog/Fills/Lockers/security.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/Resources/Prototypes/Catalog/Fills/Lockers/security.yml b/Resources/Prototypes/Catalog/Fills/Lockers/security.yml index 56683c7411..0c4f04fa12 100644 --- a/Resources/Prototypes/Catalog/Fills/Lockers/security.yml +++ b/Resources/Prototypes/Catalog/Fills/Lockers/security.yml @@ -10,7 +10,6 @@ - id: ClothingBeltSecurityFilled - id: Flash - id: ClothingEyesGlassesSecurity - - id: ClothingHeadsetAltSecurity - id: ClothingHandsGlovesCombat - id: ClothingShoesBootsJack - id: ClothingOuterCoatWarden @@ -37,7 +36,6 @@ - id: ClothingBeltSecurityFilled - id: Flash - id: ClothingEyesGlassesSecurity - - id: ClothingHeadsetAltSecurity - id: ClothingHandsGlovesCombat - id: ClothingShoesBootsJack - id: ClothingOuterCoatWarden From 3c6c5ab6c937f7b36da73fc171eb3179f230ee30 Mon Sep 17 00:00:00 2001 From: slarticodefast <161409025+slarticodefast@users.noreply.github.com> Date: Mon, 25 Nov 2024 05:26:54 +0100 Subject: [PATCH 42/59] fix airlocks inconsistently auto-closing after unbolting (#33524) fix door auto close timer --- Content.Shared/Doors/Components/DoorComponent.cs | 2 +- Content.Shared/Doors/DoorEvents.cs | 13 +++++++++++++ Content.Shared/Doors/Systems/SharedAirlockSystem.cs | 10 +++++++++- .../Doors/Systems/SharedDoorSystem.Bolts.cs | 4 ++++ Content.Shared/Doors/Systems/SharedDoorSystem.cs | 2 ++ 5 files changed, 29 insertions(+), 2 deletions(-) diff --git a/Content.Shared/Doors/Components/DoorComponent.cs b/Content.Shared/Doors/Components/DoorComponent.cs index 21fad142b3..5e35045b10 100644 --- a/Content.Shared/Doors/Components/DoorComponent.cs +++ b/Content.Shared/Doors/Components/DoorComponent.cs @@ -66,7 +66,7 @@ public sealed partial class DoorComponent : Component /// /// When the door is active, this is the time when the state will next update. /// - [AutoNetworkedField] + [AutoNetworkedField, ViewVariables] public TimeSpan? NextStateChange; /// diff --git a/Content.Shared/Doors/DoorEvents.cs b/Content.Shared/Doors/DoorEvents.cs index 08a2c8b18b..849ea83730 100644 --- a/Content.Shared/Doors/DoorEvents.cs +++ b/Content.Shared/Doors/DoorEvents.cs @@ -15,6 +15,19 @@ namespace Content.Shared.Doors } } + /// + /// Raised when the door's bolt status was changed. + /// + public sealed class DoorBoltsChangedEvent : EntityEventArgs + { + public readonly bool BoltsDown; + + public DoorBoltsChangedEvent(bool boltsDown) + { + BoltsDown = boltsDown; + } + } + /// /// Raised when the door is determining whether it is able to open. /// Cancel to stop the door from being opened. diff --git a/Content.Shared/Doors/Systems/SharedAirlockSystem.cs b/Content.Shared/Doors/Systems/SharedAirlockSystem.cs index e404a91bdd..bdd119004e 100644 --- a/Content.Shared/Doors/Systems/SharedAirlockSystem.cs +++ b/Content.Shared/Doors/Systems/SharedAirlockSystem.cs @@ -22,6 +22,7 @@ public abstract class SharedAirlockSystem : EntitySystem SubscribeLocalEvent(OnBeforeDoorClosed); SubscribeLocalEvent(OnStateChanged); + SubscribeLocalEvent(OnBoltsChanged); SubscribeLocalEvent(OnBeforeDoorOpened); SubscribeLocalEvent(OnBeforeDoorDenied); SubscribeLocalEvent(OnGetPryMod); @@ -70,6 +71,13 @@ public abstract class SharedAirlockSystem : EntitySystem } } + private void OnBoltsChanged(EntityUid uid, AirlockComponent component, DoorBoltsChangedEvent args) + { + // If unbolted, reset the auto close timer + if (!args.BoltsDown) + UpdateAutoClose(uid, component); + } + private void OnBeforeDoorOpened(EntityUid uid, AirlockComponent component, BeforeDoorOpenedEvent args) { if (!CanChangeState(uid, component)) @@ -145,7 +153,7 @@ public abstract class SharedAirlockSystem : EntitySystem ent.Comp.EmergencyAccess = value; Dirty(ent, ent.Comp); // This only runs on the server apparently so we need this. UpdateEmergencyLightStatus(ent, ent.Comp); - + var sound = ent.Comp.EmergencyAccess ? ent.Comp.EmergencyOnSound : ent.Comp.EmergencyOffSound; if (predicted) Audio.PlayPredicted(sound, ent, user: user); diff --git a/Content.Shared/Doors/Systems/SharedDoorSystem.Bolts.cs b/Content.Shared/Doors/Systems/SharedDoorSystem.Bolts.cs index 13050616e1..d14b6c7190 100644 --- a/Content.Shared/Doors/Systems/SharedDoorSystem.Bolts.cs +++ b/Content.Shared/Doors/Systems/SharedDoorSystem.Bolts.cs @@ -96,6 +96,10 @@ public abstract partial class SharedDoorSystem Dirty(ent, ent.Comp); UpdateBoltLightStatus(ent); + // used to reset the auto-close timer after unbolting + var ev = new DoorBoltsChangedEvent(value); + RaiseLocalEvent(ent.Owner, ev); + var sound = value ? ent.Comp.BoltDownSound : ent.Comp.BoltUpSound; if (predicted) Audio.PlayPredicted(sound, ent, user: user); diff --git a/Content.Shared/Doors/Systems/SharedDoorSystem.cs b/Content.Shared/Doors/Systems/SharedDoorSystem.cs index 7fd5d61db7..835adb31c0 100644 --- a/Content.Shared/Doors/Systems/SharedDoorSystem.cs +++ b/Content.Shared/Doors/Systems/SharedDoorSystem.cs @@ -700,6 +700,8 @@ public abstract partial class SharedDoorSystem : EntitySystem } door.NextStateChange = GameTiming.CurTime + delay.Value; + Dirty(uid, door); + _activeDoors.Add((uid, door)); } From ed2cd23309f86c161eb62736f0aa7154493c84e5 Mon Sep 17 00:00:00 2001 From: PJBot Date: Mon, 25 Nov 2024 04:28:02 +0000 Subject: [PATCH 43/59] Automatic changelog update --- Resources/Changelog/Changelog.yml | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index 1a6a2a8a46..b89ab7aeaf 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,11 +1,4 @@ Entries: -- author: Moomoobeef - changes: - - message: Added pitchers for the chef who wants to serve beverages too. - type: Add - id: 7150 - time: '2024-08-19T03:01:26.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/31105 - author: EmoGarbage404 changes: - message: Space carp and Sharkminnows now drop teeth when butchered. @@ -3928,3 +3921,11 @@ id: 7649 time: '2024-11-24T08:49:31.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/32890 +- author: slarticodefast + changes: + - message: Fixed doors not auto-closing correctly after being unbolted in an open + state. + type: Fix + id: 7650 + time: '2024-11-25T04:26:54.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/33524 From f53e3ec3c1b5fa9989d38ae820311d3663f18793 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Schr=C3=B6dinger?= <132720404+Schrodinger71@users.noreply.github.com> Date: Mon, 25 Nov 2024 07:20:31 +0000 Subject: [PATCH 44/59] [BUGFIX] "Ghost" in the lobby lets you see the whole chat (#33529) * fix bug, in ghost command lobby * fix * Fix build --- Content.Server/Ghost/GhostCommand.cs | 10 ++++++++++ Resources/Locale/en-US/chat/commands/ghost-command.ftl | 1 + 2 files changed, 11 insertions(+) diff --git a/Content.Server/Ghost/GhostCommand.cs b/Content.Server/Ghost/GhostCommand.cs index a2f361d29d..26163f6d4d 100644 --- a/Content.Server/Ghost/GhostCommand.cs +++ b/Content.Server/Ghost/GhostCommand.cs @@ -1,7 +1,9 @@ using Content.Server.Popups; using Content.Shared.Administration; +using Content.Shared.GameTicking; using Content.Shared.Mind; using Robust.Shared.Console; +using Content.Server.GameTicking; namespace Content.Server.Ghost { @@ -23,6 +25,14 @@ namespace Content.Server.Ghost return; } + var gameTicker = _entities.System(); + if (!gameTicker.PlayerGameStatuses.TryGetValue(player.UserId, out var playerStatus) || + playerStatus is not PlayerGameStatus.JoinedGame) + { + shell.WriteLine("ghost-command-error-lobby"); + return; + } + if (player.AttachedEntity is { Valid: true } frozen && _entities.HasComponent(frozen)) { diff --git a/Resources/Locale/en-US/chat/commands/ghost-command.ftl b/Resources/Locale/en-US/chat/commands/ghost-command.ftl index 08e78d34ce..53dfa478d6 100644 --- a/Resources/Locale/en-US/chat/commands/ghost-command.ftl +++ b/Resources/Locale/en-US/chat/commands/ghost-command.ftl @@ -3,3 +3,4 @@ ghost-command-help-text = The ghost command turns you into a ghost and makes the Please note that you cannot return to your character's body after ghosting. ghost-command-no-session = You have no session, you can't ghost. ghost-command-denied = You cannot ghost right now. +ghost-command-error-lobby = You can't ghost right now. You are not in the game! From da9b2e6a1027c7632f480fa5627a471e6828ede7 Mon Sep 17 00:00:00 2001 From: PJBot Date: Mon, 25 Nov 2024 07:21:39 +0000 Subject: [PATCH 45/59] Automatic changelog update --- Resources/Changelog/Changelog.yml | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index b89ab7aeaf..ded4cc512d 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,13 +1,4 @@ Entries: -- author: EmoGarbage404 - changes: - - message: Space carp and Sharkminnows now drop teeth when butchered. - type: Add - - message: Added new bounties for carp and shark teeth. - type: Add - id: 7151 - time: '2024-08-19T03:04:59.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/31070 - author: to4no_fix changes: - message: Now it takes 5 seconds to take off or put on a muzzle @@ -3929,3 +3920,11 @@ id: 7650 time: '2024-11-25T04:26:54.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/33524 +- author: Schrodinger71 + changes: + - message: Fixed a bug letting players type "ghost" in the console and then see + the whole chat while being in the lobby. + type: Fix + id: 7651 + time: '2024-11-25T07:20:32.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/33529 From 32f48d974f4fc446ce175b1b01afc3df63b64fe5 Mon Sep 17 00:00:00 2001 From: Ben Date: Mon, 25 Nov 2024 06:39:10 -0500 Subject: [PATCH 46/59] removed obsolete netmessage creator (#33542) removed opsolete netmessage createor --- Content.Client/Eui/BaseEui.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Content.Client/Eui/BaseEui.cs b/Content.Client/Eui/BaseEui.cs index 7f86ded7e4..c11ba5a9b6 100644 --- a/Content.Client/Eui/BaseEui.cs +++ b/Content.Client/Eui/BaseEui.cs @@ -55,7 +55,7 @@ namespace Content.Client.Eui /// protected void SendMessage(EuiMessageBase msg) { - var netMsg = _netManager.CreateNetMessage(); + var netMsg = new MsgEuiMessage(); netMsg.Id = Id; netMsg.Message = msg; From ea7f5433ac4728a7e00c68b151d1cf2f4d965150 Mon Sep 17 00:00:00 2001 From: Nikolai Korolev Date: Mon, 25 Nov 2024 11:53:12 +0000 Subject: [PATCH 47/59] Fix RA0003 warning for ChatBox (#33531) --- .../UserInterface/Systems/Chat/Widgets/ChatBox.xaml.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Content.Client/UserInterface/Systems/Chat/Widgets/ChatBox.xaml.cs b/Content.Client/UserInterface/Systems/Chat/Widgets/ChatBox.xaml.cs index 0696ae9d3f..62b3b19e38 100644 --- a/Content.Client/UserInterface/Systems/Chat/Widgets/ChatBox.xaml.cs +++ b/Content.Client/UserInterface/Systems/Chat/Widgets/ChatBox.xaml.cs @@ -16,9 +16,8 @@ using static Robust.Client.UserInterface.Controls.LineEdit; namespace Content.Client.UserInterface.Systems.Chat.Widgets; [GenerateTypedNameReferences] -#pragma warning disable RA0003 +[Virtual] public partial class ChatBox : UIWidget -#pragma warning restore RA0003 { private readonly ChatUIController _controller; private readonly IEntityManager _entManager; From 45cf4ec3400dfe82e47d3746e695248b8a6f3163 Mon Sep 17 00:00:00 2001 From: Minemoder5000 Date: Mon, 25 Nov 2024 05:23:57 -0700 Subject: [PATCH 48/59] Shark plushies now goes rawr on hit. (#33540) Shark goes rawr more --- Resources/Prototypes/Entities/Objects/Fun/toys.yml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Resources/Prototypes/Entities/Objects/Fun/toys.yml b/Resources/Prototypes/Entities/Objects/Fun/toys.yml index d774c4469c..eddf92c5ae 100644 --- a/Resources/Prototypes/Entities/Objects/Fun/toys.yml +++ b/Resources/Prototypes/Entities/Objects/Fun/toys.yml @@ -498,12 +498,22 @@ - type: Sprite sprite: Objects/Fun/sharkplush.rsi state: blue + - type: EmitSoundOnLand + sound: + path: /Audio/Items/Toys/rawr.ogg + - type: EmitSoundOnTrigger + sound: + path: /Audio/Items/Toys/rawr.ogg - type: EmitSoundOnUse sound: path: /Audio/Items/Toys/rawr.ogg - type: EmitSoundOnActivate sound: path: /Audio/Items/Toys/rawr.ogg + - type: MeleeWeapon + wideAnimationRotation: 180 + soundHit: + path: /Audio/Items/Toys/rawr.ogg - type: Item heldPrefix: blue storedRotation: -90 From ae576abe1fd64ab596c51264c8cded1181236977 Mon Sep 17 00:00:00 2001 From: PJBot Date: Mon, 25 Nov 2024 12:25:04 +0000 Subject: [PATCH 49/59] Automatic changelog update --- Resources/Changelog/Changelog.yml | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index ded4cc512d..d80ebb9cc7 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,16 +1,4 @@ Entries: -- author: to4no_fix - changes: - - message: Now it takes 5 seconds to take off or put on a muzzle - type: Tweak - - message: Now it takes 5 seconds to take off or put on a blindfold - type: Tweak - - message: Added a recipe for producing a straitjacket, it opens when researching - the Special Means technology, it can be produced at the security techfab - type: Add - id: 7152 - time: '2024-08-19T03:05:25.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/31095 - author: Magicalus changes: - message: Suit sensors, borgs, and PDAs can no longer be saved to device-lists. @@ -3928,3 +3916,10 @@ id: 7651 time: '2024-11-25T07:20:32.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/33529 +- author: Minemoder + changes: + - message: The shark plushie now goes rawr when hitting something or being thrown. + type: Tweak + id: 7652 + time: '2024-11-25T12:23:57.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/33540 From 49724a9b9d48421f88d7785b972ed27ba01f4d89 Mon Sep 17 00:00:00 2001 From: Niels Huylebroeck Date: Mon, 25 Nov 2024 13:35:14 +0100 Subject: [PATCH 50/59] Turn off PointLights on VendingMachines when broken or off. (#33513) The light itself should already turn off due to `LitOnPowered` component, but the broken state of a VendingMachine did not. Fixes #33382 --- Content.Server/VendingMachines/VendingMachineSystem.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Content.Server/VendingMachines/VendingMachineSystem.cs b/Content.Server/VendingMachines/VendingMachineSystem.cs index 90fe4cb7d8..c20a6a4644 100644 --- a/Content.Server/VendingMachines/VendingMachineSystem.cs +++ b/Content.Server/VendingMachines/VendingMachineSystem.cs @@ -38,6 +38,7 @@ namespace Content.Server.VendingMachines [Dependency] private readonly ThrowingSystem _throwingSystem = default!; [Dependency] private readonly IGameTiming _timing = default!; [Dependency] private readonly SpeakOnUIClosedSystem _speakOnUIClosed = default!; + [Dependency] private readonly SharedPointLightSystem _light = default!; private const float WallVendEjectDistanceFromWall = 1f; @@ -334,6 +335,12 @@ namespace Content.Server.VendingMachines finalState = VendingMachineVisualState.Off; } + if (_light.TryGetLight(uid, out var pointlight)) + { + var lightState = finalState != VendingMachineVisualState.Broken && finalState != VendingMachineVisualState.Off; + _light.SetEnabled(uid, lightState, pointlight); + } + _appearanceSystem.SetData(uid, VendingMachineVisuals.VisualState, finalState); } From b8466d83215a5bb0acd4cbf268f975d204f0330c Mon Sep 17 00:00:00 2001 From: PJBot Date: Mon, 25 Nov 2024 12:36:20 +0000 Subject: [PATCH 51/59] Automatic changelog update --- Resources/Changelog/Changelog.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index d80ebb9cc7..511e076e57 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,11 +1,4 @@ Entries: -- author: Magicalus - changes: - - message: Suit sensors, borgs, and PDAs can no longer be saved to device-lists. - type: Tweak - id: 7153 - time: '2024-08-19T03:13:04.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/30997 - author: UBlueberry changes: - message: The guidebook entries for all antagonists have been revised. @@ -3923,3 +3916,10 @@ id: 7652 time: '2024-11-25T12:23:57.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/33540 +- author: red15 + changes: + - message: Vending machine lights turns off when broken. + type: Fix + id: 7653 + time: '2024-11-25T12:35:14.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/33513 From b8c8f7d0f8bbf40fc235520e7a18b578a09583f1 Mon Sep 17 00:00:00 2001 From: Flareguy <78941145+Flareguy@users.noreply.github.com> Date: Mon, 25 Nov 2024 07:51:41 -0600 Subject: [PATCH 52/59] Adds more diona names (#33066) * adds more diona names * more stuff * AHHHHHHHHHHHHHHHHHHHHHHH * further additions * removes depression + adds comment * fixes + remove some weird stuff + more stuff * remove haste --- Resources/Prototypes/Datasets/Names/diona.yml | 177 +++++++++++++++++- 1 file changed, 175 insertions(+), 2 deletions(-) diff --git a/Resources/Prototypes/Datasets/Names/diona.yml b/Resources/Prototypes/Datasets/Names/diona.yml index a4808d8c5d..794e7dcc0c 100644 --- a/Resources/Prototypes/Datasets/Names/diona.yml +++ b/Resources/Prototypes/Datasets/Names/diona.yml @@ -7,11 +7,28 @@ - Ivy - Stalk - Petal + - Petals - Thorn + - Thorns + - Vine + - Vines + - Branch + - Branches + - Weed + - Weeds - Rose - Dandelion + - Lilac + - Lily - Birch + - Oak + - Spruce - Willow + - Cyprus + - Mangrove + - Stump + - Sap + - Bayou - Bay - Lake - River @@ -21,12 +38,64 @@ - Mountain - Peak - Garden + - Ocean + - Arctic + - Sea + - Lake + - Spring + - Swamp + - River + - Stream + - Forest + - Rainforest - Soil + - Valley + - Moor + - Steppe + - Orchard + - Orchid + - Glacier + - Desert + - Tundra + - Taiga + - Plain + - Plains + - Plateau + - Cliff + - Coast + - Shore + - Jungle + - Tropics - Flower - + - Grass + - Bark + - Autumn + - Summer + - Winter + - Fruit + - Leaves + - Overgrowth + - Atmosphere + - Climate + - Chill + - Winds + - Blossom + - Bloom + - Cap + - Saturation + - Permeation + - Light + - Taste + - Acorn + - Shell + - Ice + - Monsoon + - Overcast + - Storm - type: dataset id: DionaLast values: +# Positive - Peace - Harmony - Relaxation @@ -47,4 +116,108 @@ - Ease - Equilibrium - Composure - - Control \ No newline at end of file + - Control + - Bliss + - Enjoyment + - Optimism + - Ecstasy + - Cheer + - Delight + - Luxury + - Euphoria + - Excitement + - Satisfaction + - Cleanliness + - Expression + - Enrichment + - Enthusiam + - Brilliance + - Determination + - Integrity + - Justice + - Kindness + - Bravery + - Empathy + - Stoicism + - Competence + - Love + - Hope + - Honesty + - Generosity + - Oppritunity + - Motivation +# Neutral + - Urgency + - Vitality + - Hardiness + - Vigor + - Agility + - Dexterity + - Perception + - Wisdom + - Charisma + - Persistence + - Perseverance + - Density + - Strength + - Congestion + - Concentration + - Intensity + - Refinement + - Obscurity + - Fortitude + - Endurance + - Patience + - Passivity + - Indifference + - Sleepiness + - Neutrality + - Fairness + - Silliness + - Restraint + - Silence + - Bewilderment + - Tactility + - Invisibility + - Darkness + - Fragility + - Action + - Awakening + - Activity + - Audacity + - Vivacity + - Knowledge + - Modification +# Negative +# These should be something a diona would still realistically name themselves, i.e not inherintly self deprecating. + - Envy + - Ineptitude + - Ignorance + - Decay + - Lethargy + - Bitterness + - Acidity + - Illness + - Weakness + - Enervation + - Fatigue + - Noxiousness + - Convlution + - Confusion + - Agitation + - Despair + - Sorrow + - Pain + - Animosity + - Fury + - Disinterest + - Anger + - Rage + - Displeasure + - Irritation + - Resentment + - Soreness + - Frustration + - Insanity + - Chaos + - Fear \ No newline at end of file From e9eca826d8d46fdfc0f8ba4a5e92486163ae10ba Mon Sep 17 00:00:00 2001 From: slarticodefast <161409025+slarticodefast@users.noreply.github.com> Date: Mon, 25 Nov 2024 23:39:04 +0100 Subject: [PATCH 53/59] minor AI cleanup (#33555) * minor cleanup * to --- .../Silicons/StationAi/SharedStationAiSystem.Airlock.cs | 4 ++-- Content.Shared/Silicons/StationAi/SharedStationAiSystem.cs | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/Content.Shared/Silicons/StationAi/SharedStationAiSystem.Airlock.cs b/Content.Shared/Silicons/StationAi/SharedStationAiSystem.Airlock.cs index 37e5cd6e6a..ca2d593dbe 100644 --- a/Content.Shared/Silicons/StationAi/SharedStationAiSystem.Airlock.cs +++ b/Content.Shared/Silicons/StationAi/SharedStationAiSystem.Airlock.cs @@ -34,7 +34,7 @@ public abstract partial class SharedStationAiSystem } /// - /// Attempts to bolt door. If wire was cut (AI) or its not powered - notifies AI and does nothing. + /// Attempts to toggle the door's emergency access. If wire was cut (AI) or its not powered - notifies AI and does nothing. /// private void OnAirlockEmergencyAccess(EntityUid ent, AirlockComponent component, StationAiEmergencyAccessEvent args) { @@ -48,7 +48,7 @@ public abstract partial class SharedStationAiSystem } /// - /// Attempts to bolt door. If wire was cut (AI or for one of power-wires) or its not powered - notifies AI and does nothing. + /// Attempts to electrify the door. If wire was cut (AI or for one of power-wires) or its not powered - notifies AI and does nothing. /// private void OnElectrified(EntityUid ent, ElectrifiedComponent component, StationAiElectrifiedEvent args) { diff --git a/Content.Shared/Silicons/StationAi/SharedStationAiSystem.cs b/Content.Shared/Silicons/StationAi/SharedStationAiSystem.cs index 189515635a..5fca5cad28 100644 --- a/Content.Shared/Silicons/StationAi/SharedStationAiSystem.cs +++ b/Content.Shared/Silicons/StationAi/SharedStationAiSystem.cs @@ -394,6 +394,9 @@ public abstract partial class SharedStationAiSystem : EntitySystem private void OnAiInsert(Entity ent, ref EntInsertedIntoContainerMessage args) { + if (args.Container.ID != StationAiCoreComponent.Container) + return; + if (_timing.ApplyingState) return; From f27fa1ed30920581c6322d08867cb3334f897589 Mon Sep 17 00:00:00 2001 From: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com> Date: Tue, 26 Nov 2024 11:59:34 +1100 Subject: [PATCH 54/59] Simplify separated screen top menu (#33047) --- .../MenuBar/Widgets/GameTopMenuBar.xaml | 29 +++++++++++-------- 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/Content.Client/UserInterface/Systems/MenuBar/Widgets/GameTopMenuBar.xaml b/Content.Client/UserInterface/Systems/MenuBar/Widgets/GameTopMenuBar.xaml index dc8972970a..5368d5d872 100644 --- a/Content.Client/UserInterface/Systems/MenuBar/Widgets/GameTopMenuBar.xaml +++ b/Content.Client/UserInterface/Systems/MenuBar/Widgets/GameTopMenuBar.xaml @@ -11,17 +11,21 @@ Orientation="Horizontal" HorizontalAlignment="Stretch" VerticalAlignment="Top" - SeparationOverride="5" > + @@ -39,7 +43,7 @@ Icon="{xe:Tex '/Textures/Interface/character.svg.192dpi.png'}" ToolTip="{Loc 'game-hud-open-character-menu-button-tooltip'}" BoundKey = "{x:Static is:ContentKeyFunctions.OpenCharacterMenu}" - MinSize="42 64" + MinSize="48 64" HorizontalExpand="True" AppendStyleClass="{x:Static style:StyleBase.ButtonSquare}" /> @@ -49,7 +53,7 @@ Icon="{xe:Tex '/Textures/Interface/emotes.svg.192dpi.png'}" ToolTip="{Loc 'game-hud-open-emotes-menu-button-tooltip'}" BoundKey = "{x:Static is:ContentKeyFunctions.OpenEmotesMenu}" - MinSize="42 64" + MinSize="48 64" HorizontalExpand="True" AppendStyleClass="{x:Static style:StyleBase.ButtonSquare}" /> @@ -59,7 +63,7 @@ Icon="{xe:Tex '/Textures/Interface/hammer.svg.192dpi.png'}" BoundKey = "{x:Static is:ContentKeyFunctions.OpenCraftingMenu}" ToolTip="{Loc 'game-hud-open-crafting-menu-button-tooltip'}" - MinSize="42 64" + MinSize="48 64" HorizontalExpand="True" AppendStyleClass="{x:Static style:StyleBase.ButtonSquare}" /> @@ -69,7 +73,7 @@ Icon="{xe:Tex '/Textures/Interface/fist.svg.192dpi.png'}" BoundKey = "{x:Static is:ContentKeyFunctions.OpenActionsMenu}" ToolTip="{Loc 'game-hud-open-actions-menu-button-tooltip'}" - MinSize="42 64" + MinSize="48 64" HorizontalExpand="True" AppendStyleClass="{x:Static style:StyleBase.ButtonSquare}" /> @@ -79,7 +83,7 @@ Icon="{xe:Tex '/Textures/Interface/gavel.svg.192dpi.png'}" BoundKey = "{x:Static is:ContentKeyFunctions.OpenAdminMenu}" ToolTip="{Loc 'game-hud-open-admin-menu-button-tooltip'}" - MinSize="42 64" + MinSize="48 64" HorizontalExpand="True" AppendStyleClass="{x:Static style:StyleBase.ButtonSquare}" /> @@ -89,7 +93,7 @@ Icon="{xe:Tex '/Textures/Interface/sandbox.svg.192dpi.png'}" BoundKey = "{x:Static is:ContentKeyFunctions.OpenSandboxWindow}" ToolTip="{Loc 'game-hud-open-sandbox-menu-button-tooltip'}" - MinSize="42 64" + MinSize="48 64" HorizontalExpand="True" AppendStyleClass="{x:Static style:StyleBase.ButtonSquare}" /> @@ -99,8 +103,9 @@ Icon="{xe:Tex '/Textures/Interface/info.svg.192dpi.png'}" BoundKey = "{x:Static is:ContentKeyFunctions.OpenAHelp}" ToolTip="{Loc 'ui-options-function-open-a-help'}" - MinSize="42 64" + MinSize="48 64" HorizontalExpand="True" - AppendStyleClass="{x:Static style:StyleBase.ButtonOpenLeft}" + AppendStyleClass="{x:Static style:StyleBase.ButtonSquare}" /> + From a69fc39fc0c75fed46b1ba83270bbc91afa5a24e Mon Sep 17 00:00:00 2001 From: PJBot Date: Tue, 26 Nov 2024 01:00:41 +0000 Subject: [PATCH 55/59] Automatic changelog update --- Resources/Changelog/Changelog.yml | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index 511e076e57..57239e0b38 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,11 +1,4 @@ Entries: -- author: UBlueberry - changes: - - message: The guidebook entries for all antagonists have been revised. - type: Tweak - id: 7154 - time: '2024-08-19T03:16:05.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/31075 - author: TheWaffleJesus changes: - message: ERT Chaplains now have blessings to use their bible. @@ -3923,3 +3916,11 @@ id: 7653 time: '2024-11-25T12:35:14.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/33513 +- author: metalgearsloth + changes: + - message: Adjusted the top menu on the separated game screen. The buttons will + now form multiple rows and no longer overflow into the viewport. + type: Tweak + id: 7654 + time: '2024-11-26T00:59:35.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/33047 From d5225d1f46f4a6701947c0ead72fd82da44eff13 Mon Sep 17 00:00:00 2001 From: Intoxicating-Innocence <188202277+Intoxicating-Innocence@users.noreply.github.com> Date: Tue, 26 Nov 2024 19:28:31 +1100 Subject: [PATCH 56/59] Ghost role drop-down alignment (#33397) * dropdown shares margin width with children * removed dependency that rider added for some reason * reduced vertical margin from 8 to 2 --- .../Systems/Ghost/Controls/Roles/GhostRolesWindow.xaml.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/Content.Client/UserInterface/Systems/Ghost/Controls/Roles/GhostRolesWindow.xaml.cs b/Content.Client/UserInterface/Systems/Ghost/Controls/Roles/GhostRolesWindow.xaml.cs index 627ecfe987..9e2ff816b3 100644 --- a/Content.Client/UserInterface/Systems/Ghost/Controls/Roles/GhostRolesWindow.xaml.cs +++ b/Content.Client/UserInterface/Systems/Ghost/Controls/Roles/GhostRolesWindow.xaml.cs @@ -71,6 +71,7 @@ namespace Content.Client.UserInterface.Systems.Ghost.Controls.Roles buttonHeading.AddStyleClass(ContainerButton.StyleClassButton); buttonHeading.Label.HorizontalAlignment = HAlignment.Center; buttonHeading.Label.HorizontalExpand = true; + buttonHeading.Margin = new Thickness(8, 0, 8, 2); var body = new CollapsibleBody { From 470c869ce2cd14136662b1895f2a8e31e68f6f6c Mon Sep 17 00:00:00 2001 From: slarticodefast <161409025+slarticodefast@users.noreply.github.com> Date: Tue, 26 Nov 2024 14:50:20 +0100 Subject: [PATCH 57/59] Greytide Virus station event (#33547) * proof of concept * full implementation * I commited a crime * t * min players increase --- .../Components/GreytideVirusComponent.cs | 38 ++++++++ .../StationEvents/Events/GreytideVirusRule.cs | 96 +++++++++++++++++++ .../Doors/Systems/SharedDoorSystem.cs | 19 ++++ .../station-events/events/greytide-virus.ftl | 1 + Resources/Prototypes/GameRules/events.yml | 22 +++++ 5 files changed, 176 insertions(+) create mode 100644 Content.Server/StationEvents/Components/GreytideVirusComponent.cs create mode 100644 Content.Server/StationEvents/Events/GreytideVirusRule.cs create mode 100644 Resources/Locale/en-US/station-events/events/greytide-virus.ftl diff --git a/Content.Server/StationEvents/Components/GreytideVirusComponent.cs b/Content.Server/StationEvents/Components/GreytideVirusComponent.cs new file mode 100644 index 0000000000..307f131db1 --- /dev/null +++ b/Content.Server/StationEvents/Components/GreytideVirusComponent.cs @@ -0,0 +1,38 @@ +using Content.Server.StationEvents.Events; +using Content.Shared.Access; +using Content.Shared.Destructible.Thresholds; +using Robust.Shared.Prototypes; + +namespace Content.Server.StationEvents.Components; + +/// +/// Greytide Virus event specific configuration +/// +[RegisterComponent, Access(typeof(GreytideVirusRule))] +public sealed partial class GreytideVirusRuleComponent : Component +{ + /// + /// Range from which the severity is randomly picked from. + /// + [DataField] + public MinMax SeverityRange = new(1, 3); + + /// + /// Severity corresponding to the number of access groups affected. + /// Will pick randomly from the SeverityRange if not specified. + /// + [DataField] + public int? Severity; + + /// + /// Access groups to pick from. + /// + [DataField] + public List> AccessGroups = new(); + + /// + /// Entities with this access level will be ignored. + /// + [DataField] + public List> Blacklist = new(); +} diff --git a/Content.Server/StationEvents/Events/GreytideVirusRule.cs b/Content.Server/StationEvents/Events/GreytideVirusRule.cs new file mode 100644 index 0000000000..f60d80ba9c --- /dev/null +++ b/Content.Server/StationEvents/Events/GreytideVirusRule.cs @@ -0,0 +1,96 @@ +using Content.Server.StationEvents.Components; +using Content.Shared.Access; +using Content.Shared.Access.Systems; +using Content.Shared.Access.Components; +using Content.Shared.Doors.Components; +using Content.Shared.Doors.Systems; +using Content.Shared.Lock; +using Content.Shared.GameTicking.Components; +using Robust.Shared.Prototypes; +using Robust.Shared.Random; + +namespace Content.Server.StationEvents.Events; + + +/// +/// Greytide Virus event +/// This will open and bolt airlocks and unlock lockers from randomly selected access groups. +/// +public sealed class GreytideVirusRule : StationEventSystem +{ + [Dependency] private readonly AccessReaderSystem _access = default!; + [Dependency] private readonly SharedDoorSystem _door = default!; + [Dependency] private readonly LockSystem _lock = default!; + [Dependency] private readonly IPrototypeManager _prototype = default!; + [Dependency] private readonly IRobustRandom _random = default!; + + protected override void Added(EntityUid uid, GreytideVirusRuleComponent virusComp, GameRuleComponent gameRule, GameRuleAddedEvent args) + { + if (!TryComp(uid, out var stationEvent)) + return; + + // pick severity randomly from range if not specified otherwise + virusComp.Severity ??= virusComp.SeverityRange.Next(_random); + virusComp.Severity = Math.Min(virusComp.Severity.Value, virusComp.AccessGroups.Count); + + stationEvent.StartAnnouncement = Loc.GetString("station-event-greytide-virus-start-announcement", ("severity", virusComp.Severity.Value)); + base.Added(uid, virusComp, gameRule, args); + } + protected override void Started(EntityUid uid, GreytideVirusRuleComponent virusComp, GameRuleComponent gameRule, GameRuleStartedEvent args) + { + base.Started(uid, virusComp, gameRule, args); + + if (virusComp.Severity == null) + return; + + // pick random access groups + var chosen = _random.GetItems(virusComp.AccessGroups, virusComp.Severity.Value, allowDuplicates: false); + + // combine all the selected access groups + var accessIds = new HashSet>(); + foreach (var group in chosen) + { + if (_prototype.TryIndex(group, out var proto)) + accessIds.UnionWith(proto.Tags); + } + + var firelockQuery = GetEntityQuery(); + var accessQuery = GetEntityQuery(); + + var lockQuery = AllEntityQuery(); + while (lockQuery.MoveNext(out var lockUid, out var lockComp)) + { + if (!accessQuery.TryComp(lockUid, out var accessComp)) + continue; + + // check access + // the AreAccessTagsAllowed function is a little weird because it technically has support for certain tags to be locked out of opening something + // which might have unintened side effects (see the comments in the function itself) + // but no one uses that yet, so it is fine for now + if (!_access.AreAccessTagsAllowed(accessIds, accessComp) || _access.AreAccessTagsAllowed(virusComp.Blacklist, accessComp)) + continue; + + // open lockers + _lock.Unlock(lockUid, null, lockComp); + } + + var airlockQuery = AllEntityQuery(); + while (airlockQuery.MoveNext(out var airlockUid, out var airlockComp, out var doorComp)) + { + // don't space everything + if (firelockQuery.HasComp(airlockUid)) + continue; + + // use the access reader from the door electronics if they exist + if (!_access.GetMainAccessReader(airlockUid, out var accessComp)) + continue; + + // check access + if (!_access.AreAccessTagsAllowed(accessIds, accessComp) || _access.AreAccessTagsAllowed(virusComp.Blacklist, accessComp)) + continue; + + // open and bolt airlocks + _door.TryOpenAndBolt(airlockUid, doorComp, airlockComp); + } + } +} diff --git a/Content.Shared/Doors/Systems/SharedDoorSystem.cs b/Content.Shared/Doors/Systems/SharedDoorSystem.cs index 835adb31c0..69905d1bd6 100644 --- a/Content.Shared/Doors/Systems/SharedDoorSystem.cs +++ b/Content.Shared/Doors/Systems/SharedDoorSystem.cs @@ -396,6 +396,25 @@ public abstract partial class SharedDoorSystem : EntitySystem Dirty(uid, door); } + + /// + /// Opens and then bolts a door. + /// Different from emagging this does not remove the access reader, so it can be repaired by simply unbolting the door. + /// + public bool TryOpenAndBolt(EntityUid uid, DoorComponent? door = null, AirlockComponent? airlock = null) + { + if (!Resolve(uid, ref door, ref airlock)) + return false; + + if (IsBolted(uid) || !airlock.Powered || door.State != DoorState.Closed) + { + return false; + } + + SetState(uid, DoorState.Emagging, door); + + return true; + } #endregion #region Closing diff --git a/Resources/Locale/en-US/station-events/events/greytide-virus.ftl b/Resources/Locale/en-US/station-events/events/greytide-virus.ftl new file mode 100644 index 0000000000..7e6f5e32ca --- /dev/null +++ b/Resources/Locale/en-US/station-events/events/greytide-virus.ftl @@ -0,0 +1 @@ +station-event-greytide-virus-start-announcement = Gr3y.T1d3 virus detected in the station's secure locking encryption subroutines. Severity level of { $severity }. Recommend station AI involvement. diff --git a/Resources/Prototypes/GameRules/events.yml b/Resources/Prototypes/GameRules/events.yml index 08218acced..98b6690ebb 100644 --- a/Resources/Prototypes/GameRules/events.yml +++ b/Resources/Prototypes/GameRules/events.yml @@ -10,6 +10,7 @@ - id: ClericalError - id: CockroachMigration - id: GasLeak + - id: GreytideVirus - id: IonStorm # its calm like 90% of the time smh - id: KudzuGrowth - id: MassHallucinations @@ -540,3 +541,24 @@ maxOccurrences: 1 # this event has diminishing returns on interesting-ness, so we cap it weight: 5 - type: MobReplacementRule + +- type: entity + id: GreytideVirus + parent: BaseStationEventShortDelay + components: + - type: StationEvent + startAudio: + path: /Audio/Announcements/attention.ogg + weight: 5 + minimumPlayers: 25 + reoccurrenceDelay: 20 + - type: GreytideVirusRule + accessGroups: + - Cargo + - Command + - Engineering + - Research + - Security + - Service + blacklist: + - External # don't space everything From 41d2cf166d5d1e8ba6c8d7937391dca7955ef820 Mon Sep 17 00:00:00 2001 From: Winkarst <74284083+Winkarst-cpu@users.noreply.github.com> Date: Tue, 26 Nov 2024 16:51:13 +0300 Subject: [PATCH 58/59] Make shuttle airlocks not snapcardinals (#33557) * Make shuttle airlocks not snapcardinals * Update Resources/Prototypes/Entities/Structures/Doors/Airlocks/shuttle.yml Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com> * Update Resources/Prototypes/Entities/Structures/Doors/Airlocks/shuttle.yml Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com> --------- Co-authored-by: Winkarst <74284083+Winkarst-cpu@users.noreply.github.co> Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com> --- .../Prototypes/Entities/Structures/Doors/Airlocks/shuttle.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Resources/Prototypes/Entities/Structures/Doors/Airlocks/shuttle.yml b/Resources/Prototypes/Entities/Structures/Doors/Airlocks/shuttle.yml index 630027384c..3752821e46 100644 --- a/Resources/Prototypes/Entities/Structures/Doors/Airlocks/shuttle.yml +++ b/Resources/Prototypes/Entities/Structures/Doors/Airlocks/shuttle.yml @@ -30,6 +30,7 @@ hard: false - type: Sprite sprite: Structures/Doors/Airlocks/Standard/shuttle.rsi + snapCardinals: false - type: Wires layoutId: Docking - type: Door @@ -95,6 +96,7 @@ - type: Sprite sprite: Structures/Doors/Airlocks/Glass/shuttle.rsi state: closed + snapCardinals: false - type: Construction graph: AirlockShuttle node: assembly From dfc3562bfc4895bdf1860ef6950d9907d8cfbbf8 Mon Sep 17 00:00:00 2001 From: PJBot Date: Tue, 26 Nov 2024 13:51:29 +0000 Subject: [PATCH 59/59] Automatic changelog update --- Resources/Changelog/Changelog.yml | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index 57239e0b38..1e2be75b29 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,11 +1,4 @@ Entries: -- author: TheWaffleJesus - changes: - - message: ERT Chaplains now have blessings to use their bible. - type: Fix - id: 7155 - time: '2024-08-19T03:19:19.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/30993 - author: DieselMohawk changes: - message: Reshaped the Security Helmet @@ -3924,3 +3917,12 @@ id: 7654 time: '2024-11-26T00:59:35.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/33047 +- author: slarticodefast + changes: + - message: Added the greytide virus station event. It will bolt open all doors in + a few randomly chosen departments and unlock lockers with the corresponding + access. + type: Add + id: 7655 + time: '2024-11-26T13:50:20.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/33547