From 64689b4cc81bc466395e935e8f143930703dc98e Mon Sep 17 00:00:00 2001 From: Leon Friedrich <60421075+ElectroJr@users.noreply.github.com> Date: Mon, 20 Jan 2025 10:59:42 +1100 Subject: [PATCH 01/15] Fix `emergency_elkridge` being saved as a map (#34496) Save `emergency_elkridge` as a grid (cherry picked from commit ef50219455f19f3139bebfe3ba233658b83cc096) --- Resources/Maps/Shuttles/emergency_elkridge.yml | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/Resources/Maps/Shuttles/emergency_elkridge.yml b/Resources/Maps/Shuttles/emergency_elkridge.yml index efeba6844b..4dafdee84a 100644 --- a/Resources/Maps/Shuttles/emergency_elkridge.yml +++ b/Resources/Maps/Shuttles/emergency_elkridge.yml @@ -18,7 +18,7 @@ entities: name: NT Evac Log - type: Transform pos: -0.42093527,-0.86894274 - parent: 637 + parent: invalid - type: MapGrid chunks: 0,0: @@ -804,18 +804,6 @@ entities: chunkSize: 4 - type: GasTileOverlay - type: RadiationGridResistance - - uid: 637 - components: - - type: MetaData - name: Map Entity - - type: Transform - - type: Map - mapPaused: True - - type: PhysicsMap - - type: GridTree - - type: MovedGrids - - type: Broadphase - - type: OccluderTree - proto: AirAlarm entities: - uid: 577 From 6361a121d52a75b0dae737e4839479fd0b4810de Mon Sep 17 00:00:00 2001 From: Southbridge <7013162+southbridge-fur@users.noreply.github.com> Date: Mon, 20 Jan 2025 05:10:51 -0500 Subject: [PATCH 02/15] Plasma Dirt Fix (#34534) did the dirt thing --- Resources/Maps/plasma.yml | 29 +++++++++-------------------- 1 file changed, 9 insertions(+), 20 deletions(-) diff --git a/Resources/Maps/plasma.yml b/Resources/Maps/plasma.yml index e2be97d6f4..b5b2c2ee6c 100644 --- a/Resources/Maps/plasma.yml +++ b/Resources/Maps/plasma.yml @@ -2210,6 +2210,8 @@ entities: 713: -32,-30 714: -31,-19 - node: + cleanable: True + zIndex: 1 color: '#FFFFFFFF' id: Dirt decals: @@ -2226,11 +2228,6 @@ entities: 6708: -71,-37 6709: -70,-36 6710: -68,-36 - - node: - cleanable: True - color: '#FFFFFFFF' - id: Dirt - decals: 5206: -56,-54 5207: -55,-55 5208: -55,-54 @@ -2293,6 +2290,8 @@ entities: 7242: -21,19 7243: -22,20 - node: + cleanable: True + zIndex: 1 color: '#FFFFFFFF' id: DirtHeavy decals: @@ -2305,11 +2304,6 @@ entities: 6083: -21,5 6084: -21,4 6085: -22,4 - - node: - cleanable: True - color: '#FFFFFFFF' - id: DirtHeavy - decals: 329: -54,-11 330: -50,-11 1572: -65,-34 @@ -2365,11 +2359,14 @@ entities: 4063: -98,-18 - node: cleanable: True + zIndex: 1 color: '#FFFFFFFF' id: DirtHeavyMonotile decals: 1579: -66,-34 - node: + cleanable: True + zIndex: 1 color: '#FFFFFFFF' id: DirtLight decals: @@ -2389,11 +2386,6 @@ entities: 6713: -71,-32 6714: -71,-31 6715: -71,-30 - - node: - cleanable: True - color: '#FFFFFFFF' - id: DirtLight - decals: 1580: -64,-33 1581: -65,-33 1582: -64,-32 @@ -2490,6 +2482,8 @@ entities: 6921: -153,-44 6922: -145,-45 - node: + cleanable: True + zIndex: 1 color: '#FFFFFFFF' id: DirtMedium decals: @@ -2652,11 +2646,6 @@ entities: 7221: -121,34 7222: -122,34 7223: -122,33 - - node: - cleanable: True - color: '#FFFFFFFF' - id: DirtMedium - decals: 331: -54,-10 332: -51,-10 333: -52,-10 From 671ab10be219a7f02ca60600b22e9ec7299b3c7c Mon Sep 17 00:00:00 2001 From: Errant <35878406+Errant-4@users.noreply.github.com> Date: Mon, 20 Jan 2025 23:30:00 +0100 Subject: [PATCH 03/15] [HOTFIX] Admin Menu player jobs (#34545) update job info on spawn --- Content.Server/GameTicking/GameTicker.Spawning.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Content.Server/GameTicking/GameTicker.Spawning.cs b/Content.Server/GameTicking/GameTicker.Spawning.cs index 605e252080..f6bf7c635e 100644 --- a/Content.Server/GameTicking/GameTicker.Spawning.cs +++ b/Content.Server/GameTicking/GameTicker.Spawning.cs @@ -2,6 +2,7 @@ using System.Globalization; using System.Linq; using System.Numerics; using Content.Server.Administration.Managers; +using Content.Server.Administration.Systems; using Content.Server.GameTicking.Events; using Content.Server.Spawners.Components; using Content.Server.Speech.Components; @@ -27,6 +28,7 @@ namespace Content.Server.GameTicking { [Dependency] private readonly IAdminManager _adminManager = default!; [Dependency] private readonly SharedJobSystem _jobs = default!; + [Dependency] private readonly AdminSystem _admin = default!; [ValidatePrototypeId] public const string ObserverPrototypeName = "MobObserver"; @@ -233,6 +235,7 @@ namespace Content.Server.GameTicking _roles.MindAddJobRole(newMind, silent: silent, jobPrototype:jobId); var jobName = _jobs.MindTryGetJobName(newMind); + _admin.UpdatePlayerList(player); if (lateJoin && !silent) { From 04c081719a3d54c2824e2c4dcceff9ce5097958e Mon Sep 17 00:00:00 2001 From: compilatron <40789662+Compilatron144@users.noreply.github.com> Date: Tue, 21 Jan 2025 15:56:47 +1100 Subject: [PATCH 04/15] Plasma station population tweak (#34549) * Plasma Station initial commit * Map fixes 1 Expanded science's SMES array Added advanced SMES Redone stamped documents with custom stamps Expanded atmospherics with more storage tanks Added status displays Add missing beacons to solars Replaced the passive gates in science with valves Removed protolathe in engineering Added guitar to CE office Replaced throngler plushie with weh cloak Add a lattice tile outside the atmos burn chamber and storange tanks Added atmos network monitor in bridge * Add cargo and emergency shuttle * Updated maps * Add plasma to map testing list * Map fixes 2 Reworked pipenets to not go under walls Redid salvage and disposals Reworked the bar to include a new bar extension facing the pool Replaced arrivals cryo with an arcade Replaced the toilets in the service plaza with cryo Removed the cryo in dorms Added more details to hallways Redid tools room to include a front desk for the janitor closet Reconnected sci to power roundstart Removed some unideal spawns Expanded the TEG airlock to be 2x3 instead of 1x3 Reduced the size of the SMES bank from 10 to 6 Disabled the plasma miners (downstreams or admins can re-enable them) Replaced illegal maint items * Fixes a 6 pack destroying the universe Ok maybe cracking a cold one with the boys wasn't a great idea. * Map fixes 3 * Quick research assistant fix * Map fixes 4 * Map fixes 5 * webedit go brrrt * Map fixes 6 * Map fixes 7 * Map fixes 8 * Fixes non-existent object It's amazing this game runs at all * Map fixes 9 * update pools * Map fixes 10 * forgot to clear my multitool I love mapping I love mapping I love mapping I love mapping I love mapping * Tweaked player counts * Update population caps Removed population cap of 60 players to make plasma into a highpop map - it's that easy! --------- Co-authored-by: jbox1 <40789662+jbox144@users.noreply.github.com> Co-authored-by: Emisse <99158783+Emisse@users.noreply.github.com> --- Resources/Prototypes/Maps/plasma.yml | 36 ++++++++++++++-------------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/Resources/Prototypes/Maps/plasma.yml b/Resources/Prototypes/Maps/plasma.yml index 1369e5a42d..85e8661200 100644 --- a/Resources/Prototypes/Maps/plasma.yml +++ b/Resources/Prototypes/Maps/plasma.yml @@ -2,8 +2,7 @@ id: Plasma mapName: 'Plasma' mapPath: /Maps/plasma.yml - minPlayers: 20 - maxPlayers: 60 + minPlayers: 30 stations: Plasma: stationProto: StandardNanotrasenStation @@ -18,10 +17,16 @@ - type: StationCargoShuttle path: /Maps/Shuttles/cargo_plasma.yml - type: StationJobs - availableJobs: - #service + availableJobs: #Total of 66 jobs roundstart, max of 93 inc. latejoins and trainees. + #command - 7 Captain: [ 1, 1 ] HeadOfPersonnel: [ 1, 1 ] + ChiefEngineer: [ 1, 1 ] + ChiefMedicalOfficer: [ 1, 1 ] + ResearchDirector: [ 1, 1 ] + HeadOfSecurity: [ 1, 1 ] + Quartermaster: [ 1, 1 ] + #service - 18-21 Bartender: [ 2, 2 ] Botanist: [ 2, 3 ] Chef: [ 2, 2 ] @@ -30,37 +35,32 @@ Librarian: [ 1, 1 ] ServiceWorker: [ 2, 2 ] Reporter: [ 2, 3 ] - #engineering - ChiefEngineer: [ 1, 1 ] + Clown: [ 1, 2 ] # This might be fun + Mime: [ 1, 1 ] + Musician: [ 1, 1 ] + #engineering - 8-12 AtmosphericTechnician: [ 4, 4 ] StationEngineer: [ 4, 4 ] TechnicalAssistant: [ 4, 4 ] - #medical - ChiefMedicalOfficer: [ 1, 1 ] + #medical - 9-13 Chemist: [ 2, 2 ] MedicalDoctor: [ 4, 4 ] Paramedic: [ 2, 2 ] MedicalIntern: [ 4, 4 ] Psychologist: [ 1, 1 ] - #science - ResearchDirector: [ 1, 1 ] + #science - 7-13 Scientist: [ 4, 4 ] ResearchAssistant: [ 4, 4 ] StationAi: [ 1, 1 ] Borg: [ 2, 4 ] - #security - HeadOfSecurity: [ 1, 1 ] + #security - 9-17 Warden: [ 1, 1 ] SecurityOfficer: [ 6, 8 ] Detective: [ 1, 2 ] SecurityCadet: [ 4, 4 ] Lawyer: [ 1, 2 ] - #supply - Quartermaster: [ 1, 1 ] + #supply - 8-10 SalvageSpecialist: [ 4, 4 ] CargoTechnician: [ 4, 6 ] - #civilian + #civilian - the tiders yearn for the mines Passenger: [ -1, -1 ] - Clown: [ 1, 1 ] - Mime: [ 1, 1 ] - Musician: [ 1, 1 ] From f092ddcb4393240c61921ee8cb68e38a8555d0a9 Mon Sep 17 00:00:00 2001 From: PJBot Date: Tue, 21 Jan 2025 04:57:55 +0000 Subject: [PATCH 05/15] 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 e9cfa5a912..fe4f56623a 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,11 +1,4 @@ Entries: -- author: lzk228 - changes: - - message: The captain now have special late join message. - type: Tweak - id: 7335 - time: '2024-09-09T19:57:37.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/31991 - author: Thinbug0 changes: - message: Teal gloves can now be found at the ClothesMate! @@ -3892,3 +3885,10 @@ id: 7834 time: '2025-01-20T01:24:40.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/34527 +- author: Compilatron144 + changes: + - message: Raised Plasma Station's population limit + type: Tweak + id: 7835 + time: '2025-01-21T04:56:47.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/34549 From 796f59917283682a9671dcd68fc975f4245afb56 Mon Sep 17 00:00:00 2001 From: John <35928781+sporkyz@users.noreply.github.com> Date: Tue, 21 Jan 2025 04:51:27 -0500 Subject: [PATCH 06/15] Job contraband rework (#33385) * contraband system rework to allow restriction by job, not just department * Fixing detective trenchcoat inheritance * removing unnecessary using declarations * trying to fix testing error by re-adding diagnostics using declaration * removing unecessary dependency, making allowedJobs nullable * Adding all of slarti's requested changes except for the hacky job icon method fix * removing accidental whitespace * choosing to use the non-localized version because we're comparing the string against the AllowedJobs field, and the contraband classes that fill that field are written in english * removing unneeded using dec, fixing nesting logic problem * didn't remove the old nesting, doing that now * using localized job title and localizing the allowed jobs string, removing usages of JobTitle field. Also networked the _jobTitle field instead. * rewrite some stuff * fixes * fix energy pen --------- Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com> --- .../Access/Components/IdCardComponent.cs | 2 + .../Contraband/ContrabandComponent.cs | 10 ++++- .../Contraband/ContrabandSeverityPrototype.cs | 4 +- Content.Shared/Contraband/ContrabandSystem.cs | 38 ++++++++++++------- .../Entities/Clothing/Belt/belts.yml | 2 +- .../Entities/Clothing/Ears/headsets.yml | 2 +- .../Entities/Clothing/OuterClothing/armor.yml | 14 +++++-- .../Entities/Clothing/OuterClothing/coats.yml | 2 +- .../Entities/Clothing/OuterClothing/vests.yml | 2 +- .../Entities/Clothing/Shoes/specific.yml | 2 +- .../Objects/Devices/encryption_keys.yml | 2 +- .../Guns/Ammunition/Cartridges/shotgun.yml | 4 +- .../Weapons/Guns/Shotguns/shotguns.yml | 4 +- .../Objects/Weapons/Melee/e_sword.yml | 1 - .../Entities/Objects/base_contraband.yml | 32 +++++++++++++--- .../Prototypes/contraband_severities.yml | 2 +- 16 files changed, 86 insertions(+), 37 deletions(-) diff --git a/Content.Shared/Access/Components/IdCardComponent.cs b/Content.Shared/Access/Components/IdCardComponent.cs index e80ced6464..3b8322671b 100644 --- a/Content.Shared/Access/Components/IdCardComponent.cs +++ b/Content.Shared/Access/Components/IdCardComponent.cs @@ -22,6 +22,8 @@ public sealed partial class IdCardComponent : Component [Access(typeof(SharedIdCardSystem), typeof(SharedPdaSystem), typeof(SharedAgentIdCardSystem), Other = AccessPermissions.ReadWrite)] public LocId? JobTitle; + [DataField] + [AutoNetworkedField] private string? _jobTitle; [Access(typeof(SharedIdCardSystem), typeof(SharedPdaSystem), typeof(SharedAgentIdCardSystem), Other = AccessPermissions.ReadWriteExecute)] diff --git a/Content.Shared/Contraband/ContrabandComponent.cs b/Content.Shared/Contraband/ContrabandComponent.cs index a4ce652f2f..f758d91f0c 100644 --- a/Content.Shared/Contraband/ContrabandComponent.cs +++ b/Content.Shared/Contraband/ContrabandComponent.cs @@ -24,5 +24,13 @@ public sealed partial class ContrabandComponent : Component /// [DataField] [AutoNetworkedField] - public HashSet>? AllowedDepartments = ["Security"]; + public HashSet> AllowedDepartments = new(); + + /// + /// Which jobs is this item restricted to? + /// If empty, no jobs are allowed to use this beyond the allowed departments. + /// + [DataField] + [AutoNetworkedField] + public HashSet> AllowedJobs = new(); } diff --git a/Content.Shared/Contraband/ContrabandSeverityPrototype.cs b/Content.Shared/Contraband/ContrabandSeverityPrototype.cs index c1ab4b8292..094275a6fd 100644 --- a/Content.Shared/Contraband/ContrabandSeverityPrototype.cs +++ b/Content.Shared/Contraband/ContrabandSeverityPrototype.cs @@ -19,8 +19,8 @@ public sealed partial class ContrabandSeverityPrototype : IPrototype public LocId ExamineText; /// - /// When examining the contraband, should this take into account the viewer's departments? + /// When examining the contraband, should this take into account the viewer's departments and job? /// [DataField] - public bool ShowDepartments; + public bool ShowDepartmentsAndJobs; } diff --git a/Content.Shared/Contraband/ContrabandSystem.cs b/Content.Shared/Contraband/ContrabandSystem.cs index e6931f2860..811ea53567 100644 --- a/Content.Shared/Contraband/ContrabandSystem.cs +++ b/Content.Shared/Contraband/ContrabandSystem.cs @@ -40,6 +40,7 @@ public sealed class ContrabandSystem : EntitySystem contraband.Severity = other.Severity; contraband.AllowedDepartments = other.AllowedDepartments; + contraband.AllowedJobs = other.AllowedJobs; Dirty(uid, contraband); } @@ -54,11 +55,15 @@ public sealed class ContrabandSystem : EntitySystem using (args.PushGroup(nameof(ContrabandComponent))) { + // TODO shouldn't department prototypes have a localized name instead of just using the ID for this? + var localizedDepartments = ent.Comp.AllowedDepartments.Select(p => Loc.GetString($"department-{p.Id}")); + var localizedJobs = ent.Comp.AllowedJobs.Select(p => _proto.Index(p).LocalizedName); + var severity = _proto.Index(ent.Comp.Severity); - if (severity.ShowDepartments && ent.Comp is { AllowedDepartments: not null }) + if (severity.ShowDepartmentsAndJobs) { - // TODO shouldn't department prototypes have a localized name instead of just using the ID for this? - var list = ContentLocalizationManager.FormatList(ent.Comp.AllowedDepartments.Select(p => Loc.GetString($"department-{p.Id}")).ToList()); + //creating a combined list of jobs and departments for the restricted text + var list = ContentLocalizationManager.FormatList(localizedDepartments.Concat(localizedJobs).ToList()); // department restricted text args.PushMarkup(Loc.GetString("contraband-examine-text-Restricted-department", ("departments", list))); @@ -69,23 +74,30 @@ public sealed class ContrabandSystem : EntitySystem } // text based on ID card - List>? departments = null; + List> departments = new(); + var jobId = ""; + if (_id.TryFindIdCard(args.Examiner, out var id)) { departments = id.Comp.JobDepartments; + if (id.Comp.LocalizedJobTitle is not null) + { + jobId = id.Comp.LocalizedJobTitle; + } } - // either its fully restricted, you have no departments, or your departments dont intersect with the restricted departments - if (ent.Comp.AllowedDepartments is null - || departments is null - || !departments.Intersect(ent.Comp.AllowedDepartments).Any()) + // for the jobs we compare the localized string in case you use an agent ID or custom job name that is not a prototype + if (departments.Intersect(ent.Comp.AllowedDepartments).Any() + || localizedJobs.Contains(jobId)) { - args.PushMarkup(Loc.GetString("contraband-examine-text-avoid-carrying-around")); - return; + // you are allowed to use this! + args.PushMarkup(Loc.GetString("contraband-examine-text-in-the-clear")); + } + else + { + // straight to jail! + args.PushMarkup(Loc.GetString("contraband-examine-text-avoid-carrying-around")); } - - // otherwise fine to use :tm: - args.PushMarkup(Loc.GetString("contraband-examine-text-in-the-clear")); } } } diff --git a/Resources/Prototypes/Entities/Clothing/Belt/belts.yml b/Resources/Prototypes/Entities/Clothing/Belt/belts.yml index 621f30dbb3..77f53f9417 100644 --- a/Resources/Prototypes/Entities/Clothing/Belt/belts.yml +++ b/Resources/Prototypes/Entities/Clothing/Belt/belts.yml @@ -542,7 +542,7 @@ # Belts without visualizers - type: entity - parent: [ClothingBeltAmmoProviderBase, BaseRestrictedContraband] + parent: [ClothingBeltAmmoProviderBase, BaseSecurityBartenderContraband] id: ClothingBeltBandolier name: bandolier description: A bandolier for holding shotgun ammunition. diff --git a/Resources/Prototypes/Entities/Clothing/Ears/headsets.yml b/Resources/Prototypes/Entities/Clothing/Ears/headsets.yml index 817f83ec92..ca9d0e89a1 100644 --- a/Resources/Prototypes/Entities/Clothing/Ears/headsets.yml +++ b/Resources/Prototypes/Entities/Clothing/Ears/headsets.yml @@ -226,7 +226,7 @@ - EncryptionKeyCommon - type: entity - parent: [ClothingHeadset, BaseRestrictedContraband] + parent: [ClothingHeadset, BaseSecurityLawyerContraband] id: ClothingHeadsetSecurity name: security headset description: This is used by your elite security force. diff --git a/Resources/Prototypes/Entities/Clothing/OuterClothing/armor.yml b/Resources/Prototypes/Entities/Clothing/OuterClothing/armor.yml index 2412dd9d5c..cdb938030d 100644 --- a/Resources/Prototypes/Entities/Clothing/OuterClothing/armor.yml +++ b/Resources/Prototypes/Entities/Clothing/OuterClothing/armor.yml @@ -1,11 +1,12 @@ # Numbers for armor here largely taken from /tg/. # NOTE: Half of the kind of armor you're probably thinking of is in vests.yml. These should probably be merged some day. -#Basic armor vest +#Basic armor vest for inheritance - type: entity parent: [ClothingOuterBaseMedium, AllowSuitStorageClothing, BaseRestrictedContraband] - id: ClothingOuterArmorBasic + id: ClothingOuterArmorBase name: armor vest + abstract: true description: A standard Type I armored vest that provides decent protection against most types of damage. components: - type: Sprite @@ -22,6 +23,11 @@ - type: ExplosionResistance damageCoefficient: 0.90 +#Standard armor vest, allowed for security and bartenders +- type: entity + parent: [ BaseSecurityBartenderContraband, ClothingOuterArmorBase] + id: ClothingOuterArmorBasic + #Alternate / slim basic armor vest - type: entity parent: ClothingOuterArmorBasic @@ -58,7 +64,7 @@ - type: GroupExamine - type: entity - parent: ClothingOuterArmorBasic + parent: ClothingOuterArmorBase id: ClothingOuterArmorBulletproof name: bulletproof vest description: A Type III heavy bulletproof vest that excels in protecting the wearer against traditional projectile weaponry and explosives to a minor extent. @@ -78,7 +84,7 @@ damageCoefficient: 0.80 - type: entity - parent: ClothingOuterArmorBasic + parent: ClothingOuterArmorBase id: ClothingOuterArmorReflective name: reflective vest description: An armored vest with advanced shielding to protect against energy weapons. diff --git a/Resources/Prototypes/Entities/Clothing/OuterClothing/coats.yml b/Resources/Prototypes/Entities/Clothing/OuterClothing/coats.yml index f2dfe7c6e7..e2db7ebd94 100644 --- a/Resources/Prototypes/Entities/Clothing/OuterClothing/coats.yml +++ b/Resources/Prototypes/Entities/Clothing/OuterClothing/coats.yml @@ -10,7 +10,7 @@ sprite: Clothing/OuterClothing/Coats/bomber.rsi - type: entity - parent: [ClothingOuterStorageBase, AllowSuitStorageClothing, ClothingOuterArmorBasic] + parent: [ClothingOuterStorageBase, AllowSuitStorageClothing, ClothingOuterArmorBase] id: ClothingOuterCoatDetective name: detective trenchcoat description: An 18th-century multi-purpose trenchcoat. Someone who wears this means serious business. diff --git a/Resources/Prototypes/Entities/Clothing/OuterClothing/vests.yml b/Resources/Prototypes/Entities/Clothing/OuterClothing/vests.yml index 994e86b548..accd24dd3c 100644 --- a/Resources/Prototypes/Entities/Clothing/OuterClothing/vests.yml +++ b/Resources/Prototypes/Entities/Clothing/OuterClothing/vests.yml @@ -42,7 +42,7 @@ #Detective's vest - type: entity - parent: [ClothingOuterArmorBasic, BaseRestrictedContraband] + parent: [ClothingOuterArmorBase, BaseRestrictedContraband] id: ClothingOuterVestDetective name: detective's vest description: A hard-boiled private investigator's armored vest. diff --git a/Resources/Prototypes/Entities/Clothing/Shoes/specific.yml b/Resources/Prototypes/Entities/Clothing/Shoes/specific.yml index 3a17dcde37..a5c32928da 100644 --- a/Resources/Prototypes/Entities/Clothing/Shoes/specific.yml +++ b/Resources/Prototypes/Entities/Clothing/Shoes/specific.yml @@ -104,7 +104,7 @@ sprite: Clothing/Shoes/Specific/cult.rsi - type: entity - parent: ClothingShoesBase + parent: [ ClothingShoesBase, BaseJanitorContraband ] id: ClothingShoesGaloshes name: galoshes description: Rubber boots. diff --git a/Resources/Prototypes/Entities/Objects/Devices/encryption_keys.yml b/Resources/Prototypes/Entities/Objects/Devices/encryption_keys.yml index 7393532654..2d23885bca 100644 --- a/Resources/Prototypes/Entities/Objects/Devices/encryption_keys.yml +++ b/Resources/Prototypes/Entities/Objects/Devices/encryption_keys.yml @@ -170,7 +170,7 @@ - state: robotics_label - type: entity - parent: [ EncryptionKey, BaseSecurityContraband ] + parent: [ EncryptionKey, BaseSecurityLawyerContraband ] id: EncryptionKeySecurity name: security encryption key description: An encryption key used by security. diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Ammunition/Cartridges/shotgun.yml b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Ammunition/Cartridges/shotgun.yml index dd00440eec..a2b9fb2737 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Ammunition/Cartridges/shotgun.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Ammunition/Cartridges/shotgun.yml @@ -22,7 +22,7 @@ - type: entity id: ShellShotgunBeanbag name: shell (.50 beanbag) - parent: BaseShellShotgun + parent: [ BaseShellShotgun, BaseSecurityBartenderContraband ] components: - type: Tag tags: @@ -55,7 +55,7 @@ - type: entity id: ShellShotgunFlare name: shell (.50 flare) - parent: BaseShellShotgun + parent: [ BaseShellShotgun, BaseSecurityBartenderContraband ] components: - type: Tag tags: diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Shotguns/shotguns.yml b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Shotguns/shotguns.yml index 58cf9eaed3..a927d880ef 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Shotguns/shotguns.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Shotguns/shotguns.yml @@ -103,7 +103,7 @@ - type: entity name: double-barreled shotgun - parent: [BaseWeaponShotgun, BaseGunWieldable, BaseMinorContraband] + parent: [BaseWeaponShotgun, BaseGunWieldable, BaseSecurityBartenderContraband] id: WeaponShotgunDoubleBarreled description: An immortal classic. Uses .50 shotgun shells. components: @@ -181,7 +181,7 @@ - type: entity name: sawn-off shotgun - parent: BaseWeaponShotgun + parent: [ BaseWeaponShotgun, BaseSecurityBartenderContraband ] id: WeaponShotgunSawn description: Groovy! Uses .50 shotgun shells. components: diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Melee/e_sword.yml b/Resources/Prototypes/Entities/Objects/Weapons/Melee/e_sword.yml index 59a27ccf0c..2e576e6a50 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Melee/e_sword.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Melee/e_sword.yml @@ -194,7 +194,6 @@ doAfterDuration: 4.0 - type: Contraband severity: Syndicate - allowedDepartments: null - type: Sprite sprite: Objects/Weapons/Melee/e_dagger.rsi layers: diff --git a/Resources/Prototypes/Entities/Objects/base_contraband.yml b/Resources/Prototypes/Entities/Objects/base_contraband.yml index 6f44767c9f..84df2f8b37 100644 --- a/Resources/Prototypes/Entities/Objects/base_contraband.yml +++ b/Resources/Prototypes/Entities/Objects/base_contraband.yml @@ -5,8 +5,6 @@ components: - type: Contraband severity: Syndicate - # no one should be carrying this around visibly! - allowedDepartments: null # minor contraband not departmentally restricted -- improvised weapons etc - type: entity @@ -15,8 +13,6 @@ components: - type: Contraband severity: Minor - # according to space law no dept is authorized to have - allowedDepartments: null # major contraband, for things like guns or weaponry that don't belong to any department and aren't syndicate specific - type: entity @@ -25,7 +21,6 @@ components: - type: Contraband severity: Major - allowedDepartments: null # minor contraband by default restricted to security only - type: entity @@ -157,6 +152,33 @@ - type: Contraband allowedDepartments: [ Medical, Science ] +# contraband restricted by job by some degree +- type: entity + id: BaseSecurityBartenderContraband + parent: BaseRestrictedContraband + abstract: true + components: + - type: Contraband + allowedDepartments: [ Security ] + allowedJobs: [ Bartender ] + +- type: entity + id: BaseSecurityLawyerContraband + parent: BaseRestrictedContraband + abstract: true + components: + - type: Contraband + allowedDepartments: [ Security ] + allowedJobs: [ Lawyer ] + +- type: entity + id: BaseJanitorContraband + parent: BaseRestrictedContraband + abstract: true + components: + - type: Contraband + allowedJobs: [ Janitor ] + # for ~objective items - type: entity id: BaseGrandTheftContraband diff --git a/Resources/Prototypes/contraband_severities.yml b/Resources/Prototypes/contraband_severities.yml index 54f5cd62ef..c103af5e0a 100644 --- a/Resources/Prototypes/contraband_severities.yml +++ b/Resources/Prototypes/contraband_severities.yml @@ -14,7 +14,7 @@ - type: contrabandSeverity id: Restricted examineText: contraband-examine-text-Restricted - showDepartments: true + showDepartmentsAndJobs: true # Having this as a regular crew member is considered grand theft. (nuke disk, captain's gear, objective items, etc) - type: contrabandSeverity From 1f6e041e05886fdc7f2fe15a079a5a86d1836ef2 Mon Sep 17 00:00:00 2001 From: PJBot Date: Tue, 21 Jan 2025 09:52:34 +0000 Subject: [PATCH 07/15] Automatic changelog update --- Resources/Changelog/Changelog.yml | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index fe4f56623a..b35fa75d2d 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,11 +1,4 @@ Entries: -- author: Thinbug0 - changes: - - message: Teal gloves can now be found at the ClothesMate! - type: Add - id: 7336 - time: '2024-09-09T21:47:53.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/31865 - author: chillyconmor changes: - message: Space Ninjas now have a new intro song. @@ -3892,3 +3885,19 @@ id: 7835 time: '2025-01-21T04:56:47.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/34549 +- author: sporkyz + changes: + - message: Galoshes are now restricted to janitor. + type: Tweak + - message: Double barrel shotguns, basic armor vests, beanbag/flare shotgun shells, + and bandoliers are now allowed for Bartenders, not just Security. + type: Tweak + - message: Lawyers now have access to the Security headset they spawn with, as well + as the encryption key inside. + type: Fix + - message: Sawn-off shotguns are now properly considered contraband instead of being + unrestricted. + type: Fix + id: 7836 + time: '2025-01-21T09:51:27.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/33385 From 9950648bbad7e6a7287e0f890e5af55dfc07bba4 Mon Sep 17 00:00:00 2001 From: ArtisticRoomba <145879011+ArtisticRoomba@users.noreply.github.com> Date: Tue, 21 Jan 2025 02:24:50 -0800 Subject: [PATCH 08/15] [HOTFIX] Fix MRP whitelist auto denying people with any medium severity notes in 14 days (#34532) * fix mrp whitelist auto denying people with warning * make headmin requested changes * godo --- Resources/Prototypes/wizardsDenWhitelists.yml | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/Resources/Prototypes/wizardsDenWhitelists.yml b/Resources/Prototypes/wizardsDenWhitelists.yml index c21d01e5a8..8b8420622a 100644 --- a/Resources/Prototypes/wizardsDenWhitelists.yml +++ b/Resources/Prototypes/wizardsDenWhitelists.yml @@ -12,20 +12,20 @@ range: 30 # 30 days action: Deny includeSecret: false - - !type:ConditionNotesPlaytimeRange # Deny for >=2 medium severity notes in the last 14 days + - !type:ConditionNotesPlaytimeRange # Deny for >=3 medium severity notes in the last 90 days includeExpired: false minimumSeverity: 2 # Medium - minimumNotes: 1 - range: 14 # 14 Days - action: Deny - includeSecret: false - - !type:ConditionNotesPlaytimeRange # Deny for >=3 low severity notes in the last 14 days - includeExpired: false - minimumSeverity: 1 # Low minimumNotes: 3 - range: 14 # 14 Days + range: 90 # 90 Days action: Deny includeSecret: false +# - !type:ConditionNotesPlaytimeRange # Deny for >=3 low severity notes in the last 14 days +# includeExpired: false +# minimumSeverity: 1 # Low +# minimumNotes: 3 +# range: 14 # 14 Days +# action: Deny +# includeSecret: false - !type:ConditionManualWhitelistMembership # Allow whitelisted players action: Allow - !type:ConditionPlayerCount # Allow when <= 15 players are online From 24219cb97b243e96fd5155a155f2819729e2a470 Mon Sep 17 00:00:00 2001 From: K-Dynamic <20566341+K-Dynamic@users.noreply.github.com> Date: Tue, 21 Jan 2025 22:39:15 +1200 Subject: [PATCH 09/15] Electrified doors/windoors now spark, new tips to deal with doors without access or when electrified (#34502) * new tips to open doors (throwing PDA/ID, dragging body) * electrified door sprite for players * tooltip to reset AI electrified doors * windoor electrified sprite * highsec electrified visual * increase tip dataset to 138 * corrected square bracket convention in this commit * removed door corpse tip from prior commit --- Resources/Locale/en-US/tips.ftl | 2 + Resources/Prototypes/Datasets/tips.yml | 2 +- .../Doors/Airlocks/base_structureairlocks.yml | 13 ++++- .../Structures/Doors/Airlocks/highsec.yml | 13 ++++- .../Doors/Windoors/base_structurewindoors.yml | 50 +++++++++++++++--- .../{electrified.png => electrified_ai.png} | Bin .../Interface/Misc/ai_hud.rsi/meta.json | 4 +- 7 files changed, 72 insertions(+), 12 deletions(-) rename Resources/Textures/Interface/Misc/ai_hud.rsi/{electrified.png => electrified_ai.png} (100%) diff --git a/Resources/Locale/en-US/tips.ftl b/Resources/Locale/en-US/tips.ftl index 154ac8e18b..dcadd15b1b 100644 --- a/Resources/Locale/en-US/tips.ftl +++ b/Resources/Locale/en-US/tips.ftl @@ -133,3 +133,5 @@ tips-dataset-132 = By right clicking on a player, and then clicking the heart ic tips-dataset-133 = Monkeys and kobolds have a rare chance to be sentient. Ook! tips-dataset-134 = You can tell if an area with firelocks up is spaced by looking to see if the firelocks have lights beside them. tips-dataset-135 = Instead of picking it up, you can alt-click food to eat it. This also works for mice and other creatures without hands. +tips-dataset-136 = If you're trapped behind an electrified door, disable the APC or throw your ID at the door to avoid getting shocked! +tips-dataset-137 = If the AI electrifies a door and you have insulated gloves, snip and mend the power wire to reset their electrification! diff --git a/Resources/Prototypes/Datasets/tips.yml b/Resources/Prototypes/Datasets/tips.yml index b710d69fab..b57f2052d9 100644 --- a/Resources/Prototypes/Datasets/tips.yml +++ b/Resources/Prototypes/Datasets/tips.yml @@ -2,4 +2,4 @@ id: Tips values: prefix: tips-dataset- - count: 135 + count: 137 diff --git a/Resources/Prototypes/Entities/Structures/Doors/Airlocks/base_structureairlocks.yml b/Resources/Prototypes/Entities/Structures/Doors/Airlocks/base_structureairlocks.yml index 90224d3136..f8099f28d7 100644 --- a/Resources/Prototypes/Entities/Structures/Doors/Airlocks/base_structureairlocks.yml +++ b/Resources/Prototypes/Entities/Structures/Doors/Airlocks/base_structureairlocks.yml @@ -31,11 +31,16 @@ shader: unshaded - state: panel_open map: ["enum.WiresVisualLayers.MaintenancePanel"] - - state: electrified + - state: electrified_ai sprite: Interface/Misc/ai_hud.rsi shader: unshaded visible: false map: ["enum.ElectrifiedLayers.HUD"] + - state: electrified + sprite: Effects/electricity.rsi + shader: unshaded + visible: false + map: ["enum.ElectrifiedLayers.Sparks"] - type: AnimationPlayer - type: Physics - type: Fixtures @@ -77,6 +82,12 @@ - type: NavMapDoor - type: DoorBolt - type: Appearance + - type: GenericVisualizer + visuals: + enum.ElectrifiedVisuals.ShowSparks: + enum.ElectrifiedLayers.Sparks: + True: { visible: True } + False: { visible: False } - type: WiresVisuals - type: ElectrocutionHUDVisuals - type: ApcPowerReceiver diff --git a/Resources/Prototypes/Entities/Structures/Doors/Airlocks/highsec.yml b/Resources/Prototypes/Entities/Structures/Doors/Airlocks/highsec.yml index ea8b866e77..6f7340c80f 100644 --- a/Resources/Prototypes/Entities/Structures/Doors/Airlocks/highsec.yml +++ b/Resources/Prototypes/Entities/Structures/Doors/Airlocks/highsec.yml @@ -27,11 +27,16 @@ shader: unshaded - state: panel_open map: ["enum.WiresVisualLayers.MaintenancePanel"] - - state: electrified + - state: electrified_ai sprite: Interface/Misc/ai_hud.rsi shader: unshaded visible: false map: ["enum.ElectrifiedLayers.HUD"] + - state: electrified + sprite: Effects/electricity.rsi + shader: unshaded + visible: false + map: ["enum.ElectrifiedLayers.Sparks"] - type: AnimationPlayer - type: Physics - type: Fixtures @@ -70,6 +75,12 @@ - type: AccessReader containerAccessProvider: board - type: Appearance + - type: GenericVisualizer + visuals: + enum.ElectrifiedVisuals.ShowSparks: + enum.ElectrifiedLayers.Sparks: + True: { visible: True } + False: { visible: False } - type: WiresVisuals - type: ElectrocutionHUDVisuals - type: ApcPowerReceiver diff --git a/Resources/Prototypes/Entities/Structures/Doors/Windoors/base_structurewindoors.yml b/Resources/Prototypes/Entities/Structures/Doors/Windoors/base_structurewindoors.yml index 81ef89997d..10062d7803 100644 --- a/Resources/Prototypes/Entities/Structures/Doors/Windoors/base_structurewindoors.yml +++ b/Resources/Prototypes/Entities/Structures/Doors/Windoors/base_structurewindoors.yml @@ -43,11 +43,16 @@ map: ["enum.DoorVisualLayers.BaseEmergencyAccess"] - state: panel_open map: ["enum.WiresVisualLayers.MaintenancePanel"] - - state: electrified + - state: electrified_ai sprite: Interface/Misc/ai_hud.rsi shader: unshaded visible: false map: ["enum.ElectrifiedLayers.HUD"] + - state: electrified + sprite: Effects/electricity.rsi + shader: unshaded + visible: false + map: ["enum.ElectrifiedLayers.Sparks"] - type: AnimationPlayer - type: ApcPowerReceiver - type: ExtensionCableReceiver @@ -142,6 +147,12 @@ enum.WiresUiKey.Key: type: WiresBoundUserInterface - type: Appearance + - type: GenericVisualizer + visuals: + enum.ElectrifiedVisuals.ShowSparks: + enum.ElectrifiedLayers.Sparks: + True: { visible: True } + False: { visible: False } - type: WiresVisuals - type: ElectrocutionHUDVisuals - type: Airtight @@ -183,11 +194,16 @@ - state: panel_open map: [ "enum.WiresVisualLayers.MaintenancePanel" ] visible: false - - state: electrified + - state: electrified_ai sprite: Interface/Misc/ai_hud.rsi shader: unshaded visible: false map: [ "enum.ElectrifiedLayers.HUD" ] + - state: electrified + sprite: Effects/electricity.rsi + shader: unshaded + visible: false + map: [ "enum.ElectrifiedLayers.Sparks" ] - type: Damageable damageModifierSet: RGlass - type: Destructible @@ -249,11 +265,16 @@ - state: panel_open map: [ "enum.WiresVisualLayers.MaintenancePanel" ] visible: false - - state: electrified + - state: electrified_ai sprite: Interface/Misc/ai_hud.rsi shader: unshaded visible: false map: [ "enum.ElectrifiedLayers.HUD" ] + - state: electrified + sprite: Effects/electricity.rsi + shader: unshaded + visible: false + map: [ "enum.ElectrifiedLayers.Sparks" ] - type: Destructible thresholds: - trigger: @@ -310,11 +331,16 @@ - state: panel_open map: [ "enum.WiresVisualLayers.MaintenancePanel" ] visible: false - - state: electrified + - state: electrified_ai sprite: Interface/Misc/ai_hud.rsi shader: unshaded visible: false - map: ["enum.ElectrifiedLayers.HUD"] + map: [ "enum.ElectrifiedLayers.HUD" ] + - state: electrified + sprite: Effects/electricity.rsi + shader: unshaded + visible: false + map: [ "enum.ElectrifiedLayers.Sparks" ] - type: Destructible thresholds: - trigger: @@ -376,11 +402,16 @@ - state: panel_open map: [ "enum.WiresVisualLayers.MaintenancePanel" ] visible: false - - state: electrified + - state: electrified_ai sprite: Interface/Misc/ai_hud.rsi shader: unshaded visible: false map: [ "enum.ElectrifiedLayers.HUD" ] + - state: electrified + sprite: Effects/electricity.rsi + shader: unshaded + visible: false + map: [ "enum.ElectrifiedLayers.Sparks" ] - type: Destructible thresholds: - trigger: @@ -437,11 +468,16 @@ - state: panel_open map: [ "enum.WiresVisualLayers.MaintenancePanel" ] visible: false - - state: electrified + - state: electrified_ai sprite: Interface/Misc/ai_hud.rsi shader: unshaded visible: false map: [ "enum.ElectrifiedLayers.HUD" ] + - state: electrified + sprite: Effects/electricity.rsi + shader: unshaded + visible: false + map: [ "enum.ElectrifiedLayers.Sparks" ] - type: Destructible thresholds: - trigger: diff --git a/Resources/Textures/Interface/Misc/ai_hud.rsi/electrified.png b/Resources/Textures/Interface/Misc/ai_hud.rsi/electrified_ai.png similarity index 100% rename from Resources/Textures/Interface/Misc/ai_hud.rsi/electrified.png rename to Resources/Textures/Interface/Misc/ai_hud.rsi/electrified_ai.png diff --git a/Resources/Textures/Interface/Misc/ai_hud.rsi/meta.json b/Resources/Textures/Interface/Misc/ai_hud.rsi/meta.json index 7f1e67ac4d..3df9d296a0 100644 --- a/Resources/Textures/Interface/Misc/ai_hud.rsi/meta.json +++ b/Resources/Textures/Interface/Misc/ai_hud.rsi/meta.json @@ -8,7 +8,7 @@ }, "states": [ { - "name": "electrified", + "name": "electrified_ai", "delays": [ [ 0.2, @@ -34,4 +34,4 @@ ] } ] -} \ No newline at end of file +} From 14aff1c49d0adfcda7d5fc48229b7203e1f2f5e8 Mon Sep 17 00:00:00 2001 From: PJBot Date: Tue, 21 Jan 2025 10:40:22 +0000 Subject: [PATCH 10/15] Automatic changelog update --- Resources/Changelog/Changelog.yml | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index b35fa75d2d..5b246d4db6 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,11 +1,4 @@ Entries: -- author: chillyconmor - changes: - - message: Space Ninjas now have a new intro song. - type: Add - id: 7337 - time: '2024-09-09T22:12:25.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/31055 - author: DieselMohawk changes: - message: Made Trooper Uniform accessible for Security Officers in loadouts @@ -3901,3 +3894,13 @@ id: 7836 time: '2025-01-21T09:51:27.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/33385 +- author: K-Dynamic + changes: + - message: Electrified doors and windoors now visibly spark when touched. + type: Tweak + - message: New tips have been added about opening electrified doors by throwing + your PDA or ID, and resetting doors that are electrified by AI. + type: Add + id: 7837 + time: '2025-01-21T10:39:16.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/34502 From 0da6a9995aeb7bb7c48ce43074aa5c5e02f11c87 Mon Sep 17 00:00:00 2001 From: Nim <128169402+Nimfar11@users.noreply.github.com> Date: Tue, 21 Jan 2025 18:08:21 +0200 Subject: [PATCH 11/15] Blueprint double emergency tank (#34232) * blueprint * NitrogenTank * description --- .../Spawners/Random/Salvage/tables_loot.yml | 1 + .../Entities/Objects/Tools/blueprint.yml | 11 +++++++++++ Resources/Prototypes/Recipes/Lathes/misc.yml | 14 ++++++++++++++ 3 files changed, 26 insertions(+) diff --git a/Resources/Prototypes/Entities/Markers/Spawners/Random/Salvage/tables_loot.yml b/Resources/Prototypes/Entities/Markers/Spawners/Random/Salvage/tables_loot.yml index 943b906560..6f753fa413 100644 --- a/Resources/Prototypes/Entities/Markers/Spawners/Random/Salvage/tables_loot.yml +++ b/Resources/Prototypes/Entities/Markers/Spawners/Random/Salvage/tables_loot.yml @@ -222,6 +222,7 @@ id: SalvageEquipmentRare table: !type:GroupSelector children: + - id: BlueprintDoubleEmergencyTank - id: FultonBeacon - id: Fulton amount: !type:RangeNumberSelector diff --git a/Resources/Prototypes/Entities/Objects/Tools/blueprint.yml b/Resources/Prototypes/Entities/Objects/Tools/blueprint.yml index 43cbdc2431..64aa91c373 100644 --- a/Resources/Prototypes/Entities/Objects/Tools/blueprint.yml +++ b/Resources/Prototypes/Entities/Objects/Tools/blueprint.yml @@ -37,3 +37,14 @@ - type: Blueprint providedRecipes: - SeismicCharge + +- type: entity + parent: BaseBlueprint + id: BlueprintDoubleEmergencyTank + name: double emergency tank blueprint + description: A blueprint with a schematic of a double emergency tank. It can be inserted into an autolathe. + components: + - type: Blueprint + providedRecipes: + - DoubleEmergencyOxygenTank + - DoubleEmergencyNitrogenTank diff --git a/Resources/Prototypes/Recipes/Lathes/misc.yml b/Resources/Prototypes/Recipes/Lathes/misc.yml index a9ae608674..19b02993b2 100644 --- a/Resources/Prototypes/Recipes/Lathes/misc.yml +++ b/Resources/Prototypes/Recipes/Lathes/misc.yml @@ -119,6 +119,20 @@ materials: Steel: 300 +- type: latheRecipe + id: DoubleEmergencyOxygenTank + result: DoubleEmergencyOxygenTank + completetime: 4 + materials: + Steel: 250 + +- type: latheRecipe + id: DoubleEmergencyNitrogenTank + result: DoubleEmergencyNitrogenTank + completetime: 4 + materials: + Steel: 250 + - type: latheRecipe id: ClothingShoesBootsMagSci result: ClothingShoesBootsMagSci From 1031d2a6c17f160caf7105aac719a67838e66f0f Mon Sep 17 00:00:00 2001 From: PJBot Date: Tue, 21 Jan 2025 16:09:27 +0000 Subject: [PATCH 12/15] 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 5b246d4db6..d1cbbc880c 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,11 +1,4 @@ Entries: -- author: DieselMohawk - changes: - - message: Made Trooper Uniform accessible for Security Officers in loadouts - type: Fix - id: 7338 - time: '2024-09-09T23:59:31.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/32019 - author: IProduceWidgets changes: - message: Visitors now can have the correct Id cards and PDA! @@ -3904,3 +3897,10 @@ id: 7837 time: '2025-01-21T10:39:16.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/34502 +- author: Nimfar11 + changes: + - message: Adds Blueprint double emergency tank. + type: Add + id: 7838 + time: '2025-01-21T16:08:21.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/34232 From ae213066b1adb0bc68742b740b39d7d135e6e679 Mon Sep 17 00:00:00 2001 From: Errant <35878406+Errant-4@users.noreply.github.com> Date: Tue, 21 Jan 2025 23:48:07 +0100 Subject: [PATCH 13/15] HOTFIX Admin playerlist character update fix (#34560) fix IdentityChangedEvent subscription --- Content.Server/Administration/Systems/AdminSystem.cs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/Content.Server/Administration/Systems/AdminSystem.cs b/Content.Server/Administration/Systems/AdminSystem.cs index 1d8c278584..eb29617f49 100644 --- a/Content.Server/Administration/Systems/AdminSystem.cs +++ b/Content.Server/Administration/Systems/AdminSystem.cs @@ -82,13 +82,14 @@ public sealed class AdminSystem : EntitySystem Subs.CVar(_config, CCVars.PanicBunkerMinAccountAge, OnPanicBunkerMinAccountAgeChanged, true); Subs.CVar(_config, CCVars.PanicBunkerMinOverallMinutes, OnPanicBunkerMinOverallMinutesChanged, true); - SubscribeLocalEvent(OnIdentityChanged); SubscribeLocalEvent(OnPlayerAttached); SubscribeLocalEvent(OnPlayerDetached); SubscribeLocalEvent(OnRoleEvent); SubscribeLocalEvent(OnRoleEvent); SubscribeLocalEvent(OnRoundRestartCleanup); + SubscribeLocalEvent(OnPlayerRenamed); + SubscribeLocalEvent(OnIdentityChanged); } private void OnRoundRestartCleanup(RoundRestartCleanupEvent ev) @@ -144,12 +145,9 @@ public sealed class AdminSystem : EntitySystem return value ?? null; } - private void OnIdentityChanged(ref IdentityChangedEvent ev) + private void OnIdentityChanged(Entity ent, ref IdentityChangedEvent ev) { - if (!TryComp(ev.CharacterEntity, out var actor)) - return; - - UpdatePlayerList(actor.PlayerSession); + UpdatePlayerList(ent.Comp.PlayerSession); } private void OnRoleEvent(RoleEvent ev) From 71c9dfc9ea5ec53333fccf566523dee7556f9e48 Mon Sep 17 00:00:00 2001 From: Pieter-Jan Briers Date: Wed, 22 Jan 2025 00:23:47 +0100 Subject: [PATCH 14/15] Add system to kick people if they connect to multiple servers at once. (#34563) --- .../Managers/BanManager.Notification.cs | 29 +---- .../Administration/Managers/BanManager.cs | 7 +- .../Managers/MultiServerKickManager.cs | 114 ++++++++++++++++++ Content.Server/Database/ServerDbBase.cs | 2 + Content.Server/Database/ServerDbManager.cs | 15 +++ Content.Server/Database/ServerDbManagerExt.cs | 76 ++++++++++++ .../ServerDbPostgres.Notifications.cs | 10 ++ Content.Server/Database/ServerDbSqlite.cs | 6 + Content.Server/Entry/EntryPoint.cs | 1 + Content.Server/IoC/ServerContentIoC.cs | 1 + Content.Shared/CCVar/CCVars.Admin.cs | 7 ++ .../administration/multi-server-kick.ftl | 1 + 12 files changed, 242 insertions(+), 27 deletions(-) create mode 100644 Content.Server/Administration/Managers/MultiServerKickManager.cs create mode 100644 Content.Server/Database/ServerDbManagerExt.cs create mode 100644 Resources/Locale/en-US/administration/multi-server-kick.ftl diff --git a/Content.Server/Administration/Managers/BanManager.Notification.cs b/Content.Server/Administration/Managers/BanManager.Notification.cs index e9bfa62884..ff84887f00 100644 --- a/Content.Server/Administration/Managers/BanManager.Notification.cs +++ b/Content.Server/Administration/Managers/BanManager.Notification.cs @@ -1,6 +1,4 @@ -using System.Text.Json; using System.Text.Json.Serialization; -using Content.Server.Database; namespace Content.Server.Administration.Managers; @@ -30,36 +28,15 @@ public sealed partial class BanManager private TimeSpan _banNotificationRateLimitStart; private int _banNotificationRateLimitCount; - private void OnDatabaseNotification(DatabaseNotification notification) + private bool OnDatabaseNotificationEarlyFilter() { - if (notification.Channel != BanNotificationChannel) - return; - - if (notification.Payload == null) - { - _sawmill.Error("Got ban notification with null payload!"); - return; - } - - BanNotificationData data; - try - { - data = JsonSerializer.Deserialize(notification.Payload) - ?? throw new JsonException("Content is null"); - } - catch (JsonException e) - { - _sawmill.Error($"Got invalid JSON in ban notification: {e}"); - return; - } - if (!CheckBanRateLimit()) { _sawmill.Verbose("Not processing ban notification due to rate limit"); - return; + return false; } - _taskManager.RunOnMainThread(() => ProcessBanNotification(data)); + return true; } private async void ProcessBanNotification(BanNotificationData data) diff --git a/Content.Server/Administration/Managers/BanManager.cs b/Content.Server/Administration/Managers/BanManager.cs index 2e21710e51..c65059f55d 100644 --- a/Content.Server/Administration/Managers/BanManager.cs +++ b/Content.Server/Administration/Managers/BanManager.cs @@ -53,7 +53,12 @@ public sealed partial class BanManager : IBanManager, IPostInjectInit { _netManager.RegisterNetMessage(); - _db.SubscribeToNotifications(OnDatabaseNotification); + _db.SubscribeToJsonNotification( + _taskManager, + _sawmill, + BanNotificationChannel, + ProcessBanNotification, + OnDatabaseNotificationEarlyFilter); _userDbData.AddOnLoadPlayer(CachePlayerData); _userDbData.AddOnPlayerDisconnect(ClearPlayerData); diff --git a/Content.Server/Administration/Managers/MultiServerKickManager.cs b/Content.Server/Administration/Managers/MultiServerKickManager.cs new file mode 100644 index 0000000000..abc8bb1f2d --- /dev/null +++ b/Content.Server/Administration/Managers/MultiServerKickManager.cs @@ -0,0 +1,114 @@ +using System.Text.Json; +using System.Text.Json.Serialization; +using Content.Server.Database; +using Content.Shared.CCVar; +using Robust.Server.Player; +using Robust.Shared.Asynchronous; +using Robust.Shared.Configuration; +using Robust.Shared.Enums; +using Robust.Shared.Network; +using Robust.Shared.Player; + +namespace Content.Server.Administration.Managers; + +/// +/// Handles kicking people that connect to multiple servers on the same DB at once. +/// +/// +public sealed class MultiServerKickManager +{ + public const string NotificationChannel = "multi_server_kick"; + + [Dependency] private readonly IPlayerManager _playerManager = null!; + [Dependency] private readonly IServerDbManager _dbManager = null!; + [Dependency] private readonly ILogManager _logManager = null!; + [Dependency] private readonly IConfigurationManager _cfg = null!; + [Dependency] private readonly IAdminManager _adminManager = null!; + [Dependency] private readonly ITaskManager _taskManager = null!; + [Dependency] private readonly IServerNetManager _netManager = null!; + [Dependency] private readonly ILocalizationManager _loc = null!; + [Dependency] private readonly ServerDbEntryManager _serverDbEntry = null!; + + private ISawmill _sawmill = null!; + private bool _allowed; + + public void Initialize() + { + _sawmill = _logManager.GetSawmill("multi_server_kick"); + + _playerManager.PlayerStatusChanged += OnPlayerStatusChanged; + _cfg.OnValueChanged(CCVars.AdminAllowMultiServerPlay, b => _allowed = b, true); + + _dbManager.SubscribeToJsonNotification( + _taskManager, + _sawmill, + NotificationChannel, + OnNotification, + OnNotificationEarlyFilter + ); + } + + // ReSharper disable once AsyncVoidMethod + private async void OnPlayerStatusChanged(object? sender, SessionStatusEventArgs e) + { + if (_allowed) + return; + + if (e.NewStatus != SessionStatus.InGame) + return; + + // Send notification to other servers so they can kick this player that just connected. + try + { + await _dbManager.SendNotification(new DatabaseNotification + { + Channel = NotificationChannel, + Payload = JsonSerializer.Serialize(new NotificationData + { + PlayerId = e.Session.UserId, + ServerId = (await _serverDbEntry.ServerEntity).Id, + }), + }); + } + catch (Exception ex) + { + _sawmill.Error($"Failed to send notification for multi server kick: {ex}"); + } + } + + private bool OnNotificationEarlyFilter() + { + if (_allowed) + { + _sawmill.Verbose("Received notification for player join, but multi server play is allowed on this server. Ignoring"); + return false; + } + + return true; + } + + // ReSharper disable once AsyncVoidMethod + private async void OnNotification(NotificationData notification) + { + if (!_playerManager.TryGetSessionById(new NetUserId(notification.PlayerId), out var player)) + return; + + if (notification.ServerId == (await _serverDbEntry.ServerEntity).Id) + return; + + if (_adminManager.IsAdmin(player, includeDeAdmin: true)) + return; + + _sawmill.Info($"Kicking {player} for connecting to another server. Multi-server play is not allowed."); + _netManager.DisconnectChannel(player.Channel, _loc.GetString("multi-server-kick-reason")); + } + + private sealed class NotificationData + { + [JsonPropertyName("player_id")] + public Guid PlayerId { get; set; } + + [JsonPropertyName("server_id")] + public int ServerId { get; set; } + } +} diff --git a/Content.Server/Database/ServerDbBase.cs b/Content.Server/Database/ServerDbBase.cs index c1a52447b7..b75870ac0e 100644 --- a/Content.Server/Database/ServerDbBase.cs +++ b/Content.Server/Database/ServerDbBase.cs @@ -1801,6 +1801,8 @@ INSERT INTO player_round (players_id, rounds_id) VALUES ({players[player]}, {id} #endregion + public abstract Task SendNotification(DatabaseNotification notification); + // SQLite returns DateTime as Kind=Unspecified, Npgsql actually knows for sure it's Kind=Utc. // Normalize DateTimes here so they're always Utc. Thanks. protected abstract DateTime NormalizeDatabaseTime(DateTime time); diff --git a/Content.Server/Database/ServerDbManager.cs b/Content.Server/Database/ServerDbManager.cs index 9fee2c021b..5ddb3a590c 100644 --- a/Content.Server/Database/ServerDbManager.cs +++ b/Content.Server/Database/ServerDbManager.cs @@ -350,6 +350,15 @@ namespace Content.Server.Database /// The notification to trigger void InjectTestNotification(DatabaseNotification notification); + /// + /// Send a notification to all other servers connected to the same database. + /// + /// + /// The local server will receive the sent notification itself again. + /// + /// The notification to send. + Task SendNotification(DatabaseNotification notification); + #endregion } @@ -1045,6 +1054,12 @@ namespace Content.Server.Database HandleDatabaseNotification(notification); } + public Task SendNotification(DatabaseNotification notification) + { + DbWriteOpsMetric.Inc(); + return RunDbCommand(() => _db.SendNotification(notification)); + } + private async void HandleDatabaseNotification(DatabaseNotification notification) { lock (_notificationHandlers) diff --git a/Content.Server/Database/ServerDbManagerExt.cs b/Content.Server/Database/ServerDbManagerExt.cs new file mode 100644 index 0000000000..fad7a7234e --- /dev/null +++ b/Content.Server/Database/ServerDbManagerExt.cs @@ -0,0 +1,76 @@ +using System.Text.Json; +using Robust.Shared.Asynchronous; + +namespace Content.Server.Database; + +public static class ServerDbManagerExt +{ + /// + /// Subscribe to a database notification on a specific channel, formatted as JSON. + /// + /// The database manager to subscribe on. + /// The task manager used to run the main callback on the main thread. + /// Sawmill to log any errors to. + /// + /// The notification channel to listen on. Only notifications on this channel will be handled. + /// + /// + /// The action to run on the notification data. + /// This runs on the main thread. + /// + /// + /// An early filter callback that runs before the JSON message is deserialized. + /// Return false to not handle the notification. + /// This does not run on the main thread. + /// + /// + /// A filter callback that runs after the JSON message is deserialized. + /// Return false to not handle the notification. + /// This does not run on the main thread. + /// + /// The type of JSON data to deserialize. + public static void SubscribeToJsonNotification( + this IServerDbManager dbManager, + ITaskManager taskManager, + ISawmill sawmill, + string channel, + Action action, + Func? earlyFilter = null, + Func? filter = null) + { + dbManager.SubscribeToNotifications(notification => + { + if (notification.Channel != channel) + return; + + if (notification.Payload == null) + { + sawmill.Error($"Got {channel} notification with null payload!"); + return; + } + + if (earlyFilter != null && !earlyFilter()) + return; + + TData data; + try + { + data = JsonSerializer.Deserialize(notification.Payload) + ?? throw new JsonException("Content is null"); + } + catch (JsonException e) + { + sawmill.Error($"Got invalid JSON in {channel} notification: {e}"); + return; + } + + if (filter != null && !filter(data)) + return; + + taskManager.RunOnMainThread(() => + { + action(data); + }); + }); + } +} diff --git a/Content.Server/Database/ServerDbPostgres.Notifications.cs b/Content.Server/Database/ServerDbPostgres.Notifications.cs index 69cf2c7d77..91db2d100f 100644 --- a/Content.Server/Database/ServerDbPostgres.Notifications.cs +++ b/Content.Server/Database/ServerDbPostgres.Notifications.cs @@ -2,6 +2,7 @@ using System.Threading; using System.Threading.Tasks; using Content.Server.Administration.Managers; +using Microsoft.EntityFrameworkCore; using Npgsql; namespace Content.Server.Database; @@ -17,6 +18,7 @@ public sealed partial class ServerDbPostgres private static readonly string[] NotificationChannels = [ BanManager.BanNotificationChannel, + MultiServerKickManager.NotificationChannel, ]; private static readonly TimeSpan ReconnectWaitIncrease = TimeSpan.FromSeconds(10); @@ -111,6 +113,14 @@ public sealed partial class ServerDbPostgres }); } + public override async Task SendNotification(DatabaseNotification notification) + { + await using var db = await GetDbImpl(); + + await db.PgDbContext.Database.ExecuteSqlAsync( + $"SELECT pg_notify({notification.Channel}, {notification.Payload})"); + } + public override void Shutdown() { _notificationTokenSource.Cancel(); diff --git a/Content.Server/Database/ServerDbSqlite.cs b/Content.Server/Database/ServerDbSqlite.cs index 6ec90c3332..c3109ec6e6 100644 --- a/Content.Server/Database/ServerDbSqlite.cs +++ b/Content.Server/Database/ServerDbSqlite.cs @@ -537,6 +537,12 @@ namespace Content.Server.Database return await base.AddAdminMessage(message); } + public override Task SendNotification(DatabaseNotification notification) + { + // Notifications not implemented on SQLite. + return Task.CompletedTask; + } + protected override DateTime NormalizeDatabaseTime(DateTime time) { DebugTools.Assert(time.Kind == DateTimeKind.Unspecified); diff --git a/Content.Server/Entry/EntryPoint.cs b/Content.Server/Entry/EntryPoint.cs index 3d4ea922dc..b9c20942a0 100644 --- a/Content.Server/Entry/EntryPoint.cs +++ b/Content.Server/Entry/EntryPoint.cs @@ -152,6 +152,7 @@ namespace Content.Server.Entry IoCManager.Resolve().GetEntitySystem().PostInitialize(); IoCManager.Resolve().Initialize(); IoCManager.Resolve().PostInit(); + IoCManager.Resolve().Initialize(); } } diff --git a/Content.Server/IoC/ServerContentIoC.cs b/Content.Server/IoC/ServerContentIoC.cs index 777e134246..50b248a9ea 100644 --- a/Content.Server/IoC/ServerContentIoC.cs +++ b/Content.Server/IoC/ServerContentIoC.cs @@ -75,6 +75,7 @@ namespace Content.Server.IoC IoCManager.Register(); IoCManager.Register(); IoCManager.Register(); + IoCManager.Register(); } } } diff --git a/Content.Shared/CCVar/CCVars.Admin.cs b/Content.Shared/CCVar/CCVars.Admin.cs index 7754a6cbb8..bbce533ed1 100644 --- a/Content.Shared/CCVar/CCVars.Admin.cs +++ b/Content.Shared/CCVar/CCVars.Admin.cs @@ -176,4 +176,11 @@ public sealed partial class CCVars public static readonly CVarDef BanHardwareIds = CVarDef.Create("ban.hardware_ids", true, CVar.SERVERONLY); + + /// + /// If true, players are allowed to connect to multiple game servers at once. + /// If false, they will be kicked from the first when connecting to another. + /// + public static readonly CVarDef AdminAllowMultiServerPlay = + CVarDef.Create("admin.allow_multi_server_play", true, CVar.SERVERONLY); } diff --git a/Resources/Locale/en-US/administration/multi-server-kick.ftl b/Resources/Locale/en-US/administration/multi-server-kick.ftl new file mode 100644 index 0000000000..2aa3c4ed35 --- /dev/null +++ b/Resources/Locale/en-US/administration/multi-server-kick.ftl @@ -0,0 +1 @@ +multi-server-kick-reason = Connected to different server in this community. From ef24e4b070ab5a4e5a35b77fec3046dcf685d5bb Mon Sep 17 00:00:00 2001 From: PJBot Date: Tue, 21 Jan 2025 23:24:53 +0000 Subject: [PATCH 15/15] Automatic changelog update --- Resources/Changelog/Admin.yml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Resources/Changelog/Admin.yml b/Resources/Changelog/Admin.yml index 3e29fcedd3..440a5d567a 100644 --- a/Resources/Changelog/Admin.yml +++ b/Resources/Changelog/Admin.yml @@ -728,5 +728,14 @@ Entries: id: 90 time: '2025-01-17T07:24:50.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/33782 +- author: PJB3005 + changes: + - message: Introduced an option to automatically disconnect players from their current + server if they join another one within the same server community. Admins are + always exempt. + type: Add + id: 91 + time: '2025-01-21T23:23:47.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/34563 Name: Admin Order: 1