From f95774b3ce4300012b8dbaa60829499ba6a68203 Mon Sep 17 00:00:00 2001 From: sleepyyapril <123355664+sleepyyapril@users.noreply.github.com> Date: Sun, 17 Nov 2024 15:47:11 -0400 Subject: [PATCH 001/114] Mass Engine Update (#1220) # Description An attempt to do all engine updates in one go. Not focusing on content associated, only what's needed for it to run and any bug fixes. --- # TODO - [x] Fix bug where unbuckling resets you to lying down. - [x] Fix bug where you can no longer get up after lying down. - [x] See what else I broke. --- --------- Signed-off-by: sleepyyapril <123355664+sleepyyapril@users.noreply.github.com> Co-authored-by: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com> Co-authored-by: Leon Friedrich <60421075+ElectroJr@users.noreply.github.com> Co-authored-by: Tayrtahn Co-authored-by: VMSolidus Co-authored-by: Nemanja <98561806+EmoGarbage404@users.noreply.github.com> Co-authored-by: ShadowCommander <10494922+ShadowCommander@users.noreply.github.com> Co-authored-by: Plykiya <58439124+Plykiya@users.noreply.github.com> Co-authored-by: plykiya Co-authored-by: Pieter-Jan Briers Co-authored-by: metalgearsloth Co-authored-by: Chief-Engineer <119664036+Chief-Engineer@users.noreply.github.com> Co-authored-by: deltanedas <39013340+deltanedas@users.noreply.github.com> --- Content.Client/Alerts/ClientAlertsSystem.cs | 2 +- Content.Client/Audio/AmbientSoundSystem.cs | 6 +- .../Audio/ClientGlobalSoundSystem.cs | 4 +- .../Audio/ContentAudioSystem.AmbientMusic.cs | 2 +- .../Audio/ContentAudioSystem.LobbyMusic.cs | 6 +- Content.Client/Buckle/BuckleSystem.cs | 66 +- .../Clickable/ClickableComponent.cs | 152 +- Content.Client/Clickable/ClickableSystem.cs | 168 ++ Content.Client/Entry/EntryPoint.cs | 3 - Content.Client/Explosion/ExplosionOverlay.cs | 3 +- Content.Client/Gameplay/GameplayStateBase.cs | 44 +- .../Guidebook/Controls/GuidebookWindow.xaml | 2 +- .../Guidebook/DocumentParsingManager.cs | 19 + Content.Client/Info/InfoSystem.cs | 25 - Content.Client/Info/RulesAndInfoWindow.cs | 14 +- Content.Client/Info/RulesControl.xaml | 24 +- Content.Client/Info/RulesControl.xaml.cs | 45 +- Content.Client/Info/RulesManager.cs | 105 - Content.Client/Info/RulesPopup.xaml | 10 +- Content.Client/Info/RulesPopup.xaml.cs | 2 - Content.Client/IoC/ClientContentIoC.cs | 40 +- .../Movement/Systems/WaddleAnimationSystem.cs | 4 +- .../Visualizers/DeepFriedVisualizer.cs | 3 +- .../Visualizers/DeepFryerVisualizer.cs | 4 +- Content.Client/Nyanotrasen/Mail/MailSystem.cs | 3 +- .../Outline/InteractionOutlineSystem.cs | 6 +- Content.Client/Revenant/RevenantSystem.cs | 3 +- Content.Client/Sandbox/SandboxSystem.cs | 2 +- Content.Client/Shuttles/FtlArrivalOverlay.cs | 82 + .../Systems/ShuttleSystem.EmergencyConsole.cs | 3 +- .../Shuttles/Systems/ShuttleSystem.cs | 21 + Content.Client/Traits/ParacusiaSystem.cs | 6 +- .../Systems/Alerts/AlertsUIController.cs | 3 +- .../Systems/Alerts/Widgets/AlertsUI.xaml.cs | 13 +- .../Systems/Info/InfoUIController.cs | 101 +- .../Systems/Storage/Controls/ItemGridPiece.cs | 4 +- Content.Client/Weather/WeatherSystem.cs | 14 +- .../Tests/Actions/ActionPvsDetachTest.cs | 22 +- .../Tests/Actions/ActionsAddedTest.cs | 2 +- .../Tests/Body/GibTest.cs | 2 +- .../Tests/Body/LegTest.cs | 8 +- .../Tests/Body/LungTest.cs | 8 +- .../Tests/Body/SaveLoadReparentTest.cs | 5 +- .../Tests/Buckle/BuckleDragTest.cs | 60 + .../Tests/Buckle/BuckleTest.Interact.cs | 108 + .../Tests/Buckle/BuckleTest.cs | 22 +- Content.IntegrationTests/Tests/CargoTest.cs | 19 +- .../Tests/Chemistry/DispenserTest.cs | 2 +- .../Chemistry/FixedPoint2SerializationTest.cs | 8 +- .../Tests/Chemistry/SolutionRoundingTest.cs | 4 +- .../Tests/Chemistry/SolutionSystemTests.cs | 12 +- .../Tests/Chemistry/TryAllReactionsTest.cs | 4 +- .../Tests/ClickableTest.cs | 4 +- .../Tests/Climbing/ClimbingTest.cs | 1 + .../Tests/Commands/PardonCommand.cs | 10 +- .../Tests/Commands/RejuvenateTest.cs | 6 +- .../Tests/Commands/RestartRoundTest.cs | 2 +- .../Interaction/ComputerContruction.cs | 10 +- .../Construction/Interaction/CraftingTests.cs | 56 +- .../Interaction/GrilleWindowConstruction.cs | 13 +- .../Interaction/MachineConstruction.cs | 7 +- .../Construction/Interaction/PanelScrewing.cs | 12 +- .../Interaction/PlaceableDeconstruction.cs | 4 +- .../Interaction/WallConstruction.cs | 9 +- .../Interaction/WindowConstruction.cs | 8 +- .../Construction/Interaction/WindowRepair.cs | 2 +- .../Tests/ContainerOcclusionTest.cs | 18 +- .../Tests/Damageable/DamageSpecifierTest.cs | 44 +- .../Tests/Damageable/DamageableTest.cs | 5 +- .../DestructibleDestructionTest.cs | 1 + .../Tests/DoAfter/DoAfterCancellationTests.cs | 39 +- .../Tests/Doors/AirlockTest.cs | 20 +- .../Tests/DummyIconTest.cs | 2 +- .../EncryptionKeys/RemoveEncryptionKeys.cs | 16 +- Content.IntegrationTests/Tests/EntityTest.cs | 12 +- .../Tests/Fluids/FluidSpillTest.cs | 27 +- .../Tests/Fluids/PuddleTest.cs | 14 +- .../Tests/FollowerSystemTest.cs | 5 +- .../Components/ActionBlocking/HandCuffTest.cs | 7 +- .../Components/Mobs/AlertsComponentTests.cs | 15 +- .../Tests/GameRules/AntagPreferenceTest.cs | 2 +- .../Tests/GameRules/FailAndStartPresetTest.cs | 24 +- .../Tests/GameRules/RuleMaxTimeRestartTest.cs | 10 +- .../Tests/Gravity/WeightlessStatusTests.cs | 8 +- .../Tests/GravityGridTest.cs | 30 +- .../Click/InteractionSystemTests.cs | 50 +- .../Tests/Interaction/InRangeUnobstructed.cs | 5 +- .../InteractionTest.EntitySpecifier.cs | 8 +- .../Interaction/InteractionTest.Helpers.cs | 403 +++- .../Tests/Interaction/InteractionTest.cs | 48 +- .../Tests/Linter/StaticFieldValidationTest.cs | 118 +- .../Tests/MachineBoardTest.cs | 11 +- .../Tests/Mapping/MappingTests.cs | 2 +- .../Tests/MaterialArbitrageTest.cs | 17 +- .../Tests/Minds/GhostTests.cs | 44 +- .../Tests/Minds/MindTests.Helpers.cs | 2 +- .../Tests/Movement/BuckleMovementTest.cs | 63 + .../{Interaction => Movement}/MovementTest.cs | 5 +- .../Tests/Movement/PullingTest.cs | 73 + .../{Slipping => Movement}/SlippingTest.cs | 6 +- .../Tests/Networking/PvsCommandTest.cs | 4 +- .../Networking/SimplePredictReconcileTest.cs | 9 +- .../Tests/Payload/ModularGrenadeTests.cs | 14 +- .../Tests/PostMapInitTest.cs | 33 +- .../Tests/Power/PowerTest.cs | 272 ++- .../Tests/PrototypeSaveTest.cs | 5 +- .../Tests/Puller/PullerTest.cs | 2 +- .../Tests/ResearchTest.cs | 4 +- Content.IntegrationTests/Tests/SalvageTest.cs | 4 +- .../Tests/SaveLoadMapTest.cs | 21 +- .../Tests/SaveLoadSaveTest.cs | 20 +- .../Tests/Serialization/SerializationTest.cs | 16 +- .../Tests/Shuttle/DockTest.cs | 5 +- Content.IntegrationTests/Tests/ShuttleTest.cs | 19 +- .../Tests/Sprite/ItemSpriteTest.cs | 10 +- .../Tests/{Minds => Station}/JobTests.cs | 0 .../Tests/Storage/StorageInteractionTest.cs | 75 + Content.IntegrationTests/Tests/Tag/TagTest.cs | 26 +- .../Tests/Tiles/TileConstructionTests.cs | 16 +- .../Tests/Toolshed/ToolshedTest.cs | 8 +- .../Tests/VendingMachineRestockTest.cs | 3 +- .../Tests/Weldable/WeldableTests.cs | 2 +- ...0606065731_RemoveLastReadRules.Designer.cs | 1909 +++++++++++++++++ .../20240606065731_RemoveLastReadRules.cs | 29 + .../PostgresServerDbContextModelSnapshot.cs | 4 - ...0606065717_RemoveLastReadRules.Designer.cs | 1834 ++++++++++++++++ .../20240606065717_RemoveLastReadRules.cs | 29 + .../SqliteServerDbContextModelSnapshot.cs | 4 - Content.Server.Database/Model.cs | 2 - .../Abilities/Mime/MimePowersComponent.cs | 8 + .../Abilities/Mime/MimePowersSystem.cs | 11 +- .../Administration/Managers/AdminManager.cs | 2 + Content.Server/Administration/ServerApi.cs | 2 +- .../Systems/AdminVerbSystem.Smites.cs | 6 +- Content.Server/Alert/Commands/ClearAlert.cs | 7 +- Content.Server/Alert/Commands/ShowAlert.cs | 7 +- Content.Server/Antag/AntagSelectionSystem.cs | 2 +- .../Components/AntagSelectionComponent.cs | 2 +- .../Antag/MobReplacementRuleSystem.cs | 11 +- .../Atmos/Components/BarotraumaComponent.cs | 10 + .../Atmos/Components/FlammableComponent.cs | 4 + .../Atmos/EntitySystems/BarotraumaSystem.cs | 11 +- .../Atmos/EntitySystems/FlammableSystem.cs | 4 +- .../Atmos/EntitySystems/GasAnalyzerSystem.cs | 6 +- .../EntitySystems/GasTileOverlaySystem.cs | 12 +- .../Unary/EntitySystems/GasPortableSystem.cs | 8 +- .../BarSign/Systems/BarSignSystem.cs | 2 +- Content.Server/Bed/BedSystem.cs | 49 +- .../Bed/Components/HealOnBuckleComponent.cs | 21 +- .../Bed/Components/HealOnBuckleHealing.cs | 1 + .../Bed/Components/StasisBedComponent.cs | 3 +- .../Body/Components/BloodstreamComponent.cs | 4 + .../Body/Components/InternalsComponent.cs | 6 + .../Body/Components/LungComponent.cs | 4 +- .../Body/Systems/BloodstreamSystem.cs | 7 +- .../Body/Systems/InternalsSystem.cs | 14 +- .../Body/Systems/MetabolizerSystem.cs | 6 + .../Body/Systems/RespiratorSystem.cs | 3 + .../Cargo/Systems/CargoSystem.Shuttle.cs | 42 +- Content.Server/Cargo/Systems/CargoSystem.cs | 3 + Content.Server/Carrying/CarryingSystem.cs | 4 +- Content.Server/Chat/Systems/ChatSystem.cs | 6 +- Content.Server/Chat/TelepathicChatSystem.cs | 10 +- .../Chemistry/ReagentEffects/AdjustAlert.cs | 8 +- Content.Server/Clothing/MagbootsSystem.cs | 4 +- .../Systems/ChameleonClothingSystem.cs | 4 +- .../Construction/PartExchangerSystem.cs | 7 +- Content.Server/Database/ServerDbBase.cs | 24 - Content.Server/Database/ServerDbManager.cs | 19 - Content.Server/Decals/DecalSystem.cs | 5 +- .../Behaviors/SpawnEntitiesBehavior.cs | 7 +- .../Destructible/Thresholds/MinMax.cs | 26 - .../Systems/NetworkConfiguratorSystem.cs | 2 +- .../Disposal/Tube/DisposalTubeSystem.cs | 16 +- .../Unit/EntitySystems/DisposalUnitSystem.cs | 11 +- Content.Server/Dragon/DragonRiftSystem.cs | 2 +- .../Ensnaring/EnsnareableSystem.Ensnaring.cs | 10 +- Content.Server/Ensnaring/EnsnareableSystem.cs | 2 +- Content.Server/Entry/EntryPoint.cs | 2 - .../GameTicking/GameTicker.GameRule.cs | 3 +- .../GameTicking/GameTicker.Spawning.cs | 15 +- .../GameTicking/Rules/DeathMatchRuleSystem.cs | 2 +- .../GameTicking/Rules/GameRulePrototype.cs | 15 - .../Rules/GameRuleSystem.Utility.cs | 2 +- .../GameTicking/Rules/GameRuleSystem.cs | 2 +- .../Rules/InactivityTimeRestartRuleSystem.cs | 2 +- .../Rules/KillCalloutRuleSystem.cs | 2 +- .../GameTicking/Rules/LoadMapRuleSystem.cs | 4 +- .../Rules/MaxTimeRestartRuleSystem.cs | 2 +- .../GameTicking/Rules/NukeopsRuleSystem.cs | 6 +- .../GameTicking/Rules/RespawnRuleSystem.cs | 3 +- .../Rules/RevolutionaryRuleSystem.cs | 2 +- .../RoundstartStationVariationRuleSystem.cs | 2 +- .../GameTicking/Rules/SandboxRuleSystem.cs | 2 +- .../GameTicking/Rules/SecretRuleSystem.cs | 2 +- .../GameTicking/Rules/SubGamemodesSystem.cs | 2 +- .../GameTicking/Rules/TraitorRuleSystem.cs | 6 +- .../GameTicking/Rules/ZombieRuleSystem.cs | 4 +- Content.Server/Geras/GerasComponent.cs | 2 +- Content.Server/Ghost/GhostSystem.cs | 28 +- Content.Server/Gravity/GravitySystem.cs | 4 +- .../Holiday/Christmas/RandomGiftSystem.cs | 2 +- Content.Server/HotPotato/HotPotatoSystem.cs | 4 +- .../HumanoidAppearanceSystem.Modifier.cs | 6 +- .../Systems/HumanoidAppearanceSystem.cs | 13 +- Content.Server/Info/InfoSystem.cs | 35 - Content.Server/Info/RulesManager.cs | 48 - Content.Server/Info/ShowRulesCommand.cs | 14 +- .../Instruments/SwappableInstrumentSystem.cs | 2 +- .../Actions/ChangeStandingStateAction.cs | 2 +- Content.Server/IoC/ServerContentIoC.cs | 2 - .../Kitchen/EntitySystems/MicrowaveSystem.cs | 8 +- .../EntitySystems/ReagentGrinderSystem.cs | 10 +- .../EntitySystems/RotatingLightSystem.cs | 2 +- Content.Server/Lightning/LightningSystem.cs | 22 +- .../Materials/MaterialReclaimerSystem.cs | 2 +- .../EntitySystems/MechGrabberSystem.cs | 10 +- Content.Server/Mech/Systems/MechSystem.cs | 10 +- Content.Server/Mood/MoodComponent.cs | 30 +- Content.Server/Mood/MoodSystem.cs | 4 +- .../Operators/Combat/UnbuckleOperator.cs | 7 +- Content.Server/NPC/Systems/NPCJukeSystem.cs | 10 +- .../Systems/NPCSteeringSystem.Obstacles.cs | 2 +- .../NPC/Systems/NPCSteeringSystem.cs | 1 + .../NameIdentifier/NameIdentifierSystem.cs | 2 +- .../Ninja/Systems/SpaceNinjaSystem.cs | 11 +- .../Commands/TileWindowsCommand.cs | 20 +- .../PlayTimeTrackingManager.Whitelist.cs | 2 +- .../StationEvents/Events/MidRoundAntagRule.cs | 2 +- Content.Server/Objectives/ObjectivesSystem.cs | 2 +- Content.Server/OfferItem/OfferItemSystem.cs | 4 +- .../Physics/Controllers/ConveyorController.cs | 4 +- Content.Server/Pinpointer/NavMapSystem.cs | 14 +- .../PowerMonitoringConsoleSystem.cs | 2 +- .../PowerCell/PowerCellSystem.Draw.cs | 4 +- Content.Server/Psionics/Dreams/DreamSystem.cs | 2 +- .../Research/Systems/ResearchSystem.Server.cs | 8 +- .../Systems/ResearchSystem.Technology.cs | 8 +- .../Revenant/EntitySystems/RevenantSystem.cs | 2 +- .../Salvage/SalvageSystem.Runner.cs | 8 +- Content.Server/Shadowkin/ShadowkinSystem.cs | 12 +- .../Shuttles/Systems/ShuttleConsoleSystem.cs | 6 +- .../Systems/ShuttleSystem.FasterThanLight.cs | 32 +- .../Shuttles/Systems/ShuttleSystem.cs | 2 + .../Charge/Systems/SiliconChargeSystem.cs | 12 +- Content.Server/Silicons/Borgs/BorgSystem.cs | 22 +- .../Components/EntityTableSpawnerComponent.cs | 30 + .../EntitySystems/ConditionalSpawnerSystem.cs | 31 +- Content.Server/Sprite/RandomSpriteSystem.cs | 2 +- .../BasicStationEventSchedulerSystem.cs | 4 +- .../Events/AlertLevelInterceptionRule.cs | 4 +- .../StationEvents/Events/AnomalySpawnRule.cs | 5 +- .../Events/BluespaceArtifactRule.cs | 3 +- .../Events/BluespaceLockerRule.cs | 2 +- .../StationEvents/Events/BreakerFlipRule.cs | 3 +- .../Events/BureaucraticErrorRule.cs | 2 +- .../StationEvents/Events/CargoGiftsRule.cs | 3 +- .../StationEvents/Events/ClericalErrorRule.cs | 2 +- .../StationEvents/Events/FalseAlarmRule.cs | 3 +- .../StationEvents/Events/FreeProberRule.cs | 15 +- .../StationEvents/Events/GasLeakRule.cs | 2 +- .../Events/GlimmerEventSystem.cs | 2 +- .../Events/GlimmerMobSpawnRule.cs | 2 +- .../Events/GlimmerRandomSentienceRule.cs | 2 +- .../Events/GlimmerRevenantSpawnRule.cs | 2 +- .../StationEvents/Events/ImmovableRodRule.cs | 4 +- .../StationEvents/Events/IonStormRule.cs | 2 +- .../StationEvents/Events/KudzuGrowthRule.cs | 2 +- .../Events/MassHallucinationsRule.cs | 2 +- .../StationEvents/Events/MassMindSwapRule.cs | 2 +- .../StationEvents/Events/MeteorSwarmRule.cs | 2 +- .../StationEvents/Events/NinjaSpawnRule.cs | 2 +- .../StationEvents/Events/NoosphericFryRule.cs | 13 +- .../Events/NoosphericStormRule.cs | 2 +- .../StationEvents/Events/NoosphericZapRule.cs | 2 +- .../Events/PirateRadioSpawnRule.cs | 2 +- .../Events/PowerGridCheckRule.cs | 2 +- .../Events/PsionicCatGotYourTongueRule.cs | 2 +- .../Events/RandomEntityStorageSpawnRule.cs | 2 +- .../Events/RandomSentienceRule.cs | 7 +- .../StationEvents/Events/RandomSpawnRule.cs | 2 +- .../StationEvents/Events/SolarFlareRule.cs | 2 +- .../Events/StationEventSystem.cs | 2 +- .../StationEvents/Events/VentClogRule.cs | 2 +- .../StationEvents/Events/VentCrittersRule.cs | 2 +- .../OscillatingStationEventScheduler.cs | 2 +- .../RampingStationEventSchedulerSystem.cs | 2 +- .../Components/TemperatureComponent.cs | 8 + .../Temperature/Systems/TemperatureSystem.cs | 14 +- .../Assorted/ForeignerTraitComponent.cs | 2 +- .../Traits/Assorted/ParacusiaSystem.cs | 6 +- .../Ranged/Systems/GunSystem.Battery.cs | 2 +- .../Ranged/Systems/GunSystem.Revolver.cs | 2 +- .../Systems/RandomInstrumentArtifactSystem.cs | 2 +- .../Zombies/ZombieSystem.Transform.cs | 2 +- .../Actions/Events/FabricateActionEvent.cs | 2 +- Content.Shared/Alert/AlertCategory.cs | 21 - .../Alert/AlertCategoryPrototype.cs | 14 + Content.Shared/Alert/AlertKey.cs | 12 +- Content.Shared/Alert/AlertOrderPrototype.cs | 35 +- Content.Shared/Alert/AlertPrototype.cs | 206 +- Content.Shared/Alert/AlertState.cs | 3 +- Content.Shared/Alert/AlertType.cs | 78 - Content.Shared/Alert/AlertsSystem.cs | 26 +- Content.Shared/Alert/ClickAlertEvent.cs | 7 +- .../Buckle/Components/BuckleComponent.cs | 113 +- .../Buckle/Components/StrapComponent.cs | 53 +- .../Buckle/SharedBuckleSystem.Buckle.cs | 571 +++-- .../Buckle/SharedBuckleSystem.Interaction.cs | 200 ++ .../Buckle/SharedBuckleSystem.Strap.cs | 257 +-- Content.Shared/Buckle/SharedBuckleSystem.cs | 49 +- Content.Shared/CCVar/CCVars.cs | 18 +- .../Chapel/SharedSacrificialAltarSystem.cs | 4 +- .../Climbing/Systems/ClimbSystem.cs | 6 +- .../SharedChameleonClothingSystem.cs | 2 +- .../Loadouts/Systems/LoadoutSystem.cs | 3 +- Content.Shared/Clothing/MagbootsComponent.cs | 4 + .../Pacification/PacificationSystem.cs | 5 +- .../Pacification/PacifiedComponent.cs | 4 + .../Containers/ContainerFillSystem.cs | 37 + .../EntityTableContainerFillComponent.cs | 13 + .../Containers/ItemSlot/ItemSlotsSystem.cs | 6 +- .../Cuffs/Components/CuffableComponent.cs | 5 + Content.Shared/Cuffs/SharedCuffableSystem.cs | 34 +- .../Damage/Components/StaminaComponent.cs | 7 +- .../Damage/Systems/StaminaSystem.cs | 17 +- Content.Shared/Decals/SharedDecalSystem.cs | 2 +- .../Destructible/Thresholds/MinMax.cs | 24 + Content.Shared/Dice/SharedDiceSystem.cs | 2 +- .../SharedElectrocutionSystem.cs | 2 +- Content.Shared/Emoting/EmoteSystem.cs | 2 +- .../Components/EnsnareableComponent.cs | 5 + .../EntitySelectors/AllSelector.cs | 25 + .../EntitySelectors/EntSelector.cs | 27 + .../EntitySelectors/EntityTableSelector.cs | 49 + .../EntitySelectors/GroupSelector.cs | 28 + .../EntitySelectors/NestedSelector.cs | 20 + .../EntitySelectors/NoneSelector.cs | 16 + .../EntityTable/EntityTablePrototype.cs | 18 + .../EntityTable/EntityTableSystem.cs | 20 + .../ValueSelector/ConstantNumberSelector.cs | 22 + .../ValueSelector/NumberSelector.cs | 16 + .../ValueSelector/RangeNumberSelector.cs | 19 + Content.Shared/Examine/ExamineSystemShared.cs | 30 +- .../OnTrigger/SmokeOnTriggerComponent.cs | 2 +- Content.Shared/Foldable/FoldableSystem.cs | 6 +- .../Friction/TileFrictionController.cs | 2 +- .../Components/ActiveGameRuleComponent.cs | 6 +- .../Components/DelayedStartRuleComponent.cs | 2 +- .../Components/EndedGameRuleComponent.cs | 6 +- .../Components/GameRuleComponent.cs | 5 +- .../Gravity/SharedFloatingVisualizerSystem.cs | 2 +- .../Gravity/SharedGravitySystem.Shake.cs | 4 +- Content.Shared/Gravity/SharedGravitySystem.cs | 15 +- .../EntitySystems/SharedHandsSystem.Drop.cs | 4 +- .../SharedHumanoidAppearanceSystem.cs | 24 +- .../Implants/SharedImplanterSystem.cs | 4 +- Content.Shared/Info/RulesMessages.cs | 25 + Content.Shared/Info/SharedInfo.cs | 28 - Content.Shared/Info/SharedRulesManager.cs | 60 - .../Instruments/SharedInstrumentSystem.cs | 4 +- .../Interaction/RotateToFaceSystem.cs | 32 +- .../Interaction/SharedInteractionSystem.cs | 2 +- .../Item/ItemToggle/SharedItemToggleSystem.cs | 19 +- .../Light/SharedHandheldLightSystem.cs | 2 +- .../Light/SharedRgbLightControllerSystem.cs | 6 +- .../Mech/EntitySystems/SharedMechSystem.cs | 6 +- .../Medical/CPR/Systems/CPRSystem.cs | 8 +- .../Mobs/Components/MobThresholdsComponent.cs | 28 +- .../Systems/MobStateSystem.Subscribers.cs | 18 +- .../Mobs/Systems/MobThresholdSystem.cs | 2 +- .../Pulling/Components/PullableComponent.cs | 4 + .../Pulling/Components/PullerComponent.cs | 6 +- .../Pulling/Events/PullStartedMessage.cs | 11 +- .../Pulling/Events/PullStoppedMessage.cs | 13 +- .../Movement/Pulling/Systems/PullingSystem.cs | 66 +- .../Movement/Systems/SharedMoverController.cs | 2 +- .../Systems/SpeedModifierContactsSystem.cs | 2 +- .../Ninja/Components/SpaceNinjaComponent.cs | 4 + .../Nutrition/Components/HungerComponent.cs | 14 +- .../Nutrition/Components/ThirstComponent.cs | 12 +- .../Nutrition/EntitySystems/HungerSystem.cs | 8 +- .../Nutrition/EntitySystems/ThirstSystem.cs | 2 +- .../OfferItem/OfferItemComponent.cs | 5 + Content.Shared/PAI/PAIComponent.cs | 2 +- .../Controllers/SharedConveyorController.cs | 4 +- .../Preferences/HumanoidCharacterProfile.cs | 36 +- Content.Shared/RCD/Systems/RCDAmmoSystem.cs | 4 +- .../Random/Helpers/SharedRandomExtensions.cs | 48 +- .../Revenant/Components/RevenantComponent.cs | 4 + .../Shadowkin/ShadowkinComponent.cs | 5 + Content.Shared/Showers/SharedShowerSystem.cs | 7 +- .../Shuttles/Components/FTLComponent.cs | 16 +- .../Components/FtlVisualizerComponent.cs | 23 + .../Shuttles/Components/PilotComponent.cs | 5 + .../Silicon/Systems/SharedSiliconSystem.cs | 4 +- .../Borgs/Components/BorgChassisComponent.cs | 10 +- .../EntitySystems/SharedEventHorizonSystem.cs | 8 +- Content.Shared/Stacks/SharedStackSystem.cs | 6 +- .../Standing/SharedLayingDownSystem.cs | 4 +- .../Standing/StandingStateSystem.cs | 6 +- .../StationRecordKeyStorageSystem.cs | 2 +- .../StatusEffect/StatusEffectPrototype.cs | 2 +- .../StatusEffect/StatusEffectsSystem.cs | 14 +- .../Storage/EntitySystems/BinSystem.cs | 6 +- Content.Shared/Stunnable/SharedStunSystem.cs | 24 +- .../SubFloor/SharedTrayScannerSystem.cs | 2 +- Content.Shared/Tag/TagSystem.cs | 54 +- .../Systems/LinkedEntitySystem.cs | 6 +- .../Assorted/Systems/LegsParalyzedSystem.cs | 27 +- .../Assorted/Systems/SharedSingerSystem.cs | 2 +- .../Marker/SharedDamageMarkerSystem.cs | 4 +- .../Weapons/Misc/SharedTetherGunSystem.cs | 22 +- .../Systems/RechargeBasicEntityAmmoSystem.cs | 8 +- .../Ranged/Systems/RechargeCycleAmmoSystem.cs | 2 +- .../Weapons/Ranged/Systems/SharedGunSystem.cs | 2 +- .../Weapons/Reflect/ReflectSystem.cs | 7 +- Content.Shared/Weather/SharedWeatherSystem.cs | 20 +- .../Shared/Alert/AlertManagerTests.cs | 17 +- .../Shared/Alert/AlertOrderPrototypeTests.cs | 26 +- .../Shared/Alert/AlertPrototypeTests.cs | 6 +- .../EinsteinEngines/default.toml | 3 +- Resources/Locale/en-US/guidebook/guides.ftl | 55 + Resources/Locale/en-US/info/rules.ftl | 3 + Resources/Prototypes/Actions/borgs.yml | 2 +- Resources/Prototypes/Actions/crit.yml | 6 +- Resources/Prototypes/Actions/diona.yml | 4 +- Resources/Prototypes/Actions/internals.yml | 2 +- Resources/Prototypes/Actions/mech.yml | 6 +- Resources/Prototypes/Actions/misc.yml | 2 +- Resources/Prototypes/Actions/ninja.yml | 12 +- Resources/Prototypes/Actions/polymorph.yml | 8 +- Resources/Prototypes/Actions/psionics.yml | 40 +- Resources/Prototypes/Actions/revenant.yml | 10 +- Resources/Prototypes/Actions/speech.yml | 2 +- Resources/Prototypes/Actions/spider.yml | 4 +- Resources/Prototypes/Actions/types.yml | 60 +- Resources/Prototypes/Alerts/categories.yml | 38 + .../Prototypes/Body/Organs/Animal/animal.yml | 12 +- .../Body/Organs/Animal/bloodsucker.yml | 6 +- .../Body/Organs/Animal/ruminant.yml | 2 +- .../Prototypes/Body/Organs/Friendstomach.yml | 2 +- Resources/Prototypes/Body/Organs/arachnid.yml | 4 +- Resources/Prototypes/Body/Organs/diona.yml | 12 +- Resources/Prototypes/Body/Organs/moth.yml | 2 +- .../Prototypes/Body/Organs/reptilian.yml | 2 +- Resources/Prototypes/Body/Parts/animal.yml | 8 +- Resources/Prototypes/Body/Parts/rat.yml | 2 +- Resources/Prototypes/Body/Parts/silicon.yml | 2 +- .../Fills/Backpacks/StarterGear/backpack.yml | 67 +- .../Fills/Backpacks/StarterGear/duffelbag.yml | 54 +- .../Fills/Backpacks/StarterGear/satchel.yml | 56 +- .../Prototypes/Catalog/Fills/Crates/fun.yml | 98 + .../Catalog/Fills/Crates/salvage.yml | 2 +- .../Prototypes/Catalog/Fills/Lockers/misc.yml | 461 ++-- .../DeltaV/Body/Organs/vulpkanin.yml | 2 +- .../Fills/Backpacks/StarterGear/backpack.yml | 6 +- .../Fills/Backpacks/StarterGear/duffelbag.yml | 6 +- .../Fills/Backpacks/StarterGear/satchel.yml | 6 +- .../Clothing/Head/hardsuit-helmets.yml | 8 +- .../Entities/Markers/Spawners/ghost_roles.yml | 2 +- .../DeltaV/Entities/Mobs/Player/human.yml | 2 +- .../Entities/Mobs/Species/vulpkanin.yml | 2 +- .../Objects/Misc/subdermal_implants.yml | 2 +- .../Entities/Objects/Specific/Mail/mail.yml | 120 +- .../Objects/Specific/Mail/mail_civilian.yml | 24 +- .../Objects/Specific/Mail/mail_command.yml | 6 +- .../Specific/Mail/mail_engineering.yml | 14 +- .../Specific/Mail/mail_epistemology.yml | 8 +- .../Objects/Specific/Mail/mail_medical.yml | 14 +- .../Objects/Specific/Mail/mail_security.yml | 14 +- .../Ammunition/Projectiles/replicated.yml | 2 +- .../Guns/Ammunition/Projectiles/special.yml | 14 +- .../Weapons/Guns/Projectiles/impacts.yml | 2 +- .../Prototypes/DeltaV/GameRules/events.yml | 8 +- .../Prototypes/DeltaV/GameRules/midround.yml | 2 +- .../DeltaV/Objectives/paradox_anomaly.yml | 6 +- .../Prototypes/DeltaV/Objectives/traitor.yml | 6 +- .../DeltaV/Roles/Jobs/NPC/syndicateNPCs.yml | 2 +- .../Prototypes/Entities/Clothing/Eyes/hud.yml | 2 +- .../Clothing/Head/base_clothinghead.yml | 8 +- .../Clothing/Head/hardsuit-helmets.yml | 2 +- .../Entities/Clothing/Head/hoods.yml | 56 +- .../Clothing/Masks/base_clothingmask.yml | 2 +- .../Entities/Clothing/Neck/misc.yml | 2 +- .../Clothing/OuterClothing/wintercoats.yml | 2 +- .../Entities/Clothing/Shoes/magboots.yml | 10 +- .../Entities/Clothing/Shoes/misc.yml | 2 +- .../Entities/Debugging/clicktest.yml | 2 +- .../Entities/Debugging/debug_sweps.yml | 2 +- .../Prototypes/Entities/Debugging/tippy.yml | 2 +- .../Entities/Effects/ambient_sounds.yml | 2 +- .../Entities/Effects/bluespace_flash.yml | 14 +- .../Entities/Effects/chemistry_effects.yml | 10 +- .../Entities/Effects/emp_effects.yml | 4 +- .../Entities/Effects/exclamation.yml | 4 +- .../Entities/Effects/explosion_light.yml | 2 +- .../Prototypes/Entities/Effects/hearts.yml | 2 +- .../Prototypes/Entities/Effects/lightning.yml | 12 +- .../Prototypes/Entities/Effects/mobspawn.yml | 2 +- .../Prototypes/Entities/Effects/radiation.yml | 2 +- Resources/Prototypes/Entities/Effects/rcd.yml | 22 +- .../Prototypes/Entities/Effects/shuttle.yml | 12 + .../Prototypes/Entities/Effects/sparks.yml | 4 +- .../Entities/Effects/weapon_arc.yml | 22 +- .../Markers/Spawners/Random/maintenance.yml | 792 ++++--- .../Entities/Markers/Spawners/corpses.yml | 2 +- .../Entities/Markers/Spawners/ghost_roles.yml | 6 +- .../Entities/Markers/clientsideclone.yml | 2 +- .../Entities/Markers/construction_ghost.yml | 2 +- .../Entities/Markers/drag_shadow.yml | 2 +- .../Entities/Markers/hover_entity.yml | 2 +- .../Entities/Mobs/Corpses/corpses.yml | 2 +- .../Prototypes/Entities/Mobs/NPCs/Rslimes.yml | 2 +- .../Prototypes/Entities/Mobs/NPCs/animals.yml | 2 +- .../Entities/Mobs/NPCs/regalrat.yml | 14 +- .../Prototypes/Entities/Mobs/NPCs/slimes.yml | 2 +- .../Prototypes/Entities/Mobs/NPCs/xenopet.yml | 14 +- .../Entities/Mobs/Player/admin_ghost.yml | 14 +- .../Prototypes/Entities/Mobs/Player/diona.yml | 2 +- .../Entities/Mobs/Player/dragon.yml | 8 +- .../Entities/Mobs/Player/guardian.yml | 2 +- .../Prototypes/Entities/Mobs/Player/human.yml | 6 +- .../Prototypes/Entities/Mobs/Player/ipc.yml | 2 +- .../Entities/Mobs/Player/observer.yml | 12 +- .../Entities/Mobs/Player/replay_observer.yml | 2 +- .../Entities/Mobs/Player/silicon.yml | 2 +- .../Entities/Mobs/Species/arachne.yml | 2 +- .../Entities/Mobs/Species/arachnid.yml | 2 +- .../Entities/Mobs/Species/diona.yml | 2 +- .../Entities/Mobs/Species/dwarf.yml | 2 +- .../Entities/Mobs/Species/gingerbread.yml | 2 +- .../Entities/Mobs/Species/harpy.yml | 6 +- .../Entities/Mobs/Species/human.yml | 2 +- .../Prototypes/Entities/Mobs/Species/moth.yml | 2 +- .../Entities/Mobs/Species/reptilian.yml | 2 +- .../Entities/Mobs/Species/shadowkin.yml | 2 +- .../Entities/Mobs/Species/skeleton.yml | 2 +- .../Entities/Mobs/Species/slime.yml | 2 +- .../Prototypes/Entities/Mobs/Species/vox.yml | 2 +- .../Consumable/Food/Containers/box.yml | 2 +- .../Objects/Consumable/Food/snacks.yml | 60 +- .../Consumable/Smokeables/Vapes/vape.yml | 2 +- .../Entities/Objects/Decoration/present.yml | 2 +- .../Objects/Devices/chameleon_projector.yml | 6 +- .../Objects/Devices/translator_implants.yml | 22 +- .../Entities/Objects/Devices/translators.yml | 8 +- .../Objects/Fun/Tabletop/backgammon.yml | 2 +- .../Entities/Objects/Fun/Tabletop/base.yml | 2 +- .../Objects/Fun/Tabletop/checkers.yml | 2 +- .../Entities/Objects/Fun/Tabletop/chess.yml | 2 +- .../Entities/Objects/Fun/Tabletop/dnd.yml | 10 +- .../Entities/Objects/Fun/Tabletop/parchis.yml | 2 +- .../Prototypes/Entities/Objects/Fun/pai.yml | 4 +- .../Entities/Objects/Fun/spray_paint.yml | 2 +- .../Entities/Objects/Misc/buffering.yml | 2 +- .../Objects/Misc/fire_extinguisher.yml | 2 +- .../Entities/Objects/Misc/paper.yml | 2 +- .../Objects/Misc/subdermal_implants.yml | 30 +- .../Entities/Objects/Power/lights.yml | 2 +- .../Objects/Specific/Chapel/bibles.yml | 2 +- .../Objects/Specific/Forensics/forensics.yml | 2 +- .../Objects/Specific/Janitorial/soap.yml | 2 +- .../Objects/Specific/Janitorial/spray.yml | 4 +- .../Objects/Specific/Mail/Items/misc.yml | 6 +- .../Objects/Specific/Mail/base_mail_large.yml | 2 +- .../Specific/Robotics/borg_modules.yml | 2 +- .../Objects/Specific/chemical-containers.yml | 48 +- .../Entities/Objects/Tools/fulton.yml | 2 +- .../Entities/Objects/Tools/glowstick.yml | 12 +- .../Entities/Objects/Tools/jetpacks.yml | 4 +- .../Entities/Objects/Weapons/Bombs/funny.yml | 2 +- .../Ammunition/Projectiles/antimateriel.yml | 2 +- .../Ammunition/Projectiles/caseless_rifle.yml | 6 +- .../Guns/Ammunition/Projectiles/grenade.yml | 6 +- .../Ammunition/Projectiles/heavy_rifle.yml | 4 +- .../Ammunition/Projectiles/light_rifle.yml | 10 +- .../Guns/Ammunition/Projectiles/magnum.yml | 12 +- .../Guns/Ammunition/Projectiles/pistol.yml | 10 +- .../Guns/Ammunition/Projectiles/rifle.yml | 10 +- .../Guns/Ammunition/Projectiles/shotgun.yml | 22 +- .../Weapons/Guns/Projectiles/hitscan.yml | 2 +- .../Weapons/Guns/Projectiles/impacts.yml | 8 +- .../Weapons/Guns/Projectiles/magic.yml | 24 +- .../Weapons/Guns/Projectiles/meteors.yml | 2 +- .../Weapons/Guns/Projectiles/projectiles.yml | 80 +- .../Objects/Weapons/Throwable/grenades.yml | 4 +- .../Entities/Stations/nanotrasen.yml | 8 +- .../Entities/Stations/syndicate.yml | 2 +- .../Prototypes/Entities/Stations/test.yml | 2 +- .../Entities/Structures/Furniture/chairs.yml | 2 + .../Structures/Furniture/rollerbeds.yml | 7 + .../Structures/Piping/Disposal/pipes.yml | 2 +- .../Power/Generation/PA/particles.yml | 4 +- .../Structures/Power/Generation/ame.yml | 2 +- .../Power/Generation/generators.yml | 2 +- .../Structures/Power/Generation/solar.yml | 2 +- .../Structures/Power/Generation/teg.yml | 2 +- .../Entities/Structures/Power/apc.yml | 4 +- .../Entities/Structures/Power/substation.yml | 4 +- .../Storage/Canisters/gas_canisters.yml | 22 +- .../Storage/Crates/base_structurecrates.yml | 4 +- .../Structures/Wallmounts/Signs/bar_sign.yml | 2 +- .../Entities/Structures/Wallmounts/switch.yml | 4 +- .../Entities/Structures/Wallmounts/timer.yml | 2 +- .../Prototypes/Entities/Virtual/beam.yml | 2 +- .../Entities/Virtual/electrocution.yml | 6 +- .../Entities/Virtual/stripping_hidden.yml | 2 +- .../Prototypes/Entities/Virtual/tether.yml | 2 +- .../Entities/Virtual/virtual_item.yml | 2 +- .../Entities/World/Debris/asteroids.yml | 16 +- .../Entities/World/Debris/wrecks.yml | 6 +- Resources/Prototypes/Entities/World/chunk.yml | 2 +- .../Prototypes/GameRules/cargo_gifts.yml | 20 +- Resources/Prototypes/GameRules/events.yml | 60 +- Resources/Prototypes/GameRules/midround.yml | 8 +- Resources/Prototypes/GameRules/roundstart.yml | 34 +- .../Prototypes/GameRules/unknown_shuttles.yml | 10 +- Resources/Prototypes/GameRules/variation.yml | 16 +- Resources/Prototypes/Guidebook/rules.yml | 362 ++++ Resources/Prototypes/Guidebook/ss14.yml | 1 + Resources/Prototypes/Magic/event_spells.yml | 2 +- .../Prototypes/Magic/forcewall_spells.yml | 2 +- Resources/Prototypes/Magic/knock_spell.yml | 2 +- .../Prototypes/Magic/projectile_spells.yml | 6 +- Resources/Prototypes/Magic/rune_spells.yml | 8 +- Resources/Prototypes/Magic/smite_spells.yml | 2 +- Resources/Prototypes/Magic/spawn_spells.yml | 2 +- Resources/Prototypes/Magic/staves.yml | 2 +- .../Prototypes/Magic/teleport_spells.yml | 2 +- Resources/Prototypes/Magic/utility_spells.yml | 2 +- .../Prototypes/Nyanotrasen/Actions/types.yml | 4 +- .../Fills/Backpacks/StarterGear/backpack.yml | 2 +- .../Fills/Backpacks/StarterGear/duffelbag.yml | 2 +- .../Fills/Backpacks/StarterGear/satchel.yml | 2 +- .../Nyanotrasen/Catalog/Fills/Books/lore.yml | 2 +- .../Catalog/Fills/Paper/salvage_lore.yml | 8 +- .../Clothing/Head/hardsuit-helmets.yml | 6 +- .../Entities/Effects/lightning.yml | 2 +- .../Entities/Markers/Spawners/ghost_roles.yml | 6 +- .../Entities/Mobs/Player/special.yml | 2 +- .../Nyanotrasen/Entities/Mobs/Species/Oni.yml | 2 +- .../Entities/Mobs/Species/felinid.yml | 2 +- .../Objects/Consumable/Food/ration.yml | 2 +- .../Objects/Specific/Mail/base_mail.yml | 2 +- .../Weapons/Guns/Projectiles/shotgun.yml | 2 +- .../Nyanotrasen/GameRules/events.yml | 30 +- .../Nyanotrasen/Objectives/traitor.yml | 6 +- Resources/Prototypes/Objectives/dragon.yml | 4 +- Resources/Prototypes/Objectives/ninja.yml | 12 +- Resources/Prototypes/Objectives/thief.yml | 82 +- Resources/Prototypes/Objectives/traitor.yml | 42 +- .../Prototypes/Roles/Jobs/Civilian/mime.yml | 2 +- .../Guidebook/ServerRules/BanDurations.xml | 17 + .../Guidebook/ServerRules/BanTypes.xml | 11 + .../ServerRules/CoreRules/RuleC0.xml | 19 + .../ServerRules/CoreRules/RuleC10AHelp.xml | 29 + .../CoreRules/RuleC11AhelpThreats.xml | 20 + .../ServerRules/CoreRules/RuleC12MinAge.xml | 6 + .../CoreRules/RuleC13CharacterNames.xml | 66 + .../ServerRules/CoreRules/RuleC14ICinOOC.xml | 13 + .../ServerRules/CoreRules/RuleC1Admins.xml | 6 + .../ServerRules/CoreRules/RuleC2DBAD.xml | 7 + .../ServerRules/CoreRules/RuleC3NoHate.xml | 20 + .../ServerRules/CoreRules/RuleC4NoERP.xml | 23 + .../ServerRules/CoreRules/RuleC5Metacomms.xml | 18 + .../CoreRules/RuleC6BanEvasion.xml | 15 + .../CoreRules/RuleC7EnglishOnly.xml | 10 + .../ServerRules/CoreRules/RuleC8Exploits.xml | 12 + .../ServerRules/CoreRules/RuleC9Multikey.xml | 7 + .../Guidebook/ServerRules/DefaultRules.xml | 5 + .../Guidebook/ServerRules/README.txt | 5 + .../Guidebook/ServerRules/RoleTypes.xml | 21 + .../ServerRules/RoleplayRules/RuleR0.xml | 26 + .../RoleplayRules/RuleR10Subordination.xml | 26 + .../RuleR11-1AnimalEscalation.xml | 36 + .../RoleplayRules/RuleR11-2ConflictTypes.xml | 30 + .../RoleplayRules/RuleR11Escalation.xml | 67 + .../RoleplayRules/RuleR12RoleAbandonment.xml | 28 + .../RoleplayRules/RuleR13PerformRole.xml | 26 + .../RoleplayRules/RuleR14SecComStandard.xml | 37 + .../RoleplayRules/RuleR15SpaceLaw.xml | 21 + .../RoleplayRules/RuleR1Silicons.xml | 4 + .../RoleplayRules/RuleR2Familiars.xml | 6 + .../RoleplayRules/RuleR3NormalRP.xml | 20 + .../RoleplayRules/RuleR4Metashield.xml | 103 + .../RoleplayRules/RuleR5Arrivals.xml | 22 + .../RoleplayRules/RuleR6SelfAntag.xml | 22 + .../RoleplayRules/RuleR7RoundStalling.xml | 16 + .../RoleplayRules/RuleR8NoFriendlyAntag.xml | 22 + .../RoleplayRules/RuleR9MassSabotage.xml | 23 + .../ServerRules/SiliconRules/RuleS0.xml | 15 + .../SiliconRules/RuleS10OrderConflicts.xml | 9 + .../ServerRules/SiliconRules/RuleS1Laws.xml | 6 + .../SiliconRules/RuleS2LawPriority.xml | 9 + .../SiliconRules/RuleS3LawRedefinition.xml | 8 + .../SiliconRules/RuleS4RequestChanges.xml | 6 + .../SiliconRules/RuleS5FreeSilicon.xml | 4 + .../SiliconRules/RuleS6UnreasonableOrders.xml | 22 + .../SiliconRules/RuleS7Consistency.xml | 6 + .../RuleS8DefaultCrewDefinition.xml | 4 + .../RuleS9DefaultHarmDefinition.xml | 25 + .../SpaceLaw/SLControlledSubstances.xml | 14 + .../ServerRules/SpaceLaw/SLRestrictedGear.xml | 21 + .../SpaceLaw/SLRestrictedWeapons.xml | 11 + .../ServerRules/SpaceLaw/SpaceLaw.xml | 67 + .../ServerRules/WizDenCoreOnlyRules.xml | 26 + .../Guidebook/ServerRules/WizDenLRPRules.xml | 65 + .../Guidebook/ServerRules/WizDenMRPRules.xml | 65 + Resources/ServerInfo/Rules.txt | 60 - .../Effects/medi_holo.rsi/medi_holo.png | Bin 0 -> 1286 bytes .../Textures/Effects/medi_holo.rsi/meta.json | 26 + RobustToolbox | 2 +- 713 files changed, 11681 insertions(+), 4685 deletions(-) create mode 100644 Content.Client/Clickable/ClickableSystem.cs delete mode 100644 Content.Client/Info/InfoSystem.cs delete mode 100644 Content.Client/Info/RulesManager.cs create mode 100644 Content.Client/Shuttles/FtlArrivalOverlay.cs create mode 100644 Content.Client/Shuttles/Systems/ShuttleSystem.cs create mode 100644 Content.IntegrationTests/Tests/Buckle/BuckleDragTest.cs create mode 100644 Content.IntegrationTests/Tests/Buckle/BuckleTest.Interact.cs create mode 100644 Content.IntegrationTests/Tests/Movement/BuckleMovementTest.cs rename Content.IntegrationTests/Tests/{Interaction => Movement}/MovementTest.cs (93%) create mode 100644 Content.IntegrationTests/Tests/Movement/PullingTest.cs rename Content.IntegrationTests/Tests/{Slipping => Movement}/SlippingTest.cs (92%) rename Content.IntegrationTests/Tests/{Minds => Station}/JobTests.cs (100%) create mode 100644 Content.IntegrationTests/Tests/Storage/StorageInteractionTest.cs create mode 100644 Content.Server.Database/Migrations/Postgres/20240606065731_RemoveLastReadRules.Designer.cs create mode 100644 Content.Server.Database/Migrations/Postgres/20240606065731_RemoveLastReadRules.cs create mode 100644 Content.Server.Database/Migrations/Sqlite/20240606065717_RemoveLastReadRules.Designer.cs create mode 100644 Content.Server.Database/Migrations/Sqlite/20240606065717_RemoveLastReadRules.cs delete mode 100644 Content.Server/Destructible/Thresholds/MinMax.cs delete mode 100644 Content.Server/GameTicking/Rules/GameRulePrototype.cs delete mode 100644 Content.Server/Info/InfoSystem.cs delete mode 100644 Content.Server/Info/RulesManager.cs create mode 100644 Content.Server/Spawners/Components/EntityTableSpawnerComponent.cs delete mode 100644 Content.Shared/Alert/AlertCategory.cs create mode 100644 Content.Shared/Alert/AlertCategoryPrototype.cs delete mode 100644 Content.Shared/Alert/AlertType.cs create mode 100644 Content.Shared/Buckle/SharedBuckleSystem.Interaction.cs create mode 100644 Content.Shared/Containers/EntityTableContainerFillComponent.cs create mode 100644 Content.Shared/Destructible/Thresholds/MinMax.cs create mode 100644 Content.Shared/EntityTable/EntitySelectors/AllSelector.cs create mode 100644 Content.Shared/EntityTable/EntitySelectors/EntSelector.cs create mode 100644 Content.Shared/EntityTable/EntitySelectors/EntityTableSelector.cs create mode 100644 Content.Shared/EntityTable/EntitySelectors/GroupSelector.cs create mode 100644 Content.Shared/EntityTable/EntitySelectors/NestedSelector.cs create mode 100644 Content.Shared/EntityTable/EntitySelectors/NoneSelector.cs create mode 100644 Content.Shared/EntityTable/EntityTablePrototype.cs create mode 100644 Content.Shared/EntityTable/EntityTableSystem.cs create mode 100644 Content.Shared/EntityTable/ValueSelector/ConstantNumberSelector.cs create mode 100644 Content.Shared/EntityTable/ValueSelector/NumberSelector.cs create mode 100644 Content.Shared/EntityTable/ValueSelector/RangeNumberSelector.cs rename {Content.Server => Content.Shared}/GameTicking/Components/ActiveGameRuleComponent.cs (67%) rename {Content.Server => Content.Shared}/GameTicking/Components/DelayedStartRuleComponent.cs (91%) rename {Content.Server => Content.Shared}/GameTicking/Components/EndedGameRuleComponent.cs (61%) rename {Content.Server => Content.Shared}/GameTicking/Components/GameRuleComponent.cs (92%) create mode 100644 Content.Shared/Info/RulesMessages.cs delete mode 100644 Content.Shared/Info/SharedInfo.cs delete mode 100644 Content.Shared/Info/SharedRulesManager.cs rename {Content.Server => Content.Shared}/Shuttles/Components/FTLComponent.cs (81%) create mode 100644 Content.Shared/Shuttles/Components/FtlVisualizerComponent.cs create mode 100644 Resources/Prototypes/Alerts/categories.yml create mode 100644 Resources/Prototypes/Entities/Effects/shuttle.yml create mode 100644 Resources/Prototypes/Guidebook/rules.yml create mode 100644 Resources/ServerInfo/Guidebook/ServerRules/BanDurations.xml create mode 100644 Resources/ServerInfo/Guidebook/ServerRules/BanTypes.xml create mode 100644 Resources/ServerInfo/Guidebook/ServerRules/CoreRules/RuleC0.xml create mode 100644 Resources/ServerInfo/Guidebook/ServerRules/CoreRules/RuleC10AHelp.xml create mode 100644 Resources/ServerInfo/Guidebook/ServerRules/CoreRules/RuleC11AhelpThreats.xml create mode 100644 Resources/ServerInfo/Guidebook/ServerRules/CoreRules/RuleC12MinAge.xml create mode 100644 Resources/ServerInfo/Guidebook/ServerRules/CoreRules/RuleC13CharacterNames.xml create mode 100644 Resources/ServerInfo/Guidebook/ServerRules/CoreRules/RuleC14ICinOOC.xml create mode 100644 Resources/ServerInfo/Guidebook/ServerRules/CoreRules/RuleC1Admins.xml create mode 100644 Resources/ServerInfo/Guidebook/ServerRules/CoreRules/RuleC2DBAD.xml create mode 100644 Resources/ServerInfo/Guidebook/ServerRules/CoreRules/RuleC3NoHate.xml create mode 100644 Resources/ServerInfo/Guidebook/ServerRules/CoreRules/RuleC4NoERP.xml create mode 100644 Resources/ServerInfo/Guidebook/ServerRules/CoreRules/RuleC5Metacomms.xml create mode 100644 Resources/ServerInfo/Guidebook/ServerRules/CoreRules/RuleC6BanEvasion.xml create mode 100644 Resources/ServerInfo/Guidebook/ServerRules/CoreRules/RuleC7EnglishOnly.xml create mode 100644 Resources/ServerInfo/Guidebook/ServerRules/CoreRules/RuleC8Exploits.xml create mode 100644 Resources/ServerInfo/Guidebook/ServerRules/CoreRules/RuleC9Multikey.xml create mode 100644 Resources/ServerInfo/Guidebook/ServerRules/DefaultRules.xml create mode 100644 Resources/ServerInfo/Guidebook/ServerRules/README.txt create mode 100644 Resources/ServerInfo/Guidebook/ServerRules/RoleTypes.xml create mode 100644 Resources/ServerInfo/Guidebook/ServerRules/RoleplayRules/RuleR0.xml create mode 100644 Resources/ServerInfo/Guidebook/ServerRules/RoleplayRules/RuleR10Subordination.xml create mode 100644 Resources/ServerInfo/Guidebook/ServerRules/RoleplayRules/RuleR11-1AnimalEscalation.xml create mode 100644 Resources/ServerInfo/Guidebook/ServerRules/RoleplayRules/RuleR11-2ConflictTypes.xml create mode 100644 Resources/ServerInfo/Guidebook/ServerRules/RoleplayRules/RuleR11Escalation.xml create mode 100644 Resources/ServerInfo/Guidebook/ServerRules/RoleplayRules/RuleR12RoleAbandonment.xml create mode 100644 Resources/ServerInfo/Guidebook/ServerRules/RoleplayRules/RuleR13PerformRole.xml create mode 100644 Resources/ServerInfo/Guidebook/ServerRules/RoleplayRules/RuleR14SecComStandard.xml create mode 100644 Resources/ServerInfo/Guidebook/ServerRules/RoleplayRules/RuleR15SpaceLaw.xml create mode 100644 Resources/ServerInfo/Guidebook/ServerRules/RoleplayRules/RuleR1Silicons.xml create mode 100644 Resources/ServerInfo/Guidebook/ServerRules/RoleplayRules/RuleR2Familiars.xml create mode 100644 Resources/ServerInfo/Guidebook/ServerRules/RoleplayRules/RuleR3NormalRP.xml create mode 100644 Resources/ServerInfo/Guidebook/ServerRules/RoleplayRules/RuleR4Metashield.xml create mode 100644 Resources/ServerInfo/Guidebook/ServerRules/RoleplayRules/RuleR5Arrivals.xml create mode 100644 Resources/ServerInfo/Guidebook/ServerRules/RoleplayRules/RuleR6SelfAntag.xml create mode 100644 Resources/ServerInfo/Guidebook/ServerRules/RoleplayRules/RuleR7RoundStalling.xml create mode 100644 Resources/ServerInfo/Guidebook/ServerRules/RoleplayRules/RuleR8NoFriendlyAntag.xml create mode 100644 Resources/ServerInfo/Guidebook/ServerRules/RoleplayRules/RuleR9MassSabotage.xml create mode 100644 Resources/ServerInfo/Guidebook/ServerRules/SiliconRules/RuleS0.xml create mode 100644 Resources/ServerInfo/Guidebook/ServerRules/SiliconRules/RuleS10OrderConflicts.xml create mode 100644 Resources/ServerInfo/Guidebook/ServerRules/SiliconRules/RuleS1Laws.xml create mode 100644 Resources/ServerInfo/Guidebook/ServerRules/SiliconRules/RuleS2LawPriority.xml create mode 100644 Resources/ServerInfo/Guidebook/ServerRules/SiliconRules/RuleS3LawRedefinition.xml create mode 100644 Resources/ServerInfo/Guidebook/ServerRules/SiliconRules/RuleS4RequestChanges.xml create mode 100644 Resources/ServerInfo/Guidebook/ServerRules/SiliconRules/RuleS5FreeSilicon.xml create mode 100644 Resources/ServerInfo/Guidebook/ServerRules/SiliconRules/RuleS6UnreasonableOrders.xml create mode 100644 Resources/ServerInfo/Guidebook/ServerRules/SiliconRules/RuleS7Consistency.xml create mode 100644 Resources/ServerInfo/Guidebook/ServerRules/SiliconRules/RuleS8DefaultCrewDefinition.xml create mode 100644 Resources/ServerInfo/Guidebook/ServerRules/SiliconRules/RuleS9DefaultHarmDefinition.xml create mode 100644 Resources/ServerInfo/Guidebook/ServerRules/SpaceLaw/SLControlledSubstances.xml create mode 100644 Resources/ServerInfo/Guidebook/ServerRules/SpaceLaw/SLRestrictedGear.xml create mode 100644 Resources/ServerInfo/Guidebook/ServerRules/SpaceLaw/SLRestrictedWeapons.xml create mode 100644 Resources/ServerInfo/Guidebook/ServerRules/SpaceLaw/SpaceLaw.xml create mode 100644 Resources/ServerInfo/Guidebook/ServerRules/WizDenCoreOnlyRules.xml create mode 100644 Resources/ServerInfo/Guidebook/ServerRules/WizDenLRPRules.xml create mode 100644 Resources/ServerInfo/Guidebook/ServerRules/WizDenMRPRules.xml delete mode 100644 Resources/ServerInfo/Rules.txt create mode 100644 Resources/Textures/Effects/medi_holo.rsi/medi_holo.png create mode 100644 Resources/Textures/Effects/medi_holo.rsi/meta.json diff --git a/Content.Client/Alerts/ClientAlertsSystem.cs b/Content.Client/Alerts/ClientAlertsSystem.cs index 223bf7876a..359c8957f9 100644 --- a/Content.Client/Alerts/ClientAlertsSystem.cs +++ b/Content.Client/Alerts/ClientAlertsSystem.cs @@ -91,7 +91,7 @@ private void OnPlayerDetached(EntityUid uid, AlertsComponent component, LocalPla ClearAlerts?.Invoke(this, EventArgs.Empty); } - public void AlertClicked(AlertType alertType) + public void AlertClicked(ProtoId alertType) { RaiseNetworkEvent(new ClickAlertEvent(alertType)); } diff --git a/Content.Client/Audio/AmbientSoundSystem.cs b/Content.Client/Audio/AmbientSoundSystem.cs index 0206017bae..f4e755a013 100644 --- a/Content.Client/Audio/AmbientSoundSystem.cs +++ b/Content.Client/Audio/AmbientSoundSystem.cs @@ -303,7 +303,11 @@ private void ProcessNearbyAmbience(TransformComponent playerXform) .WithMaxDistance(comp.Range); var stream = _audio.PlayEntity(comp.Sound, Filter.Local(), uid, false, audioParams); - _playingSounds[comp] = (stream.Value.Entity, comp.Sound, key); + + if (stream == null) + continue; + + _playingSounds[comp] = (stream!.Value.Entity, comp.Sound, key); playingCount++; if (_playingSounds.Count >= _maxAmbientCount) diff --git a/Content.Client/Audio/ClientGlobalSoundSystem.cs b/Content.Client/Audio/ClientGlobalSoundSystem.cs index 7c77865f74..6619285a96 100644 --- a/Content.Client/Audio/ClientGlobalSoundSystem.cs +++ b/Content.Client/Audio/ClientGlobalSoundSystem.cs @@ -67,7 +67,7 @@ private void PlayAdminSound(AdminSoundEvent soundEvent) if(!_adminAudioEnabled) return; var stream = _audio.PlayGlobal(soundEvent.Filename, Filter.Local(), false, soundEvent.AudioParams); - _adminAudio.Add(stream.Value.Entity); + _adminAudio.Add(stream!.Value.Entity); } private void PlayStationEventMusic(StationEventMusicEvent soundEvent) @@ -76,7 +76,7 @@ private void PlayStationEventMusic(StationEventMusicEvent soundEvent) if(!_eventAudioEnabled || _eventAudio.ContainsKey(soundEvent.Type)) return; var stream = _audio.PlayGlobal(soundEvent.Filename, Filter.Local(), false, soundEvent.AudioParams); - _eventAudio.Add(soundEvent.Type, stream.Value.Entity); + _eventAudio.Add(soundEvent.Type, stream!.Value.Entity); } private void PlayGameSound(GameGlobalSoundEvent soundEvent) diff --git a/Content.Client/Audio/ContentAudioSystem.AmbientMusic.cs b/Content.Client/Audio/ContentAudioSystem.AmbientMusic.cs index 84b787a4ec..58cd026da4 100644 --- a/Content.Client/Audio/ContentAudioSystem.AmbientMusic.cs +++ b/Content.Client/Audio/ContentAudioSystem.AmbientMusic.cs @@ -210,7 +210,7 @@ private void UpdateAmbientMusic() track.ToString(), Filter.Local(), false, - AudioParams.Default.WithVolume(_musicProto.Sound.Params.Volume + _volumeSlider)); + AudioParams.Default.WithVolume(_musicProto.Sound.Params.Volume + _volumeSlider))!; _ambientMusicStream = strim.Value.Entity; diff --git a/Content.Client/Audio/ContentAudioSystem.LobbyMusic.cs b/Content.Client/Audio/ContentAudioSystem.LobbyMusic.cs index 92c5b7a419..60b81b1c2d 100644 --- a/Content.Client/Audio/ContentAudioSystem.LobbyMusic.cs +++ b/Content.Client/Audio/ContentAudioSystem.LobbyMusic.cs @@ -185,7 +185,11 @@ private void PlaySoundtrack(string soundtrackFilename) false, _lobbySoundtrackParams.WithVolume(_lobbySoundtrackParams.Volume + SharedAudioSystem.GainToVolume(_configManager.GetCVar(CCVars.LobbyMusicVolume))) ); - if (playResult.Value.Entity == default) + + if (playResult == null) + return; + + if (playResult!.Value.Entity == default) { _sawmill.Warning( $"Tried to play lobby soundtrack '{{Filename}}' using {nameof(SharedAudioSystem)}.{nameof(SharedAudioSystem.PlayGlobal)} but it returned default value of EntityUid!", diff --git a/Content.Client/Buckle/BuckleSystem.cs b/Content.Client/Buckle/BuckleSystem.cs index d4614210d9..4429996aca 100644 --- a/Content.Client/Buckle/BuckleSystem.cs +++ b/Content.Client/Buckle/BuckleSystem.cs @@ -3,6 +3,7 @@ using Content.Shared.Buckle.Components; using Content.Shared.Rotation; using Robust.Client.GameObjects; +using Robust.Shared.GameStates; namespace Content.Client.Buckle; @@ -14,40 +15,63 @@ public override void Initialize() { base.Initialize(); - SubscribeLocalEvent(OnBuckleAfterAutoHandleState); + SubscribeLocalEvent(OnHandleState); SubscribeLocalEvent(OnAppearanceChange); + SubscribeLocalEvent(OnStrapMoveEvent); } - private void OnBuckleAfterAutoHandleState(EntityUid uid, BuckleComponent component, ref AfterAutoHandleStateEvent args) + private void OnStrapMoveEvent(EntityUid uid, StrapComponent component, ref MoveEvent args) { - ActionBlocker.UpdateCanMove(uid); + // I'm moving this to the client-side system, but for the sake of posterity let's keep this comment: + // > This is mega cursed. Please somebody save me from Mr Buckle's wild ride - if (!TryComp(uid, out var ownerSprite)) + // The nice thing is its still true, this is quite cursed, though maybe not omega cursed anymore. + // This code is garbage, it doesn't work with rotated viewports. I need to finally get around to reworking + // sprite rendering for entity layers & direction dependent sorting. + + if (args.NewRotation == args.OldRotation) return; - // Adjust draw depth when the chair faces north so that the seat back is drawn over the player. - // Reset the draw depth when rotated in any other direction. - // TODO when ECSing, make this a visualizer - // This code was written before rotatable viewports were introduced, so hard-coding Direction.North - // and comparing it against LocalRotation now breaks this in other rotations. This is a FIXME, but - // better to get it working for most people before we look at a more permanent solution. - if (component is { Buckled: true, LastEntityBuckledTo: { } } && - Transform(component.LastEntityBuckledTo.Value).LocalRotation.GetCardinalDir() == Direction.North && - TryComp(component.LastEntityBuckledTo, out var buckledSprite)) - { - component.OriginalDrawDepth ??= ownerSprite.DrawDepth; - ownerSprite.DrawDepth = buckledSprite.DrawDepth - 1; + if (!TryComp(uid, out var strapSprite)) return; - } - // If here, we're not turning north and should restore the saved draw depth. - if (component.OriginalDrawDepth.HasValue) + var isNorth = Transform(uid).LocalRotation.GetCardinalDir() == Direction.North; + foreach (var buckledEntity in component.BuckledEntities) { - ownerSprite.DrawDepth = component.OriginalDrawDepth.Value; - component.OriginalDrawDepth = null; + if (!TryComp(buckledEntity, out var buckle)) + continue; + + if (!TryComp(buckledEntity, out var buckledSprite)) + continue; + + if (isNorth) + { + buckle.OriginalDrawDepth ??= buckledSprite.DrawDepth; + buckledSprite.DrawDepth = strapSprite.DrawDepth - 1; + } + else if (buckle.OriginalDrawDepth.HasValue) + { + buckledSprite.DrawDepth = buckle.OriginalDrawDepth.Value; + buckle.OriginalDrawDepth = null; + } } } + private void OnHandleState(Entity ent, ref ComponentHandleState args) + { + if (args.Current is not BuckleState state) + return; + + ent.Comp.DontCollide = state.DontCollide; + ent.Comp.BuckleTime = state.BuckleTime; + var strapUid = EnsureEntity(state.BuckledTo, ent); + + SetBuckledTo(ent, strapUid == null ? null : new (strapUid.Value, null)); + + var (uid, component) = ent; + + } + private void OnAppearanceChange(EntityUid uid, BuckleComponent component, ref AppearanceChangeEvent args) { if (!TryComp(uid, out var rotVisuals) diff --git a/Content.Client/Clickable/ClickableComponent.cs b/Content.Client/Clickable/ClickableComponent.cs index 6f75df4683..da81ed4c84 100644 --- a/Content.Client/Clickable/ClickableComponent.cs +++ b/Content.Client/Clickable/ClickableComponent.cs @@ -1,145 +1,17 @@ -using System.Numerics; -using Robust.Client.GameObjects; -using Robust.Client.Graphics; -using Robust.Client.Utility; -using Robust.Shared.Graphics; -using static Robust.Client.GameObjects.SpriteComponent; -using Direction = Robust.Shared.Maths.Direction; +namespace Content.Client.Clickable; -namespace Content.Client.Clickable +[RegisterComponent] +public sealed partial class ClickableComponent : Component { - [RegisterComponent] - public sealed partial class ClickableComponent : Component - { - [Dependency] private readonly IClickMapManager _clickMapManager = default!; - - [DataField("bounds")] public DirBoundData? Bounds; - - /// - /// Used to check whether a click worked. Will first check if the click falls inside of some explicit bounding - /// boxes (see ). If that fails, attempts to use automatically generated click maps. - /// - /// The world position that was clicked. - /// - /// The draw depth for the sprite that captured the click. - /// - /// True if the click worked, false otherwise. - public bool CheckClick(SpriteComponent sprite, TransformComponent transform, EntityQuery xformQuery, Vector2 worldPos, IEye eye, out int drawDepth, out uint renderOrder, out float bottom) - { - if (!sprite.Visible) - { - drawDepth = default; - renderOrder = default; - bottom = default; - return false; - } - - drawDepth = sprite.DrawDepth; - renderOrder = sprite.RenderOrder; - var (spritePos, spriteRot) = transform.GetWorldPositionRotation(xformQuery); - var spriteBB = sprite.CalculateRotatedBoundingBox(spritePos, spriteRot, eye.Rotation); - bottom = Matrix3Helpers.CreateRotation(eye.Rotation).TransformBox(spriteBB).Bottom; - - Matrix3x2.Invert(sprite.GetLocalMatrix(), out var invSpriteMatrix); - - // This should have been the rotation of the sprite relative to the screen, but this is not the case with no-rot or directional sprites. - var relativeRotation = (spriteRot + eye.Rotation).Reduced().FlipPositive(); - - Angle cardinalSnapping = sprite.SnapCardinals ? relativeRotation.GetCardinalDir().ToAngle() : Angle.Zero; - - // First we get `localPos`, the clicked location in the sprite-coordinate frame. - var entityXform = Matrix3Helpers.CreateInverseTransform(transform.WorldPosition, sprite.NoRotation ? -eye.Rotation : spriteRot - cardinalSnapping); - var localPos = Vector2.Transform(Vector2.Transform(worldPos, entityXform), invSpriteMatrix); - - // Check explicitly defined click-able bounds - if (CheckDirBound(sprite, relativeRotation, localPos)) - return true; - - // Next check each individual sprite layer using automatically computed click maps. - foreach (var spriteLayer in sprite.AllLayers) - { - if (!spriteLayer.Visible || spriteLayer is not Layer layer) - continue; - - // Check the layer's texture, if it has one - if (layer.Texture != null) - { - // Convert to image coordinates - var imagePos = (Vector2i) (localPos * EyeManager.PixelsPerMeter * new Vector2(1, -1) + layer.Texture.Size / 2f); - - if (_clickMapManager.IsOccluding(layer.Texture, imagePos)) - return true; - } - - // Either we weren't clicking on the texture, or there wasn't one. In which case: check the RSI next - if (layer.ActualRsi is not { } rsi || !rsi.TryGetState(layer.State, out var rsiState)) - continue; - - var dir = Layer.GetDirection(rsiState.RsiDirections, relativeRotation); + [DataField] public DirBoundData? Bounds; - // convert to layer-local coordinates - layer.GetLayerDrawMatrix(dir, out var matrix); - Matrix3x2.Invert(matrix, out var inverseMatrix); - var layerLocal = Vector2.Transform(localPos, inverseMatrix); - - // Convert to image coordinates - var layerImagePos = (Vector2i) (layerLocal * EyeManager.PixelsPerMeter * new Vector2(1, -1) + rsiState.Size / 2f); - - // Next, to get the right click map we need the "direction" of this layer that is actually being used to draw the sprite on the screen. - // This **can** differ from the dir defined before, but can also just be the same. - if (sprite.EnableDirectionOverride) - dir = sprite.DirectionOverride.Convert(rsiState.RsiDirections); - dir = dir.OffsetRsiDir(layer.DirOffset); - - if (_clickMapManager.IsOccluding(layer.ActualRsi!, layer.State, dir, layer.AnimationFrame, layerImagePos)) - return true; - } - - drawDepth = default; - renderOrder = default; - bottom = default; - return false; - } - - public bool CheckDirBound(SpriteComponent sprite, Angle relativeRotation, Vector2 localPos) - { - if (Bounds == null) - return false; - - // These explicit bounds only work for either 1 or 4 directional sprites. - - // This would be the orientation of a 4-directional sprite. - var direction = relativeRotation.GetCardinalDir(); - - var modLocalPos = sprite.NoRotation - ? localPos - : direction.ToAngle().RotateVec(localPos); - - // First, check the bounding box that is valid for all orientations - if (Bounds.All.Contains(modLocalPos)) - return true; - - // Next, get and check the appropriate bounding box for the current sprite orientation - var boundsForDir = (sprite.EnableDirectionOverride ? sprite.DirectionOverride : direction) switch - { - Direction.East => Bounds.East, - Direction.North => Bounds.North, - Direction.South => Bounds.South, - Direction.West => Bounds.West, - _ => throw new InvalidOperationException() - }; - - return boundsForDir.Contains(modLocalPos); - } - - [DataDefinition] - public sealed partial class DirBoundData - { - [DataField("all")] public Box2 All; - [DataField("north")] public Box2 North; - [DataField("south")] public Box2 South; - [DataField("east")] public Box2 East; - [DataField("west")] public Box2 West; - } + [DataDefinition] + public sealed partial class DirBoundData + { + [DataField] public Box2 All; + [DataField] public Box2 North; + [DataField] public Box2 South; + [DataField] public Box2 East; + [DataField] public Box2 West; } } diff --git a/Content.Client/Clickable/ClickableSystem.cs b/Content.Client/Clickable/ClickableSystem.cs new file mode 100644 index 0000000000..15d13df625 --- /dev/null +++ b/Content.Client/Clickable/ClickableSystem.cs @@ -0,0 +1,168 @@ +using System.Numerics; +using Robust.Client.GameObjects; +using Robust.Client.Graphics; +using Robust.Client.Utility; +using Robust.Shared.Graphics; + +namespace Content.Client.Clickable; + +/// +/// Handles click detection for sprites. +/// +public sealed class ClickableSystem : EntitySystem +{ + [Dependency] private readonly IClickMapManager _clickMapManager = default!; + [Dependency] private readonly SharedTransformSystem _transforms = default!; + [Dependency] private readonly SpriteSystem _sprites = default!; + + private EntityQuery _clickableQuery; + private EntityQuery _xformQuery; + + public override void Initialize() + { + base.Initialize(); + _clickableQuery = GetEntityQuery(); + _xformQuery = GetEntityQuery(); + } + + /// + /// Used to check whether a click worked. Will first check if the click falls inside of some explicit bounding + /// boxes (see ). If that fails, attempts to use automatically generated click maps. + /// + /// The world position that was clicked. + /// + /// The draw depth for the sprite that captured the click. + /// + /// True if the click worked, false otherwise. + public bool CheckClick(Entity entity, Vector2 worldPos, IEye eye, out int drawDepth, out uint renderOrder, out float bottom) + { + if (!_clickableQuery.Resolve(entity.Owner, ref entity.Comp1, false)) + { + drawDepth = default; + renderOrder = default; + bottom = default; + return false; + } + + if (!_xformQuery.Resolve(entity.Owner, ref entity.Comp3)) + { + drawDepth = default; + renderOrder = default; + bottom = default; + return false; + } + + var sprite = entity.Comp2; + var transform = entity.Comp3; + + if (!sprite.Visible) + { + drawDepth = default; + renderOrder = default; + bottom = default; + return false; + } + + drawDepth = sprite.DrawDepth; + renderOrder = sprite.RenderOrder; + var (spritePos, spriteRot) = _transforms.GetWorldPositionRotation(transform); + var spriteBB = sprite.CalculateRotatedBoundingBox(spritePos, spriteRot, eye.Rotation); + bottom = Matrix3Helpers.CreateRotation(eye.Rotation).TransformBox(spriteBB).Bottom; + + Matrix3x2.Invert(sprite.GetLocalMatrix(), out var invSpriteMatrix); + + // This should have been the rotation of the sprite relative to the screen, but this is not the case with no-rot or directional sprites. + var relativeRotation = (spriteRot + eye.Rotation).Reduced().FlipPositive(); + + var cardinalSnapping = sprite.SnapCardinals ? relativeRotation.GetCardinalDir().ToAngle() : Angle.Zero; + + // First we get `localPos`, the clicked location in the sprite-coordinate frame. + var entityXform = Matrix3Helpers.CreateInverseTransform(spritePos, sprite.NoRotation ? -eye.Rotation : spriteRot - cardinalSnapping); + var localPos = Vector2.Transform(Vector2.Transform(worldPos, entityXform), invSpriteMatrix); + + // Check explicitly defined click-able bounds + if (CheckDirBound((entity.Owner, entity.Comp1, entity.Comp2), relativeRotation, localPos)) + return true; + + // Next check each individual sprite layer using automatically computed click maps. + foreach (var spriteLayer in sprite.AllLayers) + { + if (spriteLayer is not SpriteComponent.Layer layer || !_sprites.IsVisible(layer)) + { + continue; + } + + // Check the layer's texture, if it has one + if (layer.Texture != null) + { + // Convert to image coordinates + var imagePos = (Vector2i) (localPos * EyeManager.PixelsPerMeter * new Vector2(1, -1) + layer.Texture.Size / 2f); + + if (_clickMapManager.IsOccluding(layer.Texture, imagePos)) + return true; + } + + // Either we weren't clicking on the texture, or there wasn't one. In which case: check the RSI next + if (layer.ActualRsi is not { } rsi || !rsi.TryGetState(layer.State, out var rsiState)) + continue; + + var dir = SpriteComponent.Layer.GetDirection(rsiState.RsiDirections, relativeRotation); + + // convert to layer-local coordinates + layer.GetLayerDrawMatrix(dir, out var matrix); + Matrix3x2.Invert(matrix, out var inverseMatrix); + var layerLocal = Vector2.Transform(localPos, inverseMatrix); + + // Convert to image coordinates + var layerImagePos = (Vector2i) (layerLocal * EyeManager.PixelsPerMeter * new Vector2(1, -1) + rsiState.Size / 2f); + + // Next, to get the right click map we need the "direction" of this layer that is actually being used to draw the sprite on the screen. + // This **can** differ from the dir defined before, but can also just be the same. + if (sprite.EnableDirectionOverride) + dir = sprite.DirectionOverride.Convert(rsiState.RsiDirections); + dir = dir.OffsetRsiDir(layer.DirOffset); + + if (_clickMapManager.IsOccluding(layer.ActualRsi!, layer.State, dir, layer.AnimationFrame, layerImagePos)) + return true; + } + + drawDepth = default; + renderOrder = default; + bottom = default; + return false; + } + + public bool CheckDirBound(Entity entity, Angle relativeRotation, Vector2 localPos) + { + var clickable = entity.Comp1; + var sprite = entity.Comp2; + + if (clickable.Bounds == null) + return false; + + // These explicit bounds only work for either 1 or 4 directional sprites. + + // This would be the orientation of a 4-directional sprite. + var direction = relativeRotation.GetCardinalDir(); + + var modLocalPos = sprite.NoRotation + ? localPos + : direction.ToAngle().RotateVec(localPos); + + // First, check the bounding box that is valid for all orientations + if (clickable.Bounds.All.Contains(modLocalPos)) + return true; + + // Next, get and check the appropriate bounding box for the current sprite orientation + var boundsForDir = (sprite.EnableDirectionOverride ? sprite.DirectionOverride : direction) switch + { + Direction.East => clickable.Bounds.East, + Direction.North => clickable.Bounds.North, + Direction.South => clickable.Bounds.South, + Direction.West => clickable.Bounds.West, + _ => throw new InvalidOperationException() + }; + + return boundsForDir.Contains(modLocalPos); + } +} diff --git a/Content.Client/Entry/EntryPoint.cs b/Content.Client/Entry/EntryPoint.cs index 1ab213ae0a..bf5f021be3 100644 --- a/Content.Client/Entry/EntryPoint.cs +++ b/Content.Client/Entry/EntryPoint.cs @@ -8,7 +8,6 @@ using Content.Client.Fullscreen; using Content.Client.GhostKick; using Content.Client.Guidebook; -using Content.Client.Info; using Content.Client.Input; using Content.Client.IoC; using Content.Client.Launcher; @@ -54,7 +53,6 @@ public sealed class EntryPoint : GameClient [Dependency] private readonly IScreenshotHook _screenshotHook = default!; [Dependency] private readonly FullscreenHook _fullscreenHook = default!; [Dependency] private readonly ChangelogManager _changelogManager = default!; - [Dependency] private readonly RulesManager _rulesManager = default!; [Dependency] private readonly ViewportManager _viewportManager = default!; [Dependency] private readonly IUserInterfaceManager _userInterfaceManager = default!; [Dependency] private readonly IInputManager _inputManager = default!; @@ -131,7 +129,6 @@ public override void Init() _screenshotHook.Initialize(); _fullscreenHook.Initialize(); _changelogManager.Initialize(); - _rulesManager.Initialize(); _viewportManager.Initialize(); _ghostKick.Initialize(); _extendedDisconnectInformation.Initialize(); diff --git a/Content.Client/Explosion/ExplosionOverlay.cs b/Content.Client/Explosion/ExplosionOverlay.cs index 8cf7447a5d..f8f8ae5362 100644 --- a/Content.Client/Explosion/ExplosionOverlay.cs +++ b/Content.Client/Explosion/ExplosionOverlay.cs @@ -29,6 +29,7 @@ public ExplosionOverlay() protected override void Draw(in OverlayDrawArgs args) { + var appearanceSystem = _entMan.System(); var drawHandle = args.WorldHandle; drawHandle.UseShader(_shader); @@ -41,7 +42,7 @@ protected override void Draw(in OverlayDrawArgs args) if (visuals.Epicenter.MapId != args.MapId) continue; - if (!appearance.TryGetData(ExplosionAppearanceData.Progress, out int index)) + if (!appearanceSystem.TryGetData(appearance.Owner, ExplosionAppearanceData.Progress, out int index)) continue; index = Math.Min(index, visuals.Intensity.Count - 1); diff --git a/Content.Client/Gameplay/GameplayStateBase.cs b/Content.Client/Gameplay/GameplayStateBase.cs index 6236cd8e95..315c053d93 100644 --- a/Content.Client/Gameplay/GameplayStateBase.cs +++ b/Content.Client/Gameplay/GameplayStateBase.cs @@ -2,6 +2,7 @@ using System.Numerics; using Content.Client.Clickable; using Content.Client.UserInterface; +using Content.Client.Viewport; using Content.Shared.Input; using Robust.Client.ComponentTrees; using Robust.Client.GameObjects; @@ -13,11 +14,13 @@ using Robust.Client.UserInterface.Controls; using Robust.Client.UserInterface.CustomControls; using Robust.Shared.Console; +using Robust.Shared.Graphics; using Robust.Shared.Input; using Robust.Shared.Input.Binding; using Robust.Shared.Map; using Robust.Shared.Player; using Robust.Shared.Timing; +using YamlDotNet.Serialization.TypeInspectors; namespace Content.Client.Gameplay { @@ -98,7 +101,15 @@ private bool HandleInspect(ICommonSession? session, EntityCoordinates coords, En public EntityUid? GetClickedEntity(MapCoordinates coordinates) { - var first = GetClickableEntities(coordinates).FirstOrDefault(); + return GetClickedEntity(coordinates, _eyeManager.CurrentEye); + } + + public EntityUid? GetClickedEntity(MapCoordinates coordinates, IEye? eye) + { + if (eye == null) + return null; + + var first = GetClickableEntities(coordinates, eye).FirstOrDefault(); return first.IsValid() ? first : null; } @@ -109,6 +120,20 @@ public IEnumerable GetClickableEntities(EntityCoordinates coordinates public IEnumerable GetClickableEntities(MapCoordinates coordinates) { + return GetClickableEntities(coordinates, _eyeManager.CurrentEye); + } + + public IEnumerable GetClickableEntities(MapCoordinates coordinates, IEye? eye) + { + /* + * TODO: + * 1. Stuff like MeleeWeaponSystem need an easy way to hook into viewport specific entities / entities under mouse + * 2. Cleanup the mess around InteractionOutlineSystem + below the keybind click detection. + */ + + if (eye == null) + return Array.Empty(); + // Find all the entities intersecting our click var spriteTree = _entityManager.EntitySysManager.GetEntitySystem(); var entities = spriteTree.QueryAabb(coordinates.MapId, Box2.CenteredAround(coordinates.Position, new Vector2(1, 1))); @@ -116,15 +141,12 @@ public IEnumerable GetClickableEntities(MapCoordinates coordinates) // Check the entities against whether or not we can click them var foundEntities = new List<(EntityUid, int, uint, float)>(entities.Count); var clickQuery = _entityManager.GetEntityQuery(); - var xformQuery = _entityManager.GetEntityQuery(); - - // TODO: Smelly - var eye = _eyeManager.CurrentEye; + var clickables = _entityManager.System(); foreach (var entity in entities) { if (clickQuery.TryGetComponent(entity.Uid, out var component) && - component.CheckClick(entity.Component, entity.Transform, xformQuery, coordinates.Position, eye, out var drawDepthClicked, out var renderOrder, out var bottom)) + clickables.CheckClick((entity.Uid, component, entity.Component, entity.Transform), coordinates.Position, eye, out var drawDepthClicked, out var renderOrder, out var bottom)) { foundEntities.Add((entity.Uid, drawDepthClicked, renderOrder, bottom)); } @@ -187,7 +209,15 @@ protected virtual void OnKeyBindStateChanged(ViewportBoundKeyEventArgs args) if (args.Viewport is IViewportControl vp) { var mousePosWorld = vp.PixelToMap(kArgs.PointerLocation.Position); - entityToClick = GetClickedEntity(mousePosWorld); + + if (vp is ScalingViewport svp) + { + entityToClick = GetClickedEntity(mousePosWorld, svp.Eye); + } + else + { + entityToClick = GetClickedEntity(mousePosWorld); + } coordinates = _mapManager.TryFindGridAt(mousePosWorld, out _, out var grid) ? grid.MapToGrid(mousePosWorld) : diff --git a/Content.Client/Guidebook/Controls/GuidebookWindow.xaml b/Content.Client/Guidebook/Controls/GuidebookWindow.xaml index 8dbfde3c47..cc6cc6e82b 100644 --- a/Content.Client/Guidebook/Controls/GuidebookWindow.xaml +++ b/Content.Client/Guidebook/Controls/GuidebookWindow.xaml @@ -18,7 +18,7 @@ Name="SearchBar" PlaceHolder="{Loc 'guidebook-filter-placeholder-text'}" HorizontalExpand="True" - Margin="0 5 10 5"> + Margin="0 5 10 5"> diff --git a/Content.Client/Guidebook/DocumentParsingManager.cs b/Content.Client/Guidebook/DocumentParsingManager.cs index b81866a626..9c9e569eb4 100644 --- a/Content.Client/Guidebook/DocumentParsingManager.cs +++ b/Content.Client/Guidebook/DocumentParsingManager.cs @@ -2,6 +2,8 @@ using Content.Client.Guidebook.Richtext; using Pidgin; using Robust.Client.UserInterface; +using Robust.Shared.ContentPack; +using Robust.Shared.Prototypes; using Robust.Shared.Reflection; using Robust.Shared.Sandboxing; using static Pidgin.Parser; @@ -13,7 +15,9 @@ namespace Content.Client.Guidebook; /// public sealed partial class DocumentParsingManager { + [Dependency] private readonly IPrototypeManager _prototype = default!; [Dependency] private readonly IReflectionManager _reflectionManager = default!; + [Dependency] private readonly IResourceManager _resourceManager = default!; [Dependency] private readonly ISandboxHelper _sandboxHelper = default!; private readonly Dictionary> _tagControlParsers = new(); @@ -37,6 +41,21 @@ public void Initialize() ControlParser = SkipWhitespaces.Then(_controlParser.Many()); } + public bool TryAddMarkup(Control control, ProtoId entryId, bool log = true) + { + if (!_prototype.TryIndex(entryId, out var entry)) + return false; + + using var file = _resourceManager.ContentFileReadText(entry.Text); + return TryAddMarkup(control, file.ReadToEnd(), log); + } + + public bool TryAddMarkup(Control control, GuideEntry entry, bool log = true) + { + using var file = _resourceManager.ContentFileReadText(entry.Text); + return TryAddMarkup(control, file.ReadToEnd(), log); + } + public bool TryAddMarkup(Control control, string text, bool log = true) { try diff --git a/Content.Client/Info/InfoSystem.cs b/Content.Client/Info/InfoSystem.cs deleted file mode 100644 index b697994981..0000000000 --- a/Content.Client/Info/InfoSystem.cs +++ /dev/null @@ -1,25 +0,0 @@ -using Content.Shared.Info; -using Robust.Shared.Log; - -namespace Content.Client.Info; - -public sealed class InfoSystem : EntitySystem -{ - public RulesMessage Rules = new RulesMessage("Server Rules", "The server did not send any rules."); - [Dependency] private readonly RulesManager _rules = default!; - - public override void Initialize() - { - base.Initialize(); - SubscribeNetworkEvent(OnRulesReceived); - Log.Debug("Requested server info."); - RaiseNetworkEvent(new RequestRulesMessage()); - } - - private void OnRulesReceived(RulesMessage message, EntitySessionEventArgs eventArgs) - { - Log.Debug("Received server rules."); - Rules = message; - _rules.UpdateRules(); - } -} diff --git a/Content.Client/Info/RulesAndInfoWindow.cs b/Content.Client/Info/RulesAndInfoWindow.cs index 7a763a1d6f..b9131dcb3c 100644 --- a/Content.Client/Info/RulesAndInfoWindow.cs +++ b/Content.Client/Info/RulesAndInfoWindow.cs @@ -1,10 +1,8 @@ using System.Numerics; using Content.Client.UserInterface.Systems.EscapeMenu; -using Robust.Client.ResourceManagement; using Robust.Client.UserInterface; using Robust.Client.UserInterface.Controls; using Robust.Client.UserInterface.CustomControls; -using Robust.Shared.Configuration; using Robust.Shared.ContentPack; namespace Content.Client.Info @@ -12,7 +10,6 @@ namespace Content.Client.Info public sealed class RulesAndInfoWindow : DefaultWindow { [Dependency] private readonly IResourceManager _resourceManager = default!; - [Dependency] private readonly RulesManager _rules = default!; public RulesAndInfoWindow() { @@ -22,8 +19,14 @@ public RulesAndInfoWindow() var rootContainer = new TabContainer(); - var rulesList = new Info(); - var tutorialList = new Info(); + var rulesList = new RulesControl + { + Margin = new Thickness(10) + }; + var tutorialList = new Info + { + Margin = new Thickness(10) + }; rootContainer.AddChild(rulesList); rootContainer.AddChild(tutorialList); @@ -31,7 +34,6 @@ public RulesAndInfoWindow() TabContainer.SetTabTitle(rulesList, Loc.GetString("ui-info-tab-rules")); TabContainer.SetTabTitle(tutorialList, Loc.GetString("ui-info-tab-tutorial")); - AddSection(rulesList, _rules.RulesSection()); PopulateTutorial(tutorialList); Contents.AddChild(rootContainer); diff --git a/Content.Client/Info/RulesControl.xaml b/Content.Client/Info/RulesControl.xaml index 3b24764688..04fa719123 100644 --- a/Content.Client/Info/RulesControl.xaml +++ b/Content.Client/Info/RulesControl.xaml @@ -1,6 +1,18 @@ - + + + + + + +