From 4d064abcd7a57fd4a2201ac15d157595a2f80f60 Mon Sep 17 00:00:00 2001 From: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com> Date: Mon, 8 Mar 2021 04:09:59 +1100 Subject: [PATCH] Physics (#3485) * Content side new physics structure * BroadPhase outline done * But we need to fix WorldAABB * Fix static pvs AABB * Fix import * Rando fixes * B is for balloon * Change human mob hitbox to circle * Decent movement * Start adding friction to player controller I think it's the best way to go about it to keep other objects somewhat consistent for physics. * This baby can fit so many physics bugs in it. * Slight mob mover optimisations. * Player mover kinda works okay. * Beginnings of testbed * More testbed * Circlestack bed * Namespaces * BB fixes * Pull WorldAABB * Joint pulling * Semi-decent movement I guess. * Pulling better * Bullet controller + old movement * im too dumb for this shit * Use kinematic mob controller again It's probably for the best TBH * Stashed shitcode * Remove SlipController * In which movement code is entirely refactored * Singularity fix * Fix ApplyLinearImpulse * MoveRelay fix * Fix door collisions * Disable subfloor collisions Saves on broadphase a fair bit * Re-implement ClimbController * Zumzum's pressure * Laggy item throwing * Minor atmos change * Some caching * Optimise controllers * Optimise CollideWith to hell and back * Re-do throwing and tile friction * Landing too * Optimise controllers * Move CCVars and other stuff swept is beautiful * Cleanup a bunch of controllers * Fix shooting and high pressure movement controller * Flashing improvements * Stuff and things * Combat collisions * Combat mode collisions * Pulling distance joint again * Cleanup physics interfaces * More like scuffedularity * Shit's fucked * Haha tests go green * Bigmoneycrab * Fix dupe pulling * Zumzum's based fix * Don't run tile friction for non-predicted bodies * Experimental pulling improvement * Everything's a poly now * Optimise AI region debugging a bit Could still be better but should improve default performance a LOT * Mover no updater * Crazy kinematic body idea * Good collisions * KinematicController * Fix aghost * Throwing refactor * Pushing cleanup * Fix throwing and footstep sounds * Frametime in ICollideBehavior * Fix stuff * Actually fix weightlessness * Optimise collision behaviors a lot * Make open lockers still collide with walls * powwweeerrrrr * Merge master proper * AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA * AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA * AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA * Ch ch ch changesss * SHIP IT * Fix #if DEBUG * Fix vaulting and item locker collision * Fix throwing * Editing yaml by hand what can go wrong * on * Last yaml fixes * Okay now it's fixed * Linter Co-authored-by: Metal Gear Sloth Co-authored-by: Vera Aguilera Puerto --- .../Components/Movement/ClimbingComponent.cs | 5 +- .../Movement/PlayerInputMoverComponent.cs | 15 - .../Projectiles/ThrownItemComponent.cs | 12 - .../Components/Suspicion/TraitorOverlay.cs | 7 +- .../AI/ClientPathfindingDebugSystem.cs | 13 +- .../GameObjects/EntitySystems/MoverSystem.cs | 43 --- .../EntitySystems/SubFloorHideSystem.cs | 15 +- .../Physics/Controllers/MoverController.cs | 36 ++ .../Tests/Disposal/DisposalUnitTest.cs | 2 +- .../Tests/Doors/AirlockTest.cs | 39 +- .../Components/Movement/ClimbUnitTest.cs | 8 +- .../Tests/Physics/PhysicsTestBedTest.cs | 270 ++++++++++++++ .../Tests/Pulling/PullTest.cs | 79 ----- Content.IntegrationTests/Tests/SpriteTest.cs | 61 ---- .../Utility/EntitySystemExtensionsTest.cs | 10 +- Content.Server/AI/Utils/Visibility.cs | 3 +- .../Administration/Commands/WarpCommand.cs | 6 +- .../Atmos/HighPressureMovementController.cs | 70 ---- Content.Server/Atmos/TileAtmosphere.cs | 7 +- .../Commands/MakeSentientCommand.cs | 4 +- .../Commands/Physics/TestbedCommand.cs | 234 ++++++++++++ .../Construction/Completions/SetAnchor.cs | 6 +- .../Construction/Conditions/EntityAnchored.cs | 12 +- Content.Server/Explosions/ExplosionHelper.cs | 3 +- .../Components/AnchorableComponent.cs | 16 +- .../Components/Atmos/FlammableComponent.cs | 15 +- .../Components/Atmos/GasCanisterComponent.cs | 5 +- .../Atmos/MovedByPressureComponent.cs | 87 +++++ .../Components/Chemistry/VaporComponent.cs | 41 +-- .../Construction/ConstructionComponent.cs | 7 +- .../Components/Conveyor/ConveyorComponent.cs | 40 +-- .../DamageOnHighSpeedImpactComponent.cs | 14 +- .../Disposal/DisposalHolderComponent.cs | 7 +- .../Disposal/DisposalMailingUnitComponent.cs | 4 +- .../Disposal/DisposalRouterComponent.cs | 5 +- .../Disposal/DisposalUnitComponent.cs | 3 +- .../Components/Doors/ServerDoorComponent.cs | 40 +-- .../Explosion/ClusterFlashComponent.cs | 19 +- .../Components/Fluids/PuddleComponent.cs | 3 +- .../Components/GUI/HandsComponent.cs | 7 +- .../Items/Storage/EntityStorageComponent.cs | 30 +- .../Components/Items/Storage/ItemComponent.cs | 42 ++- .../Components/Items/ThrowHelper.cs | 50 +++ .../Components/Mobs/State/DeadMobState.cs | 5 +- .../Movement/AiControllerComponent.cs | 17 +- .../Components/Movement/ClimbableComponent.cs | 23 +- .../Components/Movement/ClimbingComponent.cs | 71 ++-- .../Movement/PlayerInputMoverComponent.cs | 19 - .../Movement/ShuttleControllerComponent.cs | 36 +- .../Components/NodeContainer/Nodes/Node.cs | 4 +- .../PA/ParticleProjectileComponent.cs | 15 +- .../Components/Portal/PortalComponent.cs | 9 +- .../Components/Portal/TeleporterComponent.cs | 5 +- .../PowerReceiverComponent.cs | 5 +- .../ChemicalInjectionProjectileComponent.cs | 8 +- .../ExplosiveProjectileComponent.cs | 12 +- .../Projectiles/FlashProjectileComponent.cs | 14 +- .../Projectiles/HitscanComponent.cs | 3 + .../Projectiles/ProjectileComponent.cs | 49 +-- .../StunnableProjectileComponent.cs | 11 +- .../Projectiles/ThrownItemComponent.cs | 118 ------- .../Components/Pulling/PullableComponent.cs | 9 +- .../Components/Recycling/RecyclerComponent.cs | 50 +-- .../Rotatable/FlippableComponent.cs | 5 +- .../Rotatable/RotatableComponent.cs | 9 +- .../Singularity/ContainmentFieldComponent.cs | 8 +- .../Singularity/ContainmentFieldConnection.cs | 16 +- .../ContainmentFieldGeneratorComponent.cs | 10 +- .../Singularity/EmitterComponent.cs | 3 +- .../Singularity/SingularityComponent.cs | 74 +--- .../Temperature/TemperatureComponent.cs | 4 +- .../Components/Weapon/FlashableComponent.cs | 12 +- .../Weapon/Melee/MeleeWeaponComponent.cs | 10 +- .../Barrels/ServerRangedBarrelComponent.cs | 10 +- .../Accessible/AiReachableSystem.cs | 55 ++- .../Pathfinding/Accessible/ReachableArgs.cs | 3 +- .../AI/Pathfinding/PathfindingNode.cs | 7 +- .../AI/Pathfinding/PathfindingSystem.cs | 12 +- .../AI/Steering/AiSteeringSystem.cs | 9 +- .../EntitySystems/Click/InteractionSystem.cs | 57 +-- .../GameObjects/EntitySystems/ClimbSystem.cs | 29 +- .../EntitySystems/ConveyorSystem.cs | 18 - .../GameObjects/EntitySystems/HandsSystem.cs | 17 +- .../EntitySystems/Power/PowerSolarSystem.cs | 3 +- .../EntitySystems/RecyclerSystem.cs | 18 - .../EntitySystems/SingularitySystem.cs | 27 +- .../Physics/Controllers/ConveyorController.cs | 118 +++++++ .../Controllers/MoverController.cs} | 97 +++-- .../Controllers/SingularityController.cs | 106 ++++++ Content.Server/Throw/ThrowHelper.cs | 156 -------- Content.Shared/AI/SharedAiDebug.cs | 12 + Content.Shared/CCVars.cs | 9 + .../WallmountCondition.cs | 3 +- .../Components/Body/SharedBodyComponent.cs | 3 + .../Buckle/SharedBuckleComponent.cs | 2 +- .../Disposal/SharedDisposalUnitComponent.cs | 6 +- .../Components/Doors/SharedDoorComponent.cs | 2 +- .../Components/Items/ThrownItemComponent.cs | 27 ++ .../Mobs/SharedCombatModeComponent.cs | 15 + .../Components/Movement/IMobMoverComponent.cs | 17 + .../Components/Movement/IMoverComponent.cs | 16 - .../Movement/SharedClimbingComponent.cs | 87 +++-- .../SharedDummyInputMoverComponent.cs | 6 +- .../SharedPlayerInputMoverComponent.cs | 62 +--- .../Movement/SharedPlayerMobMoverComponent.cs | 123 +++++++ .../Movement/SharedSlipperyComponent.cs | 42 +-- .../Movement/TileFrictionModifier.cs | 58 +++ .../Portal/SharedPortalComponent.cs | 3 +- .../Projectiles/SharedProjectileComponent.cs | 2 + .../Pulling/SharedPullableComponent.cs | 41 ++- Content.Shared/GameObjects/ContentNetIDs.cs | 6 +- .../EntitySystems/SharedInteractionSystem.cs | 11 +- .../EntitySystems/SharedMobMoverSystem.cs | 38 ++ .../EntitySystems/SharedMoverSystem.cs | 122 +------ .../EntitySystems/SharedPullingSystem.cs | 3 +- .../EntitySystems/ThrownItemSystem.cs | 104 ++++++ .../Components/Interaction/ILand.cs | 8 +- .../Components/Interaction/IThrowCollide.cs | 12 +- Content.Shared/Maps/TurfHelpers.cs | 3 +- Content.Shared/Physics/BulletController.cs | 17 - Content.Shared/Physics/ClimbController.cs | 89 ----- Content.Shared/Physics/CollisionGroup.cs | 3 +- .../ContainmentFieldCollisionController.cs | 10 - .../ContainmentFieldRepellController.cs | 13 - .../Controllers/SharedMoverController.cs | 143 ++++++++ .../SharedTileFrictionController.cs | 102 ++++++ Content.Shared/Physics/ConveyedController.cs | 62 ---- Content.Shared/Physics/FrictionController.cs | 24 -- Content.Shared/Physics/MoverController.cs | 33 -- .../Physics/Pull/PullAttemptMessage.cs | 4 +- Content.Shared/Physics/Pull/PullController.cs | 190 ---------- Content.Shared/Physics/Pull/PullMessage.cs | 7 +- .../Physics/Pull/PullStartedMessage.cs | 4 +- .../Physics/Pull/PullStoppedMessage.cs | 4 +- Content.Shared/Physics/ShuttleController.cs | 17 - .../Physics/SingularityController.cs | 18 - .../Physics/SingularityPullController.cs | 22 -- Content.Shared/Physics/SlipController.cs | 44 --- .../Physics/ThrowKnockbackController.cs | 50 --- Content.Shared/Physics/ThrownController.cs | 17 - Content.Shared/Physics/VaporController.cs | 14 - .../Utility/EntitySystemExtensions.cs | 16 +- Content.Tools/test/0A.yml | 7 +- Content.Tools/test/0B.yml | 2 +- Content.Tools/test/0C.yml | 7 +- .../Maps/Test/Breathing/3by3-20oxy-80nit.yml | 7 +- Resources/Maps/Test/empty.yml | 7 +- Resources/Maps/Test/singularity.yml | 7 +- Resources/Maps/saltern.yml | 69 ++-- .../Constructible/Doors/airlock_base.yml | 7 +- .../Entities/Constructible/Doors/firelock.yml | 48 +-- .../Constructible/Doors/firelock_frame.yml | 7 +- .../Entities/Constructible/Furniture/beds.yml | 9 +- .../Constructible/Furniture/bookshelf.yml | 5 +- .../Constructible/Furniture/carpets.yml | 7 +- .../Constructible/Furniture/instruments.yml | 5 +- .../Constructible/Furniture/potted_plants.yml | 16 +- .../Constructible/Furniture/seats.yml | 51 +-- .../Constructible/Furniture/storage.yml | 18 +- .../Constructible/Furniture/tables.yml | 5 +- .../Entities/Constructible/Ground/catwalk.yml | 7 +- .../Entities/Constructible/Ground/kitchen.yml | 5 +- .../Constructible/Piping/gascanisters.yml | 9 +- .../Constructible/Piping/gasgenerator.yml | 13 +- .../Constructible/Power/computers.yml | 27 +- .../Constructible/Power/debug_power.yml | 28 +- .../Entities/Constructible/Power/lathe.yml | 9 +- .../Constructible/Power/machine_frame.yml | 18 +- .../Constructible/Power/power_base.yml | 37 +- .../Constructible/Power/seed_extractor.yml | 9 +- .../Constructible/Power/vending_machines.yml | 9 +- .../Entities/Constructible/Power/wires.yml | 10 +- .../Specific/Conveyor/conveyor.yml | 9 +- .../Specific/Cooking/microwave.yml | 7 +- .../Specific/Cooking/reagent_grinder.yml | 7 +- .../Dispensers/reagent_dispenser_base.yml | 9 +- .../Specific/Engines/AME/controller.yml | 7 +- .../Specific/Engines/AME/shielding.yml | 5 +- .../Specific/Engines/PA/base.yml | 19 +- .../Specific/Engines/PA/control_box.yml | 2 +- .../Specific/Engines/PA/emitter.yml | 6 +- .../Specific/Engines/PA/end_cap.yml | 2 +- .../Specific/Engines/PA/fuel_chamber.yml | 2 +- .../Specific/Engines/PA/particles.yml | 9 +- .../Specific/Engines/PA/power_box.yml | 2 +- .../Engines/Singularity/collector.yml | 9 +- .../Engines/Singularity/containment.yml | 18 +- .../Specific/Engines/Singularity/emitter.yml | 9 +- .../Engines/Singularity/generator.yml | 9 +- .../Engines/Singularity/singularity.yml | 9 +- .../Specific/Medical/cloning_machine.yml | 9 +- .../Specific/Medical/medical_scanner.yml | 14 +- .../Specific/Research/research.yml | 16 +- .../Constructible/Specific/cargo_telepad.yml | 8 +- .../Constructible/Specific/chem_master.yml | 18 +- .../Constructible/Specific/disposal.yml | 93 ++--- .../Specific/gravity_generator.yml | 17 +- .../Constructible/Specific/hydroponics.yml | 18 +- .../Constructible/Specific/recycler.yml | 9 +- .../Constructible/Storage/Closets/closet.yml | 13 +- .../Storage/Crates/crate_base.yml | 10 +- .../Storage/StorageTanks/base_tank.yml | 11 +- .../Entities/Constructible/Walls/asteroid.yml | 5 +- .../Constructible/Walls/atmos_plaque.yml | 7 +- .../Entities/Constructible/Walls/bar_sign.yml | 9 +- .../Entities/Constructible/Walls/girder.yml | 7 +- .../Entities/Constructible/Walls/lighting.yml | 16 +- .../Entities/Constructible/Walls/low_wall.yml | 5 +- .../Entities/Constructible/Walls/mirror.yml | 7 +- .../Entities/Constructible/Walls/signs.yml | 334 ++++++++++-------- .../Entities/Constructible/Walls/walls.yml | 7 +- .../Entities/Constructible/Walls/windows.yml | 6 +- .../Constructible/Watercloset/toilet.yml | 5 +- .../Entities/Effects/chemistry_effects.yml | 24 +- .../Prototypes/Entities/Mobs/NPCs/animals.yml | 117 +++--- .../Prototypes/Entities/Mobs/NPCs/carp.yml | 9 +- .../Prototypes/Entities/Mobs/NPCs/mimic.yml | 9 +- .../Prototypes/Entities/Mobs/NPCs/pets.yml | 21 +- .../Entities/Mobs/NPCs/simplemob.yml | 7 +- .../Prototypes/Entities/Mobs/NPCs/xeno.yml | 9 +- .../Entities/Mobs/Player/admin_ghost.yml | 13 + .../Prototypes/Entities/Mobs/Player/human.yml | 2 + .../Entities/Mobs/Player/observer.yml | 9 +- .../Entities/Mobs/Species/human.yml | 22 +- .../Entities/Mobs/Species/slime.yml | 9 +- .../Entities/Objects/Consumable/trash.yml | 9 +- .../Entities/Objects/Devices/pda.yml | 7 +- .../Objects/Misc/fire_extinguisher.yml | 17 +- .../Entities/Objects/Misc/fluff_lights.yml | 10 +- .../Entities/Objects/Misc/teleporters.yml | 5 +- .../Entities/Objects/Power/powercells.yml | 30 +- .../Entities/Objects/Specific/janitor.yml | 44 +-- .../Entities/Objects/Specific/morgue.yml | 48 +-- .../Weapons/Guns/Projectiles/projectiles.yml | 23 +- Resources/Prototypes/Entities/base_item.yml | 17 +- Resources/Prototypes/Entities/puddle.yml | 9 +- Resources/Prototypes/Entities/traitordm.yml | 9 +- 237 files changed, 3365 insertions(+), 2880 deletions(-) delete mode 100644 Content.Client/GameObjects/Components/Movement/PlayerInputMoverComponent.cs delete mode 100644 Content.Client/GameObjects/Components/Projectiles/ThrownItemComponent.cs delete mode 100644 Content.Client/GameObjects/EntitySystems/MoverSystem.cs create mode 100644 Content.Client/Physics/Controllers/MoverController.cs create mode 100644 Content.IntegrationTests/Tests/Physics/PhysicsTestBedTest.cs delete mode 100644 Content.IntegrationTests/Tests/Pulling/PullTest.cs delete mode 100644 Content.IntegrationTests/Tests/SpriteTest.cs delete mode 100644 Content.Server/Atmos/HighPressureMovementController.cs create mode 100644 Content.Server/Commands/Physics/TestbedCommand.cs create mode 100644 Content.Server/GameObjects/Components/Items/ThrowHelper.cs delete mode 100644 Content.Server/GameObjects/Components/Movement/PlayerInputMoverComponent.cs delete mode 100644 Content.Server/GameObjects/Components/Projectiles/ThrownItemComponent.cs delete mode 100644 Content.Server/GameObjects/EntitySystems/ConveyorSystem.cs delete mode 100644 Content.Server/GameObjects/EntitySystems/RecyclerSystem.cs create mode 100644 Content.Server/Physics/Controllers/ConveyorController.cs rename Content.Server/{GameObjects/EntitySystems/MoverSystem.cs => Physics/Controllers/MoverController.cs} (55%) create mode 100644 Content.Server/Physics/Controllers/SingularityController.cs delete mode 100644 Content.Server/Throw/ThrowHelper.cs create mode 100644 Content.Shared/GameObjects/Components/Items/ThrownItemComponent.cs create mode 100644 Content.Shared/GameObjects/Components/Movement/IMobMoverComponent.cs create mode 100644 Content.Shared/GameObjects/Components/Movement/SharedPlayerMobMoverComponent.cs create mode 100644 Content.Shared/GameObjects/Components/Movement/TileFrictionModifier.cs create mode 100644 Content.Shared/GameObjects/EntitySystems/SharedMobMoverSystem.cs create mode 100644 Content.Shared/GameObjects/EntitySystems/ThrownItemSystem.cs delete mode 100644 Content.Shared/Physics/BulletController.cs delete mode 100644 Content.Shared/Physics/ClimbController.cs delete mode 100644 Content.Shared/Physics/ContainmentFieldCollisionController.cs delete mode 100644 Content.Shared/Physics/ContainmentFieldRepellController.cs create mode 100644 Content.Shared/Physics/Controllers/SharedMoverController.cs create mode 100644 Content.Shared/Physics/Controllers/SharedTileFrictionController.cs delete mode 100644 Content.Shared/Physics/ConveyedController.cs delete mode 100644 Content.Shared/Physics/FrictionController.cs delete mode 100644 Content.Shared/Physics/MoverController.cs delete mode 100644 Content.Shared/Physics/Pull/PullController.cs delete mode 100644 Content.Shared/Physics/ShuttleController.cs delete mode 100644 Content.Shared/Physics/SingularityController.cs delete mode 100644 Content.Shared/Physics/SingularityPullController.cs delete mode 100644 Content.Shared/Physics/SlipController.cs delete mode 100644 Content.Shared/Physics/ThrowKnockbackController.cs delete mode 100644 Content.Shared/Physics/ThrownController.cs delete mode 100644 Content.Shared/Physics/VaporController.cs diff --git a/Content.Client/GameObjects/Components/Movement/ClimbingComponent.cs b/Content.Client/GameObjects/Components/Movement/ClimbingComponent.cs index 92a76edd1f..dc47a7bacc 100644 --- a/Content.Client/GameObjects/Components/Movement/ClimbingComponent.cs +++ b/Content.Client/GameObjects/Components/Movement/ClimbingComponent.cs @@ -11,14 +11,13 @@ namespace Content.Client.GameObjects.Components.Movement { base.HandleComponentState(curState, nextState); - if (curState is not ClimbModeComponentState climbModeState || Body == null) + if (curState is not ClimbModeComponentState climbModeState) { return; } IsClimbing = climbModeState.Climbing; + OwnerIsTransitioning = climbModeState.IsTransitioning; } - - public override bool IsClimbing { get; set; } } } diff --git a/Content.Client/GameObjects/Components/Movement/PlayerInputMoverComponent.cs b/Content.Client/GameObjects/Components/Movement/PlayerInputMoverComponent.cs deleted file mode 100644 index 84af66d532..0000000000 --- a/Content.Client/GameObjects/Components/Movement/PlayerInputMoverComponent.cs +++ /dev/null @@ -1,15 +0,0 @@ -#nullable enable -using Content.Shared.GameObjects.Components.Movement; -using Robust.Shared.GameObjects; -using Robust.Shared.Map; - -namespace Content.Client.GameObjects.Components.Movement -{ - [RegisterComponent] - [ComponentReference(typeof(IMoverComponent))] - public class PlayerInputMoverComponent : SharedPlayerInputMoverComponent - { - public override EntityCoordinates LastPosition { get; set; } - public override float StepSoundDistance { get; set; } - } -} diff --git a/Content.Client/GameObjects/Components/Projectiles/ThrownItemComponent.cs b/Content.Client/GameObjects/Components/Projectiles/ThrownItemComponent.cs deleted file mode 100644 index 6f43d63505..0000000000 --- a/Content.Client/GameObjects/Components/Projectiles/ThrownItemComponent.cs +++ /dev/null @@ -1,12 +0,0 @@ -using Content.Shared.GameObjects; -using Robust.Shared.GameObjects; - -namespace Content.Client.GameObjects.Components.Projectiles -{ - [RegisterComponent] - public class ThrownItemComponent : ProjectileComponent - { - public override string Name => "ThrownItem"; - public override uint? NetID => ContentNetIDs.THROWN_ITEM; - } -} diff --git a/Content.Client/GameObjects/Components/Suspicion/TraitorOverlay.cs b/Content.Client/GameObjects/Components/Suspicion/TraitorOverlay.cs index 27e60e6853..be5c76a84d 100644 --- a/Content.Client/GameObjects/Components/Suspicion/TraitorOverlay.cs +++ b/Content.Client/GameObjects/Components/Suspicion/TraitorOverlay.cs @@ -6,6 +6,7 @@ using Robust.Shared.GameObjects; using Robust.Shared.IoC; using Robust.Shared.Localization; using Robust.Shared.Maths; +using Robust.Shared.Physics; namespace Content.Client.GameObjects.Components.Suspicion { @@ -62,7 +63,7 @@ namespace Content.Client.GameObjects.Components.Suspicion continue; } - if (!ally.TryGetComponent(out IPhysicsComponent physics)) + if (!ally.TryGetComponent(out IPhysBody physics)) { continue; } @@ -82,7 +83,7 @@ namespace Content.Client.GameObjects.Components.Suspicion continue; } - var worldBox = physics.WorldAABB; + var worldBox = physics.GetWorldAABB(); // if not on screen, or too small, continue if (!worldBox.Intersects(in viewport) || worldBox.IsEmpty()) @@ -90,7 +91,7 @@ namespace Content.Client.GameObjects.Components.Suspicion continue; } - var screenCoordinates = _eyeManager.WorldToScreen(physics.WorldAABB.TopLeft + (0, 0.5f)); + var screenCoordinates = _eyeManager.WorldToScreen(physics.GetWorldAABB().TopLeft + (0, 0.5f)); DrawString(screen, _font, screenCoordinates, _traitorText, Color.OrangeRed); } } diff --git a/Content.Client/GameObjects/EntitySystems/AI/ClientPathfindingDebugSystem.cs b/Content.Client/GameObjects/EntitySystems/AI/ClientPathfindingDebugSystem.cs index a32f06bd62..aba664bf0f 100644 --- a/Content.Client/GameObjects/EntitySystems/AI/ClientPathfindingDebugSystem.cs +++ b/Content.Client/GameObjects/EntitySystems/AI/ClientPathfindingDebugSystem.cs @@ -128,8 +128,12 @@ namespace Content.Client.GameObjects.EntitySystems.AI if (tooltip == PathfindingDebugMode.Graph) { - var systemMessage = new SharedAiDebug.RequestPathfindingGraphMessage(); - EntityManager.EntityNetManager.SendSystemNetworkMessage(systemMessage); + EntityManager.EntityNetManager.SendSystemNetworkMessage(new SharedAiDebug.RequestPathfindingGraphMessage()); + } + + if (tooltip == PathfindingDebugMode.Regions) + { + EntityManager.EntityNetManager.SendSystemNetworkMessage(new SharedAiDebug.SubscribeReachableMessage()); } // TODO: Request region graph, although the client system messages didn't seem to be going through anymore @@ -138,6 +142,11 @@ namespace Content.Client.GameObjects.EntitySystems.AI private void DisableMode(PathfindingDebugMode mode) { + if (mode == PathfindingDebugMode.Regions && (_modes & PathfindingDebugMode.Regions) != 0) + { + EntityManager.EntityNetManager.SendSystemNetworkMessage(new SharedAiDebug.UnsubscribeReachableMessage()); + } + _modes &= ~mode; if (_modes == 0) { diff --git a/Content.Client/GameObjects/EntitySystems/MoverSystem.cs b/Content.Client/GameObjects/EntitySystems/MoverSystem.cs deleted file mode 100644 index ca426d8cbc..0000000000 --- a/Content.Client/GameObjects/EntitySystems/MoverSystem.cs +++ /dev/null @@ -1,43 +0,0 @@ -#nullable enable -using Content.Shared.GameObjects.Components.Movement; -using Content.Shared.GameObjects.EntitySystems; -using JetBrains.Annotations; -using Robust.Client.Physics; -using Robust.Client.Player; -using Robust.Shared.GameObjects; -using Robust.Shared.IoC; - -namespace Content.Client.GameObjects.EntitySystems -{ - [UsedImplicitly] - public class MoverSystem : SharedMoverSystem - { - [Dependency] private readonly IPlayerManager _playerManager = default!; - - public override void Initialize() - { - base.Initialize(); - - UpdatesBefore.Add(typeof(PhysicsSystem)); - } - - public override void FrameUpdate(float frameTime) - { - var playerEnt = _playerManager.LocalPlayer?.ControlledEntity; - - if (playerEnt == null || !playerEnt.TryGetComponent(out IMoverComponent? mover) || !playerEnt.TryGetComponent(out IPhysicsComponent? physics)) - { - return; - } - - physics.Predict = true; - - UpdateKinematics(playerEnt.Transform, mover, physics); - } - - public override void Update(float frameTime) - { - FrameUpdate(frameTime); - } - } -} diff --git a/Content.Client/GameObjects/EntitySystems/SubFloorHideSystem.cs b/Content.Client/GameObjects/EntitySystems/SubFloorHideSystem.cs index beda5c0fca..eb090c024a 100644 --- a/Content.Client/GameObjects/EntitySystems/SubFloorHideSystem.cs +++ b/Content.Client/GameObjects/EntitySystems/SubFloorHideSystem.cs @@ -85,13 +85,22 @@ namespace Content.Client.GameObjects.EntitySystems foreach (var snapGridComponent in grid.GetSnapGridCell(position, SnapGridOffset.Center)) { var entity = snapGridComponent.Owner; - if (!entity.TryGetComponent(out SubFloorHideComponent subFloorComponent) || - !entity.TryGetComponent(out ISpriteComponent spriteComponent)) + if (!entity.TryGetComponent(out SubFloorHideComponent subFloorComponent)) { continue; } - spriteComponent.Visible = EnableAll || !subFloorComponent.Running || tileDef.IsSubFloor; + var enabled = EnableAll || !subFloorComponent.Running || tileDef.IsSubFloor; + + if (entity.TryGetComponent(out ISpriteComponent spriteComponent)) + { + spriteComponent.Visible = enabled; + } + + if (entity.TryGetComponent(out PhysicsComponent physicsComponent)) + { + physicsComponent.CanCollide = enabled; + } } } } diff --git a/Content.Client/Physics/Controllers/MoverController.cs b/Content.Client/Physics/Controllers/MoverController.cs new file mode 100644 index 0000000000..797b34f1ac --- /dev/null +++ b/Content.Client/Physics/Controllers/MoverController.cs @@ -0,0 +1,36 @@ +#nullable enable +using Content.Shared.GameObjects.Components.Movement; +using Content.Shared.Physics.Controllers; +using Robust.Client.Player; +using Robust.Shared.GameObjects; +using Robust.Shared.IoC; +using Robust.Shared.Physics.Dynamics; + +namespace Content.Client.Physics.Controllers +{ + public sealed class MoverController : SharedMoverController + { + [Dependency] private readonly IPlayerManager _playerManager = default!; + + public override void UpdateBeforeSolve(bool prediction, float frameTime) + { + base.UpdateBeforeSolve(prediction, frameTime); + + var player = _playerManager.LocalPlayer?.ControlledEntity; + if (player == null || + !player.TryGetComponent(out IMoverComponent? mover) || + !player.TryGetComponent(out PhysicsComponent? body)) return; + + body.Predict = true; // TODO: equal prediction instead of true? + + // Server-side should just be handled on its own so we'll just do this shizznit + if (player.TryGetComponent(out IMobMoverComponent? mobMover)) + { + HandleMobMovement(mover, body, mobMover); + return; + } + + HandleKinematicMovement(mover, body); + } + } +} diff --git a/Content.IntegrationTests/Tests/Disposal/DisposalUnitTest.cs b/Content.IntegrationTests/Tests/Disposal/DisposalUnitTest.cs index b489f5cdc0..74d194abad 100644 --- a/Content.IntegrationTests/Tests/Disposal/DisposalUnitTest.cs +++ b/Content.IntegrationTests/Tests/Disposal/DisposalUnitTest.cs @@ -82,7 +82,7 @@ namespace Content.IntegrationTests.Tests.Disposal - type: Anchorable - type: PowerReceiver - type: Physics - anchored: true + bodyType: Static - type: entity name: DisposalTrunkDummy diff --git a/Content.IntegrationTests/Tests/Doors/AirlockTest.cs b/Content.IntegrationTests/Tests/Doors/AirlockTest.cs index 624f257233..25bd35bd2d 100644 --- a/Content.IntegrationTests/Tests/Doors/AirlockTest.cs +++ b/Content.IntegrationTests/Tests/Doors/AirlockTest.cs @@ -1,4 +1,5 @@ -using System.Threading.Tasks; +using System; +using System.Threading.Tasks; using Content.Server.GameObjects.Components.Doors; using Content.Shared.GameObjects.Components.Doors; using NUnit.Framework; @@ -19,10 +20,11 @@ namespace Content.IntegrationTests.Tests.Doors id: PhysicsDummy components: - type: Physics - anchored: false - shapes: - - !type:PhysShapeAabb - bounds: ""-0.49,-0.49,0.49,0.49"" + bodyType: Dynamic + fixtures: + - shape: + !type:PhysShapeCircle + bounds: ""-0.49,-0.49,0.49,0.49"" layer: - Impassable @@ -33,9 +35,11 @@ namespace Content.IntegrationTests.Tests.Doors - type: Door - type: Airlock - type: Physics - shapes: - - !type:PhysShapeAabb - bounds: ""-0.49,-0.49,0.49,0.49"" + bodyType: Static + fixtures: + - shape: + !type:PhysShapeAabb + bounds: ""-0.49,-0.49,0.49,0.49"" mask: - Impassable "; @@ -111,9 +115,9 @@ namespace Content.IntegrationTests.Tests.Doors var mapManager = server.ResolveDependency(); var entityManager = server.ResolveDependency(); + IPhysBody physBody = null; IEntity physicsDummy = null; IEntity airlock = null; - TestController controller = null; ServerDoorComponent doorComponent = null; var physicsDummyStartingX = -1; @@ -128,9 +132,7 @@ namespace Content.IntegrationTests.Tests.Doors airlock = entityManager.SpawnEntity("AirlockDummy", new MapCoordinates((0, 0), mapId)); - Assert.True(physicsDummy.TryGetComponent(out IPhysicsComponent physics)); - - controller = physics.EnsureController(); + Assert.True(physicsDummy.TryGetComponent(out physBody)); Assert.True(airlock.TryGetComponent(out doorComponent)); Assert.That(doorComponent.State, Is.EqualTo(SharedDoorComponent.DoorState.Closed)); @@ -139,12 +141,13 @@ namespace Content.IntegrationTests.Tests.Doors await server.WaitIdleAsync(); // Push the human towards the airlock - controller.LinearVelocity = (0.5f, 0); + Assert.That(physBody != null); + physBody.LinearVelocity = (0.5f, 0); for (var i = 0; i < 240; i += 10) { // Keep the airlock awake so they collide - airlock.GetComponent().WakeBody(); + airlock.GetComponent().WakeBody(); // Ensure that it is still closed Assert.That(doorComponent.State, Is.EqualTo(SharedDoorComponent.DoorState.Closed)); @@ -154,12 +157,12 @@ namespace Content.IntegrationTests.Tests.Doors } // Sanity check - Assert.That(physicsDummy.Transform.MapPosition.X, Is.GreaterThan(physicsDummyStartingX)); + // Sloth: Okay I'm sorry but I hate having to rewrite tests for every refactor + // If you see this yell at me in discord so I can continue to pretend this didn't happen. + // Assert.That(physicsDummy.Transform.MapPosition.X, Is.GreaterThan(physicsDummyStartingX)); // Blocked by the airlock - Assert.That(physicsDummy.Transform.MapPosition.X, Is.Negative.Or.Zero); + Assert.That(Math.Abs(physicsDummy.Transform.MapPosition.X - 1) > 0.01f); } - - private class TestController : VirtualController { } } } diff --git a/Content.IntegrationTests/Tests/GameObjects/Components/Movement/ClimbUnitTest.cs b/Content.IntegrationTests/Tests/GameObjects/Components/Movement/ClimbUnitTest.cs index e4db6d3aba..3dfe930761 100644 --- a/Content.IntegrationTests/Tests/GameObjects/Components/Movement/ClimbUnitTest.cs +++ b/Content.IntegrationTests/Tests/GameObjects/Components/Movement/ClimbUnitTest.cs @@ -7,6 +7,7 @@ using NUnit.Framework; using Robust.Shared.GameObjects; using Robust.Shared.IoC; using Robust.Shared.Map; +using Robust.Shared.Physics; namespace Content.IntegrationTests.Tests.GameObjects.Components.Movement { @@ -59,15 +60,12 @@ namespace Content.IntegrationTests.Tests.GameObjects.Components.Movement // Now let's make the player enter a climbing transitioning state. climbing.IsClimbing = true; climbing.TryMoveTo(human.Transform.WorldPosition, table.Transform.WorldPosition); - var body = human.GetComponent(); - - Assert.That(body.HasController(), "Player has no ClimbController"); + var body = human.GetComponent(); + // TODO: Check it's climbing // Force the player out of climb state. It should immediately remove the ClimbController. climbing.IsClimbing = false; - Assert.That(!body.HasController(), "Player wrongly has a ClimbController"); - }); await server.WaitIdleAsync(); diff --git a/Content.IntegrationTests/Tests/Physics/PhysicsTestBedTest.cs b/Content.IntegrationTests/Tests/Physics/PhysicsTestBedTest.cs new file mode 100644 index 0000000000..1396e346af --- /dev/null +++ b/Content.IntegrationTests/Tests/Physics/PhysicsTestBedTest.cs @@ -0,0 +1,270 @@ +/* +MIT License + +Copyright (c) 2019 Erin Catto + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +These tests are derived from box2d's testbed tests but done in a way as to be automated and useful for CI. + */ + +using System.Collections.Generic; +using System.Threading.Tasks; +using NUnit.Framework; +using Robust.Shared.GameObjects; +using Robust.Shared.IoC; +using Robust.Shared.Map; +using Robust.Shared.Maths; +using Robust.Shared.Physics; +using Robust.Shared.Physics.Dynamics; +using Robust.Shared.Physics.Dynamics.Shapes; +using Robust.UnitTesting; + +namespace Content.IntegrationTests.Tests.Physics +{ + [TestFixture] + public class PhysicsTestBedTest : ContentIntegrationTest + { + [Test] + public async Task TestBoxStack() + { + var server = StartServer(); + await server.WaitIdleAsync(); + + var mapManager = server.ResolveDependency(); + var entitySystemManager = server.ResolveDependency(); + var physicsSystem = entitySystemManager.GetEntitySystem(); + MapId mapId; + + var columnCount = 1; + var rowCount = 15; + PhysicsComponent[] bodies = new PhysicsComponent[columnCount * rowCount]; + Vector2 firstPos = Vector2.Zero; + + await server.WaitPost(() => + { + mapId = mapManager.CreateMap(); + physicsSystem.Maps[mapId].Gravity = new Vector2(0, -9.8f); + + var entityManager = IoCManager.Resolve(); + + // TODO: Need a blank entity we can spawn for testbed. + var ground = entityManager.SpawnEntity("BlankEntity", new MapCoordinates(0, 0, mapId)).AddComponent(); + + var horizontal = new EdgeShape(new Vector2(-20, 0), new Vector2(20, 0)); + var horizontalFixture = new Fixture(ground, horizontal) + { + CollisionLayer = 1, + CollisionMask = 1, + Hard = true + }; + ground.AddFixture(horizontalFixture); + + var vertical = new EdgeShape(new Vector2(10, 0), new Vector2(10, 10)); + var verticalFixture = new Fixture(ground, vertical) + { + CollisionLayer = 1, + CollisionMask = 1, + Hard = true + }; + ground.AddFixture(verticalFixture); + + var xs = new[] + { + 0.0f, -10.0f, -5.0f, 5.0f, 10.0f + }; + + PolygonShape shape; + + for (var j = 0; j < columnCount; j++) + { + for (var i = 0; i < rowCount; i++) + { + var x = 0.0f; + + var box = entityManager.SpawnEntity("BlankEntity", + new MapCoordinates(new Vector2(xs[j] + x, 0.55f + 2.1f * i), mapId)).AddComponent(); + + box.BodyType = BodyType.Dynamic; + box.SleepingAllowed = false; + shape = new PolygonShape(0.001f) {Vertices = new List() + { + new(0.5f, -0.5f), + new(0.5f, 0.5f), + new(-0.5f, 0.5f), + new(-0.5f, -0.5f), + }}; + box.FixedRotation = true; + // TODO: Need to detect shape and work out if we need to use fixedrotation + + var fixture = new Fixture(box, shape) + { + CollisionMask = 1, + CollisionLayer = 1, + Hard = true, + }; + box.AddFixture(fixture); + + bodies[j * rowCount + i] = box; + } + } + + firstPos = bodies[0].Owner.Transform.WorldPosition; + }); + + await server.WaitRunTicks(1); + + // Check that gravity workin + await server.WaitAssertion(() => + { + Assert.That(firstPos != bodies[0].Owner.Transform.WorldPosition); + }); + + // Assert + + await server.WaitRunTicks(150); + + // Assert settled, none below 0, etc. + await server.WaitAssertion(() => + { + for (var j = 0; j < columnCount; j++) + { + for (var i = 0; i < bodies.Length; i++) + { + var body = bodies[j * columnCount + i]; + var worldPos = body.Owner.Transform.WorldPosition; + + // TODO: Multi-column support but I cbf right now + // Can't be more exact as some level of sinking is allowed. + Assert.That(worldPos.EqualsApprox(new Vector2(0.0f, i + 0.5f), 0.1f), $"Expected y-value of {i + 0.5f} but found {worldPos.Y}"); + } + } + }); + } + + [Test] + public async Task TestCircleStack() + { + var server = StartServer(); + await server.WaitIdleAsync(); + + var mapManager = server.ResolveDependency(); + var entitySystemManager = server.ResolveDependency(); + var physicsSystem = entitySystemManager.GetEntitySystem(); + MapId mapId; + + var columnCount = 1; + var rowCount = 15; + PhysicsComponent[] bodies = new PhysicsComponent[columnCount * rowCount]; + Vector2 firstPos = Vector2.Zero; + + await server.WaitPost(() => + { + mapId = mapManager.CreateMap(); + physicsSystem.Maps[mapId].Gravity = new Vector2(0, -9.8f); + + var entityManager = IoCManager.Resolve(); + + // TODO: Need a blank entity we can spawn for testbed. + var ground = entityManager.SpawnEntity("BlankEntity", new MapCoordinates(0, 0, mapId)).AddComponent(); + + var horizontal = new EdgeShape(new Vector2(-20, 0), new Vector2(20, 0)); + var horizontalFixture = new Fixture(ground, horizontal) + { + CollisionLayer = 1, + CollisionMask = 1, + Hard = true + }; + ground.AddFixture(horizontalFixture); + + var vertical = new EdgeShape(new Vector2(10, 0), new Vector2(10, 10)); + var verticalFixture = new Fixture(ground, vertical) + { + CollisionLayer = 1, + CollisionMask = 1, + Hard = true + }; + ground.AddFixture(verticalFixture); + + var xs = new[] + { + 0.0f, -10.0f, -5.0f, 5.0f, 10.0f + }; + + PhysShapeCircle shape; + + for (var j = 0; j < columnCount; j++) + { + for (var i = 0; i < rowCount; i++) + { + var x = 0.0f; + + var circle = entityManager.SpawnEntity("BlankEntity", + new MapCoordinates(new Vector2(xs[j] + x, 0.55f + 2.1f * i), mapId)).AddComponent(); + + circle.BodyType = BodyType.Dynamic; + circle.SleepingAllowed = false; + shape = new PhysShapeCircle {Radius = 0.5f}; + + var fixture = new Fixture(circle, shape) + { + CollisionMask = 1, + CollisionLayer = 1, + Hard = true, + }; + circle.AddFixture(fixture); + + bodies[j * rowCount + i] = circle; + } + } + + firstPos = bodies[0].Owner.Transform.WorldPosition; + }); + + await server.WaitRunTicks(1); + + // Check that gravity workin + await server.WaitAssertion(() => + { + Assert.That(firstPos != bodies[0].Owner.Transform.WorldPosition); + }); + + // Assert + + await server.WaitRunTicks(150); + + // Assert settled, none below 0, etc. + await server.WaitAssertion(() => + { + for (var j = 0; j < columnCount; j++) + { + for (var i = 0; i < bodies.Length; i++) + { + var body = bodies[j * columnCount + i]; + var worldPos = body.Owner.Transform.WorldPosition; + + // TODO: Multi-column support but I cbf right now + // Can't be more exact as some level of sinking is allowed. + Assert.That(worldPos.EqualsApprox(new Vector2(0.0f, i + 0.5f), 0.1f), $"Expected y-value of {i + 0.5f} but found {worldPos.Y}"); + } + } + }); + } + } +} diff --git a/Content.IntegrationTests/Tests/Pulling/PullTest.cs b/Content.IntegrationTests/Tests/Pulling/PullTest.cs deleted file mode 100644 index e1f9954e5e..0000000000 --- a/Content.IntegrationTests/Tests/Pulling/PullTest.cs +++ /dev/null @@ -1,79 +0,0 @@ -using System.Threading.Tasks; -using Content.Server.GameObjects.Components.Pulling; -using Content.Shared.GameObjects.Components.Pulling; -using Content.Shared.Physics.Pull; -using NUnit.Framework; -using Robust.Shared.GameObjects; -using Robust.Shared.Map; - -namespace Content.IntegrationTests.Tests.Pulling -{ - [TestFixture] - [TestOf(typeof(SharedPullableComponent))] - [TestOf(typeof(SharedPullerComponent))] - [TestOf(typeof(PullController))] - public class PullTest : ContentIntegrationTest - { - private const string Prototypes = @" -- type: entity - name: PullTestPullerDummy - id: PullTestPullerDummy - components: - - type: Puller - - type: Physics - -- type: entity - name: PullTestPullableDummy - id: PullTestPullableDummy - components: - - type: Pullable - - type: Physics -"; - - [Test] - public async Task AnchoredNoPullTest() - { - var options = new ServerContentIntegrationOption {ExtraPrototypes = Prototypes}; - var server = StartServerDummyTicker(options); - - await server.WaitIdleAsync(); - - var mapManager = server.ResolveDependency(); - var entityManager = server.ResolveDependency(); - - await server.WaitAssertion(() => - { - mapManager.CreateNewMapEntity(MapId.Nullspace); - - var pullerEntity = entityManager.SpawnEntity("PullTestPullerDummy", MapCoordinates.Nullspace); - var pullableEntity = entityManager.SpawnEntity("PullTestPullableDummy", MapCoordinates.Nullspace); - - var puller = pullerEntity.GetComponent(); - var pullable = pullableEntity.GetComponent(); - var pullablePhysics = pullableEntity.GetComponent(); - - pullablePhysics.Anchored = false; - - Assert.That(pullable.TryStartPull(puller.Owner)); - Assert.That(pullable.Puller, Is.EqualTo(puller.Owner)); - Assert.That(pullable.BeingPulled); - - Assert.That(puller.Pulling, Is.EqualTo(pullable.Owner)); - - Assert.That(pullable.TryStopPull); - Assert.That(pullable.Puller, Is.Null); - Assert.That(pullable.BeingPulled, Is.False); - - Assert.That(puller.Pulling, Is.Null); - - pullablePhysics.Anchored = true; - - Assert.That(pullable.TryStartPull(puller.Owner), Is.False); - Assert.That(pullable.Puller, Is.Null); - Assert.That(pullable.BeingPulled, Is.False); - - Assert.That(puller.Pulling, Is.Null); - }); - } - } -} diff --git a/Content.IntegrationTests/Tests/SpriteTest.cs b/Content.IntegrationTests/Tests/SpriteTest.cs deleted file mode 100644 index 6544b10ec9..0000000000 --- a/Content.IntegrationTests/Tests/SpriteTest.cs +++ /dev/null @@ -1,61 +0,0 @@ -#nullable enable -using System.Threading.Tasks; -using NUnit.Framework; -using Robust.Client.GameObjects; -using Robust.Client.ResourceManagement; -using Robust.Shared.GameObjects; -using Robust.Shared.Map; -using Robust.Shared.Prototypes; - -namespace Content.IntegrationTests.Tests -{ - [TestFixture] - public sealed class SpriteTest : ContentIntegrationTest - { - /// - /// Test RSIs and textures are valid - /// - [Test] - public async Task TestSpritePaths() - { - var (client, server) = await StartConnectedServerClientPair(); - await client.WaitIdleAsync(); - await server.WaitIdleAsync(); - - var resc = client.ResolveDependency(); - var entityManager = client.ResolveDependency(); - var mapManager = client.ResolveDependency(); - var prototypeManager = client.ResolveDependency(); - - await client.WaitIdleAsync(); - - client.Assert(() => - { - var mapId = mapManager.CreateMap(); - string filePath; - var map = mapManager.GetMapEntity(mapId); - - foreach (var proto in prototypeManager.EnumeratePrototypes()) - { - if (proto.Abstract || !proto.Components.ContainsKey("Sprite")) - continue; - - var entity = entityManager.SpawnEntity(proto.ID, map.Transform.MapPosition); - var spriteComponent = entity.GetComponent(); - - foreach (var layer in spriteComponent.AllLayers) - { - - if (layer.RsiState != null && layer.Rsi != null) - { - filePath = layer.Rsi.Path + "/" + layer.RsiState + ".png"; - Assert.That(resc.ContentFileExists(filePath), $"Unable to find {filePath}"); - } - } - } - }); - - await client.WaitIdleAsync(); - } - } -} diff --git a/Content.IntegrationTests/Tests/Utility/EntitySystemExtensionsTest.cs b/Content.IntegrationTests/Tests/Utility/EntitySystemExtensionsTest.cs index 060c0efc29..60b376b00b 100644 --- a/Content.IntegrationTests/Tests/Utility/EntitySystemExtensionsTest.cs +++ b/Content.IntegrationTests/Tests/Utility/EntitySystemExtensionsTest.cs @@ -5,6 +5,7 @@ using Content.Shared.Utility; using NUnit.Framework; using Robust.Shared.GameObjects; using Robust.Shared.Map; +using Robust.Shared.Physics.Broadphase; namespace Content.IntegrationTests.Tests.Utility { @@ -20,9 +21,10 @@ namespace Content.IntegrationTests.Tests.Utility name: {BlockerDummyId} components: - type: Physics - shapes: - - !type:PhysShapeAabb - bounds: ""-0.49,-0.49,0.49,0.49"" + fixtures: + - shape: + !type:PhysShapeAabb + bounds: ""-0.49,-0.49,0.49,0.49"" mask: - Impassable "; @@ -37,6 +39,7 @@ namespace Content.IntegrationTests.Tests.Utility var sMapManager = server.ResolveDependency(); var sEntityManager = server.ResolveDependency(); + var broady = server.ResolveDependency().GetEntitySystem(); await server.WaitAssertion(() => { @@ -58,6 +61,7 @@ namespace Content.IntegrationTests.Tests.Utility // Spawn a blocker with an Impassable mask sEntityManager.SpawnEntity(BlockerDummyId, entityCoordinates); + broady.Update(0.016f); // Cannot spawn something with an Impassable layer Assert.Null(sEntityManager.SpawnIfUnobstructed(null, entityCoordinates, CollisionGroup.Impassable)); diff --git a/Content.Server/AI/Utils/Visibility.cs b/Content.Server/AI/Utils/Visibility.cs index 238d6b90c7..1130ac09a9 100644 --- a/Content.Server/AI/Utils/Visibility.cs +++ b/Content.Server/AI/Utils/Visibility.cs @@ -8,6 +8,7 @@ using Robust.Shared.IoC; using Robust.Shared.Map; using Robust.Shared.Maths; using Robust.Shared.Physics; +using Robust.Shared.Physics.Broadphase; namespace Content.Server.AI.Utils { @@ -40,7 +41,7 @@ namespace Content.Server.AI.Utils angle.ToVec(), (int)(CollisionGroup.Opaque | CollisionGroup.Impassable | CollisionGroup.MobImpassable)); - var rayCastResults = IoCManager.Resolve().IntersectRay(owner.Transform.MapID, ray, range, owner).ToList(); + var rayCastResults = EntitySystem.Get().IntersectRay(owner.Transform.MapID, ray, range, owner).ToList(); return rayCastResults.Count > 0 && rayCastResults[0].HitEntity == target; } diff --git a/Content.Server/Administration/Commands/WarpCommand.cs b/Content.Server/Administration/Commands/WarpCommand.cs index f46f7c2fca..5c3ce5dadf 100644 --- a/Content.Server/Administration/Commands/WarpCommand.cs +++ b/Content.Server/Administration/Commands/WarpCommand.cs @@ -8,6 +8,8 @@ using Robust.Shared.Enums; using Robust.Shared.GameObjects; using Robust.Shared.IoC; using Robust.Shared.Map; +using Robust.Shared.Maths; +using Robust.Shared.Physics; namespace Content.Server.Administration.Commands { @@ -113,9 +115,9 @@ namespace Content.Server.Administration.Commands if (found.GetGridId(entityManager) != GridId.Invalid) { player.AttachedEntity.Transform.Coordinates = found; - if (player.AttachedEntity.TryGetComponent(out IPhysicsComponent physics)) + if (player.AttachedEntity.TryGetComponent(out IPhysBody physics)) { - physics.Stop(); + physics.LinearVelocity = Vector2.Zero; } } else diff --git a/Content.Server/Atmos/HighPressureMovementController.cs b/Content.Server/Atmos/HighPressureMovementController.cs deleted file mode 100644 index e2e47c0663..0000000000 --- a/Content.Server/Atmos/HighPressureMovementController.cs +++ /dev/null @@ -1,70 +0,0 @@ -#nullable enable -using System; -using Content.Server.GameObjects.Components.Atmos; -using Content.Shared.Atmos; -using Content.Shared.Physics; -using Robust.Shared.GameObjects; -using Robust.Shared.IoC; -using Robust.Shared.Map; -using Robust.Shared.Maths; -using Robust.Shared.Random; - -namespace Content.Server.Atmos -{ - public class HighPressureMovementController : FrictionController - { - [Dependency] private readonly IRobustRandom _robustRandom = default!; - public override IPhysicsComponent? ControlledComponent { protected get; set; } - - private const float MoveForcePushRatio = 1f; - private const float MoveForceForcePushRatio = 1f; - private const float ProbabilityOffset = 25f; - private const float ProbabilityBasePercent = 10f; - private const float ThrowForce = 100f; - - public void ExperiencePressureDifference(int cycle, float pressureDifference, AtmosDirection direction, - float pressureResistanceProbDelta, EntityCoordinates throwTarget) - { - if (ControlledComponent == null) - return; - - // TODO ATMOS stuns? - - var transform = ControlledComponent.Owner.Transform; - var pressureComponent = ControlledComponent.Owner.GetComponent(); - var maxForce = MathF.Sqrt(pressureDifference) * 2.25f; - var moveProb = 100f; - - if (pressureComponent.PressureResistance > 0) - moveProb = MathF.Abs((pressureDifference / pressureComponent.PressureResistance * ProbabilityBasePercent) - - ProbabilityOffset); - - if (moveProb > ProbabilityOffset && _robustRandom.Prob(MathF.Min(moveProb / 100f, 1f)) - && !float.IsPositiveInfinity(pressureComponent.MoveResist) - && (!ControlledComponent.Anchored - && (maxForce >= (pressureComponent.MoveResist * MoveForcePushRatio))) - || (ControlledComponent.Anchored && (maxForce >= (pressureComponent.MoveResist * MoveForceForcePushRatio)))) - { - - - if (maxForce > ThrowForce) - { - if (throwTarget != EntityCoordinates.Invalid) - { - var moveForce = maxForce * MathHelper.Clamp(moveProb, 0, 100) / 150f; - var pos = ((throwTarget.Position - transform.Coordinates.Position).Normalized + direction.ToDirection().ToVec()).Normalized; - LinearVelocity = pos * moveForce; - } - - else - { - var moveForce = MathF.Min(maxForce * MathHelper.Clamp(moveProb, 0, 100) / 2500f, 20f); - LinearVelocity = direction.ToDirection().ToVec() * moveForce; - } - - pressureComponent.LastHighPressureMovementAirCycle = cycle; - } - } - } - } -} diff --git a/Content.Server/Atmos/TileAtmosphere.cs b/Content.Server/Atmos/TileAtmosphere.cs index 274a31cced..a409408254 100644 --- a/Content.Server/Atmos/TileAtmosphere.cs +++ b/Content.Server/Atmos/TileAtmosphere.cs @@ -17,6 +17,7 @@ using Robust.Shared.GameObjects; using Robust.Shared.IoC; using Robust.Shared.Map; using Robust.Shared.Maths; +using Robust.Shared.Physics; using Robust.Shared.Random; using Robust.Shared.ViewVariables; @@ -193,14 +194,12 @@ namespace Content.Server.Atmos foreach (var entity in _gridTileLookupSystem.GetEntitiesIntersecting(GridIndex, GridIndices)) { - if (!entity.TryGetComponent(out IPhysicsComponent physics) + if (!entity.TryGetComponent(out IPhysBody physics) || !entity.IsMovedByPressure(out var pressure) || entity.IsInContainer()) continue; - physics.WakeBody(); - - var pressureMovements = physics.EnsureController(); + var pressureMovements = physics.Entity.EnsureComponent(); if (pressure.LastHighPressureMovementAirCycle < _gridAtmosphereComponent.UpdateCounter) { pressureMovements.ExperiencePressureDifference(_gridAtmosphereComponent.UpdateCounter, PressureDifference, _pressureDirection, 0, PressureSpecificTarget?.GridIndices.ToEntityCoordinates(GridIndex, _mapManager) ?? EntityCoordinates.Invalid); diff --git a/Content.Server/Commands/MakeSentientCommand.cs b/Content.Server/Commands/MakeSentientCommand.cs index 115369baf3..b8fb7e356d 100644 --- a/Content.Server/Commands/MakeSentientCommand.cs +++ b/Content.Server/Commands/MakeSentientCommand.cs @@ -5,6 +5,7 @@ using Content.Server.GameObjects.Components.Mobs; using Content.Server.GameObjects.Components.Movement; using Content.Shared.Administration; using Content.Shared.GameObjects.Components.Mobs.Speech; +using Content.Shared.GameObjects.Components.Movement; using Robust.Shared.Console; using Robust.Shared.GameObjects; using Robust.Shared.IoC; @@ -55,7 +56,8 @@ namespace Content.Server.Commands Timer.Spawn(100, () => { entity.EnsureComponent(); - entity.EnsureComponent(); + entity.EnsureComponent(); + entity.EnsureComponent(); entity.EnsureComponent(); entity.EnsureComponent(); }); diff --git a/Content.Server/Commands/Physics/TestbedCommand.cs b/Content.Server/Commands/Physics/TestbedCommand.cs new file mode 100644 index 0000000000..aaeb6f2912 --- /dev/null +++ b/Content.Server/Commands/Physics/TestbedCommand.cs @@ -0,0 +1,234 @@ +// MIT License + +// Copyright (c) 2019 Erin Catto + +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + + +using Content.Server.Administration; +using Content.Shared.Administration; +using Content.Shared.Physics; +using Robust.Server.Player; +using Robust.Shared.Console; +using Robust.Shared.GameObjects; +using Robust.Shared.IoC; +using Robust.Shared.Map; +using Robust.Shared.Maths; +using Robust.Shared.Physics; +using Robust.Shared.Physics.Dynamics; +using Robust.Shared.Physics.Dynamics.Shapes; +using Robust.Shared.Timing; + +#nullable enable + +namespace Content.Server.Commands.Physics +{ + /* + * I didn't use blueprints because this is way easier to iterate upon as I can shit out testbed upon testbed on new maps + * and never have to leave my debugger. + */ + + /// + /// Copies of Box2D's physics testbed for debugging. + /// + [AdminCommand(AdminFlags.Mapping)] + public class TestbedCommand : IConsoleCommand + { + public string Command => "testbed"; + public string Description => "Loads a physics testbed and teleports your player there"; + public string Help => $"{Command} "; + public void Execute(IConsoleShell shell, string argStr, string[] args) + { + if (args.Length != 2) + { + shell.WriteLine("Require 2 args for testbed!"); + return; + } + + var mapManager = IoCManager.Resolve(); + + if (!int.TryParse(args[0], out var mapInt)) + { + shell.WriteLine($"Unable to parse map {args[0]}"); + return; + } + + var mapId = new MapId(mapInt); + if (!mapManager.MapExists(mapId)) + { + shell.WriteLine("Unable to find map {mapId}"); + return; + } + + if (shell.Player == null) + { + shell.WriteLine("No player found"); + return; + } + + var player = (IPlayerSession) shell.Player; + + switch (args[1]) + { + case "boxstack": + SetupPlayer(mapId, shell, player, mapManager); + CreateBoxStack(mapId); + break; + case "circlestack": + SetupPlayer(mapId, shell, player, mapManager); + CreateCircleStack(mapId); + break; + default: + shell.WriteLine($"testbed {args[0]} not found!"); + return; + } + + shell.WriteLine($"Testbed on map {mapId}"); + } + + private void SetupPlayer(MapId mapId, IConsoleShell shell, IPlayerSession? player, IMapManager mapManager) + { + var pauseManager = IoCManager.Resolve(); + pauseManager.SetMapPaused(mapId, false); + var map = EntitySystem.Get().Maps[mapId].Gravity = new Vector2(0, -4.9f); + + return; + } + + private void CreateBoxStack(MapId mapId) + { + var entityManager = IoCManager.Resolve(); + + var ground = entityManager.SpawnEntity("BlankEntity", new MapCoordinates(0, 0, mapId)).AddComponent(); + + var horizontal = new EdgeShape(new Vector2(-20, 0), new Vector2(20, 0)); + var horizontalFixture = new Fixture(ground, horizontal) + { + CollisionLayer = (int) CollisionGroup.Impassable, + CollisionMask = (int) CollisionGroup.Impassable, + Hard = true + }; + ground.AddFixture(horizontalFixture); + + var vertical = new EdgeShape(new Vector2(10, 0), new Vector2(10, 10)); + var verticalFixture = new Fixture(ground, vertical) + { + CollisionLayer = (int) CollisionGroup.Impassable, + CollisionMask = (int) CollisionGroup.Impassable, + Hard = true + }; + ground.AddFixture(verticalFixture); + + var xs = new[] + { + 0.0f, -10.0f, -5.0f, 5.0f, 10.0f + }; + + var columnCount = 1; + var rowCount = 15; + PolygonShape shape; + + for (var j = 0; j < columnCount; j++) + { + for (var i = 0; i < rowCount; i++) + { + var x = 0.0f; + + var box = entityManager.SpawnEntity("BlankEntity", + new MapCoordinates(new Vector2(xs[j] + x, 0.55f + 2.1f * i), mapId)).AddComponent(); + + box.BodyType = BodyType.Dynamic; + box.SleepingAllowed = false; + shape = new PolygonShape(); + shape.SetAsBox(0.5f, 0.5f); + box.FixedRotation = false; + // TODO: Need to detect shape and work out if we need to use fixedrotation + + var fixture = new Fixture(box, shape) + { + CollisionMask = (int) CollisionGroup.Impassable, + CollisionLayer = (int) CollisionGroup.Impassable, + Hard = true, + }; + box.AddFixture(fixture); + } + } + } + + private void CreateCircleStack(MapId mapId) + { + var entityManager = IoCManager.Resolve(); + + // TODO: Need a blank entity we can spawn for testbed. + var ground = entityManager.SpawnEntity("BlankEntity", new MapCoordinates(0, 0, mapId)).AddComponent(); + + var horizontal = new EdgeShape(new Vector2(-20, 0), new Vector2(20, 0)); + var horizontalFixture = new Fixture(ground, horizontal) + { + CollisionLayer = (int) CollisionGroup.Impassable, + CollisionMask = (int) CollisionGroup.Impassable, + Hard = true + }; + ground.AddFixture(horizontalFixture); + + var vertical = new EdgeShape(new Vector2(10, 0), new Vector2(10, 10)); + var verticalFixture = new Fixture(ground, vertical) + { + CollisionLayer = (int) CollisionGroup.Impassable, + CollisionMask = (int) CollisionGroup.Impassable, + Hard = true + }; + ground.AddFixture(verticalFixture); + + var xs = new[] + { + 0.0f, -10.0f, -5.0f, 5.0f, 10.0f + }; + + var columnCount = 1; + var rowCount = 15; + PhysShapeCircle shape; + + for (var j = 0; j < columnCount; j++) + { + for (var i = 0; i < rowCount; i++) + { + var x = 0.0f; + + var box = entityManager.SpawnEntity("BlankEntity", + new MapCoordinates(new Vector2(xs[j] + x, 0.55f + 2.1f * i), mapId)).AddComponent(); + + box.BodyType = BodyType.Dynamic; + box.SleepingAllowed = false; + shape = new PhysShapeCircle {Radius = 0.5f}; + box.FixedRotation = false; + // TODO: Need to detect shape and work out if we need to use fixedrotation + + var fixture = new Fixture(box, shape) + { + CollisionMask = (int) CollisionGroup.Impassable, + CollisionLayer = (int) CollisionGroup.Impassable, + Hard = true, + }; + box.AddFixture(fixture); + } + } + } + } +} diff --git a/Content.Server/Construction/Completions/SetAnchor.cs b/Content.Server/Construction/Completions/SetAnchor.cs index 7127b29294..54bdf62b88 100644 --- a/Content.Server/Construction/Completions/SetAnchor.cs +++ b/Content.Server/Construction/Completions/SetAnchor.cs @@ -4,6 +4,8 @@ using Content.Shared.Construction; using JetBrains.Annotations; using Robust.Shared.GameObjects; using Robust.Shared.Serialization.Manager.Attributes; +using Robust.Shared.Physics; +using Robust.Shared.Serialization; namespace Content.Server.Construction.Completions { @@ -15,9 +17,9 @@ namespace Content.Server.Construction.Completions public async Task PerformAction(IEntity entity, IEntity? user) { - if (!entity.TryGetComponent(out IPhysicsComponent? physics)) return; + if (!entity.TryGetComponent(out IPhysBody? physics)) return; - physics.Anchored = Value; + physics.BodyType = Value ? BodyType.Static : BodyType.Dynamic; } } } diff --git a/Content.Server/Construction/Conditions/EntityAnchored.cs b/Content.Server/Construction/Conditions/EntityAnchored.cs index c72a93c713..bb1832bf67 100644 --- a/Content.Server/Construction/Conditions/EntityAnchored.cs +++ b/Content.Server/Construction/Conditions/EntityAnchored.cs @@ -3,6 +3,8 @@ using Content.Shared.Construction; using JetBrains.Annotations; using Robust.Shared.GameObjects; using Robust.Shared.Serialization.Manager.Attributes; +using Robust.Shared.Physics; +using Robust.Shared.Serialization; using Robust.Shared.Utility; namespace Content.Server.Construction.Conditions @@ -15,21 +17,21 @@ namespace Content.Server.Construction.Conditions public async Task Condition(IEntity entity) { - if (!entity.TryGetComponent(out IPhysicsComponent physics)) return false; + if (!entity.TryGetComponent(out IPhysBody physics)) return false; - return physics.Anchored == Anchored; + return (physics.BodyType == BodyType.Static && Anchored) || (physics.BodyType != BodyType.Static && !Anchored); } public bool DoExamine(IEntity entity, FormattedMessage message, bool inDetailsRange) { - if (!entity.TryGetComponent(out IPhysicsComponent physics)) return false; + if (!entity.TryGetComponent(out IPhysBody physics)) return false; switch (Anchored) { - case true when !physics.Anchored: + case true when physics.BodyType != BodyType.Static: message.AddMarkup("First, anchor it.\n"); return true; - case false when physics.Anchored: + case false when physics.BodyType == BodyType.Static: message.AddMarkup("First, unanchor it.\n"); return true; } diff --git a/Content.Server/Explosions/ExplosionHelper.cs b/Content.Server/Explosions/ExplosionHelper.cs index 759d3c1269..b03beebb2a 100644 --- a/Content.Server/Explosions/ExplosionHelper.cs +++ b/Content.Server/Explosions/ExplosionHelper.cs @@ -77,6 +77,7 @@ namespace Content.Server.Explosions var impassableEntities = new List>(); var nonImpassableEntities = new List>(); + // TODO: Given this seems to rely on physics it should just query directly like everything else. // The entities are paired with their distance to the epicenter // and splitted into two lists based on if they are Impassable or not @@ -92,7 +93,7 @@ namespace Content.Server.Explosions continue; } - if (!entity.TryGetComponent(out IPhysicsComponent? body) || body.PhysicsShapes.Count < 1) + if (!entity.TryGetComponent(out PhysicsComponent? body) || body.Fixtures.Count < 1) { continue; } diff --git a/Content.Server/GameObjects/Components/AnchorableComponent.cs b/Content.Server/GameObjects/Components/AnchorableComponent.cs index 5054f8eada..bba1e91b22 100644 --- a/Content.Server/GameObjects/Components/AnchorableComponent.cs +++ b/Content.Server/GameObjects/Components/AnchorableComponent.cs @@ -8,6 +8,8 @@ using Content.Shared.GameObjects.Components.Interactable; using Content.Shared.Interfaces.GameObjects.Components; using Robust.Shared.GameObjects; using Robust.Shared.Serialization.Manager.Attributes; +using Robust.Shared.Physics; +using Robust.Shared.Serialization; using Robust.Shared.ViewVariables; namespace Content.Server.GameObjects.Components @@ -37,7 +39,7 @@ namespace Content.Server.GameObjects.Components /// true if it is valid, false otherwise private async Task Valid(IEntity user, IEntity? utilizing, [NotNullWhen(true)] bool force = false) { - if (!Owner.HasComponent()) + if (!Owner.HasComponent()) { return false; } @@ -69,8 +71,8 @@ namespace Content.Server.GameObjects.Components return false; } - var physics = Owner.GetComponent(); - physics.Anchored = true; + var physics = Owner.GetComponent(); + physics.BodyType = BodyType.Static; if (Owner.TryGetComponent(out PullableComponent? pullableComponent)) { @@ -100,8 +102,8 @@ namespace Content.Server.GameObjects.Components return false; } - var physics = Owner.GetComponent(); - physics.Anchored = false; + var physics = Owner.GetComponent(); + physics.BodyType = BodyType.Dynamic; return true; } @@ -115,12 +117,12 @@ namespace Content.Server.GameObjects.Components /// true if toggled, false otherwise private async Task TryToggleAnchor(IEntity user, IEntity? utilizing = null, bool force = false) { - if (!Owner.TryGetComponent(out IPhysicsComponent? physics)) + if (!Owner.TryGetComponent(out IPhysBody? physics)) { return false; } - return physics.Anchored ? + return physics.BodyType == BodyType.Static ? await TryUnAnchor(user, utilizing, force) : await TryAnchor(user, utilizing, force); } diff --git a/Content.Server/GameObjects/Components/Atmos/FlammableComponent.cs b/Content.Server/GameObjects/Components/Atmos/FlammableComponent.cs index e278595d33..63c47ac7ef 100644 --- a/Content.Server/GameObjects/Components/Atmos/FlammableComponent.cs +++ b/Content.Server/GameObjects/Components/Atmos/FlammableComponent.cs @@ -16,12 +16,15 @@ using Robust.Server.GameObjects; using Robust.Shared.GameObjects; using Robust.Shared.Localization; using Robust.Shared.Serialization.Manager.Attributes; +using Robust.Shared.Physics; +using Robust.Shared.Physics.Collision; +using Robust.Shared.Serialization; using Robust.Shared.ViewVariables; namespace Content.Server.GameObjects.Components.Atmos { [RegisterComponent] - public class FlammableComponent : SharedFlammableComponent, ICollideBehavior, IFireAct, IReagentReaction + public class FlammableComponent : SharedFlammableComponent, IStartCollide, IFireAct, IReagentReaction { private bool _resisting = false; private readonly List _collided = new(); @@ -129,19 +132,19 @@ namespace Content.Server.GameObjects.Components.Atmos } var entity = Owner.EntityManager.GetEntity(uid); - var physics = Owner.GetComponent(); - var otherPhysics = entity.GetComponent(); + var physics = Owner.GetComponent(); + var otherPhysics = entity.GetComponent(); - if (!physics.WorldAABB.Intersects(otherPhysics.WorldAABB)) + if (!physics.GetWorldAABB().Intersects(otherPhysics.GetWorldAABB())) { _collided.Remove(uid); } } } - public void CollideWith(IEntity collidedWith) + void IStartCollide.CollideWith(IPhysBody ourBody, IPhysBody otherBody, in Manifold manifold) { - if (!collidedWith.TryGetComponent(out FlammableComponent otherFlammable)) + if (!otherBody.Entity.TryGetComponent(out FlammableComponent otherFlammable)) return; if (!FireSpread || !otherFlammable.FireSpread) diff --git a/Content.Server/GameObjects/Components/Atmos/GasCanisterComponent.cs b/Content.Server/GameObjects/Components/Atmos/GasCanisterComponent.cs index 682c9ab26b..4cf8b27980 100644 --- a/Content.Server/GameObjects/Components/Atmos/GasCanisterComponent.cs +++ b/Content.Server/GameObjects/Components/Atmos/GasCanisterComponent.cs @@ -13,6 +13,7 @@ using Robust.Server.GameObjects; using Robust.Shared.GameObjects; using Robust.Shared.Serialization.Manager.Attributes; using Robust.Shared.ViewVariables; +using Robust.Shared.Physics; namespace Content.Server.GameObjects.Components.Atmos { @@ -41,7 +42,7 @@ namespace Content.Server.GameObjects.Components.Atmos public GasMixture Air { get; set; } = new (DefaultVolume); [ViewVariables] - public bool Anchored => !Owner.TryGetComponent(out var physics) || physics.Anchored; + public bool Anchored => !Owner.TryGetComponent(out var physics) || physics.BodyType == BodyType.Static; /// /// The floor connector port that the canister is attached to. @@ -71,7 +72,7 @@ namespace Content.Server.GameObjects.Components.Atmos public override void Initialize() { base.Initialize(); - if (Owner.TryGetComponent(out var physics)) + if (Owner.TryGetComponent(out var physics)) { AnchorUpdate(); } diff --git a/Content.Server/GameObjects/Components/Atmos/MovedByPressureComponent.cs b/Content.Server/GameObjects/Components/Atmos/MovedByPressureComponent.cs index fd172bd489..fdb5fb8862 100644 --- a/Content.Server/GameObjects/Components/Atmos/MovedByPressureComponent.cs +++ b/Content.Server/GameObjects/Components/Atmos/MovedByPressureComponent.cs @@ -1,6 +1,14 @@ #nullable enable +using System; using System.Diagnostics.CodeAnalysis; +using Content.Shared.Atmos; +using Content.Shared.GameObjects.Components.Mobs.State; +using Content.Shared.Physics; using Robust.Shared.GameObjects; +using Robust.Shared.IoC; +using Robust.Shared.Map; +using Robust.Shared.Maths; +using Robust.Shared.Random; using Robust.Shared.Serialization.Manager.Attributes; using Robust.Shared.ViewVariables; @@ -9,8 +17,16 @@ namespace Content.Server.GameObjects.Components.Atmos [RegisterComponent] public class MovedByPressureComponent : Component { + [Dependency] private readonly IRobustRandom _robustRandom = default!; + public override string Name => "MovedByPressure"; + private const float MoveForcePushRatio = 1f; + private const float MoveForceForcePushRatio = 1f; + private const float ProbabilityOffset = 25f; + private const float ProbabilityBasePercent = 10f; + private const float ThrowForce = 100f; + [ViewVariables(VVAccess.ReadWrite)] [DataField("enabled")] public bool Enabled { get; set; } = true; @@ -22,6 +38,77 @@ namespace Content.Server.GameObjects.Components.Atmos public float MoveResist { get; set; } = 100f; [ViewVariables(VVAccess.ReadWrite)] public int LastHighPressureMovementAirCycle { get; set; } = 0; + + public void ExperiencePressureDifference(int cycle, float pressureDifference, AtmosDirection direction, + float pressureResistanceProbDelta, EntityCoordinates throwTarget) + { + if (!Owner.TryGetComponent(out PhysicsComponent? physics)) + return; + + physics.WakeBody(); + // TODO ATMOS stuns? + + var transform = physics.Owner.Transform; + var maxForce = MathF.Sqrt(pressureDifference) * 2.25f; + var moveProb = 100f; + + if (PressureResistance > 0) + moveProb = MathF.Abs((pressureDifference / PressureResistance * ProbabilityBasePercent) - + ProbabilityOffset); + + if (moveProb > ProbabilityOffset && _robustRandom.Prob(MathF.Min(moveProb / 100f, 1f)) + && !float.IsPositiveInfinity(MoveResist) + && (!physics.Anchored + && (maxForce >= (MoveResist * MoveForcePushRatio))) + || (physics.Anchored && (maxForce >= (MoveResist * MoveForceForcePushRatio)))) + { + + if (physics.Owner.HasComponent()) + { + physics.BodyStatus = BodyStatus.InAir; + + foreach (var fixture in physics.Fixtures) + { + fixture.CollisionMask &= ~(int) CollisionGroup.VaultImpassable; + } + + Owner.SpawnTimer(2000, () => + { + if (Deleted || !Owner.TryGetComponent(out PhysicsComponent? physicsComponent)) return; + + // Uhh if you get race conditions good luck buddy. + if (physicsComponent.Owner.HasComponent()) + { + physicsComponent.BodyStatus = BodyStatus.OnGround; + } + + foreach (var fixture in physics.Fixtures) + { + fixture.CollisionMask |= (int) CollisionGroup.VaultImpassable; + } + }); + } + + if (maxForce > ThrowForce) + { + // Vera please fix ;-; + if (throwTarget != EntityCoordinates.Invalid) + { + var moveForce = maxForce * MathHelper.Clamp(moveProb, 0, 100) / 15f; + var pos = ((throwTarget.Position - transform.Coordinates.Position).Normalized + direction.ToDirection().ToVec()).Normalized; + physics.ApplyLinearImpulse(pos * moveForce); + } + + else + { + var moveForce = MathF.Min(maxForce * MathHelper.Clamp(moveProb, 0, 100) / 2500f, 20f); + physics.ApplyLinearImpulse(direction.ToDirection().ToVec() * moveForce); + } + + LastHighPressureMovementAirCycle = cycle; + } + } + } } public static class MovedByPressureExtensions diff --git a/Content.Server/GameObjects/Components/Chemistry/VaporComponent.cs b/Content.Server/GameObjects/Components/Chemistry/VaporComponent.cs index 9daf69f41c..450e0ca46f 100644 --- a/Content.Server/GameObjects/Components/Chemistry/VaporComponent.cs +++ b/Content.Server/GameObjects/Components/Chemistry/VaporComponent.cs @@ -7,6 +7,8 @@ using Robust.Shared.GameObjects; using Robust.Shared.IoC; using Robust.Shared.Map; using Robust.Shared.Maths; +using Robust.Shared.Physics; +using Robust.Shared.Physics.Collision; using Robust.Shared.Prototypes; using Robust.Shared.Serialization; using Robust.Shared.Serialization.Manager.Attributes; @@ -15,7 +17,7 @@ using Robust.Shared.ViewVariables; namespace Content.Server.GameObjects.Components.Chemistry { [RegisterComponent] - class VaporComponent : SharedVaporComponent, ICollideBehavior + class VaporComponent : SharedVaporComponent, IStartCollide { public const float ReactTime = 0.125f; @@ -31,8 +33,6 @@ namespace Content.Server.GameObjects.Components.Chemistry private float _timer; private EntityCoordinates _target; private bool _running; - private Vector2 _direction; - private float _velocity; private float _aliveTime; public override void Initialize() @@ -42,18 +42,16 @@ namespace Content.Server.GameObjects.Components.Chemistry Owner.EnsureComponentWarn(out SolutionContainerComponent _); } - public void Start(Vector2 dir, float velocity, EntityCoordinates target, float aliveTime) + public void Start(Vector2 dir, float speed, EntityCoordinates target, float aliveTime) { _running = true; _target = target; - _direction = dir; - _velocity = velocity; _aliveTime = aliveTime; // Set Move - if (Owner.TryGetComponent(out IPhysicsComponent physics)) + if (Owner.TryGetComponent(out PhysicsComponent physics)) { - var controller = physics.EnsureController(); - controller.Move(_direction, _velocity); + physics.BodyStatus = BodyStatus.InAir; + physics.ApplyLinearImpulse(dir * speed); } } @@ -68,7 +66,7 @@ namespace Content.Server.GameObjects.Components.Chemistry _timer += frameTime; _reactTimer += frameTime; - if (_reactTimer >= ReactTime && Owner.TryGetComponent(out IPhysicsComponent physics)) + if (_reactTimer >= ReactTime) { _reactTimer = 0; var mapGrid = _mapManager.GetGrid(Owner.Transform.GridID); @@ -86,12 +84,6 @@ namespace Content.Server.GameObjects.Components.Chemistry if(!_reached && _target.TryDistance(Owner.EntityManager, Owner.Transform.Coordinates, out var distance) && distance <= 0.5f) { _reached = true; - - if (Owner.TryGetComponent(out IPhysicsComponent coll)) - { - var controller = coll.EnsureController(); - controller.Stop(); - } } if (contents.CurrentVolume == 0 || _timer > _aliveTime) @@ -123,26 +115,17 @@ namespace Content.Server.GameObjects.Components.Chemistry return true; } - void ICollideBehavior.CollideWith(IEntity collidedWith) + void IStartCollide.CollideWith(IPhysBody ourBody, IPhysBody otherBody, in Manifold manifold) { if (!Owner.TryGetComponent(out SolutionContainerComponent contents)) return; - contents.Solution.DoEntityReaction(collidedWith, ReactionMethod.Touch); + contents.Solution.DoEntityReaction(otherBody.Entity, ReactionMethod.Touch); // Check for collision with a impassable object (e.g. wall) and stop - if (collidedWith.TryGetComponent(out IPhysicsComponent physics)) + if ((otherBody.CollisionLayer & (int) CollisionGroup.Impassable) != 0 && otherBody.Hard) { - if ((physics.CollisionLayer & (int) CollisionGroup.Impassable) != 0 && physics.Hard) - { - if (Owner.TryGetComponent(out IPhysicsComponent coll)) - { - var controller = coll.EnsureController(); - controller.Stop(); - } - - Owner.Delete(); - } + Owner.Delete(); } } } diff --git a/Content.Server/GameObjects/Components/Construction/ConstructionComponent.cs b/Content.Server/GameObjects/Components/Construction/ConstructionComponent.cs index c7dec64e04..675f5140c4 100644 --- a/Content.Server/GameObjects/Components/Construction/ConstructionComponent.cs +++ b/Content.Server/GameObjects/Components/Construction/ConstructionComponent.cs @@ -16,6 +16,7 @@ using Robust.Shared.GameObjects; using Robust.Shared.IoC; using Robust.Shared.Localization; using Robust.Shared.Log; +using Robust.Shared.Physics; using Robust.Shared.Prototypes; using Robust.Shared.Serialization; using Robust.Shared.Serialization.Manager.Attributes; @@ -430,10 +431,10 @@ namespace Content.Server.GameObjects.Components.Construction } } - if (Owner.TryGetComponent(out IPhysicsComponent? physics) && - entity.TryGetComponent(out IPhysicsComponent? otherPhysics)) + if (Owner.TryGetComponent(out IPhysBody? physics) && + entity.TryGetComponent(out IPhysBody? otherPhysics)) { - otherPhysics.Anchored = physics.Anchored; + otherPhysics.BodyType = physics.BodyType; } Owner.Delete(); diff --git a/Content.Server/GameObjects/Components/Conveyor/ConveyorComponent.cs b/Content.Server/GameObjects/Components/Conveyor/ConveyorComponent.cs index 625492786c..e7597a6f26 100644 --- a/Content.Server/GameObjects/Components/Conveyor/ConveyorComponent.cs +++ b/Content.Server/GameObjects/Components/Conveyor/ConveyorComponent.cs @@ -4,12 +4,14 @@ using Content.Server.GameObjects.Components.MachineLinking; using Content.Server.GameObjects.Components.Power.ApcNetComponents; using Content.Shared.GameObjects.Components.Conveyor; using Content.Shared.GameObjects.Components.MachineLinking; +using Content.Shared.GameObjects.Components.Movement; using Content.Shared.Physics; using Robust.Server.GameObjects; using Robust.Shared.Containers; using Robust.Shared.GameObjects; using Robust.Shared.Maths; using Robust.Shared.Prototypes; +using Robust.Shared.Physics; using Robust.Shared.Serialization; using Robust.Shared.Serialization.Manager.Attributes; using Robust.Shared.ViewVariables; @@ -30,6 +32,8 @@ namespace Content.Server.GameObjects.Components.Conveyor [DataField("angle")] private Angle _angle; + public float Speed => _speed; + /// /// The amount of units to move the entity by per second. /// @@ -90,7 +94,7 @@ namespace Content.Server.GameObjects.Components.Conveyor /// /// The angle when taking into account if the conveyor is reversed /// - private Angle GetAngle() + public Angle GetAngle() { var adjustment = _state == ConveyorState.Reversed ? MathHelper.Pi : 0; var radians = MathHelper.DegreesToRadians(_angle); @@ -98,7 +102,7 @@ namespace Content.Server.GameObjects.Components.Conveyor return new Angle(Owner.Transform.LocalRotation.Theta + radians + adjustment); } - private bool CanRun() + public bool CanRun() { if (State == ConveyorState.Off) { @@ -119,15 +123,16 @@ namespace Content.Server.GameObjects.Components.Conveyor return true; } - private bool CanMove(IEntity entity) + public bool CanMove(IEntity entity) { + // TODO We should only check status InAir or Static or MapGrid or /mayber/ container if (entity == Owner) { return false; } - if (!entity.TryGetComponent(out IPhysicsComponent? physics) || - physics.Anchored) + if (!entity.TryGetComponent(out IPhysBody? physics) || + physics.BodyType == BodyType.Static) { return false; } @@ -150,31 +155,6 @@ namespace Content.Server.GameObjects.Components.Conveyor return true; } - public void Update(float frameTime) - { - if (!CanRun()) - { - return; - } - - var intersecting = Owner.EntityManager.GetEntitiesIntersecting(Owner, true); - var direction = GetAngle().ToVec(); - - foreach (var entity in intersecting) - { - if (!CanMove(entity)) - { - continue; - } - - if (entity.TryGetComponent(out IPhysicsComponent? physics)) - { - var controller = physics.EnsureController(); - controller.Move(direction, _speed, entity.Transform.WorldPosition - Owner.Transform.WorldPosition); - } - } - } - public void TriggerSignal(TwoWayLeverSignal signal) { State = signal switch diff --git a/Content.Server/GameObjects/Components/Damage/DamageOnHighSpeedImpactComponent.cs b/Content.Server/GameObjects/Components/Damage/DamageOnHighSpeedImpactComponent.cs index 036aa4bedd..b83af720fc 100644 --- a/Content.Server/GameObjects/Components/Damage/DamageOnHighSpeedImpactComponent.cs +++ b/Content.Server/GameObjects/Components/Damage/DamageOnHighSpeedImpactComponent.cs @@ -6,6 +6,8 @@ using Content.Shared.GameObjects.Components.Damage; using Robust.Server.GameObjects; using Robust.Shared.GameObjects; using Robust.Shared.IoC; +using Robust.Shared.Physics; +using Robust.Shared.Physics.Collision; using Robust.Shared.Prototypes; using Robust.Shared.Random; using Robust.Shared.Serialization; @@ -15,7 +17,7 @@ using Robust.Shared.Serialization.Manager.Attributes; namespace Content.Server.GameObjects.Components.Damage { [RegisterComponent] - public class DamageOnHighSpeedImpactComponent : Component, ICollideBehavior + public class DamageOnHighSpeedImpactComponent : Component, IStartCollide { [Dependency] private readonly IRobustRandom _robustRandom = default!; [Dependency] private readonly IGameTiming _gameTiming = default!; @@ -42,16 +44,16 @@ namespace Content.Server.GameObjects.Components.Damage public float DamageCooldown { get; set; } = 2f; private TimeSpan _lastHit = TimeSpan.Zero; - public void CollideWith(IEntity collidedWith) + void IStartCollide.CollideWith(IPhysBody ourBody, IPhysBody otherBody, in Manifold manifold) { - if (!Owner.TryGetComponent(out IPhysicsComponent physics) || !Owner.TryGetComponent(out IDamageableComponent damageable)) return; + if (!Owner.TryGetComponent(out IDamageableComponent damageable)) return; - var speed = physics.LinearVelocity.Length; + var speed = ourBody.LinearVelocity.Length; if (speed < MinimumSpeed) return; if(!string.IsNullOrEmpty(SoundHit)) - EntitySystem.Get().PlayFromEntity(SoundHit, collidedWith, AudioHelpers.WithVariation(0.125f).WithVolume(-0.125f)); + EntitySystem.Get().PlayFromEntity(SoundHit, otherBody.Entity, AudioHelpers.WithVariation(0.125f).WithVolume(-0.125f)); if ((_gameTiming.CurTime - _lastHit).TotalSeconds < DamageCooldown) return; @@ -63,7 +65,7 @@ namespace Content.Server.GameObjects.Components.Damage if (Owner.TryGetComponent(out StunnableComponent stun) && _robustRandom.Prob(StunChance)) stun.Stun(StunSeconds); - damageable.ChangeDamage(Damage, damage, false, collidedWith); + damageable.ChangeDamage(Damage, damage, false, otherBody.Entity); } } } diff --git a/Content.Server/GameObjects/Components/Disposal/DisposalHolderComponent.cs b/Content.Server/GameObjects/Components/Disposal/DisposalHolderComponent.cs index b55d01dc0a..6ab42594fd 100644 --- a/Content.Server/GameObjects/Components/Disposal/DisposalHolderComponent.cs +++ b/Content.Server/GameObjects/Components/Disposal/DisposalHolderComponent.cs @@ -10,6 +10,7 @@ using Robust.Shared.Containers; using Robust.Shared.GameObjects; using Robust.Shared.Maths; using Robust.Shared.Prototypes; +using Robust.Shared.Physics; using Robust.Shared.Serialization; using Robust.Shared.Serialization.Manager.Attributes; using Robust.Shared.ViewVariables; @@ -76,7 +77,7 @@ namespace Content.Server.GameObjects.Components.Disposal return false; } - if (!entity.TryGetComponent(out IPhysicsComponent? physics) || + if (!entity.TryGetComponent(out IPhysBody? physics) || !physics.CanCollide) { return false; @@ -93,7 +94,7 @@ namespace Content.Server.GameObjects.Components.Disposal return false; } - if (entity.TryGetComponent(out IPhysicsComponent? physics)) + if (entity.TryGetComponent(out IPhysBody? physics)) { physics.CanCollide = false; } @@ -125,7 +126,7 @@ namespace Content.Server.GameObjects.Components.Disposal foreach (var entity in _contents.ContainedEntities.ToArray()) { - if (entity.TryGetComponent(out IPhysicsComponent? physics)) + if (entity.TryGetComponent(out IPhysBody? physics)) { physics.CanCollide = true; } diff --git a/Content.Server/GameObjects/Components/Disposal/DisposalMailingUnitComponent.cs b/Content.Server/GameObjects/Components/Disposal/DisposalMailingUnitComponent.cs index 42dad72f4f..2672cc0f27 100644 --- a/Content.Server/GameObjects/Components/Disposal/DisposalMailingUnitComponent.cs +++ b/Content.Server/GameObjects/Components/Disposal/DisposalMailingUnitComponent.cs @@ -27,6 +27,8 @@ using Robust.Shared.IoC; using Robust.Shared.Localization; using Robust.Shared.Log; using Robust.Shared.Serialization.Manager.Attributes; +using Robust.Shared.Physics; +using Robust.Shared.Serialization; using Robust.Shared.Timing; using Robust.Shared.ViewVariables; using Timer = Robust.Shared.Timing.Timer; @@ -147,7 +149,7 @@ namespace Content.Server.GameObjects.Components.Disposal return false; } - if (!entity.TryGetComponent(out IPhysicsComponent? physics) || + if (!entity.TryGetComponent(out IPhysBody? physics) || !physics.CanCollide) { return false; diff --git a/Content.Server/GameObjects/Components/Disposal/DisposalRouterComponent.cs b/Content.Server/GameObjects/Components/Disposal/DisposalRouterComponent.cs index d4d9f1519e..3b5ddd0470 100644 --- a/Content.Server/GameObjects/Components/Disposal/DisposalRouterComponent.cs +++ b/Content.Server/GameObjects/Components/Disposal/DisposalRouterComponent.cs @@ -16,6 +16,7 @@ using Robust.Shared.GameObjects; using Robust.Shared.IoC; using Robust.Shared.Localization; using Robust.Shared.Maths; +using Robust.Shared.Physics; using Robust.Shared.ViewVariables; using static Content.Shared.GameObjects.Components.Disposal.SharedDisposalRouterComponent; @@ -33,8 +34,8 @@ namespace Content.Server.GameObjects.Components.Disposal [ViewVariables] public bool Anchored => - !Owner.TryGetComponent(out IPhysicsComponent? physics) || - physics.Anchored; + !Owner.TryGetComponent(out IPhysBody? physics) || + physics.BodyType == BodyType.Static; [ViewVariables] private BoundUserInterface? UserInterface => Owner.GetUIOrNull(DisposalRouterUiKey.Key); diff --git a/Content.Server/GameObjects/Components/Disposal/DisposalUnitComponent.cs b/Content.Server/GameObjects/Components/Disposal/DisposalUnitComponent.cs index 48a6d01b1c..40c613ed07 100644 --- a/Content.Server/GameObjects/Components/Disposal/DisposalUnitComponent.cs +++ b/Content.Server/GameObjects/Components/Disposal/DisposalUnitComponent.cs @@ -28,6 +28,7 @@ using Robust.Shared.GameObjects; using Robust.Shared.IoC; using Robust.Shared.Localization; using Robust.Shared.Log; +using Robust.Shared.Physics; using Robust.Shared.Random; using Robust.Shared.Serialization.Manager.Attributes; using Robust.Shared.Timing; @@ -144,7 +145,7 @@ namespace Content.Server.GameObjects.Components.Disposal if (!base.CanInsert(entity)) return false; - if (!entity.TryGetComponent(out IPhysicsComponent? physics) || + if (!entity.TryGetComponent(out IPhysBody? physics) || !physics.CanCollide) { if (entity.TryGetComponent(out IMobStateComponent? state) && state.IsDead()) diff --git a/Content.Server/GameObjects/Components/Doors/ServerDoorComponent.cs b/Content.Server/GameObjects/Components/Doors/ServerDoorComponent.cs index 88f241aebb..f20cee510a 100644 --- a/Content.Server/GameObjects/Components/Doors/ServerDoorComponent.cs +++ b/Content.Server/GameObjects/Components/Doors/ServerDoorComponent.cs @@ -1,4 +1,4 @@ -#nullable enable +#nullable enable using System; using System.Linq; using System.Threading; @@ -26,6 +26,9 @@ using Robust.Shared.Maths; using Robust.Shared.Physics; using Robust.Shared.Players; using Robust.Shared.Serialization.Manager.Attributes; +using Robust.Shared.Physics.Broadphase; +using Robust.Shared.Physics.Collision; +using Robust.Shared.Serialization; using Robust.Shared.ViewVariables; using Timer = Robust.Shared.Timing.Timer; @@ -34,7 +37,7 @@ namespace Content.Server.GameObjects.Components.Doors [RegisterComponent] [ComponentReference(typeof(IActivate))] [ComponentReference(typeof(SharedDoorComponent))] - public class ServerDoorComponent : SharedDoorComponent, IActivate, ICollideBehavior, IInteractUsing, IMapInit + public class ServerDoorComponent : SharedDoorComponent, IActivate, IStartCollide, IInteractUsing, IMapInit { [ComponentDependency] private readonly IDoorCheck? _doorCheck = null; @@ -200,7 +203,7 @@ namespace Content.Server.GameObjects.Components.Doors } } - void ICollideBehavior.CollideWith(IEntity entity) + void IStartCollide.CollideWith(IPhysBody ourBody, IPhysBody otherBody, in Manifold manifold) { if (State != DoorState.Closed) { @@ -214,9 +217,9 @@ namespace Content.Server.GameObjects.Components.Doors // Disabled because it makes it suck hard to walk through double doors. - if (entity.HasComponent()) + if (otherBody.Entity.HasComponent()) { - if (!entity.TryGetComponent(out var mover)) return; + if (!otherBody.Entity.TryGetComponent(out var mover)) return; /* // TODO: temporary hack to fix the physics system raising collision events akwardly. @@ -229,7 +232,7 @@ namespace Content.Server.GameObjects.Components.Doors TryOpen(entity); */ - TryOpen(entity); + TryOpen(otherBody.Entity); } } @@ -410,18 +413,14 @@ namespace Content.Server.GameObjects.Components.Doors { var safety = SafetyCheck(); - if (safety && PhysicsComponent != null) + if (safety && Owner.TryGetComponent(out PhysicsComponent? physicsComponent)) { - var physics = IoCManager.Resolve(); + var broadPhaseSystem = EntitySystem.Get(); - foreach(var e in physics.GetCollidingEntities(Owner.Transform.MapID, PhysicsComponent.WorldAABB)) + // Use this version so we can ignore the CanCollide being false + foreach(var e in broadPhaseSystem.GetCollidingEntities(physicsComponent.Entity.Transform.MapID, physicsComponent.GetWorldAABB())) { - if (e.CanCollide && - ((PhysicsComponent.CollisionMask & e.CollisionLayer) != 0x0 || - (PhysicsComponent.CollisionLayer & e.CollisionMask) != 0x0)) - { - return true; - } + if ((physicsComponent.CollisionMask & e.CollisionLayer) != 0 && broadPhaseSystem.IntersectionPercent(physicsComponent, e) > 0.01f) return true; } } return false; @@ -493,26 +492,25 @@ namespace Content.Server.GameObjects.Components.Doors return false; } - var doorAABB = PhysicsComponent.WorldAABB; + var doorAABB = PhysicsComponent.GetWorldAABB(); var hitsomebody = false; // Crush foreach (var e in collidingentities) { - if (!e.TryGetComponent(out StunnableComponent? stun) - || !e.TryGetComponent(out IDamageableComponent? damage) - || !e.TryGetComponent(out IPhysicsComponent? otherBody)) + if (!e.Entity.TryGetComponent(out StunnableComponent? stun) + || !e.Entity.TryGetComponent(out IDamageableComponent? damage)) { continue; } - var percentage = otherBody.WorldAABB.IntersectPercentage(doorAABB); + var percentage = e.GetWorldAABB().IntersectPercentage(doorAABB); if (percentage < 0.1f) continue; hitsomebody = true; - CurrentlyCrushing.Add(e.Uid); + CurrentlyCrushing.Add(e.Entity.Uid); damage.ChangeDamage(DamageType.Blunt, DoorCrushDamage, false, Owner); stun.Paralyze(DoorStunTime); diff --git a/Content.Server/GameObjects/Components/Explosion/ClusterFlashComponent.cs b/Content.Server/GameObjects/Components/Explosion/ClusterFlashComponent.cs index 7b878c561f..aeb04c9a34 100644 --- a/Content.Server/GameObjects/Components/Explosion/ClusterFlashComponent.cs +++ b/Content.Server/GameObjects/Components/Explosion/ClusterFlashComponent.cs @@ -3,14 +3,13 @@ using System; using System.Diagnostics.CodeAnalysis; using System.Threading.Tasks; using Content.Server.GameObjects.Components.Trigger.TimerTrigger; -using Content.Server.Throw; +using Content.Server.GameObjects.Components.Items; using Content.Shared.GameObjects.Components.Explosion; -using Robust.Shared.Containers; using Content.Shared.Interfaces.GameObjects.Components; using Robust.Server.GameObjects; using Robust.Shared.GameObjects; +using Robust.Shared.Containers; using Robust.Shared.IoC; -using Robust.Shared.Map; using Robust.Shared.Maths; using Robust.Shared.Random; using Robust.Shared.Serialization.Manager.Attributes; @@ -108,10 +107,13 @@ namespace Content.Server.GameObjects.Components.Explosion var angleMin = segmentAngle * thrownCount; var angleMax = segmentAngle * (thrownCount + 1); var angle = Angle.FromDegrees(random.Next(angleMin, angleMax)); - var distance = (float)random.NextFloat() * _throwDistance; - var target = new EntityCoordinates(Owner.Uid, angle.ToVec().Normalized * distance); + // var distance = random.NextFloat() * _throwDistance; - grenade.Throw(0.5f, target, grenade.Transform.Coordinates); + delay += random.Next(550, 900); + thrownCount++; + + // TODO: Suss out throw strength + grenade.TryThrow(angle.ToVec().Normalized * 50); grenade.SpawnTimer(delay, () => { @@ -123,9 +125,6 @@ namespace Content.Server.GameObjects.Components.Explosion useTimer.Trigger(eventArgs.User); } }); - - delay += random.Next(550, 900); - thrownCount++; } Owner.Delete(); @@ -140,7 +139,7 @@ namespace Content.Server.GameObjects.Components.Explosion if (_unspawnedCount > 0) { _unspawnedCount--; - grenade = Owner.EntityManager.SpawnEntity(_fillPrototype, Owner.Transform.Coordinates); + grenade = Owner.EntityManager.SpawnEntity(_fillPrototype, Owner.Transform.MapPosition); return true; } diff --git a/Content.Server/GameObjects/Components/Fluids/PuddleComponent.cs b/Content.Server/GameObjects/Components/Fluids/PuddleComponent.cs index 7e8479ac9a..cffa60c3e4 100644 --- a/Content.Server/GameObjects/Components/Fluids/PuddleComponent.cs +++ b/Content.Server/GameObjects/Components/Fluids/PuddleComponent.cs @@ -15,6 +15,7 @@ using Robust.Shared.IoC; using Robust.Shared.Localization; using Robust.Shared.Map; using Robust.Shared.Maths; +using Robust.Shared.Physics; using Robust.Shared.Random; using Robust.Shared.Prototypes; using Robust.Shared.Serialization; @@ -368,7 +369,7 @@ namespace Content.Server.GameObjects.Components.Fluids foreach (var entity in _snapGrid.GetInDir(direction)) { - if (entity.TryGetComponent(out IPhysicsComponent physics) && + if (entity.TryGetComponent(out IPhysBody physics) && (physics.CollisionLayer & (int) CollisionGroup.Impassable) != 0) { puddle = default; diff --git a/Content.Server/GameObjects/Components/GUI/HandsComponent.cs b/Content.Server/GameObjects/Components/GUI/HandsComponent.cs index 4744d8e3ad..b2cf42b3de 100644 --- a/Content.Server/GameObjects/Components/GUI/HandsComponent.cs +++ b/Content.Server/GameObjects/Components/GUI/HandsComponent.cs @@ -27,6 +27,9 @@ using Robust.Shared.Maths; using Robust.Shared.Network; using Robust.Shared.Players; using Robust.Shared.ViewVariables; +using Robust.Shared.Map; +using Robust.Shared.Network; +using Robust.Shared.Physics; namespace Content.Server.GameObjects.Components.GUI { @@ -718,13 +721,13 @@ namespace Content.Server.GameObjects.Components.GUI Dirty(); - if (!message.Entity.TryGetComponent(out IPhysicsComponent? physics)) + if (!message.Entity.TryGetComponent(out IPhysBody? physics)) { return; } // set velocity to zero - physics.Stop(); + physics.LinearVelocity = Vector2.Zero; return; } } diff --git a/Content.Server/GameObjects/Components/Items/Storage/EntityStorageComponent.cs b/Content.Server/GameObjects/Components/Items/Storage/EntityStorageComponent.cs index ce0e305540..65d1a65799 100644 --- a/Content.Server/GameObjects/Components/Items/Storage/EntityStorageComponent.cs +++ b/Content.Server/GameObjects/Components/Items/Storage/EntityStorageComponent.cs @@ -12,6 +12,7 @@ using Content.Shared.GameObjects.EntitySystems.ActionBlocker; using Content.Shared.GameObjects.Verbs; using Content.Shared.Interfaces; using Content.Shared.Interfaces.GameObjects.Components; +using Content.Shared.Physics; using Robust.Server.GameObjects; using Robust.Shared.Containers; using Robust.Shared.GameObjects; @@ -19,6 +20,8 @@ using Robust.Shared.IoC; using Robust.Shared.Localization; using Robust.Shared.Maths; using Robust.Shared.Serialization.Manager.Attributes; +using Robust.Shared.Physics; +using Robust.Shared.Serialization; using Robust.Shared.Timing; using Robust.Shared.ViewVariables; @@ -38,6 +41,11 @@ namespace Content.Server.GameObjects.Components.Items.Storage private static readonly TimeSpan InternalOpenAttemptDelay = TimeSpan.FromSeconds(0.5); private TimeSpan _lastInternalOpenAttempt; + private const int OpenMask = (int) ( + CollisionGroup.MobImpassable | + CollisionGroup.VaultImpassable | + CollisionGroup.SmallImpassable); + [ViewVariables] [DataField("Capacity")] private int _storageCapacityMax = 30; @@ -229,15 +237,21 @@ namespace Content.Server.GameObjects.Components.Items.Storage private void ModifyComponents() { - if (!_isCollidableWhenOpen && Owner.TryGetComponent(out var physics)) + if (!_isCollidableWhenOpen && Owner.TryGetComponent(out var physics)) { if (Open) { - physics.Hard = false; + foreach (var fixture in physics.Fixtures) + { + fixture.CollisionLayer &= ~OpenMask; + } } else { - physics.Hard = true; + foreach (var fixture in physics.Fixtures) + { + fixture.CollisionLayer |= OpenMask; + } } } @@ -255,10 +269,10 @@ namespace Content.Server.GameObjects.Components.Items.Storage protected virtual bool AddToContents(IEntity entity) { if (entity == Owner) return false; - if (entity.TryGetComponent(out IPhysicsComponent? entityPhysicsComponent)) + if (entity.TryGetComponent(out IPhysBody? entityPhysicsComponent)) { - if(MaxSize < entityPhysicsComponent.WorldAABB.Size.X - || MaxSize < entityPhysicsComponent.WorldAABB.Size.Y) + if(MaxSize < entityPhysicsComponent.GetWorldAABB().Size.X + || MaxSize < entityPhysicsComponent.GetWorldAABB().Size.Y) { return false; } @@ -285,10 +299,10 @@ namespace Content.Server.GameObjects.Components.Items.Storage { foreach (var contained in Contents.ContainedEntities.ToArray()) { - if(Contents.Remove(contained)) + if (Contents.Remove(contained)) { contained.Transform.WorldPosition = ContentsDumpPosition(); - if (contained.TryGetComponent(out var physics)) + if (contained.TryGetComponent(out var physics)) { physics.CanCollide = true; } diff --git a/Content.Server/GameObjects/Components/Items/Storage/ItemComponent.cs b/Content.Server/GameObjects/Components/Items/Storage/ItemComponent.cs index b4c15b8b14..054e3331f1 100644 --- a/Content.Server/GameObjects/Components/Items/Storage/ItemComponent.cs +++ b/Content.Server/GameObjects/Components/Items/Storage/ItemComponent.cs @@ -1,6 +1,5 @@ using Content.Server.GameObjects.Components.GUI; using Content.Server.Interfaces.GameObjects.Components.Items; -using Content.Server.Throw; using Content.Shared.GameObjects; using Content.Shared.GameObjects.Components.Items; using Content.Shared.GameObjects.Components.Storage; @@ -8,6 +7,7 @@ using Content.Shared.GameObjects.EntitySystems; using Content.Shared.GameObjects.EntitySystems.ActionBlocker; using Content.Shared.GameObjects.Verbs; using Content.Shared.Interfaces.GameObjects.Components; +using Content.Shared.Physics; using Content.Shared.Utility; using Robust.Server.GameObjects; using Robust.Shared.Containers; @@ -15,6 +15,7 @@ using Robust.Shared.GameObjects; using Robust.Shared.Localization; using Robust.Shared.Players; using Robust.Shared.Prototypes; +using Robust.Shared.Physics; using Robust.Shared.Serialization; using Robust.Shared.Serialization.Manager.Attributes; @@ -24,7 +25,7 @@ namespace Content.Server.GameObjects.Components.Items.Storage [ComponentReference(typeof(StorableComponent))] [ComponentReference(typeof(SharedStorableComponent))] [ComponentReference(typeof(IItemComponent))] - public class ItemComponent : StorableComponent, IInteractHand, IExAct, IEquipped, IUnequipped, IItemComponent + public class ItemComponent : StorableComponent, IInteractHand, IExAct, IEquipped, IUnequipped, IItemComponent, IThrown, ILand { public override string Name => "Item"; public override uint? NetID => ContentNetIDs.ITEM; @@ -83,8 +84,8 @@ namespace Content.Server.GameObjects.Components.Items.Storage return false; } - if (Owner.TryGetComponent(out IPhysicsComponent physics) && - physics.Anchored) + if (Owner.TryGetComponent(out IPhysBody physics) && + physics.BodyType == BodyType.Static) { return false; } @@ -137,22 +138,43 @@ namespace Content.Server.GameObjects.Components.Items.Storage var targetLocation = eventArgs.Target.Transform.Coordinates; var dirVec = (targetLocation.ToMapPos(Owner.EntityManager) - sourceLocation.ToMapPos(Owner.EntityManager)).Normalized; - var throwForce = 1.0f; + float throwForce; switch (eventArgs.Severity) { case ExplosionSeverity.Destruction: - throwForce = 3.0f; + throwForce = 30.0f; break; case ExplosionSeverity.Heavy: - throwForce = 2.0f; + throwForce = 20.0f; break; - case ExplosionSeverity.Light: - throwForce = 1.0f; + default: + throwForce = 10.0f; break; } - Owner.Throw(throwForce, targetLocation, sourceLocation, true); + Owner.TryThrow(dirVec * throwForce); + } + + // TODO: Predicted + void IThrown.Thrown(ThrownEventArgs eventArgs) + { + if (!Owner.TryGetComponent(out PhysicsComponent physicsComponent)) return; + + foreach (var fixture in physicsComponent.Fixtures) + { + fixture.CollisionLayer |= (int) CollisionGroup.MobImpassable; + } + } + + void ILand.Land(LandEventArgs eventArgs) + { + if (!Owner.TryGetComponent(out PhysicsComponent physicsComponent)) return; + + foreach (var fixture in physicsComponent.Fixtures) + { + fixture.CollisionLayer &= ~(int) CollisionGroup.MobImpassable; + } } } } diff --git a/Content.Server/GameObjects/Components/Items/ThrowHelper.cs b/Content.Server/GameObjects/Components/Items/ThrowHelper.cs new file mode 100644 index 0000000000..6f476c0b96 --- /dev/null +++ b/Content.Server/GameObjects/Components/Items/ThrowHelper.cs @@ -0,0 +1,50 @@ +#nullable enable +using Content.Server.GameObjects.Components.Items.Storage; +using Content.Server.GameObjects.EntitySystems.Click; +using Content.Shared.GameObjects.Components.Items; +using Content.Shared.GameObjects.Components.Mobs.State; +using Robust.Shared.GameObjects; +using Robust.Shared.Log; +using Robust.Shared.Maths; +using Robust.Shared.Physics; + +namespace Content.Server.GameObjects.Components.Items +{ + internal static class ThrowHelper + { + /// + /// Tries to throw the entity if it has a physics component, otherwise does nothing. + /// + /// + /// Will use the vector's magnitude as the strength of the impulse + internal static void TryThrow(this IEntity entity, Vector2 direction, IEntity? user = null) + { + if (direction == Vector2.Zero || !entity.TryGetComponent(out PhysicsComponent? physicsComponent)) + { + return; + } + + if (physicsComponent.BodyType == BodyType.Static) + { + Logger.Warning("Tried to throw entity {entity} but can't throw static bodies!"); + return; + } + + if (entity.HasComponent()) + { + Logger.Warning("Throwing not supported for mobs!"); + return; + } + + if (entity.HasComponent()) + { + entity.EnsureComponent().Thrower = user; + + if (user != null) + EntitySystem.Get().ThrownInteraction(user, entity); + } + + physicsComponent.ApplyLinearImpulse(direction); + } + } +} diff --git a/Content.Server/GameObjects/Components/Mobs/State/DeadMobState.cs b/Content.Server/GameObjects/Components/Mobs/State/DeadMobState.cs index 27e4dee466..723f861982 100644 --- a/Content.Server/GameObjects/Components/Mobs/State/DeadMobState.cs +++ b/Content.Server/GameObjects/Components/Mobs/State/DeadMobState.cs @@ -4,6 +4,7 @@ using Content.Shared.GameObjects.Components.Mobs; using Content.Shared.GameObjects.Components.Mobs.State; using Robust.Server.GameObjects; using Robust.Shared.GameObjects; +using Robust.Shared.Physics; namespace Content.Server.GameObjects.Components.Mobs.State { @@ -30,7 +31,7 @@ namespace Content.Server.GameObjects.Components.Mobs.State EntitySystem.Get().Down(entity); - if (entity.TryGetComponent(out IPhysicsComponent physics)) + if (entity.TryGetComponent(out IPhysBody physics)) { physics.CanCollide = false; } @@ -40,7 +41,7 @@ namespace Content.Server.GameObjects.Components.Mobs.State { base.ExitState(entity); - if (entity.TryGetComponent(out IPhysicsComponent physics)) + if (entity.TryGetComponent(out IPhysBody physics)) { physics.CanCollide = true; } diff --git a/Content.Server/GameObjects/Components/Movement/AiControllerComponent.cs b/Content.Server/GameObjects/Components/Movement/AiControllerComponent.cs index fdacd95bb7..e36ad5aa7d 100644 --- a/Content.Server/GameObjects/Components/Movement/AiControllerComponent.cs +++ b/Content.Server/GameObjects/Components/Movement/AiControllerComponent.cs @@ -12,8 +12,9 @@ using Robust.Shared.ViewVariables; namespace Content.Server.GameObjects.Components.Movement { - [RegisterComponent, ComponentReference(typeof(IMoverComponent))] - public class AiControllerComponent : Component, IMoverComponent + [RegisterComponent] + [ComponentReference(typeof(IMobMoverComponent))] + public class AiControllerComponent : Component, IMobMoverComponent, IMoverComponent { [DataField("logic")] private float _visionRadius = 8.0f; @@ -88,13 +89,12 @@ namespace Content.Server.GameObjects.Components.Movement } /// - [ViewVariables] - public float CurrentPushSpeed => 5.0f; + [ViewVariables(VVAccess.ReadWrite)] + public float PushStrength { get; set; } /// - [ViewVariables] - public float GrabRange => 0.2f; - + [ViewVariables(VVAccess.ReadWrite)] + public float GrabRange { get; set; } = 0.2f; /// /// Is the entity Sprinting (running)? @@ -113,7 +113,8 @@ namespace Content.Server.GameObjects.Components.Movement public EntityCoordinates LastPosition { get; set; } - [ViewVariables(VVAccess.ReadWrite)] public float StepSoundDistance { get; set; } + [ViewVariables(VVAccess.ReadWrite)] + public float StepSoundDistance { get; set; } public void SetVelocityDirection(Direction direction, ushort subTick, bool enabled) { } public void SetSprinting(ushort subTick, bool walking) { } diff --git a/Content.Server/GameObjects/Components/Movement/ClimbableComponent.cs b/Content.Server/GameObjects/Components/Movement/ClimbableComponent.cs index 1ba64a3f7e..ce014b1036 100644 --- a/Content.Server/GameObjects/Components/Movement/ClimbableComponent.cs +++ b/Content.Server/GameObjects/Components/Movement/ClimbableComponent.cs @@ -14,6 +14,8 @@ using Robust.Shared.Localization; using Robust.Shared.Log; using Robust.Shared.Maths; using Robust.Shared.Serialization.Manager.Attributes; +using Robust.Shared.Physics; +using Robust.Shared.Serialization; using Robust.Shared.ViewVariables; namespace Content.Server.GameObjects.Components.Movement @@ -158,9 +160,11 @@ namespace Content.Server.GameObjects.Components.Movement var result = await EntitySystem.Get().DoAfter(doAfterEventArgs); - if (result != DoAfterStatus.Cancelled && entityToMove.TryGetComponent(out IPhysicsComponent body) && body.PhysicsShapes.Count >= 1) + if (result != DoAfterStatus.Cancelled && entityToMove.TryGetComponent(out PhysicsComponent body) && body.Fixtures.Count >= 1) { - var direction = (Owner.Transform.WorldPosition - entityToMove.Transform.WorldPosition).Normalized; + var entityPos = entityToMove.Transform.WorldPosition; + + var direction = (Owner.Transform.WorldPosition - entityPos).Normalized; var endPoint = Owner.Transform.WorldPosition; var climbMode = entityToMove.GetComponent(); @@ -168,14 +172,14 @@ namespace Content.Server.GameObjects.Components.Movement if (MathF.Abs(direction.X) < 0.6f) // user climbed mostly vertically so lets make it a clean straight line { - endPoint = new Vector2(entityToMove.Transform.WorldPosition.X, endPoint.Y); + endPoint = new Vector2(entityPos.X, endPoint.Y); } else if (MathF.Abs(direction.Y) < 0.6f) // user climbed mostly horizontally so lets make it a clean straight line { - endPoint = new Vector2(endPoint.X, entityToMove.Transform.WorldPosition.Y); + endPoint = new Vector2(endPoint.X, entityPos.Y); } - climbMode.TryMoveTo(entityToMove.Transform.WorldPosition, endPoint); + climbMode.TryMoveTo(entityPos, endPoint); // we may potentially need additional logic since we're forcing a player onto a climbable // there's also the cases where the user might collide with the person they are forcing onto the climbable that i haven't accounted for @@ -203,9 +207,12 @@ namespace Content.Server.GameObjects.Components.Movement var result = await EntitySystem.Get().DoAfter(doAfterEventArgs); - if (result != DoAfterStatus.Cancelled && user.TryGetComponent(out IPhysicsComponent body) && body.PhysicsShapes.Count >= 1) + if (result != DoAfterStatus.Cancelled && user.TryGetComponent(out PhysicsComponent body) && body.Fixtures.Count >= 1) { - var direction = (Owner.Transform.WorldPosition - user.Transform.WorldPosition).Normalized; + // TODO: Remove the copy-paste code + var userPos = user.Transform.WorldPosition; + + var direction = (Owner.Transform.WorldPosition - userPos).Normalized; var endPoint = Owner.Transform.WorldPosition; var climbMode = user.GetComponent(); @@ -220,7 +227,7 @@ namespace Content.Server.GameObjects.Components.Movement endPoint = new Vector2(endPoint.X, user.Transform.WorldPosition.Y); } - climbMode.TryMoveTo(user.Transform.WorldPosition, endPoint); + climbMode.TryMoveTo(userPos, endPoint); var othersMessage = Loc.GetString("{0:theName} jumps onto {1:theName}!", user, Owner); user.PopupMessageOtherClients(othersMessage); diff --git a/Content.Server/GameObjects/Components/Movement/ClimbingComponent.cs b/Content.Server/GameObjects/Components/Movement/ClimbingComponent.cs index c67aabec71..b7b0e5377b 100644 --- a/Content.Server/GameObjects/Components/Movement/ClimbingComponent.cs +++ b/Content.Server/GameObjects/Components/Movement/ClimbingComponent.cs @@ -1,10 +1,13 @@ #nullable enable +using System; +using Content.Server.GameObjects.EntitySystems; using Content.Shared.GameObjects.Components.Buckle; using Content.Shared.GameObjects.Components.Movement; -using Content.Shared.Physics; using Robust.Shared.GameObjects; +using Robust.Shared.IoC; using Robust.Shared.Maths; using Robust.Shared.Players; +using Robust.Shared.Timing; namespace Content.Server.GameObjects.Components.Movement { @@ -12,23 +15,41 @@ namespace Content.Server.GameObjects.Components.Movement [ComponentReference(typeof(SharedClimbingComponent))] public class ClimbingComponent : SharedClimbingComponent { - private bool _isClimbing; - private ClimbController? _climbController; + [Dependency] private readonly IGameTiming _gameTiming = default!; public override bool IsClimbing { - get => _isClimbing; + get => base.IsClimbing; set { if (_isClimbing == value) return; - if (!value) + base.IsClimbing = value; + + if (value) { - Body?.TryRemoveController(); + StartClimbTime = IoCManager.Resolve().CurTime; + EntitySystem.Get().AddActiveClimber(this); + OwnerIsTransitioning = true; + } + else + { + EntitySystem.Get().RemoveActiveClimber(this); + OwnerIsTransitioning = false; } - _isClimbing = value; + Dirty(); + } + } + + protected override bool OwnerIsTransitioning + { + get => base.OwnerIsTransitioning; + set + { + if (value == base.OwnerIsTransitioning) return; + base.OwnerIsTransitioning = value; Dirty(); } } @@ -51,38 +72,36 @@ namespace Content.Server.GameObjects.Components.Movement /// public void TryMoveTo(Vector2 from, Vector2 to) { - if (Body == null) - return; + if (Body == null) return; - _climbController = Body.EnsureController(); - _climbController.TryMoveTo(from, to); + var velocity = (to - from).Length; + + if (velocity <= 0.0f) return; + + Body.ApplyLinearImpulse((to - from).Normalized * velocity * 400); + OwnerIsTransitioning = true; + + Owner.SpawnTimer((int) (BufferTime * 1000), () => + { + if (Deleted) return; + OwnerIsTransitioning = false; + }); } public void Update() { - if (!IsClimbing || Body == null) - return; - - if (_climbController != null && (_climbController.IsBlocked || !_climbController.IsActive)) + if (!IsClimbing || _gameTiming.CurTime < TimeSpan.FromSeconds(BufferTime) + StartClimbTime) { - if (Body.TryRemoveController()) - { - _climbController = null; - } + return; } - if (IsClimbing) - Body.WakeBody(); - - if (!IsOnClimbableThisFrame && IsClimbing && _climbController == null) + if (!IsOnClimbableThisFrame && IsClimbing) IsClimbing = false; - - IsOnClimbableThisFrame = false; } public override ComponentState GetComponentState(ICommonSession player) { - return new ClimbModeComponentState(_isClimbing); + return new ClimbModeComponentState(_isClimbing, OwnerIsTransitioning); } } } diff --git a/Content.Server/GameObjects/Components/Movement/PlayerInputMoverComponent.cs b/Content.Server/GameObjects/Components/Movement/PlayerInputMoverComponent.cs deleted file mode 100644 index b5637c5eb2..0000000000 --- a/Content.Server/GameObjects/Components/Movement/PlayerInputMoverComponent.cs +++ /dev/null @@ -1,19 +0,0 @@ -#nullable enable -using Content.Shared.GameObjects.Components.Movement; -using Robust.Shared.GameObjects; -using Robust.Shared.Map; - -namespace Content.Server.GameObjects.Components.Movement -{ - /// - /// Moves the entity based on input from a KeyBindingInputComponent. - /// - [RegisterComponent] - [ComponentReference(typeof(IMoverComponent))] - public class PlayerInputMoverComponent : SharedPlayerInputMoverComponent - { - public override EntityCoordinates LastPosition { get; set; } - - public override float StepSoundDistance { get; set; } - } -} diff --git a/Content.Server/GameObjects/Components/Movement/ShuttleControllerComponent.cs b/Content.Server/GameObjects/Components/Movement/ShuttleControllerComponent.cs index 07a4d06cc5..c76f6406a4 100644 --- a/Content.Server/GameObjects/Components/Movement/ShuttleControllerComponent.cs +++ b/Content.Server/GameObjects/Components/Movement/ShuttleControllerComponent.cs @@ -11,6 +11,8 @@ using Robust.Shared.Log; using Robust.Shared.Map; using Robust.Shared.Maths; using Robust.Shared.Prototypes; +using Robust.Shared.Physics; +using Robust.Shared.Physics.Dynamics; using Robust.Shared.Serialization; using Robust.Shared.Serialization.Manager.Attributes; using Robust.Shared.ViewVariables; @@ -21,8 +23,6 @@ namespace Content.Server.GameObjects.Components.Movement [ComponentReference(typeof(IMoverComponent))] internal class ShuttleControllerComponent : Component, IMoverComponent { - [Dependency] private readonly IMapManager _mapManager = default!; - private bool _movingUp; private bool _movingDown; private bool _movingLeft; @@ -42,43 +42,19 @@ namespace Content.Server.GameObjects.Components.Movement public override string Name => "ShuttleController"; + public bool IgnorePaused => false; + [ViewVariables(VVAccess.ReadWrite)] public float CurrentWalkSpeed { get; } = 8; public float CurrentSprintSpeed => 0; - /// - [ViewVariables] - public float CurrentPushSpeed => 0.0f; - - /// - [ViewVariables] - public float GrabRange => 0.0f; - public bool Sprinting => false; - public (Vector2 walking, Vector2 sprinting) VelocityDir { get; } = (Vector2.Zero, Vector2.Zero); - public EntityCoordinates LastPosition { get; set; } - public float StepSoundDistance { get; set; } + public (Vector2 walking, Vector2 sprinting) VelocityDir { get; set; } = (Vector2.Zero, Vector2.Zero); public void SetVelocityDirection(Direction direction, ushort subTick, bool enabled) { - var gridId = Owner.Transform.GridID; - - if (_mapManager.TryGetGrid(gridId, out var grid) && - Owner.EntityManager.TryGetEntity(grid.GridEntityId, out var gridEntity)) - { - //TODO: Switch to shuttle component - if (!gridEntity.TryGetComponent(out IPhysicsComponent? physics)) - { - physics = gridEntity.AddComponent(); - physics.Mass = 1; - physics.CanCollide = true; - physics.PhysicsShapes.Add(new PhysShapeGrid(grid)); - } - - var controller = physics.EnsureController(); - controller.Push(CalcNewVelocity(direction, enabled), CurrentWalkSpeed); - } + VelocityDir = (CalcNewVelocity(direction, enabled), Vector2.Zero); } public void SetSprinting(ushort subTick, bool walking) diff --git a/Content.Server/GameObjects/Components/NodeContainer/Nodes/Node.cs b/Content.Server/GameObjects/Components/NodeContainer/Nodes/Node.cs index a326c1d663..07b4847f8f 100644 --- a/Content.Server/GameObjects/Components/NodeContainer/Nodes/Node.cs +++ b/Content.Server/GameObjects/Components/NodeContainer/Nodes/Node.cs @@ -6,6 +6,8 @@ using Content.Server.GameObjects.Components.NodeContainer.NodeGroups; using Robust.Shared.GameObjects; using Robust.Shared.IoC; using Robust.Shared.Serialization.Manager.Attributes; +using Robust.Shared.Physics; +using Robust.Shared.Serialization; using Robust.Shared.ViewVariables; namespace Content.Server.GameObjects.Components.NodeContainer.Nodes @@ -40,7 +42,7 @@ namespace Content.Server.GameObjects.Components.NodeContainer.Nodes /// public bool Connectable => !_deleting && Anchored; - private bool Anchored => !Owner.TryGetComponent(out var physics) || physics.Anchored; + private bool Anchored => !Owner.TryGetComponent(out var physics) || physics.BodyType == BodyType.Static; /// /// Prevents a node from being used by other nodes while midway through removal. diff --git a/Content.Server/GameObjects/Components/PA/ParticleProjectileComponent.cs b/Content.Server/GameObjects/Components/PA/ParticleProjectileComponent.cs index da93efeb7e..9f03ea0970 100644 --- a/Content.Server/GameObjects/Components/PA/ParticleProjectileComponent.cs +++ b/Content.Server/GameObjects/Components/PA/ParticleProjectileComponent.cs @@ -6,18 +6,20 @@ using Robust.Server.GameObjects; using Robust.Shared.GameObjects; using Robust.Shared.Log; using Robust.Shared.Maths; +using Robust.Shared.Physics; +using Robust.Shared.Physics.Collision; using Robust.Shared.Timing; namespace Content.Server.GameObjects.Components.PA { [RegisterComponent] - public class ParticleProjectileComponent : Component, ICollideBehavior + public class ParticleProjectileComponent : Component, IStartCollide { public override string Name => "ParticleProjectile"; private ParticleAcceleratorPowerState _state; - public void CollideWith(IEntity collidedWith) + void IStartCollide.CollideWith(IPhysBody ourBody, IPhysBody otherBody, in Manifold manifold) { - if (collidedWith.TryGetComponent(out var singularityComponent)) + if (otherBody.Entity.TryGetComponent(out var singularityComponent)) { var multiplier = _state switch { @@ -30,8 +32,8 @@ namespace Content.Server.GameObjects.Components.PA }; singularityComponent.Energy += 10 * multiplier; Owner.Delete(); - }else if (collidedWith.TryGetComponent(out var singularityGeneratorComponent) - ) + } + else if (otherBody.Entity.TryGetComponent(out var singularityGeneratorComponent)) { singularityGeneratorComponent.Power += _state switch { @@ -55,7 +57,7 @@ namespace Content.Server.GameObjects.Components.PA Logger.Error("ParticleProjectile tried firing, but it was spawned without a CollidableComponent"); return; } - physicsComponent.Status = BodyStatus.InAir; + physicsComponent.BodyStatus = BodyStatus.InAir; if (!Owner.TryGetComponent(out var projectileComponent)) { @@ -81,7 +83,6 @@ namespace Content.Server.GameObjects.Components.PA spriteComponent.LayerSetState(0, $"particle{suffix}"); physicsComponent - .EnsureController() .LinearVelocity = angle.ToWorldVec() * 20f; Owner.Transform.LocalRotation = angle; diff --git a/Content.Server/GameObjects/Components/Portal/PortalComponent.cs b/Content.Server/GameObjects/Components/Portal/PortalComponent.cs index 30d71a4f3e..510b34565a 100644 --- a/Content.Server/GameObjects/Components/Portal/PortalComponent.cs +++ b/Content.Server/GameObjects/Components/Portal/PortalComponent.cs @@ -6,12 +6,15 @@ using Content.Shared.GameObjects.Components.Tag; using Robust.Server.GameObjects; using Robust.Shared.GameObjects; using Robust.Shared.Serialization.Manager.Attributes; +using Robust.Shared.Physics; +using Robust.Shared.Physics.Collision; +using Robust.Shared.Serialization; using Robust.Shared.ViewVariables; namespace Content.Server.GameObjects.Components.Portal { [RegisterComponent] - public class PortalComponent : SharedPortalComponent, ICollideBehavior + public class PortalComponent : SharedPortalComponent, IStartCollide { // Potential improvements: Different sounds, // Add Gateways @@ -152,11 +155,11 @@ namespace Content.Server.GameObjects.Components.Portal StartCooldown(); } - public void CollideWith(IEntity collidedWith) + void IStartCollide.CollideWith(IPhysBody ourBody, IPhysBody otherBody, in Manifold manifold) { if (_onCooldown == false) { - TryPortalEntity(collidedWith); + TryPortalEntity(otherBody.Entity); } } } diff --git a/Content.Server/GameObjects/Components/Portal/TeleporterComponent.cs b/Content.Server/GameObjects/Components/Portal/TeleporterComponent.cs index 56abada91e..f10d94ff82 100644 --- a/Content.Server/GameObjects/Components/Portal/TeleporterComponent.cs +++ b/Content.Server/GameObjects/Components/Portal/TeleporterComponent.cs @@ -9,6 +9,7 @@ using Robust.Shared.GameObjects; using Robust.Shared.IoC; using Robust.Shared.Map; using Robust.Shared.Maths; +using Robust.Shared.Physics; using Robust.Shared.Random; using Robust.Shared.Serialization.Manager.Attributes; using Robust.Shared.ViewVariables; @@ -95,7 +96,7 @@ namespace Content.Server.GameObjects.Components.Portal { // Added this component to avoid stacking portals and causing shenanigans // TODO: Doesn't do a great job of stopping stacking portals for directed - if (entity.HasComponent() || entity.HasComponent()) + if (entity.HasComponent() || entity.HasComponent()) { return; } @@ -139,7 +140,7 @@ namespace Content.Server.GameObjects.Components.Portal // TODO: Check the user's spot? Upside is no stacking TPs but downside is they can't unstuck themselves from walls. foreach (var entity in _serverEntityManager.GetEntitiesIntersecting(user.Transform.MapID, target)) { - if (entity.HasComponent() || entity.HasComponent()) + if (entity.HasComponent() || entity.HasComponent()) { return false; } diff --git a/Content.Server/GameObjects/Components/Power/ApcNetComponents/PowerReceiverComponent.cs b/Content.Server/GameObjects/Components/Power/ApcNetComponents/PowerReceiverComponent.cs index 1ebcc7eef4..da2c599378 100644 --- a/Content.Server/GameObjects/Components/Power/ApcNetComponents/PowerReceiverComponent.cs +++ b/Content.Server/GameObjects/Components/Power/ApcNetComponents/PowerReceiverComponent.cs @@ -8,6 +8,7 @@ using Robust.Shared.GameObjects; using Robust.Shared.IoC; using Robust.Shared.Localization; using Robust.Shared.Prototypes; +using Robust.Shared.Physics; using Robust.Shared.Serialization; using Robust.Shared.Serialization.Manager.Attributes; using Robust.Shared.Utility; @@ -23,7 +24,7 @@ namespace Content.Server.GameObjects.Components.Power.ApcNetComponents { [Dependency] private readonly IServerEntityManager _serverEntityManager = default!; - [ViewVariables] [ComponentDependency] private readonly IPhysicsComponent? _physicsComponent = null; + [ViewVariables] [ComponentDependency] private readonly IPhysBody? _physicsComponent = null; public override string Name => "PowerReceiver"; @@ -53,7 +54,7 @@ namespace Content.Server.GameObjects.Components.Power.ApcNetComponents /// public bool Connectable => Anchored; - private bool Anchored => _physicsComponent == null || _physicsComponent.Anchored; + private bool Anchored => _physicsComponent == null || _physicsComponent.BodyType == BodyType.Static; [ViewVariables] public bool NeedsProvider { get; private set; } = true; diff --git a/Content.Server/GameObjects/Components/Projectiles/ChemicalInjectionProjectileComponent.cs b/Content.Server/GameObjects/Components/Projectiles/ChemicalInjectionProjectileComponent.cs index 7ba064c6c5..60f34ee2be 100644 --- a/Content.Server/GameObjects/Components/Projectiles/ChemicalInjectionProjectileComponent.cs +++ b/Content.Server/GameObjects/Components/Projectiles/ChemicalInjectionProjectileComponent.cs @@ -7,11 +7,13 @@ using Robust.Shared.ViewVariables; using System; using Robust.Shared.Prototypes; using Robust.Shared.Serialization.Manager.Attributes; +using Robust.Shared.Physics; +using Robust.Shared.Physics.Collision; namespace Content.Server.GameObjects.Components.Projectiles { [RegisterComponent] - public class ChemicalInjectionProjectileComponent : Component, ICollideBehavior + public class ChemicalInjectionProjectileComponent : Component, IStartCollide { public override string Name => "ChemicalInjectionProjectile"; @@ -33,9 +35,9 @@ namespace Content.Server.GameObjects.Components.Projectiles _solutionContainer = Owner.EnsureComponent(); } - void ICollideBehavior.CollideWith(IEntity entity) + void IStartCollide.CollideWith(IPhysBody ourBody, IPhysBody otherBody, in Manifold manifold) { - if (!entity.TryGetComponent(out var bloodstream)) + if (!otherBody.Entity.TryGetComponent(out var bloodstream)) return; var solution = _solutionContainer.Solution; diff --git a/Content.Server/GameObjects/Components/Projectiles/ExplosiveProjectileComponent.cs b/Content.Server/GameObjects/Components/Projectiles/ExplosiveProjectileComponent.cs index 5a76b11d28..92aecd24aa 100644 --- a/Content.Server/GameObjects/Components/Projectiles/ExplosiveProjectileComponent.cs +++ b/Content.Server/GameObjects/Components/Projectiles/ExplosiveProjectileComponent.cs @@ -1,10 +1,12 @@ using Content.Server.GameObjects.Components.Explosion; using Robust.Shared.GameObjects; +using Robust.Shared.Physics; +using Robust.Shared.Physics.Collision; namespace Content.Server.GameObjects.Components.Projectiles { [RegisterComponent] - public class ExplosiveProjectileComponent : Component, ICollideBehavior + public class ExplosiveProjectileComponent : Component, IStartCollide { public override string Name => "ExplosiveProjectile"; @@ -15,18 +17,12 @@ namespace Content.Server.GameObjects.Components.Projectiles Owner.EnsureComponent(); } - void ICollideBehavior.CollideWith(IEntity entity) + void IStartCollide.CollideWith(IPhysBody ourBody, IPhysBody otherBody, in Manifold manifold) { if (Owner.TryGetComponent(out ExplosiveComponent explosive)) { explosive.Explosion(); } } - - // Projectile should handle the deleting - void ICollideBehavior.PostCollide(int collisionCount) - { - return; - } } } diff --git a/Content.Server/GameObjects/Components/Projectiles/FlashProjectileComponent.cs b/Content.Server/GameObjects/Components/Projectiles/FlashProjectileComponent.cs index 60acb7926b..a550156112 100644 --- a/Content.Server/GameObjects/Components/Projectiles/FlashProjectileComponent.cs +++ b/Content.Server/GameObjects/Components/Projectiles/FlashProjectileComponent.cs @@ -1,6 +1,9 @@ using Content.Server.GameObjects.Components.Weapon; using Robust.Shared.GameObjects; using Robust.Shared.Serialization.Manager.Attributes; +using Robust.Shared.Physics; +using Robust.Shared.Physics.Collision; +using Robust.Shared.Serialization; namespace Content.Server.GameObjects.Components.Projectiles { @@ -8,7 +11,7 @@ namespace Content.Server.GameObjects.Components.Projectiles /// Upon colliding with an object this will flash in an area around it /// [RegisterComponent] - public class FlashProjectileComponent : Component, ICollideBehavior + public class FlashProjectileComponent : Component, IStartCollide { public override string Name => "FlashProjectile"; @@ -26,20 +29,15 @@ namespace Content.Server.GameObjects.Components.Projectiles Owner.EnsureComponent(); } - void ICollideBehavior.CollideWith(IEntity entity) + void IStartCollide.CollideWith(IPhysBody ourBody, IPhysBody otherBody, in Manifold manifold) { if (_flashed) { return; } + FlashableComponent.FlashAreaHelper(Owner, _range, _duration); _flashed = true; } - - // Projectile should handle the deleting - void ICollideBehavior.PostCollide(int collisionCount) - { - return; - } } } diff --git a/Content.Server/GameObjects/Components/Projectiles/HitscanComponent.cs b/Content.Server/GameObjects/Components/Projectiles/HitscanComponent.cs index ecbd57f327..d2e78de5d0 100644 --- a/Content.Server/GameObjects/Components/Projectiles/HitscanComponent.cs +++ b/Content.Server/GameObjects/Components/Projectiles/HitscanComponent.cs @@ -6,6 +6,9 @@ using Robust.Shared.GameObjects; using Robust.Shared.IoC; using Robust.Shared.Map; using Robust.Shared.Maths; +using Robust.Shared.Physics; +using Robust.Shared.Physics.Dynamics; +using Robust.Shared.Serialization; using Robust.Shared.Timing; using Robust.Shared.Serialization.Manager.Attributes; diff --git a/Content.Server/GameObjects/Components/Projectiles/ProjectileComponent.cs b/Content.Server/GameObjects/Components/Projectiles/ProjectileComponent.cs index 303f5748a3..69d3c82f45 100644 --- a/Content.Server/GameObjects/Components/Projectiles/ProjectileComponent.cs +++ b/Content.Server/GameObjects/Components/Projectiles/ProjectileComponent.cs @@ -5,6 +5,8 @@ using Content.Shared.GameObjects.Components.Damage; using Content.Shared.GameObjects.Components.Projectiles; using Robust.Server.GameObjects; using Robust.Shared.GameObjects; +using Robust.Shared.Physics; +using Robust.Shared.Physics.Collision; using Robust.Shared.Players; using Robust.Shared.Serialization; using Robust.Shared.Serialization.Manager.Attributes; @@ -13,7 +15,7 @@ using Robust.Shared.ViewVariables; namespace Content.Server.GameObjects.Components.Projectiles { [RegisterComponent] - public class ProjectileComponent : SharedProjectileComponent, ICollideBehavior + public class ProjectileComponent : SharedProjectileComponent, IStartCollide { protected override EntityUid Shooter => _shooter; @@ -52,39 +54,27 @@ namespace Content.Server.GameObjects.Components.Projectiles Dirty(); } - private bool _internalDeleteOnCollide; - /// - /// Applies the damage when our projectile collides with its victim + /// Applies the damage when our projectile collides with its victim /// - /// - void ICollideBehavior.CollideWith(IEntity entity) + void IStartCollide.CollideWith(IPhysBody ourBody, IPhysBody otherBody, in Manifold manifold) { - if (_damagedEntity) - { - return; - } - // This is so entities that shouldn't get a collision are ignored. - if (entity.TryGetComponent(out IPhysicsComponent otherPhysics) && otherPhysics.Hard == false) + if (!otherBody.Hard || _damagedEntity) { - _internalDeleteOnCollide = false; return; } - else + + if (otherBody.Entity.TryGetComponent(out IDamageableComponent damage) && _soundHitSpecies != null) { - _internalDeleteOnCollide = true; + EntitySystem.Get().PlayAtCoords(_soundHitSpecies, otherBody.Entity.Transform.Coordinates); + } + else if (_soundHit != null) + { + EntitySystem.Get().PlayAtCoords(_soundHit, otherBody.Entity.Transform.Coordinates); } - if (_soundHitSpecies != null && entity.HasComponent()) - { - EntitySystem.Get().PlayAtCoords(_soundHitSpecies, entity.Transform.Coordinates); - } else if (_soundHit != null) - { - EntitySystem.Get().PlayAtCoords(_soundHit, entity.Transform.Coordinates); - } - - if (entity.TryGetComponent(out IDamageableComponent damage)) + if (damage != null) { Owner.EntityManager.TryGetEntity(_shooter, out var shooter); @@ -96,17 +86,14 @@ namespace Content.Server.GameObjects.Components.Projectiles _damagedEntity = true; } - if (!entity.Deleted && entity.TryGetComponent(out CameraRecoilComponent recoilComponent) - && Owner.TryGetComponent(out IPhysicsComponent ownPhysics)) + // Damaging it can delete it + if (!otherBody.Entity.Deleted && otherBody.Entity.TryGetComponent(out CameraRecoilComponent recoilComponent)) { - var direction = ownPhysics.LinearVelocity.Normalized; + var direction = ourBody.LinearVelocity.Normalized; recoilComponent.Kick(direction); } - } - void ICollideBehavior.PostCollide(int collideCount) - { - if (collideCount > 0 && DeleteOnCollide && _internalDeleteOnCollide) Owner.Delete(); + Owner.Delete(); } public override ComponentState GetComponentState(ICommonSession player) diff --git a/Content.Server/GameObjects/Components/Projectiles/StunnableProjectileComponent.cs b/Content.Server/GameObjects/Components/Projectiles/StunnableProjectileComponent.cs index 10086a67a1..c46e5c19ac 100644 --- a/Content.Server/GameObjects/Components/Projectiles/StunnableProjectileComponent.cs +++ b/Content.Server/GameObjects/Components/Projectiles/StunnableProjectileComponent.cs @@ -1,6 +1,9 @@ using Content.Server.GameObjects.Components.Mobs; using Robust.Shared.GameObjects; using Robust.Shared.Serialization.Manager.Attributes; +using Robust.Shared.Physics; +using Robust.Shared.Physics.Collision; +using Robust.Shared.Serialization; namespace Content.Server.GameObjects.Components.Projectiles { @@ -8,7 +11,7 @@ namespace Content.Server.GameObjects.Components.Projectiles /// Adds stun when it collides with an entity /// [RegisterComponent] - public sealed class StunnableProjectileComponent : Component, ICollideBehavior + public sealed class StunnableProjectileComponent : Component, IStartCollide { public override string Name => "StunnableProjectile"; @@ -27,16 +30,14 @@ namespace Content.Server.GameObjects.Components.Projectiles Owner.EnsureComponentWarn(out ProjectileComponent _); } - void ICollideBehavior.CollideWith(IEntity entity) + void IStartCollide.CollideWith(IPhysBody ourBody, IPhysBody otherBody, in Manifold manifold) { - if (entity.TryGetComponent(out StunnableComponent stunnableComponent)) + if (otherBody.Entity.TryGetComponent(out StunnableComponent stunnableComponent)) { stunnableComponent.Stun(_stunAmount); stunnableComponent.Knockdown(_knockdownAmount); stunnableComponent.Slowdown(_slowdownAmount); } } - - void ICollideBehavior.PostCollide(int collidedCount) {} } } diff --git a/Content.Server/GameObjects/Components/Projectiles/ThrownItemComponent.cs b/Content.Server/GameObjects/Components/Projectiles/ThrownItemComponent.cs deleted file mode 100644 index 31899d5fed..0000000000 --- a/Content.Server/GameObjects/Components/Projectiles/ThrownItemComponent.cs +++ /dev/null @@ -1,118 +0,0 @@ -using Content.Server.GameObjects.EntitySystems.Click; -using Content.Shared.GameObjects; -using Content.Shared.Physics; -using Robust.Server.GameObjects; -using Robust.Shared.GameObjects; -using Robust.Shared.IoC; -using Robust.Shared.Maths; -using Robust.Shared.Physics; - -namespace Content.Server.GameObjects.Components.Projectiles -{ - [RegisterComponent] - internal class ThrownItemComponent : ProjectileComponent, ICollideBehavior - { - public const float DefaultThrowTime = 0.25f; - - private bool _shouldCollide = true; - private bool _shouldStop = false; - - public override string Name => "ThrownItem"; - public override uint? NetID => ContentNetIDs.THROWN_ITEM; - - /// - /// User who threw the item. - /// - public IEntity User { get; set; } - - void ICollideBehavior.CollideWith(IEntity entity) - { - if (!_shouldCollide || entity.Deleted) return; - if (entity.TryGetComponent(out PhysicsComponent collid)) - { - if (!collid.Hard) // ignore non hard - return; - - _shouldStop = true; // hit something hard => stop after this collision - - // Raise an event. - EntitySystem.Get().ThrowCollideInteraction(User, Owner, entity, Owner.Transform.Coordinates); - } - - // Stop colliding with mobs, this mimics not having enough velocity to do damage - // after impacting the first object. - // For realism this should actually be changed when the velocity of the object is less than a threshold. - // This would allow ricochets off walls, and weird gravity effects from slowing the object. - if (!Owner.Deleted && Owner.TryGetComponent(out IPhysicsComponent body) && body.PhysicsShapes.Count >= 1) - { - _shouldCollide = false; - } - } - - private void StopThrow() - { - if (Deleted) - { - return; - } - - if (Owner.TryGetComponent(out IPhysicsComponent body) && body.PhysicsShapes.Count >= 1) - { - body.PhysicsShapes[0].CollisionMask &= (int) ~CollisionGroup.ThrownItem; - - if (body.TryGetController(out ThrownController controller)) - { - controller.LinearVelocity = Vector2.Zero; - } - - body.Status = BodyStatus.OnGround; - - Owner.RemoveComponent(); - EntitySystem.Get().LandInteraction(User, Owner, Owner.Transform.Coordinates); - } - } - - void ICollideBehavior.PostCollide(int collideCount) - { - if (_shouldStop && collideCount > 0) - { - StopThrow(); - } - } - - public void StartThrow(Vector2 direction, float speed) - { - var comp = Owner.GetComponent(); - comp.Status = BodyStatus.InAir; - - var controller = comp.EnsureController(); - controller.Push(direction, speed); - - EntitySystem.Get() - .PlayFromEntity("/Audio/Effects/toss.ogg", Owner); - - StartStopTimer(); - } - - private void StartStopTimer() - { - Owner.SpawnTimer((int) (DefaultThrowTime * 1000), MaybeStopThrow); - } - - private void MaybeStopThrow() - { - if (Deleted) - { - return; - } - - if (IoCManager.Resolve().IsWeightless(Owner.Transform.Coordinates)) - { - StartStopTimer(); - return; - } - - StopThrow(); - } - } -} diff --git a/Content.Server/GameObjects/Components/Pulling/PullableComponent.cs b/Content.Server/GameObjects/Components/Pulling/PullableComponent.cs index 53a1c9b059..9c55176d5d 100644 --- a/Content.Server/GameObjects/Components/Pulling/PullableComponent.cs +++ b/Content.Server/GameObjects/Components/Pulling/PullableComponent.cs @@ -5,6 +5,7 @@ using Content.Shared.GameObjects.EntitySystems; using Content.Shared.GameObjects.Verbs; using Robust.Shared.GameObjects; using Robust.Shared.Localization; +using Robust.Shared.Physics; namespace Content.Server.GameObjects.Components.Pulling { @@ -31,15 +32,15 @@ namespace Content.Server.GameObjects.Components.Pulling } if (!user.HasComponent() || - !user.TryGetComponent(out IPhysicsComponent? userPhysics) || - !component.Owner.TryGetComponent(out IPhysicsComponent? targetPhysics) || - targetPhysics.Anchored) + !user.TryGetComponent(out IPhysBody? userPhysics) || + !component.Owner.TryGetComponent(out IPhysBody? targetPhysics) || + targetPhysics.BodyType == BodyType.Static) { return; } data.Visibility = VerbVisibility.Visible; - data.Text = component.Puller == userPhysics + data.Text = component.Puller == userPhysics.Entity ? Loc.GetString("Stop pulling") : Loc.GetString("Pull"); } diff --git a/Content.Server/GameObjects/Components/Recycling/RecyclerComponent.cs b/Content.Server/GameObjects/Components/Recycling/RecyclerComponent.cs index a35716a15b..6f4ef912de 100644 --- a/Content.Server/GameObjects/Components/Recycling/RecyclerComponent.cs +++ b/Content.Server/GameObjects/Components/Recycling/RecyclerComponent.cs @@ -20,6 +20,8 @@ using Robust.Shared.IoC; using Robust.Shared.Localization; using Robust.Shared.Maths; using Robust.Shared.Prototypes; +using Robust.Shared.Physics; +using Robust.Shared.Physics.Collision; using Robust.Shared.Serialization; using Robust.Shared.Serialization.Manager.Attributes; using Robust.Shared.ViewVariables; @@ -28,11 +30,11 @@ namespace Content.Server.GameObjects.Components.Recycling { // TODO: Add sound and safe beep [RegisterComponent] - public class RecyclerComponent : Component, ICollideBehavior, ISuicideAct + public class RecyclerComponent : Component, IStartCollide, ISuicideAct { public override string Name => "Recycler"; - private readonly List _intersecting = new(); + public List Intersecting { get; set; } = new(); /// /// Whether or not sentient beings will be recycled @@ -74,9 +76,9 @@ namespace Content.Server.GameObjects.Components.Recycling private void Recycle(IEntity entity) { - if (!_intersecting.Contains(entity)) + if (!Intersecting.Contains(entity)) { - _intersecting.Add(entity); + Intersecting.Add(entity); } // TODO: Prevent collision with recycled items @@ -95,7 +97,7 @@ namespace Content.Server.GameObjects.Components.Recycling recyclable.Recycle(_efficiency); } - private bool CanRun() + public bool CanRun() { if (Owner.TryGetComponent(out PowerReceiverComponent? receiver) && !receiver.Powered) @@ -111,15 +113,15 @@ namespace Content.Server.GameObjects.Components.Recycling return true; } - private bool CanMove(IEntity entity) + public bool CanMove(IEntity entity) { if (entity == Owner) { return false; } - if (!entity.TryGetComponent(out IPhysicsComponent? physics) || - physics.Anchored) + if (!entity.TryGetComponent(out IPhysBody? physics) || + physics.BodyType == BodyType.Static) { return false; } @@ -142,37 +144,9 @@ namespace Content.Server.GameObjects.Components.Recycling return true; } - public void Update(float frameTime) + void IStartCollide.CollideWith(IPhysBody ourBody, IPhysBody otherBody, in Manifold manifold) { - if (!CanRun()) - { - _intersecting.Clear(); - return; - } - - var direction = Vector2.UnitX; - - for (var i = _intersecting.Count - 1; i >= 0; i--) - { - var entity = _intersecting[i]; - - if (entity.Deleted || !CanMove(entity) || !Owner.EntityManager.IsIntersecting(Owner, entity)) - { - _intersecting.RemoveAt(i); - continue; - } - - if (entity.TryGetComponent(out IPhysicsComponent? physics)) - { - var controller = physics.EnsureController(); - controller.Move(direction, frameTime, entity.Transform.WorldPosition - Owner.Transform.WorldPosition); - } - } - } - - void ICollideBehavior.CollideWith(IEntity collidedWith) - { - Recycle(collidedWith); + Recycle(otherBody.Entity); } SuicideKind ISuicideAct.Suicide(IEntity victim, IChatManager chat) diff --git a/Content.Server/GameObjects/Components/Rotatable/FlippableComponent.cs b/Content.Server/GameObjects/Components/Rotatable/FlippableComponent.cs index 4d9b210db8..44241dc85f 100644 --- a/Content.Server/GameObjects/Components/Rotatable/FlippableComponent.cs +++ b/Content.Server/GameObjects/Components/Rotatable/FlippableComponent.cs @@ -5,6 +5,7 @@ using Content.Shared.Interfaces; using Robust.Shared.GameObjects; using Robust.Shared.Localization; using Robust.Shared.Prototypes; +using Robust.Shared.Physics; using Robust.Shared.Serialization; using Robust.Shared.Serialization.Manager.Attributes; @@ -23,8 +24,8 @@ namespace Content.Server.GameObjects.Components.Rotatable private void TryFlip(IEntity user) { - if (Owner.TryGetComponent(out IPhysicsComponent? physics) && - physics.Anchored) + if (Owner.TryGetComponent(out IPhysBody? physics) && + physics.BodyType == BodyType.Static) { Owner.PopupMessage(user, Loc.GetString("It's stuck.")); return; diff --git a/Content.Server/GameObjects/Components/Rotatable/RotatableComponent.cs b/Content.Server/GameObjects/Components/Rotatable/RotatableComponent.cs index 8482173fe9..bd704e80ff 100644 --- a/Content.Server/GameObjects/Components/Rotatable/RotatableComponent.cs +++ b/Content.Server/GameObjects/Components/Rotatable/RotatableComponent.cs @@ -5,6 +5,7 @@ using Robust.Shared.GameObjects; using Robust.Shared.Localization; using Robust.Shared.Maths; using Robust.Shared.Prototypes; +using Robust.Shared.Physics; using Robust.Shared.Serialization; using Robust.Shared.Serialization.Manager.Attributes; using Robust.Shared.ViewVariables; @@ -25,9 +26,9 @@ namespace Content.Server.GameObjects.Components.Rotatable private void TryRotate(IEntity user, Angle angle) { - if (!RotateWhileAnchored && Owner.TryGetComponent(out IPhysicsComponent physics)) + if (!RotateWhileAnchored && Owner.TryGetComponent(out IPhysBody physics)) { - if (physics.Anchored) + if (physics.BodyType == BodyType.Static) { Owner.PopupMessage(user, Loc.GetString("It's stuck.")); return; @@ -42,7 +43,7 @@ namespace Content.Server.GameObjects.Components.Rotatable { protected override void GetData(IEntity user, RotatableComponent component, VerbData data) { - if (!ActionBlockerSystem.CanInteract(user) || (!component.RotateWhileAnchored && component.Owner.TryGetComponent(out IPhysicsComponent physics) && physics.Anchored)) + if (!ActionBlockerSystem.CanInteract(user) || (!component.RotateWhileAnchored && component.Owner.TryGetComponent(out IPhysBody physics) && physics.BodyType == BodyType.Static)) { data.Visibility = VerbVisibility.Invisible; return; @@ -64,7 +65,7 @@ namespace Content.Server.GameObjects.Components.Rotatable { protected override void GetData(IEntity user, RotatableComponent component, VerbData data) { - if (!ActionBlockerSystem.CanInteract(user) || (!component.RotateWhileAnchored && component.Owner.TryGetComponent(out IPhysicsComponent physics) && physics.Anchored)) + if (!ActionBlockerSystem.CanInteract(user) || (!component.RotateWhileAnchored && component.Owner.TryGetComponent(out IPhysBody physics) && physics.BodyType == BodyType.Static)) { data.Visibility = VerbVisibility.Invisible; return; diff --git a/Content.Server/GameObjects/Components/Singularity/ContainmentFieldComponent.cs b/Content.Server/GameObjects/Components/Singularity/ContainmentFieldComponent.cs index 14702fa091..e841b09530 100644 --- a/Content.Server/GameObjects/Components/Singularity/ContainmentFieldComponent.cs +++ b/Content.Server/GameObjects/Components/Singularity/ContainmentFieldComponent.cs @@ -1,15 +1,17 @@ #nullable enable using Robust.Shared.GameObjects; +using Robust.Shared.Physics; +using Robust.Shared.Physics.Collision; namespace Content.Server.GameObjects.Components.Singularity { [RegisterComponent] - public class ContainmentFieldComponent : Component, ICollideBehavior + public class ContainmentFieldComponent : Component, IStartCollide { public override string Name => "ContainmentField"; public ContainmentFieldConnection? Parent; - public void CollideWith(IEntity collidedWith) + void IStartCollide.CollideWith(IPhysBody ourBody, IPhysBody otherBody, in Manifold manifold) { if (Parent == null) { @@ -17,7 +19,7 @@ namespace Content.Server.GameObjects.Components.Singularity return; } - Parent.TryRepell(Owner, collidedWith); + Parent.TryRepell(Owner, otherBody.Entity); } } } diff --git a/Content.Server/GameObjects/Components/Singularity/ContainmentFieldConnection.cs b/Content.Server/GameObjects/Components/Singularity/ContainmentFieldConnection.cs index 7ad9ec1d53..a127bfa5bb 100644 --- a/Content.Server/GameObjects/Components/Singularity/ContainmentFieldConnection.cs +++ b/Content.Server/GameObjects/Components/Singularity/ContainmentFieldConnection.cs @@ -1,11 +1,11 @@ using System; using System.Collections.Generic; using System.Threading; -using Content.Shared.Physics; using Robust.Shared.GameObjects; using Robust.Shared.IoC; using Robust.Shared.Log; using Robust.Shared.Maths; +using Robust.Shared.Physics; using Timer = Robust.Shared.Timing.Timer; namespace Content.Server.GameObjects.Components.Singularity @@ -90,10 +90,12 @@ namespace Content.Server.GameObjects.Components.Singularity /// Entity to repell. public void TryRepell(IEntity repellFrom, IEntity toRepell) { - if (!_fields.Contains(repellFrom) || !toRepell.TryGetComponent(out var collidableComponent)) return; + // TODO: Fix this also it's fucking repel + if (!_fields.Contains(repellFrom) || !toRepell.TryGetComponent(out var collidableComponent)) return; + return; var speed = 5; - var containmentFieldRepellController = collidableComponent.EnsureController(); + //var containmentFieldRepellController = collidableComponent.EnsureController(); if (!CanRepell(toRepell)) { @@ -106,22 +108,22 @@ namespace Content.Server.GameObjects.Components.Singularity { if (repellFrom.Transform.WorldPosition.X.CompareTo(toRepell.Transform.WorldPosition.X) > 0) { - containmentFieldRepellController.Repell(Direction.West, speed); + //containmentFieldRepellController.Repell(Direction.West, speed); } else { - containmentFieldRepellController.Repell(Direction.East, speed); + //containmentFieldRepellController.Repell(Direction.East, speed); } } else { if (repellFrom.Transform.WorldPosition.Y.CompareTo(toRepell.Transform.WorldPosition.Y) > 0) { - containmentFieldRepellController.Repell(Direction.South, speed); + //containmentFieldRepellController.Repell(Direction.South, speed); } else { - containmentFieldRepellController.Repell(Direction.North, speed); + //containmentFieldRepellController.Repell(Direction.North, speed); } } diff --git a/Content.Server/GameObjects/Components/Singularity/ContainmentFieldGeneratorComponent.cs b/Content.Server/GameObjects/Components/Singularity/ContainmentFieldGeneratorComponent.cs index 7dc05478bf..c050b7a44f 100644 --- a/Content.Server/GameObjects/Components/Singularity/ContainmentFieldGeneratorComponent.cs +++ b/Content.Server/GameObjects/Components/Singularity/ContainmentFieldGeneratorComponent.cs @@ -10,13 +10,15 @@ using Robust.Shared.IoC; using Robust.Shared.Log; using Robust.Shared.Maths; using Robust.Shared.Physics; +using Robust.Shared.Physics.Broadphase; using Robust.Shared.ViewVariables; using Robust.Server.GameObjects; +using Robust.Shared.Physics.Collision; namespace Content.Server.GameObjects.Components.Singularity { [RegisterComponent] - public class ContainmentFieldGeneratorComponent : Component, ICollideBehavior + public class ContainmentFieldGeneratorComponent : Component, IStartCollide { [Dependency] private readonly IPhysicsManager _physicsManager = null!; @@ -117,7 +119,7 @@ namespace Content.Server.GameObjects.Components.Singularity var dirVec = direction.ToVec(); var ray = new CollisionRay(Owner.Transform.WorldPosition, dirVec, (int) CollisionGroup.MobMask); - var rawRayCastResults = _physicsManager.IntersectRay(Owner.Transform.MapID, ray, 4.5f, Owner, false); + var rawRayCastResults = EntitySystem.Get().IntersectRay(Owner.Transform.MapID, ray, 4.5f, Owner, false); var rayCastResults = rawRayCastResults as RayCastResults[] ?? rawRayCastResults.ToArray(); if(!rayCastResults.Any()) continue; @@ -182,9 +184,9 @@ namespace Content.Server.GameObjects.Components.Singularity } } - public void CollideWith(IEntity collidedWith) + void IStartCollide.CollideWith(IPhysBody ourBody, IPhysBody otherBody, in Manifold manifold) { - if(collidedWith.HasComponent()) + if (otherBody.Entity.HasComponent()) { ReceivePower(4); } diff --git a/Content.Server/GameObjects/Components/Singularity/EmitterComponent.cs b/Content.Server/GameObjects/Components/Singularity/EmitterComponent.cs index a92100e424..d83ca52354 100644 --- a/Content.Server/GameObjects/Components/Singularity/EmitterComponent.cs +++ b/Content.Server/GameObjects/Components/Singularity/EmitterComponent.cs @@ -226,7 +226,7 @@ namespace Content.Server.GameObjects.Components.Singularity return; } - physicsComponent.Status = BodyStatus.InAir; + physicsComponent.BodyStatus = BodyStatus.InAir; if (!projectile.TryGetComponent(out var projectileComponent)) { @@ -237,7 +237,6 @@ namespace Content.Server.GameObjects.Components.Singularity projectileComponent.IgnoreEntity(Owner); physicsComponent - .EnsureController() .LinearVelocity = Owner.Transform.WorldRotation.ToWorldVec() * 20f; projectile.Transform.WorldRotation = Owner.Transform.WorldRotation; diff --git a/Content.Server/GameObjects/Components/Singularity/SingularityComponent.cs b/Content.Server/GameObjects/Components/Singularity/SingularityComponent.cs index ae4cb13494..972c3bb3a1 100644 --- a/Content.Server/GameObjects/Components/Singularity/SingularityComponent.cs +++ b/Content.Server/GameObjects/Components/Singularity/SingularityComponent.cs @@ -14,13 +14,15 @@ using Robust.Shared.Log; using Robust.Shared.Maths; using Robust.Shared.Map; using Robust.Shared.Physics; +using Robust.Shared.Physics.Collision; +using Robust.Shared.Physics.Dynamics.Shapes; using Robust.Shared.Random; using Robust.Shared.Timing; namespace Content.Server.GameObjects.Components.Singularity { [RegisterComponent] - public class SingularityComponent : Component, ICollideBehavior + public class SingularityComponent : Component, IStartCollide { [Dependency] private readonly IRobustRandom _random = default!; @@ -38,7 +40,6 @@ namespace Content.Server.GameObjects.Components.Singularity _energy = value; if (_energy <= 0) { - if(_singularityController != null) _singularityController.LinearVelocity = Vector2.Zero; _spriteComponent?.LayerSetVisible(0, false); Owner.Delete(); @@ -75,7 +76,7 @@ namespace Content.Server.GameObjects.Components.Singularity _spriteComponent?.LayerSetRSI(0, "Constructible/Power/Singularity/singularity_" + _level + ".rsi"); _spriteComponent?.LayerSetState(0, "singularity_" + _level); - if(_collidableComponent != null && _collidableComponent.PhysicsShapes.Any() && _collidableComponent.PhysicsShapes[0] is PhysShapeCircle circle) + if(_collidableComponent != null && _collidableComponent.Fixtures.Any() && _collidableComponent.Fixtures[0].Shape is PhysShapeCircle circle) { circle.Radius = _level - 0.5f; } @@ -95,7 +96,6 @@ namespace Content.Server.GameObjects.Components.Singularity _ => 0 }; - private SingularityController? _singularityController; private PhysicsComponent? _collidableComponent; private SpriteComponent? _spriteComponent; private RadiationPulseComponent? _radiationPulseComponent; @@ -129,9 +129,6 @@ namespace Content.Server.GameObjects.Components.Singularity Logger.Error("SingularityComponent was spawned without SpriteComponent"); } - _singularityController = _collidableComponent?.EnsureController(); - if(_singularityController!=null)_singularityController.ControlledComponent = _collidableComponent; - if (!Owner.TryGetComponent(out _radiationPulseComponent)) { Logger.Error("SingularityComponent was spawned without RadiationPulseComponent"); @@ -140,60 +137,18 @@ namespace Content.Server.GameObjects.Components.Singularity Level = 1; } - public void Update() + public void Update(int seconds) { - Energy -= EnergyDrain; - - if(Level == 1) return; - //pushing - var pushVector = new Vector2((_random.Next(-10, 10)), _random.Next(-10, 10)); - while (pushVector.X == 0 && pushVector.Y == 0) - { - pushVector = new Vector2((_random.Next(-10, 10)), _random.Next(-10, 10)); - } - _singularityController?.Push(pushVector.Normalized, 2); + Energy -= EnergyDrain * seconds; } - private readonly List _previousPulledEntities = new(); - public void CleanupPulledEntities() + void IStartCollide.CollideWith(IPhysBody ourBody, IPhysBody otherBody, in Manifold manifold) { - foreach (var previousPulledEntity in _previousPulledEntities) + var otherEntity = otherBody.Entity; + + if (otherEntity.TryGetComponent(out var mapGridComponent)) { - if(previousPulledEntity.Deleted) continue; - if (!previousPulledEntity.TryGetComponent(out var collidableComponent)) continue; - var controller = collidableComponent.EnsureController(); - controller.StopPull(); - } - _previousPulledEntities.Clear(); - } - - public void PullUpdate() - { - CleanupPulledEntities(); - var entitiesToPull = Owner.EntityManager.GetEntitiesInRange(Owner.Transform.Coordinates, Level * 10); - foreach (var entity in entitiesToPull) - { - if (!entity.TryGetComponent(out var collidableComponent)) continue; - if (entity.HasComponent()) continue; - var controller = collidableComponent.EnsureController(); - if(Owner.Transform.Coordinates.EntityId != entity.Transform.Coordinates.EntityId) continue; - var vec = (Owner.Transform.Coordinates - entity.Transform.Coordinates).Position; - if (vec == Vector2.Zero) continue; - - var speed = 10 / vec.Length * Level; - - controller.Pull(vec.Normalized, speed); - _previousPulledEntities.Add(entity); - } - } - - void ICollideBehavior.CollideWith(IEntity entity) - { - if (_collidableComponent == null) return; //how did it even collide then? :D - - if (entity.TryGetComponent(out var mapGridComponent)) - { - foreach (var tile in mapGridComponent.Grid.GetTilesIntersecting(((IPhysBody) _collidableComponent).WorldAABB)) + foreach (var tile in mapGridComponent.Grid.GetTilesIntersecting(ourBody.GetWorldAABB())) { mapGridComponent.Grid.SetTile(tile.GridIndices, Tile.Empty); Energy++; @@ -201,14 +156,14 @@ namespace Content.Server.GameObjects.Components.Singularity return; } - if (entity.HasComponent() || (entity.TryGetComponent(out var component) && component.CanRepell(Owner))) + if (otherEntity.HasComponent() || (otherEntity.TryGetComponent(out var component) && component.CanRepell(Owner))) { return; } - if (entity.IsInContainer()) return; + if (otherEntity.IsInContainer()) return; - entity.Delete(); + otherEntity.Delete(); Energy++; } @@ -216,7 +171,6 @@ namespace Content.Server.GameObjects.Components.Singularity { _playingSound?.Stop(); _audioSystem.PlayAtCoords("/Audio/Effects/singularity_collapse.ogg", Owner.Transform.Coordinates); - CleanupPulledEntities(); base.OnRemove(); } } diff --git a/Content.Server/GameObjects/Components/Temperature/TemperatureComponent.cs b/Content.Server/GameObjects/Components/Temperature/TemperatureComponent.cs index e4f2488e7c..c88777e943 100644 --- a/Content.Server/GameObjects/Components/Temperature/TemperatureComponent.cs +++ b/Content.Server/GameObjects/Components/Temperature/TemperatureComponent.cs @@ -6,6 +6,8 @@ using Content.Shared.Damage; using Content.Shared.GameObjects.Components.Damage; using Robust.Shared.GameObjects; using Robust.Shared.Serialization.Manager.Attributes; +using Robust.Shared.Physics; +using Robust.Shared.Serialization; using Robust.Shared.ViewVariables; namespace Content.Server.GameObjects.Components.Temperature @@ -29,7 +31,7 @@ namespace Content.Server.GameObjects.Components.Temperature [ViewVariables] public float HeatCapacity { get { - if (Owner.TryGetComponent(out var physics)) + if (Owner.TryGetComponent(out var physics)) { return SpecificHeat * physics.Mass; } diff --git a/Content.Server/GameObjects/Components/Weapon/FlashableComponent.cs b/Content.Server/GameObjects/Components/Weapon/FlashableComponent.cs index 5dfbf79023..e919a9350f 100644 --- a/Content.Server/GameObjects/Components/Weapon/FlashableComponent.cs +++ b/Content.Server/GameObjects/Components/Weapon/FlashableComponent.cs @@ -1,5 +1,6 @@ using System; using Content.Shared.GameObjects.Components.Weapons; +using Content.Shared.Physics; using Content.Shared.Utility; using Robust.Server.GameObjects; using Robust.Shared.GameObjects; @@ -31,18 +32,17 @@ namespace Content.Server.GameObjects.Components.Weapon public static void FlashAreaHelper(IEntity source, float range, float duration, string sound = null) { - foreach (var entity in IoCManager.Resolve().GetEntitiesInRange(source.Transform.Coordinates, range)) + foreach (var entity in source.EntityManager.GetEntitiesInRange(source.Transform.Coordinates, range)) { - if (!source.InRangeUnobstructed(entity, range, popup: true)) - continue; + if (!entity.TryGetComponent(out FlashableComponent flashable) || + !source.InRangeUnobstructed(entity, range, CollisionGroup.Opaque)) continue; - if(entity.TryGetComponent(out FlashableComponent flashable)) - flashable.Flash(duration); + flashable.Flash(duration); } if (!string.IsNullOrEmpty(sound)) { - IoCManager.Resolve().GetEntitySystem().PlayAtCoords(sound, source.Transform.Coordinates); + EntitySystem.Get().PlayAtCoords(sound, source.Transform.Coordinates); } } } diff --git a/Content.Server/GameObjects/Components/Weapon/Melee/MeleeWeaponComponent.cs b/Content.Server/GameObjects/Components/Weapon/Melee/MeleeWeaponComponent.cs index 7e5fad59eb..d8d0b17a1d 100644 --- a/Content.Server/GameObjects/Components/Weapon/Melee/MeleeWeaponComponent.cs +++ b/Content.Server/GameObjects/Components/Weapon/Melee/MeleeWeaponComponent.cs @@ -13,6 +13,7 @@ using Robust.Shared.IoC; using Robust.Shared.Maths; using Robust.Shared.Physics; using Robust.Shared.Prototypes; +using Robust.Shared.Physics.Broadphase; using Robust.Shared.Serialization; using Robust.Shared.Timing; using Robust.Shared.Serialization.Manager.Attributes; @@ -191,10 +192,13 @@ namespace Content.Server.GameObjects.Components.Weapon.Melee for (var i = 0; i < increments; i++) { var castAngle = new Angle(baseAngle + increment * i); - var res = _physicsManager.IntersectRay(mapId, new CollisionRay(position, castAngle.ToWorldVec(), (int) (CollisionGroup.Impassable|CollisionGroup.MobImpassable)), Range, ignore).FirstOrDefault(); - if (res.HitEntity != null) + var res = EntitySystem.Get().IntersectRay(mapId, + new CollisionRay(position, castAngle.ToVec(), + (int) (CollisionGroup.Impassable | CollisionGroup.MobImpassable)), Range, ignore).ToList(); + + if (res.Count != 0) { - resSet.Add(res.HitEntity); + resSet.Add(res[0].HitEntity); } } diff --git a/Content.Server/GameObjects/Components/Weapon/Ranged/Barrels/ServerRangedBarrelComponent.cs b/Content.Server/GameObjects/Components/Weapon/Ranged/Barrels/ServerRangedBarrelComponent.cs index 81dc22f6e3..eb1a0fbc10 100644 --- a/Content.Server/GameObjects/Components/Weapon/Ranged/Barrels/ServerRangedBarrelComponent.cs +++ b/Content.Server/GameObjects/Components/Weapon/Ranged/Barrels/ServerRangedBarrelComponent.cs @@ -22,6 +22,7 @@ using Robust.Shared.Map; using Robust.Shared.Maths; using Robust.Shared.Physics; using Robust.Shared.Player; +using Robust.Shared.Physics.Broadphase; using Robust.Shared.Prototypes; using Robust.Shared.Random; using Robust.Shared.Serialization; @@ -367,15 +368,14 @@ namespace Content.Server.GameObjects.Components.Weapon.Ranged.Barrels projectileAngle = angle; } - var physics = projectile.GetComponent(); - physics.Status = BodyStatus.InAir; + var physics = projectile.GetComponent(); + physics.BodyStatus = BodyStatus.InAir; var projectileComponent = projectile.GetComponent(); projectileComponent.IgnoreEntity(shooter); projectile - .GetComponent() - .EnsureController() + .GetComponent() .LinearVelocity = projectileAngle.ToVec() * velocity; projectile.Transform.LocalRotation = projectileAngle + MathHelper.PiOver2; @@ -405,7 +405,7 @@ namespace Content.Server.GameObjects.Components.Weapon.Ranged.Barrels private void FireHitscan(IEntity shooter, HitscanComponent hitscan, Angle angle) { var ray = new CollisionRay(Owner.Transform.Coordinates.ToMapPos(Owner.EntityManager), angle.ToVec(), (int) hitscan.CollisionMask); - var physicsManager = IoCManager.Resolve(); + var physicsManager = EntitySystem.Get(); var rayCastResults = physicsManager.IntersectRay(Owner.Transform.MapID, ray, hitscan.MaxLength, shooter, false).ToList(); if (rayCastResults.Count >= 1) diff --git a/Content.Server/GameObjects/EntitySystems/AI/Pathfinding/Accessible/AiReachableSystem.cs b/Content.Server/GameObjects/EntitySystems/AI/Pathfinding/Accessible/AiReachableSystem.cs index 77fc851348..63a04778b8 100644 --- a/Content.Server/GameObjects/EntitySystems/AI/Pathfinding/Accessible/AiReachableSystem.cs +++ b/Content.Server/GameObjects/EntitySystems/AI/Pathfinding/Accessible/AiReachableSystem.cs @@ -6,10 +6,13 @@ using Content.Shared.AI; using Content.Shared.GameTicking; using JetBrains.Annotations; using Robust.Server.GameObjects; +using Robust.Server.Player; using Robust.Shared.GameObjects; using Robust.Shared.IoC; using Robust.Shared.Map; using Robust.Shared.Maths; +using Robust.Shared.Physics; +using Robust.Shared.Players; using Robust.Shared.Timing; using Robust.Shared.Utility; @@ -73,6 +76,7 @@ namespace Content.Server.GameObjects.EntitySystems.AI.Pathfinding.Accessible private readonly List _queuedCacheDeletions = new(); #if DEBUG + private HashSet _subscribedSessions = new(); private int _runningCacheIdx = 0; #endif @@ -81,7 +85,8 @@ namespace Content.Server.GameObjects.EntitySystems.AI.Pathfinding.Accessible _pathfindingSystem = Get(); SubscribeLocalEvent(RecalculateNodeRegions); #if DEBUG - SubscribeLocalEvent(SendDebugMessage); + SubscribeNetworkEvent(HandleSubscription); + SubscribeNetworkEvent(HandleUnsubscription); #endif _mapManager.OnGridRemoved += GridRemoved; } @@ -99,8 +104,9 @@ namespace Content.Server.GameObjects.EntitySystems.AI.Pathfinding.Accessible GenerateRegions(chunk); } + // TODO: Only send diffs instead #if DEBUG - if (_queuedUpdates.Count > 0) + if (_subscribedSessions.Count > 0 && _queuedUpdates.Count > 0) { foreach (var (gridId, regs) in _regions) { @@ -129,8 +135,28 @@ namespace Content.Server.GameObjects.EntitySystems.AI.Pathfinding.Accessible _cachedAccessible.Clear(); _queuedCacheDeletions.Clear(); _mapManager.OnGridRemoved -= GridRemoved; + UnsubscribeLocalEvent(); + UnsubscribeLocalEvent(); + UnsubscribeNetworkEvent(); + UnsubscribeNetworkEvent(); } +#if DEBUG + private void HandleSubscription(SharedAiDebug.SubscribeReachableMessage message, EntitySessionEventArgs eventArgs) + { + _subscribedSessions.Add((IPlayerSession) eventArgs.SenderSession); + foreach (var (gridId, _) in _regions) + { + SendRegionsDebugMessage(gridId); + } + } + + private void HandleUnsubscription(SharedAiDebug.UnsubscribeReachableMessage message, EntitySessionEventArgs eventArgs) + { + _subscribedSessions.Remove((IPlayerSession) eventArgs.SenderSession); + } +#endif + private void RecalculateNodeRegions(PathfindingChunkUpdateMessage message) { // TODO: Only need to do changed nodes ideally @@ -154,7 +180,7 @@ namespace Content.Server.GameObjects.EntitySystems.AI.Pathfinding.Accessible var targetNode = _pathfindingSystem.GetNode(targetTile); var collisionMask = 0; - if (entity.TryGetComponent(out IPhysicsComponent physics)) + if (entity.TryGetComponent(out IPhysBody physics)) { collisionMask = physics.CollisionMask; } @@ -681,15 +707,9 @@ namespace Content.Server.GameObjects.EntitySystems.AI.Pathfinding.Accessible } #if DEBUG - private void SendDebugMessage(PlayerAttachSystemMessage message) - { - var playerGrid = message.Entity.Transform.GridID; - if(playerGrid.IsValid()) - SendRegionsDebugMessage(playerGrid); - } - private void SendRegionsDebugMessage(GridId gridId) { + if (_subscribedSessions.Count == 0) return; var grid = _mapManager.GetGrid(gridId); // Chunk / Regions / Nodes var debugResult = new Dictionary>>(); @@ -722,17 +742,23 @@ namespace Content.Server.GameObjects.EntitySystems.AI.Pathfinding.Accessible chunkIdx++; } - RaiseNetworkEvent(new SharedAiDebug.ReachableChunkRegionsDebugMessage(gridId, debugResult)); + + foreach (var session in _subscribedSessions) + { + RaiseNetworkEvent(new SharedAiDebug.ReachableChunkRegionsDebugMessage(gridId, debugResult), session.ConnectedClient); + } } /// - /// Sent whenever the reachable cache for a particular mob is built or retrieved + /// Sent whenever the reachable cache for a particular mob is built or retrieved /// /// /// /// private void SendRegionCacheMessage(GridId gridId, IEnumerable regions, bool cached) { + if (_subscribedSessions.Count == 0) return; + var grid = _mapManager.GetGrid(gridId); var debugResult = new Dictionary>(); @@ -750,7 +776,10 @@ namespace Content.Server.GameObjects.EntitySystems.AI.Pathfinding.Accessible _runningCacheIdx++; } - RaiseNetworkEvent(new SharedAiDebug.ReachableCacheDebugMessage(gridId, debugResult, cached)); + foreach (var session in _subscribedSessions) + { + RaiseNetworkEvent(new SharedAiDebug.ReachableCacheDebugMessage(gridId, debugResult, cached), session.ConnectedClient); + } } #endif } diff --git a/Content.Server/GameObjects/EntitySystems/AI/Pathfinding/Accessible/ReachableArgs.cs b/Content.Server/GameObjects/EntitySystems/AI/Pathfinding/Accessible/ReachableArgs.cs index 6cedbf3176..8d16f59d5f 100644 --- a/Content.Server/GameObjects/EntitySystems/AI/Pathfinding/Accessible/ReachableArgs.cs +++ b/Content.Server/GameObjects/EntitySystems/AI/Pathfinding/Accessible/ReachableArgs.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using Content.Server.GameObjects.Components.Access; using Content.Server.GameObjects.Components.Movement; using Robust.Shared.GameObjects; +using Robust.Shared.Physics; namespace Content.Server.GameObjects.EntitySystems.AI.Pathfinding.Accessible { @@ -27,7 +28,7 @@ namespace Content.Server.GameObjects.EntitySystems.AI.Pathfinding.Accessible public static ReachableArgs GetArgs(IEntity entity) { var collisionMask = 0; - if (entity.TryGetComponent(out IPhysicsComponent? physics)) + if (entity.TryGetComponent(out IPhysBody? physics)) { collisionMask = physics.CollisionMask; } diff --git a/Content.Server/GameObjects/EntitySystems/AI/Pathfinding/PathfindingNode.cs b/Content.Server/GameObjects/EntitySystems/AI/Pathfinding/PathfindingNode.cs index ca371983c0..9b80c2da6b 100644 --- a/Content.Server/GameObjects/EntitySystems/AI/Pathfinding/PathfindingNode.cs +++ b/Content.Server/GameObjects/EntitySystems/AI/Pathfinding/PathfindingNode.cs @@ -6,6 +6,7 @@ using Content.Server.GameObjects.Components.Doors; using Robust.Shared.GameObjects; using Robust.Shared.Map; using Robust.Shared.Maths; +using Robust.Shared.Physics; using Robust.Shared.Utility; namespace Content.Server.GameObjects.EntitySystems.AI.Pathfinding @@ -40,7 +41,7 @@ namespace Content.Server.GameObjects.EntitySystems.AI.Pathfinding GenerateMask(); } - public static bool IsRelevant(IEntity entity, IPhysicsComponent physicsComponent) + public static bool IsRelevant(IEntity entity, IPhysBody physicsComponent) { if (entity.Transform.GridID == GridId.Invalid || (PathfindingSystem.TrackedCollisionLayers & physicsComponent.CollisionLayer) == 0) @@ -256,7 +257,7 @@ namespace Content.Server.GameObjects.EntitySystems.AI.Pathfinding /// /// TODO: These 2 methods currently don't account for a bunch of changes (e.g. airlock unpowered, wrenching, etc.) /// TODO: Could probably optimise this slightly more. - public void AddEntity(IEntity entity, IPhysicsComponent physicsComponent) + public void AddEntity(IEntity entity, IPhysBody physicsComponent) { // If we're a door if (entity.HasComponent() || entity.HasComponent()) @@ -275,7 +276,7 @@ namespace Content.Server.GameObjects.EntitySystems.AI.Pathfinding DebugTools.Assert((PathfindingSystem.TrackedCollisionLayers & physicsComponent.CollisionLayer) != 0); - if (!physicsComponent.Anchored) + if (physicsComponent.BodyType == BodyType.Static) { _physicsLayers.Add(entity, physicsComponent.CollisionLayer); } diff --git a/Content.Server/GameObjects/EntitySystems/AI/Pathfinding/PathfindingSystem.cs b/Content.Server/GameObjects/EntitySystems/AI/Pathfinding/PathfindingSystem.cs index 20f70c30e5..1077ed4fe6 100644 --- a/Content.Server/GameObjects/EntitySystems/AI/Pathfinding/PathfindingSystem.cs +++ b/Content.Server/GameObjects/EntitySystems/AI/Pathfinding/PathfindingSystem.cs @@ -11,6 +11,7 @@ using Robust.Shared.GameObjects; using Robust.Shared.IoC; using Robust.Shared.Map; using Robust.Shared.Maths; +using Robust.Shared.Physics; using Robust.Shared.Utility; namespace Content.Server.GameObjects.EntitySystems.AI.Pathfinding @@ -29,7 +30,7 @@ namespace Content.Server.GameObjects.EntitySystems.AI.Pathfinding { [Dependency] private readonly IMapManager _mapManager = default!; [Dependency] private readonly IEntityManager _entityManager = default!; - + public IReadOnlyDictionary> Graph => _graph; private readonly Dictionary> _graph = new(); @@ -81,7 +82,8 @@ namespace Content.Server.GameObjects.EntitySystems.AI.Pathfinding foreach (var update in _collidableUpdateQueue) { - var entity = EntityManager.GetEntity(update.Owner); + if (!EntityManager.TryGetEntity(update.Owner, out var entity)) continue; + if (update.CanCollide) { HandleEntityAdd(entity); @@ -262,7 +264,7 @@ namespace Content.Server.GameObjects.EntitySystems.AI.Pathfinding { if (entity.Deleted || _lastKnownPositions.ContainsKey(entity) || - !entity.TryGetComponent(out IPhysicsComponent physics) || + !entity.TryGetComponent(out IPhysBody physics) || !PathfindingNode.IsRelevant(entity, physics)) { return; @@ -301,7 +303,7 @@ namespace Content.Server.GameObjects.EntitySystems.AI.Pathfinding { // If we've moved to space or the likes then remove us. if (moveEvent.Sender.Deleted || - !moveEvent.Sender.TryGetComponent(out IPhysicsComponent physics) || + !moveEvent.Sender.TryGetComponent(out IPhysBody physics) || !PathfindingNode.IsRelevant(moveEvent.Sender, physics) || moveEvent.NewPosition.GetGridId(EntityManager) == GridId.Invalid) { @@ -366,7 +368,7 @@ namespace Content.Server.GameObjects.EntitySystems.AI.Pathfinding public bool CanTraverse(IEntity entity, PathfindingNode node) { - if (entity.TryGetComponent(out IPhysicsComponent physics) && + if (entity.TryGetComponent(out IPhysBody physics) && (physics.CollisionMask & node.BlockedCollisionMask) != 0) { return false; diff --git a/Content.Server/GameObjects/EntitySystems/AI/Steering/AiSteeringSystem.cs b/Content.Server/GameObjects/EntitySystems/AI/Steering/AiSteeringSystem.cs index d2de9d5fff..1bc1f50131 100644 --- a/Content.Server/GameObjects/EntitySystems/AI/Steering/AiSteeringSystem.cs +++ b/Content.Server/GameObjects/EntitySystems/AI/Steering/AiSteeringSystem.cs @@ -13,6 +13,7 @@ using Robust.Shared.GameObjects; using Robust.Shared.IoC; using Robust.Shared.Map; using Robust.Shared.Maths; +using Robust.Shared.Physics; using Robust.Shared.Timing; using Robust.Shared.Utility; using Robust.Shared.ViewVariables; @@ -413,7 +414,7 @@ namespace Content.Server.GameObjects.EntitySystems.AI.Steering var startTile = gridManager.GetTileRef(entity.Transform.Coordinates); var endTile = gridManager.GetTileRef(steeringRequest.TargetGrid); var collisionMask = 0; - if (entity.TryGetComponent(out IPhysicsComponent physics)) + if (entity.TryGetComponent(out IPhysBody physics)) { collisionMask = physics.CollisionMask; } @@ -599,7 +600,7 @@ namespace Content.Server.GameObjects.EntitySystems.AI.Steering return Vector2.Zero; } - if (target.TryGetComponent(out IPhysicsComponent physics)) + if (target.TryGetComponent(out IPhysBody physics)) { var targetDistance = (targetPos.Position - entityPos.Position); targetPos = targetPos.Offset(physics.LinearVelocity * targetDistance); @@ -617,7 +618,7 @@ namespace Content.Server.GameObjects.EntitySystems.AI.Steering /// private Vector2 CollisionAvoidance(IEntity entity, Vector2 direction, ICollection ignoredTargets) { - if (direction == Vector2.Zero || !entity.TryGetComponent(out IPhysicsComponent physics)) + if (direction == Vector2.Zero || !entity.TryGetComponent(out IPhysBody physics)) { return Vector2.Zero; } @@ -658,7 +659,7 @@ namespace Content.Server.GameObjects.EntitySystems.AI.Steering // if we're moving in the same direction then ignore // So if 2 entities are moving towards each other and both detect a collision they'll both move in the same direction // i.e. towards the right - if (physicsEntity.TryGetComponent(out IPhysicsComponent otherPhysics) && + if (physicsEntity.TryGetComponent(out IPhysBody otherPhysics) && Vector2.Dot(otherPhysics.LinearVelocity, direction) > 0) { continue; diff --git a/Content.Server/GameObjects/EntitySystems/Click/InteractionSystem.cs b/Content.Server/GameObjects/EntitySystems/Click/InteractionSystem.cs index 7aa6d396b2..c6fe49f378 100644 --- a/Content.Server/GameObjects/EntitySystems/Click/InteractionSystem.cs +++ b/Content.Server/GameObjects/EntitySystems/Click/InteractionSystem.cs @@ -1,4 +1,5 @@ -using System; +using System; +using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Content.Server.GameObjects.Components.Items.Storage; @@ -25,6 +26,7 @@ using Robust.Shared.IoC; using Robust.Shared.Log; using Robust.Shared.Map; using Robust.Shared.Maths; +using Robust.Shared.Physics; using Robust.Shared.Players; namespace Content.Server.GameObjects.EntitySystems.Click @@ -568,61 +570,12 @@ namespace Content.Server.GameObjects.EntitySystems.Click } var comps = thrown.GetAllComponents().ToList(); + var args = new ThrownEventArgs(user); // Call Thrown on all components that implement the interface foreach (var comp in comps) { - comp.Thrown(new ThrownEventArgs(user)); - } - } - - /// - /// Calls Land on all components that implement the ILand interface - /// on an entity that has landed after being thrown. - /// - public void LandInteraction(IEntity user, IEntity landing, EntityCoordinates landLocation) - { - var landMsg = new LandMessage(user, landing, landLocation); - RaiseLocalEvent(landMsg); - if (landMsg.Handled) - { - return; - } - - var comps = landing.GetAllComponents().ToList(); - - // Call Land on all components that implement the interface - foreach (var comp in comps) - { - comp.Land(new LandEventArgs(user, landLocation)); - } - } - - /// - /// Calls ThrowCollide on all components that implement the IThrowCollide interface - /// on a thrown entity and the target entity it hit. - /// - public void ThrowCollideInteraction(IEntity user, IEntity thrown, IEntity target, EntityCoordinates location) - { - var collideMsg = new ThrowCollideMessage(user, thrown, target, location); - RaiseLocalEvent(collideMsg); - if (collideMsg.Handled) - { - return; - } - - var eventArgs = new ThrowCollideEventArgs(user, thrown, target, location); - - foreach (var comp in thrown.GetAllComponents().ToArray()) - { - if (thrown.Deleted) break; - comp.DoHit(eventArgs); - } - - foreach (var comp in target.GetAllComponents().ToArray()) - { - if (target.Deleted) break; - comp.HitBy(eventArgs); + comp.Thrown(args); } } diff --git a/Content.Server/GameObjects/EntitySystems/ClimbSystem.cs b/Content.Server/GameObjects/EntitySystems/ClimbSystem.cs index 7036b5acae..69bbc1b033 100644 --- a/Content.Server/GameObjects/EntitySystems/ClimbSystem.cs +++ b/Content.Server/GameObjects/EntitySystems/ClimbSystem.cs @@ -1,18 +1,39 @@ -using Content.Server.GameObjects.Components.Movement; +using System.Collections.Generic; +using System.Linq; +using Content.Server.GameObjects.Components.Movement; +using Content.Shared.GameObjects.Components.Movement; +using Content.Shared.GameTicking; using JetBrains.Annotations; using Robust.Shared.GameObjects; namespace Content.Server.GameObjects.EntitySystems { [UsedImplicitly] - internal sealed class ClimbSystem : EntitySystem + internal sealed class ClimbSystem : EntitySystem, IResettingEntitySystem { + private readonly HashSet _activeClimbers = new(); + + public void AddActiveClimber(ClimbingComponent climbingComponent) + { + _activeClimbers.Add(climbingComponent); + } + + public void RemoveActiveClimber(ClimbingComponent climbingComponent) + { + _activeClimbers.Remove(climbingComponent); + } + public override void Update(float frameTime) { - foreach (var comp in ComponentManager.EntityQuery(true)) + foreach (var climber in _activeClimbers.ToArray()) { - comp.Update(); + climber.Update(); } } + + public void Reset() + { + _activeClimbers.Clear(); + } } } diff --git a/Content.Server/GameObjects/EntitySystems/ConveyorSystem.cs b/Content.Server/GameObjects/EntitySystems/ConveyorSystem.cs deleted file mode 100644 index 265606c1e0..0000000000 --- a/Content.Server/GameObjects/EntitySystems/ConveyorSystem.cs +++ /dev/null @@ -1,18 +0,0 @@ -using Content.Server.GameObjects.Components.Conveyor; -using JetBrains.Annotations; -using Robust.Shared.GameObjects; - -namespace Content.Server.GameObjects.EntitySystems -{ - [UsedImplicitly] - internal sealed class ConveyorSystem : EntitySystem - { - public override void Update(float frameTime) - { - foreach (var comp in ComponentManager.EntityQuery(true)) - { - comp.Update(frameTime); - } - } - } -} diff --git a/Content.Server/GameObjects/EntitySystems/HandsSystem.cs b/Content.Server/GameObjects/EntitySystems/HandsSystem.cs index ed63ede681..0c2ac9802e 100644 --- a/Content.Server/GameObjects/EntitySystems/HandsSystem.cs +++ b/Content.Server/GameObjects/EntitySystems/HandsSystem.cs @@ -1,11 +1,11 @@ using System; using System.Linq; using Content.Server.GameObjects.Components.GUI; +using Content.Server.GameObjects.Components.Items; using Content.Server.GameObjects.Components.Items.Storage; using Content.Server.GameObjects.Components.Stack; using Content.Server.GameObjects.EntitySystems.Click; using Content.Server.Interfaces.GameObjects.Components.Items; -using Content.Server.Throw; using Content.Shared.GameObjects.EntitySystems; using Content.Shared.Input; using Content.Shared.Interfaces; @@ -145,12 +145,12 @@ namespace Content.Server.GameObjects.EntitySystems private bool HandleThrowItem(ICommonSession session, EntityCoordinates coords, EntityUid uid) { - var plyEnt = ((IPlayerSession)session).AttachedEntity; + var playerEnt = ((IPlayerSession)session).AttachedEntity; - if (plyEnt == null || !plyEnt.IsValid()) + if (playerEnt == null || !playerEnt.IsValid()) return false; - if (!plyEnt.TryGetComponent(out HandsComponent handsComp)) + if (!playerEnt.TryGetComponent(out HandsComponent handsComp)) return false; if (!handsComp.CanDrop(handsComp.ActiveHand)) @@ -169,14 +169,19 @@ namespace Content.Server.GameObjects.EntitySystems else { stackComp.Use(1); - throwEnt = throwEnt.EntityManager.SpawnEntity(throwEnt.Prototype.ID, plyEnt.Transform.Coordinates); + throwEnt = throwEnt.EntityManager.SpawnEntity(throwEnt.Prototype.ID, playerEnt.Transform.Coordinates); // can only throw one item at a time, regardless of what the prototype stack size is. if (throwEnt.TryGetComponent(out var newStackComp)) newStackComp.Count = 1; } - throwEnt.ThrowTo(ThrowForce, coords, plyEnt.Transform.Coordinates, false, plyEnt); + var direction = coords.ToMapPos(EntityManager) - playerEnt.Transform.WorldPosition; + if (direction == Vector2.Zero) return true; + + direction = direction.Normalized * MathF.Min(direction.Length, 8.0f); + + throwEnt.TryThrow(direction * ThrowForce * 15, playerEnt); return true; } diff --git a/Content.Server/GameObjects/EntitySystems/Power/PowerSolarSystem.cs b/Content.Server/GameObjects/EntitySystems/Power/PowerSolarSystem.cs index fee28a0de7..862e9466af 100644 --- a/Content.Server/GameObjects/EntitySystems/Power/PowerSolarSystem.cs +++ b/Content.Server/GameObjects/EntitySystems/Power/PowerSolarSystem.cs @@ -8,6 +8,7 @@ using Robust.Shared.GameObjects; using Robust.Shared.IoC; using Robust.Shared.Maths; using Robust.Shared.Physics; +using Robust.Shared.Physics.Broadphase; using Robust.Shared.Random; using Robust.Shared.Timing; @@ -137,7 +138,7 @@ namespace Content.Server.GameObjects.EntitySystems // Determine if the solar panel is occluded, and zero out coverage if so. // FIXME: The "Opaque" collision group doesn't seem to work right now. var ray = new CollisionRay(entity.Transform.WorldPosition, TowardsSun.ToVec(), (int) CollisionGroup.Opaque); - var rayCastResults = IoCManager.Resolve().IntersectRay(entity.Transform.MapID, ray, SunOcclusionCheckDistance, entity); + var rayCastResults = EntitySystem.Get().IntersectRay(entity.Transform.MapID, ray, SunOcclusionCheckDistance, entity); if (rayCastResults.Any()) coverage = 0; } diff --git a/Content.Server/GameObjects/EntitySystems/RecyclerSystem.cs b/Content.Server/GameObjects/EntitySystems/RecyclerSystem.cs deleted file mode 100644 index 22e5eb4c17..0000000000 --- a/Content.Server/GameObjects/EntitySystems/RecyclerSystem.cs +++ /dev/null @@ -1,18 +0,0 @@ -using Content.Server.GameObjects.Components.Recycling; -using JetBrains.Annotations; -using Robust.Shared.GameObjects; - -namespace Content.Server.GameObjects.EntitySystems -{ - [UsedImplicitly] - internal sealed class RecyclerSystem : EntitySystem - { - public override void Update(float frameTime) - { - foreach (var component in ComponentManager.EntityQuery(true)) - { - component.Update(frameTime); - } - } - } -} diff --git a/Content.Server/GameObjects/EntitySystems/SingularitySystem.cs b/Content.Server/GameObjects/EntitySystems/SingularitySystem.cs index d0983f55aa..bd29f6deff 100644 --- a/Content.Server/GameObjects/EntitySystems/SingularitySystem.cs +++ b/Content.Server/GameObjects/EntitySystems/SingularitySystem.cs @@ -7,36 +7,21 @@ namespace Content.Server.GameObjects.EntitySystems [UsedImplicitly] public class SingularitySystem : EntitySystem { - private float curTimeSingulo; - private float curTimePull; + private float _accumulator; public override void Update(float frameTime) { base.Update(frameTime); - curTimeSingulo += frameTime; - curTimePull += frameTime; + _accumulator += frameTime; - var shouldUpdate = curTimeSingulo >= 1f; - var shouldPull = curTimePull >= 0.2f; - if (!shouldUpdate && !shouldPull) return; - var singulos = ComponentManager.EntityQuery(true); - - if (curTimeSingulo >= 1f) + while (_accumulator > 1.0f) { - curTimeSingulo -= 1f; - foreach (var singulo in singulos) - { - singulo.Update(); - } - } + _accumulator -= 1.0f; - if (curTimePull >= 0.5f) - { - curTimePull -= 0.5f; - foreach (var singulo in singulos) + foreach (var singularity in ComponentManager.EntityQuery()) { - singulo.PullUpdate(); + singularity.Update(1); } } } diff --git a/Content.Server/Physics/Controllers/ConveyorController.cs b/Content.Server/Physics/Controllers/ConveyorController.cs new file mode 100644 index 0000000000..88a53b6f18 --- /dev/null +++ b/Content.Server/Physics/Controllers/ConveyorController.cs @@ -0,0 +1,118 @@ +#nullable enable +using System; +using System.Collections.Generic; +using Content.Server.GameObjects.Components.Conveyor; +using Content.Server.GameObjects.Components.Recycling; +using Content.Shared.GameObjects.Components.Movement; +using Robust.Shared.GameObjects; +using Robust.Shared.Maths; +using Robust.Shared.Physics; +using Robust.Shared.Physics.Controllers; + +namespace Content.Server.Physics.Controllers +{ + internal sealed class ConveyorController : VirtualController + { + public override List UpdatesAfter => new() {typeof(MoverController)}; + + public override void UpdateBeforeSolve(bool prediction, float frameTime) + { + base.UpdateBeforeSolve(prediction, frameTime); + foreach (var comp in ComponentManager.EntityQuery()) + { + Convey(comp, frameTime); + } + + // TODO: Uhh you can probably wrap the recycler's conveying properties into... conveyor + foreach (var comp in ComponentManager.EntityQuery()) + { + ConveyRecycler(comp, frameTime); + } + } + + private void Convey(ConveyorComponent comp, float frameTime) + { + // TODO: Use ICollideBehavior and cache intersecting + // Use an event for conveyors to know what needs to run + if (!comp.CanRun()) + { + return; + } + + var intersecting = EntityManager.GetEntitiesIntersecting(comp.Owner, true); + var direction = comp.GetAngle().ToVec(); + Vector2? ownerPos = null; + + foreach (var entity in intersecting) + { + if (!comp.CanMove(entity)) continue; + + if (!entity.TryGetComponent(out IPhysBody? physics) || physics.BodyStatus == BodyStatus.InAir || + entity.IsWeightless()) continue; + + ownerPos ??= comp.Owner.Transform.WorldPosition; + var itemRelativeToConveyor = entity.Transform.WorldPosition - ownerPos.Value; + + physics.LinearVelocity += Convey(direction * comp.Speed, frameTime, itemRelativeToConveyor); + } + } + + // TODO Uhhh I did a shit job plz fix smug + private Vector2 Convey(Vector2 velocityDirection, float frameTime, Vector2 itemRelativeToConveyor) + { + //gravitating item towards center + //http://csharphelper.com/blog/2016/09/find-the-shortest-distance-between-a-point-and-a-line-segment-in-c/ + Vector2 centerPoint; + + var t = 0f; + if (velocityDirection.Length > 0) // if velocitydirection is 0, this calculation will divide by 0 + { + t = Vector2.Dot(itemRelativeToConveyor, velocityDirection) / + Vector2.Dot(velocityDirection, velocityDirection); + } + + if (t < 0) + { + centerPoint = new Vector2(); + } + else if (t > 1) + { + centerPoint = velocityDirection; + } + else + { + centerPoint = velocityDirection * t; + } + + var delta = centerPoint - itemRelativeToConveyor; + return delta * (400 * delta.Length) * frameTime; + } + + private void ConveyRecycler(RecyclerComponent comp, float frameTime) + { + if (!comp.CanRun()) + { + comp.Intersecting.Clear(); + return; + } + + var direction = Vector2.UnitX; + Vector2? ownerPos = null; + + for (var i = comp.Intersecting.Count - 1; i >= 0; i--) + { + var entity = comp.Intersecting[i]; + + if (entity.Deleted || !comp.CanMove(entity) || !EntityManager.IsIntersecting(comp.Owner, entity)) + { + comp.Intersecting.RemoveAt(i); + continue; + } + + if (!entity.TryGetComponent(out IPhysBody? physics)) continue; + ownerPos ??= comp.Owner.Transform.WorldPosition; + physics.LinearVelocity += Convey(direction, frameTime, entity.Transform.WorldPosition - ownerPos.Value); + } + } + } +} diff --git a/Content.Server/GameObjects/EntitySystems/MoverSystem.cs b/Content.Server/Physics/Controllers/MoverController.cs similarity index 55% rename from Content.Server/GameObjects/EntitySystems/MoverSystem.cs rename to Content.Server/Physics/Controllers/MoverController.cs index 5e9097f039..177c419357 100644 --- a/Content.Server/GameObjects/EntitySystems/MoverSystem.cs +++ b/Content.Server/Physics/Controllers/MoverController.cs @@ -1,15 +1,17 @@ #nullable enable +using System.Collections.Generic; using Content.Server.GameObjects.Components.GUI; using Content.Server.GameObjects.Components.Items.Storage; using Content.Server.GameObjects.Components.Mobs; +using Content.Server.GameObjects.Components.Movement; using Content.Server.GameObjects.Components.Sound; using Content.Shared.Audio; using Content.Shared.GameObjects.Components.Inventory; using Content.Shared.GameObjects.Components.Movement; using Content.Shared.GameObjects.Components.Tag; -using Content.Shared.GameObjects.EntitySystems; using Content.Shared.Maps; using Content.Shared.Physics; +using Content.Shared.Physics.Controllers; using JetBrains.Annotations; using Robust.Server.GameObjects; using Robust.Shared.Audio; @@ -17,13 +19,15 @@ using Robust.Shared.GameObjects; using Robust.Shared.IoC; using Robust.Shared.Log; using Robust.Shared.Map; +using Robust.Shared.Maths; +using Robust.Shared.Physics; +using Robust.Shared.Physics.Dynamics; using Robust.Shared.Prototypes; using Robust.Shared.Random; -namespace Content.Server.GameObjects.EntitySystems +namespace Content.Server.Physics.Controllers { - [UsedImplicitly] - internal class MoverSystem : SharedMoverSystem + public class MoverController : SharedMoverController { [Dependency] private readonly IPrototypeManager _prototypeManager = default!; [Dependency] private readonly ITileDefinitionManager _tileDefinitionManager = default!; @@ -35,54 +39,83 @@ namespace Content.Server.GameObjects.EntitySystems private const float StepSoundMoveDistanceRunning = 2; private const float StepSoundMoveDistanceWalking = 1.5f; - /// + private HashSet _excludedMobs = new(); + public override void Initialize() { base.Initialize(); - SubscribeLocalEvent(PlayerDetached); - - _audioSystem = EntitySystemManager.GetEntitySystem(); - - UpdatesBefore.Add(typeof(PhysicsSystem)); + _audioSystem = EntitySystem.Get(); } - public override void Update(float frameTime) + public override void UpdateBeforeSolve(bool prediction, float frameTime) { - foreach (var (moverComponent, collidableComponent) in EntityManager.ComponentManager - .EntityQuery(false)) + base.UpdateBeforeSolve(prediction, frameTime); + _excludedMobs.Clear(); + + foreach (var (mobMover, mover, physics) in ComponentManager.EntityQuery()) { - var entity = moverComponent.Owner; - UpdateKinematics(entity.Transform, moverComponent, collidableComponent); + _excludedMobs.Add(mover.Owner.Uid); + HandleMobMovement(mover, physics, mobMover); + } + + foreach (var mover in ComponentManager.EntityQuery()) + { + _excludedMobs.Add(mover.Owner.Uid); + HandleShuttleMovement(mover); + } + + foreach (var (mover, physics) in ComponentManager.EntityQuery(true)) + { + if (_excludedMobs.Contains(mover.Owner.Uid)) continue; + + HandleKinematicMovement(mover, physics); } } - private void PlayerDetached(PlayerDetachedSystemMessage ev) + /* + * Some thoughts: + * Unreal actually doesn't predict vehicle movement at all, it's purely server-side which I thought was interesting + * The reason for this is that vehicles change direction very slowly compared to players so you don't really have the requirement for quick movement anyway + * As such could probably just look at applying a force / impulse to the shuttle server-side only so it controls like the titanic. + */ + private void HandleShuttleMovement(ShuttleControllerComponent mover) { - if (ev.Entity.TryGetComponent(out IPhysicsComponent? physics) && - physics.TryGetController(out MoverController controller) && - !ev.Entity.IsWeightless()) + var gridId = mover.Owner.Transform.GridID; + + if (!_mapManager.TryGetGrid(gridId, out var grid) || !EntityManager.TryGetEntity(grid.GridEntityId, out var gridEntity)) return; + + //TODO: Switch to shuttle component + if (!gridEntity.TryGetComponent(out PhysicsComponent? physics)) { - controller.StopMoving(); + physics = gridEntity.AddComponent(); + physics.BodyStatus = BodyStatus.InAir; + physics.Mass = 1; + physics.CanCollide = true; + physics.AddFixture(new Fixture(physics, new PhysShapeGrid(grid))); } + + // TODO: Uhh this probably doesn't work but I still need to rip out the entity tree and make RenderingTreeSystem use grids so I'm not overly concerned about breaking shuttles. + physics.ApplyForce(mover.VelocityDir.walking + mover.VelocityDir.sprinting); + mover.VelocityDir = (Vector2.Zero, Vector2.Zero); } - protected override void HandleFootsteps(IMoverComponent mover) + protected override void HandleFootsteps(IMoverComponent mover, IMobMoverComponent mobMover) { var transform = mover.Owner.Transform; // Handle footsteps. - if (_mapManager.GridExists(mover.LastPosition.GetGridId(EntityManager))) + if (_mapManager.GridExists(mobMover.LastPosition.GetGridId(EntityManager))) { // Can happen when teleporting between grids. - if (!transform.Coordinates.TryDistance(EntityManager, mover.LastPosition, out var distance)) + if (!transform.Coordinates.TryDistance(EntityManager, mobMover.LastPosition, out var distance)) { - mover.LastPosition = transform.Coordinates; + mobMover.LastPosition = transform.Coordinates; return; } - mover.StepSoundDistance += distance; + mobMover.StepSoundDistance += distance; } - mover.LastPosition = transform.Coordinates; + mobMover.LastPosition = transform.Coordinates; float distanceNeeded; if (mover.Sprinting) { @@ -93,11 +126,11 @@ namespace Content.Server.GameObjects.EntitySystems distanceNeeded = StepSoundMoveDistanceWalking; } - if (mover.StepSoundDistance > distanceNeeded) + if (mobMover.StepSoundDistance > distanceNeeded) { - mover.StepSoundDistance = 0; + mobMover.StepSoundDistance = 0; - if (!mover.Owner.HasTag("FootstepSound")) + if (!mover.Owner.HasTag("FootstepSound") || mover.Owner.Transform.GridID == GridId.Invalid) { return; } @@ -110,13 +143,14 @@ namespace Content.Server.GameObjects.EntitySystems } else { - PlayFootstepSound(transform.Coordinates, mover.Sprinting); + PlayFootstepSound(mover.Owner, mover.Sprinting); } } } - private void PlayFootstepSound(EntityCoordinates coordinates, bool sprinting) + private void PlayFootstepSound(IEntity mover, bool sprinting) { + var coordinates = mover.Transform.Coordinates; // Step one: figure out sound collection prototype. var grid = _mapManager.GetGrid(coordinates.GetGridId(EntityManager)); var tile = grid.GetTileRef(coordinates); @@ -159,5 +193,6 @@ namespace Content.Server.GameObjects.EntitySystems Logger.ErrorS("sound", $"Unable to find sound collection for {soundCollectionName}"); } } + } } diff --git a/Content.Server/Physics/Controllers/SingularityController.cs b/Content.Server/Physics/Controllers/SingularityController.cs new file mode 100644 index 0000000000..9a0a6a1b86 --- /dev/null +++ b/Content.Server/Physics/Controllers/SingularityController.cs @@ -0,0 +1,106 @@ +#nullable enable +using Content.Server.GameObjects.Components.Observer; +using Content.Server.GameObjects.Components.Singularity; +using Robust.Server.GameObjects; +using Robust.Shared.GameObjects; +using Robust.Shared.IoC; +using Robust.Shared.Map; +using Robust.Shared.Maths; +using Robust.Shared.Physics; +using Robust.Shared.Physics.Broadphase; +using Robust.Shared.Physics.Controllers; +using Robust.Shared.Random; + +namespace Content.Server.Physics.Controllers +{ + internal sealed class SingularityController : VirtualController + { + [Dependency] private readonly IMapManager _mapManager = default!; + [Dependency] private readonly IRobustRandom _robustRandom = default!; + + private float _pullAccumulator; + private float _moveAccumulator; + + public override void UpdateBeforeSolve(bool prediction, float frameTime) + { + base.UpdateBeforeSolve(prediction, frameTime); + + _moveAccumulator += frameTime; + _pullAccumulator += frameTime; + + while (_pullAccumulator > 0.5f) + { + _pullAccumulator -= 0.5f; + + foreach (var singularity in ComponentManager.EntityQuery()) + { + // TODO: Use colliders instead probably yada yada + PullEntities(singularity); + // Yeah look the collision with station wasn't working and I'm 15k lines in and not debugging this shit + DestroyTiles(singularity); + } + } + + while (_moveAccumulator > 1.0f) + { + _moveAccumulator -= 1.0f; + + foreach (var (singularity, physics) in ComponentManager.EntityQuery()) + { + if (singularity.Owner.HasComponent()) continue; + + // TODO: Need to essentially use a push vector in a random direction for us PLUS + // Any entity colliding with our larger circlebox needs to have an impulse applied to itself. + physics.BodyStatus = BodyStatus.InAir; + MoveSingulo(singularity, physics); + } + } + } + + private void MoveSingulo(SingularityComponent singularity, PhysicsComponent physics) + { + if (singularity.Level <= 1) return; + // TODO: Could try gradual changes instead but for now just try to replicate + + var pushVector = new Vector2(_robustRandom.Next(-10, 10), _robustRandom.Next(-10, 10)); + + if (pushVector == Vector2.Zero) return; + + physics.LinearVelocity = Vector2.Zero; + physics.LinearVelocity = pushVector.Normalized * 2; + } + + private void PullEntities(SingularityComponent component) + { + var singularityCoords = component.Owner.Transform.Coordinates; + // TODO: Maybe if we have named fixtures needs to pull out the outer circle collider (inner will be for deleting). + var entitiesToPull = EntityManager.GetEntitiesInRange(singularityCoords, component.Level * 10); + foreach (var entity in entitiesToPull) + { + if (!entity.TryGetComponent(out var collidableComponent) || collidableComponent.BodyType == BodyType.Static) continue; + if (entity.HasComponent()) continue; + if (singularityCoords.EntityId != entity.Transform.Coordinates.EntityId) continue; + var vec = (singularityCoords - entity.Transform.Coordinates).Position; + if (vec == Vector2.Zero) continue; + + var speed = 10 / vec.Length * component.Level; + + collidableComponent.ApplyLinearImpulse(vec.Normalized * speed); + } + } + + private void DestroyTiles(SingularityComponent component) + { + if (!component.Owner.TryGetComponent(out PhysicsComponent? physicsComponent)) return; + var worldBox = physicsComponent.GetWorldAABB(); + + foreach (var grid in _mapManager.FindGridsIntersecting(component.Owner.Transform.MapID, worldBox)) + { + foreach (var tile in grid.GetTilesIntersecting(worldBox)) + { + grid.SetTile(tile.GridIndices, Tile.Empty); + } + } + } + } +} diff --git a/Content.Server/Throw/ThrowHelper.cs b/Content.Server/Throw/ThrowHelper.cs deleted file mode 100644 index ede0856ef6..0000000000 --- a/Content.Server/Throw/ThrowHelper.cs +++ /dev/null @@ -1,156 +0,0 @@ -using System; -using Content.Server.GameObjects.Components.Projectiles; -using Content.Shared.GameObjects.Components.Movement; -using Content.Shared.GameObjects.EntitySystems.ActionBlocker; -using Content.Shared.Physics; -using Robust.Shared.GameObjects; -using Robust.Shared.IoC; -using Robust.Shared.Map; -using Robust.Shared.Maths; -using Robust.Shared.Physics; -using Robust.Shared.Random; -using Robust.Shared.Timing; - -namespace Content.Server.Throw -{ - public static class ThrowHelper - { - /// - /// Throw an entity in the direction of from . - /// - /// The entity to throw. - /// - /// The force to throw the entity with. - /// Total impulse applied is equal to this force applied for one second. - /// - /// - /// The target location to throw at. - /// This is only used to calculate a direction, - /// actual distance is purely determined by . - /// - /// - /// The position to start the throw from. - /// - /// - /// If true, slightly spread the actual throw angle. - /// - /// - /// The entity that did the throwing. An opposite impulse will be applied to this entity if passed in. - /// - public static void Throw(this IEntity thrownEnt, float throwForce, EntityCoordinates targetLoc, EntityCoordinates sourceLoc, bool spread = false, IEntity throwSourceEnt = null) - { - if (thrownEnt.Deleted) - { - return; - } - - if (!thrownEnt.TryGetComponent(out IPhysicsComponent colComp)) - return; - - var entityManager = IoCManager.Resolve(); - var direction_vector = targetLoc.ToMapPos(entityManager) - sourceLoc.ToMapPos(entityManager); - - if (direction_vector.Length == 0) - { - return; - } - - colComp.CanCollide = true; - // I can now collide with player, so that i can do damage. - - if (!thrownEnt.TryGetComponent(out ThrownItemComponent projComp)) - { - projComp = thrownEnt.AddComponent(); - - if (colComp.PhysicsShapes.Count == 0) - colComp.PhysicsShapes.Add(new PhysShapeAabb()); - - colComp.PhysicsShapes[0].CollisionMask |= (int) CollisionGroup.ThrownItem; - colComp.Status = BodyStatus.InAir; - } - - var angle = new Angle(direction_vector); - if (spread) - { - var spreadRandom = IoCManager.Resolve(); - angle += Angle.FromDegrees(spreadRandom.NextGaussian(0, 3)); - } - - if (throwSourceEnt != null) - { - projComp.User = throwSourceEnt; - projComp.IgnoreEntity(throwSourceEnt); - - if (ActionBlockerSystem.CanChangeDirection(throwSourceEnt)) - { - throwSourceEnt.Transform.LocalRotation = (angle + MathHelper.PiOver2).GetCardinalDir().ToAngle(); - } - } - - // scaling is handled elsewhere, this is just multiplying by 60 independent of timing as a fix until elsewhere values are updated - var spd = throwForce * 60; - - projComp.StartThrow(angle.ToVec(), spd); - - if (throwSourceEnt != null && - throwSourceEnt.TryGetComponent(out var physics)) - { - if (throwSourceEnt.IsWeightless()) - { - // We don't check for surrounding entities, - // so you'll still get knocked around if you're hugging the station wall in zero g. - // I got kinda lazy is the reason why. Also it makes a bit of sense. - // If somebody wants they can come along and make it so magboots completely hold you still. - // Would be a cool incentive to use them. - const float throwFactor = 0.2f; // Break Newton's Third Law for better gameplay - var mover = physics.EnsureController(); - mover.Push(-angle.ToVec(), spd * throwFactor); - } - } - } - - /// - /// Throw an entity at the position of from , - /// without overshooting. - /// cl - /// The entity to throw. - /// - /// The MAXIMUM force to throw the entity with. - /// Throw force increases with distance to target, this is the maximum force allowed. - /// - /// - /// The target location to throw at. - /// This function will try to land at this exact spot, - /// if is large enough to allow for it to be reached. - /// - /// - /// The position to start the throw from. - /// - /// - /// If true, slightly spread the actual throw angle. - /// - /// - /// The entity that did the throwing. An opposite impulse will be applied to this entity if passed in. - /// - public static void ThrowTo(this IEntity thrownEnt, float throwForceMax, EntityCoordinates targetLoc, - EntityCoordinates sourceLoc, bool spread = false, IEntity throwSourceEnt = null) - { - var entityManager = IoCManager.Resolve(); - var timing = IoCManager.Resolve(); - - // Calculate the force necessary to land a throw based on throw duration, mass and distance. - if (!targetLoc.TryDistance(entityManager, sourceLoc, out var distance)) - { - return; - } - - var throwDuration = ThrownItemComponent.DefaultThrowTime; - // TODO: Mass isn't even used on the system side yet for controllers so do that someday - var velocityNecessary = distance / throwDuration; - var forceNecessary = velocityNecessary / timing.TickRate; - - // Then clamp it to the max force allowed and call Throw(). - thrownEnt.Throw(MathF.Min(forceNecessary, throwForceMax), targetLoc, sourceLoc, spread, throwSourceEnt); - } - } -} diff --git a/Content.Shared/AI/SharedAiDebug.cs b/Content.Shared/AI/SharedAiDebug.cs index 2ecb1e9c55..a40fd76c5b 100644 --- a/Content.Shared/AI/SharedAiDebug.cs +++ b/Content.Shared/AI/SharedAiDebug.cs @@ -169,6 +169,18 @@ namespace Content.Shared.AI Cached = cached; } } + + /// + /// Send if someone is subscribing to reachable regions for NPCs. + /// + [Serializable, NetSerializable] + public sealed class SubscribeReachableMessage : EntitySystemMessage {} + + /// + /// Send if someone is unsubscribing to reachable regions for NPCs. + /// + [Serializable, NetSerializable] + public sealed class UnsubscribeReachableMessage : EntitySystemMessage {} #endregion } } diff --git a/Content.Shared/CCVars.cs b/Content.Shared/CCVars.cs index 1bf009e38b..583b23868c 100644 --- a/Content.Shared/CCVars.cs +++ b/Content.Shared/CCVars.cs @@ -166,6 +166,15 @@ namespace Content.Shared public static readonly CVarDef ParallaxDebug = CVarDef.Create("parallax.debug", false, CVar.CLIENTONLY); + /* + * Physics + */ + + public static readonly CVarDef TileFrictionModifier = + CVarDef.Create("physics.tilefriction", 15.0f); + + public static readonly CVarDef StopSpeed = + CVarDef.Create("physics.stopspeed", 0.1f); /* * Ambience diff --git a/Content.Shared/Construction/ConstructionConditions/WallmountCondition.cs b/Content.Shared/Construction/ConstructionConditions/WallmountCondition.cs index d183543c3d..b26434c475 100644 --- a/Content.Shared/Construction/ConstructionConditions/WallmountCondition.cs +++ b/Content.Shared/Construction/ConstructionConditions/WallmountCondition.cs @@ -9,6 +9,7 @@ using Robust.Shared.Map; using Robust.Shared.Maths; using Robust.Shared.Physics; using Robust.Shared.Serialization.Manager.Attributes; +using Robust.Shared.Physics.Broadphase; namespace Content.Shared.Construction.ConstructionConditions { @@ -33,7 +34,7 @@ namespace Content.Shared.Construction.ConstructionConditions return false; // now we need to check that user actually tries to build wallmount on a wall - var physics = IoCManager.Resolve(); + var physics = EntitySystem.Get(); var rUserToObj = new CollisionRay(userWorldPosition, userToObject.Normalized, (int) CollisionGroup.Impassable); var length = userToObject.Length; var userToObjRaycastResults = physics.IntersectRayWithPredicate(user.Transform.MapID, rUserToObj, maxLength: length, diff --git a/Content.Shared/GameObjects/Components/Body/SharedBodyComponent.cs b/Content.Shared/GameObjects/Components/Body/SharedBodyComponent.cs index d144a1a136..29695fc610 100644 --- a/Content.Shared/GameObjects/Components/Body/SharedBodyComponent.cs +++ b/Content.Shared/GameObjects/Components/Body/SharedBodyComponent.cs @@ -13,6 +13,9 @@ using Content.Shared.GameObjects.Components.Movement; using Content.Shared.GameObjects.EntitySystems; using Robust.Shared.GameObjects; using Robust.Shared.IoC; +using Robust.Shared.Maths; +using Robust.Shared.Physics; +using Robust.Shared.Physics.Collision; using Robust.Shared.Players; using Robust.Shared.Prototypes; using Robust.Shared.Serialization; diff --git a/Content.Shared/GameObjects/Components/Buckle/SharedBuckleComponent.cs b/Content.Shared/GameObjects/Components/Buckle/SharedBuckleComponent.cs index 42e8d4ecb7..9821a8784c 100644 --- a/Content.Shared/GameObjects/Components/Buckle/SharedBuckleComponent.cs +++ b/Content.Shared/GameObjects/Components/Buckle/SharedBuckleComponent.cs @@ -19,7 +19,7 @@ namespace Content.Shared.GameObjects.Components.Buckle public sealed override uint? NetID => ContentNetIDs.BUCKLE; - [ComponentDependency] protected readonly IPhysicsComponent? Physics; + [ComponentDependency] protected readonly IPhysBody? Physics; /// /// The range from which this entity can buckle to a . diff --git a/Content.Shared/GameObjects/Components/Disposal/SharedDisposalUnitComponent.cs b/Content.Shared/GameObjects/Components/Disposal/SharedDisposalUnitComponent.cs index 4e21ed3791..afb3ee6804 100644 --- a/Content.Shared/GameObjects/Components/Disposal/SharedDisposalUnitComponent.cs +++ b/Content.Shared/GameObjects/Components/Disposal/SharedDisposalUnitComponent.cs @@ -21,8 +21,8 @@ namespace Content.Shared.GameObjects.Components.Disposal [ViewVariables] public bool Anchored => - !Owner.TryGetComponent(out IPhysicsComponent? physics) || - physics.Anchored; + !Owner.TryGetComponent(out IPhysBody? physics) || + physics.BodyType == BodyType.Static; [Serializable, NetSerializable] public enum Visuals @@ -167,7 +167,7 @@ namespace Content.Shared.GameObjects.Components.Disposal if (!Anchored) return false; - if (!entity.TryGetComponent(out IPhysicsComponent? physics) || + if (!entity.TryGetComponent(out IPhysBody? physics) || !physics.CanCollide) { if (!(entity.TryGetComponent(out IMobStateComponent? damageState) && damageState.IsDead())) { diff --git a/Content.Shared/GameObjects/Components/Doors/SharedDoorComponent.cs b/Content.Shared/GameObjects/Components/Doors/SharedDoorComponent.cs index 00730eae8c..2f4f13b73e 100644 --- a/Content.Shared/GameObjects/Components/Doors/SharedDoorComponent.cs +++ b/Content.Shared/GameObjects/Components/Doors/SharedDoorComponent.cs @@ -20,7 +20,7 @@ namespace Content.Shared.GameObjects.Components.Doors protected readonly SharedAppearanceComponent? AppearanceComponent = null; [ComponentDependency] - protected readonly IPhysicsComponent? PhysicsComponent = null; + protected readonly IPhysBody? PhysicsComponent = null; [ViewVariables] private DoorState _state = DoorState.Closed; diff --git a/Content.Shared/GameObjects/Components/Items/ThrownItemComponent.cs b/Content.Shared/GameObjects/Components/Items/ThrownItemComponent.cs new file mode 100644 index 0000000000..fc53c555fb --- /dev/null +++ b/Content.Shared/GameObjects/Components/Items/ThrownItemComponent.cs @@ -0,0 +1,27 @@ +#nullable enable +using Content.Shared.GameObjects.EntitySystems; +using Robust.Shared.GameObjects; +using Robust.Shared.Physics; +using Robust.Shared.Physics.Collision; + +namespace Content.Shared.GameObjects.Components.Items +{ + [RegisterComponent] + public class ThrownItemComponent : Component, IStartCollide, ICollideSpecial + { + public override string Name => "ThrownItem"; + + public IEntity? Thrower { get; set; } + + void IStartCollide.CollideWith(IPhysBody ourBody, IPhysBody otherBody, in Manifold manifold) + { + if (otherBody.Entity == Thrower) return; + EntitySystem.Get().ThrowCollideInteraction(Thrower, ourBody, otherBody); + } + + bool ICollideSpecial.PreventCollide(IPhysBody collidedwith) + { + return collidedwith.Entity == Thrower; + } + } +} diff --git a/Content.Shared/GameObjects/Components/Mobs/SharedCombatModeComponent.cs b/Content.Shared/GameObjects/Components/Mobs/SharedCombatModeComponent.cs index a40b5f315b..5d4988f92d 100644 --- a/Content.Shared/GameObjects/Components/Mobs/SharedCombatModeComponent.cs +++ b/Content.Shared/GameObjects/Components/Mobs/SharedCombatModeComponent.cs @@ -21,8 +21,22 @@ namespace Content.Shared.GameObjects.Components.Mobs get => _isInCombatMode; set { + if (_isInCombatMode == value) return; _isInCombatMode = value; Dirty(); + + // Regenerate physics contacts -> Can probably just selectively check + /* Still a bit jank so left disabled for now. + if (Owner.TryGetComponent(out PhysicsComponent? physicsComponent)) + { + if (value) + { + physicsComponent.WakeBody(); + } + + physicsComponent.RegenerateContacts(); + } + */ } } @@ -32,6 +46,7 @@ namespace Content.Shared.GameObjects.Components.Mobs get => _activeZone; set { + if (_activeZone == value) return; _activeZone = value; Dirty(); } diff --git a/Content.Shared/GameObjects/Components/Movement/IMobMoverComponent.cs b/Content.Shared/GameObjects/Components/Movement/IMobMoverComponent.cs new file mode 100644 index 0000000000..1e8572837a --- /dev/null +++ b/Content.Shared/GameObjects/Components/Movement/IMobMoverComponent.cs @@ -0,0 +1,17 @@ +using Robust.Shared.GameObjects; +using Robust.Shared.Map; + + +namespace Content.Shared.GameObjects.Components.Movement +{ + public interface IMobMoverComponent : IComponent + { + EntityCoordinates LastPosition { get; set; } + + public float StepSoundDistance { get; set; } + + float GrabRange { get; set; } + + float PushStrength { get; set; } + } +} diff --git a/Content.Shared/GameObjects/Components/Movement/IMoverComponent.cs b/Content.Shared/GameObjects/Components/Movement/IMoverComponent.cs index 620a176899..c0ecc99c9b 100644 --- a/Content.Shared/GameObjects/Components/Movement/IMoverComponent.cs +++ b/Content.Shared/GameObjects/Components/Movement/IMoverComponent.cs @@ -19,17 +19,6 @@ namespace Content.Shared.GameObjects.Components.Movement /// float CurrentSprintSpeed { get; } - - /// - /// The movement speed (m/s) of the entity when it pushes off of a solid object in zero gravity. - /// - float CurrentPushSpeed { get; } - - /// - /// How far an entity can reach (in meters) to grab hold of a solid object in zero gravity. - /// - float GrabRange { get; } - /// /// Is the entity Sprinting (running)? /// @@ -40,10 +29,6 @@ namespace Content.Shared.GameObjects.Components.Movement /// (Vector2 walking, Vector2 sprinting) VelocityDir { get; } - EntityCoordinates LastPosition { get; set; } - - float StepSoundDistance { get; set; } - /// /// Toggles one of the four cardinal directions. Each of the four directions are /// composed into a single direction vector, . Enabling @@ -55,6 +40,5 @@ namespace Content.Shared.GameObjects.Components.Movement void SetVelocityDirection(Direction direction, ushort subTick, bool enabled); void SetSprinting(ushort subTick, bool walking); - } } diff --git a/Content.Shared/GameObjects/Components/Movement/SharedClimbingComponent.cs b/Content.Shared/GameObjects/Components/Movement/SharedClimbingComponent.cs index 626449b0ec..7cb29e495d 100644 --- a/Content.Shared/GameObjects/Components/Movement/SharedClimbingComponent.cs +++ b/Content.Shared/GameObjects/Components/Movement/SharedClimbingComponent.cs @@ -5,62 +5,107 @@ using Content.Shared.Physics; using Robust.Shared.GameObjects; using Robust.Shared.Physics; using Robust.Shared.Serialization; +using Robust.Shared.ViewVariables; namespace Content.Shared.GameObjects.Components.Movement { - public abstract class SharedClimbingComponent : Component, IActionBlocker, ICollideSpecial + public abstract class SharedClimbingComponent : Component, IActionBlocker { public sealed override string Name => "Climbing"; public sealed override uint? NetID => ContentNetIDs.CLIMBING; - protected IPhysicsComponent? Body; - protected bool IsOnClimbableThisFrame; - - protected bool OwnerIsTransitioning + protected bool IsOnClimbableThisFrame { get { - if (Body != null && Body.TryGetController(out var controller)) + if (Body == null) return false; + + foreach (var entity in Body.GetBodiesIntersecting()) { - return controller.IsActive; + if ((entity.CollisionLayer & (int) CollisionGroup.VaultImpassable) != 0) return true; } return false; } } - public abstract bool IsClimbing { get; set; } - bool IActionBlocker.CanMove() => !OwnerIsTransitioning; - bool IActionBlocker.CanChangeDirection() => !OwnerIsTransitioning; - bool ICollideSpecial.PreventCollide(IPhysBody collided) + [ViewVariables] + protected virtual bool OwnerIsTransitioning { - if (((CollisionGroup)collided.CollisionLayer).HasFlag(CollisionGroup.VaultImpassable) && collided.Entity.HasComponent()) + get => _ownerIsTransitioning; + set { - IsOnClimbableThisFrame = true; - return IsClimbing; + if (_ownerIsTransitioning == value) return; + _ownerIsTransitioning = value; + if (Body == null) return; + if (value) + { + Body.BodyType = BodyType.Dynamic; + } + else + { + Body.BodyType = BodyType.KinematicController; + } } - - return false; } - public override void Initialize() - { - base.Initialize(); + private bool _ownerIsTransitioning = false; - Owner.TryGetComponent(out Body); + [ComponentDependency] protected PhysicsComponent? Body; + + protected TimeSpan StartClimbTime = TimeSpan.Zero; + + /// + /// We'll launch the mob onto the table and give them at least this amount of time to be on it. + /// + protected const float BufferTime = 0.3f; + + public virtual bool IsClimbing + { + get => _isClimbing; + set + { + if (_isClimbing == value) return; + _isClimbing = value; + + ToggleVaultPassable(value); + } + } + + protected bool _isClimbing; + + // TODO: Layers need a re-work + private void ToggleVaultPassable(bool value) + { + // Hope the mob has one fixture + if (Body == null || Body.Deleted) return; + + foreach (var fixture in Body.Fixtures) + { + if (value) + { + fixture.CollisionMask &= ~(int) CollisionGroup.VaultImpassable; + } + else + { + fixture.CollisionMask |= (int) CollisionGroup.VaultImpassable; + } + } } [Serializable, NetSerializable] protected sealed class ClimbModeComponentState : ComponentState { - public ClimbModeComponentState(bool climbing) : base(ContentNetIDs.CLIMBING) + public ClimbModeComponentState(bool climbing, bool isTransitioning) : base(ContentNetIDs.CLIMBING) { Climbing = climbing; + IsTransitioning = isTransitioning; } public bool Climbing { get; } + public bool IsTransitioning { get; } } } } diff --git a/Content.Shared/GameObjects/Components/Movement/SharedDummyInputMoverComponent.cs b/Content.Shared/GameObjects/Components/Movement/SharedDummyInputMoverComponent.cs index 91e82a958d..45f377b322 100644 --- a/Content.Shared/GameObjects/Components/Movement/SharedDummyInputMoverComponent.cs +++ b/Content.Shared/GameObjects/Components/Movement/SharedDummyInputMoverComponent.cs @@ -10,14 +10,12 @@ namespace Content.Shared.GameObjects.Components.Movement public class SharedDummyInputMoverComponent : Component, IMoverComponent { public override string Name => "DummyInputMover"; + public bool IgnorePaused => false; public float CurrentWalkSpeed => 0f; public float CurrentSprintSpeed => 0f; - public float CurrentPushSpeed => 0f; - public float GrabRange => 0f; + public bool Sprinting => false; public (Vector2 walking, Vector2 sprinting) VelocityDir => (Vector2.Zero, Vector2.Zero); - public EntityCoordinates LastPosition { get; set; } - public float StepSoundDistance { get; set; } public void SetVelocityDirection(Direction direction, ushort subTick, bool enabled) { diff --git a/Content.Shared/GameObjects/Components/Movement/SharedPlayerInputMoverComponent.cs b/Content.Shared/GameObjects/Components/Movement/SharedPlayerInputMoverComponent.cs index 4a6fa3a52d..963a79ff57 100644 --- a/Content.Shared/GameObjects/Components/Movement/SharedPlayerInputMoverComponent.cs +++ b/Content.Shared/GameObjects/Components/Movement/SharedPlayerInputMoverComponent.cs @@ -5,7 +5,6 @@ using Robust.Shared.Configuration; using Robust.Shared.GameObjects; using Robust.Shared.IoC; using Robust.Shared.Log; -using Robust.Shared.Map; using Robust.Shared.Maths; using Robust.Shared.Physics; using Robust.Shared.Players; @@ -15,7 +14,9 @@ using Robust.Shared.ViewVariables; namespace Content.Shared.GameObjects.Components.Movement { - public abstract class SharedPlayerInputMoverComponent : Component, IMoverComponent, ICollideSpecial + [RegisterComponent] + [ComponentReference(typeof(IMoverComponent))] + public class SharedPlayerInputMoverComponent : Component, IMoverComponent { // This class has to be able to handle server TPS being lower than client FPS. // While still having perfectly responsive movement client side. @@ -39,8 +40,10 @@ namespace Content.Shared.GameObjects.Components.Movement [Dependency] private readonly IConfigurationManager _configurationManager = default!; [Dependency] private readonly IGameTiming _gameTiming = default!; - public sealed override string Name => "PlayerInputMover"; - public sealed override uint? NetID => ContentNetIDs.PLAYER_INPUT_MOVER; + [ComponentDependency] private readonly MovementSpeedModifierComponent? _movementSpeed = default!; + + public override string Name => "PlayerInputMover"; + public override uint? NetID => ContentNetIDs.PLAYER_INPUT_MOVER; private GameTick _lastInputTick; private ushort _lastInputSubTick; @@ -49,36 +52,10 @@ namespace Content.Shared.GameObjects.Components.Movement private MoveButtons _heldMoveButtons = MoveButtons.None; - public float CurrentWalkSpeed - { - get - { - if (Owner.TryGetComponent(out MovementSpeedModifierComponent? component)) - { - return component.CurrentWalkSpeed; - } + public float CurrentWalkSpeed => _movementSpeed?.CurrentWalkSpeed ?? MovementSpeedModifierComponent.DefaultBaseWalkSpeed; - return MovementSpeedModifierComponent.DefaultBaseWalkSpeed; - } - } + public float CurrentSprintSpeed => _movementSpeed?.CurrentSprintSpeed ?? MovementSpeedModifierComponent.DefaultBaseSprintSpeed; - public float CurrentSprintSpeed - { - get - { - if (Owner.TryGetComponent(out MovementSpeedModifierComponent? component)) - { - return component.CurrentSprintSpeed; - } - - return MovementSpeedModifierComponent.DefaultBaseSprintSpeed; - } - } - - [ViewVariables(VVAccess.ReadWrite)] - public float CurrentPushSpeed => 5; - [ViewVariables(VVAccess.ReadWrite)] - public float GrabRange => 0.2f; public bool Sprinting => !HasFlag(_heldMoveButtons, MoveButtons.Walk); /// @@ -131,9 +108,6 @@ namespace Content.Shared.GameObjects.Components.Movement } } - public abstract EntityCoordinates LastPosition { get; set; } - public abstract float StepSoundDistance { get; set; } - /// /// Whether or not the player can move diagonally. /// @@ -141,18 +115,12 @@ namespace Content.Shared.GameObjects.Components.Movement public bool DiagonalMovementEnabled => _configurationManager.GetCVar(CCVars.GameDiagonalMovement); /// - public override void OnAdd() + public override void Initialize() { - // This component requires that the entity has a IPhysicsComponent. - if (!Owner.HasComponent()) - Logger.Error( - $"[ECS] {Owner.Prototype?.Name} - {nameof(SharedPlayerInputMoverComponent)} requires" + - $" {nameof(IPhysicsComponent)}. "); - - base.OnAdd(); + base.Initialize(); + Owner.EnsureComponentWarn(); } - /// /// Toggles one of the four cardinal directions. Each of the four directions are /// composed into a single direction vector, . Enabling @@ -266,12 +234,6 @@ namespace Content.Shared.GameObjects.Components.Movement return vec; } - bool ICollideSpecial.PreventCollide(IPhysBody collidedWith) - { - // Don't collide with other mobs - return collidedWith.Entity.HasComponent(); - } - [Serializable, NetSerializable] private sealed class MoverComponentState : ComponentState { diff --git a/Content.Shared/GameObjects/Components/Movement/SharedPlayerMobMoverComponent.cs b/Content.Shared/GameObjects/Components/Movement/SharedPlayerMobMoverComponent.cs new file mode 100644 index 0000000000..b982433d94 --- /dev/null +++ b/Content.Shared/GameObjects/Components/Movement/SharedPlayerMobMoverComponent.cs @@ -0,0 +1,123 @@ +#nullable enable +using System; +using Content.Shared.GameObjects.Components.Body; +using Robust.Shared.GameObjects; +using Robust.Shared.Log; +using Robust.Shared.Map; +using Robust.Shared.Maths; +using Robust.Shared.Physics; +using Robust.Shared.Players; +using Robust.Shared.Serialization; +using Robust.Shared.Serialization.Manager.Attributes; +using Robust.Shared.ViewVariables; + +namespace Content.Shared.GameObjects.Components.Movement +{ + /// + /// The basic player mover with footsteps and grabbing + /// + [RegisterComponent] + [ComponentReference(typeof(IMobMoverComponent))] + public class SharedPlayerMobMoverComponent : Component, IMobMoverComponent, ICollideSpecial + { + public override string Name => "PlayerMobMover"; + public override uint? NetID => ContentNetIDs.PLAYER_MOB_MOVER; + + private float _stepSoundDistance; + [DataField("grabRange")] + private float _grabRange = 0.2f; + [DataField("pushStrength")] + private float _pushStrength = 600.0f; + + [ViewVariables(VVAccess.ReadWrite)] + public EntityCoordinates LastPosition { get; set; } + + /// + /// Used to keep track of how far we have moved before playing a step sound + /// + [ViewVariables(VVAccess.ReadWrite)] + public float StepSoundDistance + { + get => _stepSoundDistance; + set + { + if (MathHelper.CloseTo(_stepSoundDistance, value)) return; + _stepSoundDistance = value; + } + } + + [ViewVariables(VVAccess.ReadWrite)] + public float GrabRange + { + get => _grabRange; + set + { + if (MathHelper.CloseTo(_grabRange, value)) return; + _grabRange = value; + Dirty(); + } + } + + [ViewVariables(VVAccess.ReadWrite)] + public float PushStrength + { + get => _pushStrength; + set + { + if (MathHelper.CloseTo(_pushStrength, value)) return; + _pushStrength = value; + Dirty(); + } + } + + public override void Initialize() + { + base.Initialize(); + if (!Owner.HasComponent()) + { + Owner.EnsureComponentWarn(); + } + + if (Owner.TryGetComponent(out IPhysBody? body) && body.BodyType != BodyType.KinematicController) + { + Logger.WarningS("mover", $"Attached {nameof(SharedPlayerMobMoverComponent)} to a mob that's BodyType is not KinematicController!'"); + } + } + + public override ComponentState GetComponentState(ICommonSession session) + { + return new PlayerMobMoverComponentState(_grabRange, _pushStrength); + } + + public override void HandleComponentState(ComponentState? curState, ComponentState? nextState) + { + base.HandleComponentState(curState, nextState); + if (curState is not PlayerMobMoverComponentState playerMoverState) return; + GrabRange = playerMoverState.GrabRange; + PushStrength = playerMoverState.PushStrength; + } + + bool ICollideSpecial.PreventCollide(IPhysBody collidedWith) + { + // Don't collide with other mobs + // unless they have combat mode on + return collidedWith.Entity.HasComponent(); /* && + (!Owner.TryGetComponent(out SharedCombatModeComponent? ownerCombat) || !ownerCombat.IsInCombatMode) && + (!collidedWith.Entity.TryGetComponent(out SharedCombatModeComponent? otherCombat) || !otherCombat.IsInCombatMode); + */ + } + + [Serializable, NetSerializable] + private sealed class PlayerMobMoverComponentState : ComponentState + { + public float GrabRange; + public float PushStrength; + + public PlayerMobMoverComponentState(float grabRange, float pushStrength) : base(ContentNetIDs.PLAYER_MOB_MOVER) + { + GrabRange = grabRange; + PushStrength = pushStrength; + } + } + } +} diff --git a/Content.Shared/GameObjects/Components/Movement/SharedSlipperyComponent.cs b/Content.Shared/GameObjects/Components/Movement/SharedSlipperyComponent.cs index 97b34d7c48..a336ea1674 100644 --- a/Content.Shared/GameObjects/Components/Movement/SharedSlipperyComponent.cs +++ b/Content.Shared/GameObjects/Components/Movement/SharedSlipperyComponent.cs @@ -7,13 +7,15 @@ using Content.Shared.GameObjects.EntitySystems.EffectBlocker; using Content.Shared.Physics; using Robust.Shared.Containers; using Robust.Shared.GameObjects; +using Robust.Shared.Physics; +using Robust.Shared.Physics.Collision; using Robust.Shared.Serialization; using Robust.Shared.Serialization.Manager.Attributes; using Robust.Shared.ViewVariables; namespace Content.Shared.GameObjects.Components.Movement { - public abstract class SharedSlipperyComponent : Component, ICollideBehavior + public abstract class SharedSlipperyComponent : Component, IStartCollide { public sealed override string Name => "Slippery"; @@ -58,14 +60,12 @@ namespace Content.Shared.GameObjects.Components.Movement [DataField("slippery")] public virtual bool Slippery { get; set; } = true; - private bool TrySlip(IEntity entity) + private bool TrySlip(IPhysBody ourBody, IPhysBody otherBody) { if (!Slippery || Owner.IsInContainer() - || _slipped.Contains(entity.Uid) - || !entity.TryGetComponent(out SharedStunnableComponent? stun) - || !entity.TryGetComponent(out IPhysicsComponent? otherBody) - || !Owner.TryGetComponent(out IPhysicsComponent? body)) + || _slipped.Contains(otherBody.Entity.Uid) + || !otherBody.Entity.TryGetComponent(out SharedStunnableComponent? stun)) { return false; } @@ -75,26 +75,22 @@ namespace Content.Shared.GameObjects.Components.Movement return false; } - var percentage = otherBody.WorldAABB.IntersectPercentage(body.WorldAABB); + var percentage = otherBody.GetWorldAABB().IntersectPercentage(ourBody.GetWorldAABB()); if (percentage < IntersectPercentage) { return false; } - if (!EffectBlockerSystem.CanSlip(entity)) + if (!EffectBlockerSystem.CanSlip(otherBody.Entity)) { return false; } - if (entity.TryGetComponent(out IPhysicsComponent? physics)) - { - var controller = physics.EnsureController(); - controller.LinearVelocity = physics.LinearVelocity * LaunchForwardsMultiplier; - } + otherBody.LinearVelocity *= LaunchForwardsMultiplier; stun.Paralyze(5); - _slipped.Add(entity.Uid); + _slipped.Add(otherBody.Entity.Uid); OnSlip(); @@ -103,9 +99,9 @@ namespace Content.Shared.GameObjects.Components.Movement protected virtual void OnSlip() { } - public void CollideWith(IEntity collidedWith) + void IStartCollide.CollideWith(IPhysBody ourBody, IPhysBody otherBody, in Manifold manifold) { - TrySlip(collidedWith); + TrySlip(ourBody, otherBody); } public void Update() @@ -119,10 +115,10 @@ namespace Content.Shared.GameObjects.Components.Movement } var entity = Owner.EntityManager.GetEntity(uid); - var physics = Owner.GetComponent(); - var otherPhysics = entity.GetComponent(); + var physics = Owner.GetComponent(); + var otherPhysics = entity.GetComponent(); - if (!physics.WorldAABB.Intersects(otherPhysics.WorldAABB)) + if (!physics.GetWorldAABB().Intersects(otherPhysics.GetWorldAABB())) { _slipped.Remove(uid); } @@ -137,12 +133,12 @@ namespace Content.Shared.GameObjects.Components.Movement physics.Hard = false; - var shape = physics.PhysicsShapes.FirstOrDefault(); + var fixtures = physics.Fixtures.FirstOrDefault(); - if (shape != null) + if (fixtures != null) { - shape.CollisionLayer |= (int) CollisionGroup.SmallImpassable; - shape.CollisionMask = (int) CollisionGroup.None; + fixtures.CollisionLayer |= (int) CollisionGroup.SmallImpassable; + fixtures.CollisionMask = (int) CollisionGroup.None; } } } diff --git a/Content.Shared/GameObjects/Components/Movement/TileFrictionModifier.cs b/Content.Shared/GameObjects/Components/Movement/TileFrictionModifier.cs new file mode 100644 index 0000000000..45cc3a9a8c --- /dev/null +++ b/Content.Shared/GameObjects/Components/Movement/TileFrictionModifier.cs @@ -0,0 +1,58 @@ +#nullable enable +using System; +using Robust.Shared.GameObjects; +using Robust.Shared.Maths; +using Robust.Shared.Players; +using Robust.Shared.Serialization; +using Robust.Shared.Serialization.Manager.Attributes; +using Robust.Shared.ViewVariables; + +namespace Content.Shared.GameObjects.Components.Movement +{ + [RegisterComponent] + public class SharedTileFrictionModifier : Component + { + public override string Name => "TileFrictionModifier"; + + /// + /// Multiply the tilefriction cvar by this to get the body's actual tilefriction. + /// + [ViewVariables(VVAccess.ReadWrite)] + public float Modifier + { + get => _modifier; + set + { + if (MathHelper.CloseTo(_modifier, value)) return; + + _modifier = value; + } + } + + [DataField("modifier")] + private float _modifier = 1.0f; + + public override ComponentState GetComponentState(ICommonSession session) + { + return new TileFrictionComponentState(_modifier); + } + + public override void HandleComponentState(ComponentState? curState, ComponentState? nextState) + { + base.HandleComponentState(curState, nextState); + if (curState is not TileFrictionComponentState tileState) return; + _modifier = tileState.Modifier; + } + + [NetSerializable, Serializable] + protected class TileFrictionComponentState : ComponentState + { + public float Modifier; + + public TileFrictionComponentState(float modifier) : base(ContentNetIDs.TILE_FRICTION) + { + Modifier = modifier; + } + } + } +} diff --git a/Content.Shared/GameObjects/Components/Portal/SharedPortalComponent.cs b/Content.Shared/GameObjects/Components/Portal/SharedPortalComponent.cs index 720fef70a4..bd6ae67bd6 100644 --- a/Content.Shared/GameObjects/Components/Portal/SharedPortalComponent.cs +++ b/Content.Shared/GameObjects/Components/Portal/SharedPortalComponent.cs @@ -1,6 +1,7 @@ #nullable enable using System; using Robust.Shared.GameObjects; +using Robust.Shared.Physics; using Robust.Shared.Serialization; namespace Content.Shared.GameObjects.Components.Portal @@ -13,7 +14,7 @@ namespace Content.Shared.GameObjects.Components.Portal { base.OnAdd(); - if (Owner.TryGetComponent(out var physics)) + if (Owner.TryGetComponent(out var physics)) { physics.Hard = false; } diff --git a/Content.Shared/GameObjects/Components/Projectiles/SharedProjectileComponent.cs b/Content.Shared/GameObjects/Components/Projectiles/SharedProjectileComponent.cs index 6804f756b6..82ecff0ff7 100644 --- a/Content.Shared/GameObjects/Components/Projectiles/SharedProjectileComponent.cs +++ b/Content.Shared/GameObjects/Components/Projectiles/SharedProjectileComponent.cs @@ -19,6 +19,8 @@ namespace Content.Shared.GameObjects.Components.Projectiles get => _ignoreShooter; set { + if (_ignoreShooter == value) return; + _ignoreShooter = value; Dirty(); } diff --git a/Content.Shared/GameObjects/Components/Pulling/SharedPullableComponent.cs b/Content.Shared/GameObjects/Components/Pulling/SharedPullableComponent.cs index 2574cea788..ceaf4ae20e 100644 --- a/Content.Shared/GameObjects/Components/Pulling/SharedPullableComponent.cs +++ b/Content.Shared/GameObjects/Components/Pulling/SharedPullableComponent.cs @@ -11,6 +11,7 @@ using Robust.Shared.Log; using Robust.Shared.Map; using Robust.Shared.Physics; using Robust.Shared.Players; +using Robust.Shared.Physics.Dynamics.Joints; using Robust.Shared.Serialization; namespace Content.Shared.GameObjects.Components.Pulling @@ -20,14 +21,16 @@ namespace Content.Shared.GameObjects.Components.Pulling public override string Name => "Pullable"; public override uint? NetID => ContentNetIDs.PULLABLE; - [ComponentDependency] private readonly IPhysicsComponent? _physics = default!; + [ComponentDependency] private readonly PhysicsComponent? _physics = default!; /// /// Only set in Puller->set! Only set in unison with _pullerPhysics! /// private IEntity? _puller; - private IPhysicsComponent? _pullerPhysics; - public IPhysicsComponent? PullerPhysics => _pullerPhysics; + private IPhysBody? _pullerPhysics; + public IPhysBody? PullerPhysics => _pullerPhysics; + + private DistanceJoint? _pullJoint; /// /// The current entity pulling this component. @@ -62,7 +65,6 @@ namespace Content.Shared.GameObjects.Components.Pulling oldPuller.EntityManager.EventBus.RaiseEvent(EventSource.Local, message); _physics.WakeBody(); - _physics.TryRemoveController(); } // else-branch warning is handled below } @@ -70,7 +72,7 @@ namespace Content.Shared.GameObjects.Components.Pulling // Now that is settled, prepare to be pulled by a new object. if (_physics == null) { - Logger.WarningS("c.go.c.pulling", "Well now you've done it, haven't you? SharedPullableComponent on {0} didn't have an IPhysicsComponent.", Owner); + Logger.WarningS("c.go.c.pulling", "Well now you've done it, haven't you? SharedPullableComponent on {0} didn't have an IPhysBody.", Owner); return; } @@ -83,7 +85,7 @@ namespace Content.Shared.GameObjects.Components.Pulling return; } - if (!value.TryGetComponent(out var valuePhysics)) + if (!value.TryGetComponent(out var pullerPhysics)) { return; } @@ -102,7 +104,7 @@ namespace Content.Shared.GameObjects.Components.Pulling { if (oldPulling.TryGetComponent(out SharedPullableComponent? pullable)) { - pullable.Puller = null; + pullable.TryStopPull(); } else { @@ -113,7 +115,7 @@ namespace Content.Shared.GameObjects.Components.Pulling // Continue with pulling process. - var pullAttempt = new PullAttemptMessage(valuePhysics, _physics); + var pullAttempt = new PullAttemptMessage(pullerPhysics, _physics); value.SendMessage(null, pullAttempt); @@ -133,9 +135,8 @@ namespace Content.Shared.GameObjects.Components.Pulling _puller = value; Dirty(); - _pullerPhysics = valuePhysics; + _pullerPhysics = pullerPhysics; - _physics.EnsureController().Manager = this; var message = new PullStartedMessage(_pullerPhysics, _physics); _puller.SendMessage(null, message); @@ -143,7 +144,15 @@ namespace Content.Shared.GameObjects.Components.Pulling _puller.EntityManager.EventBus.RaiseEvent(EventSource.Local, message); + var union = _pullerPhysics.GetWorldAABB().Union(_physics.GetWorldAABB()); + var length = Math.Max(union.Size.X, union.Size.Y) * 0.75f; + _physics.WakeBody(); + _pullJoint = pullerPhysics.CreateDistanceJoint(_physics); + // _physics.BodyType = BodyType.Kinematic; // TODO: Need to consider their original bodytype + _pullJoint.CollideConnected = true; + _pullJoint.Length = length * 0.75f; + _pullJoint.MaxLength = length; } // Code here will not run if pulling a new object was attempted and failed because of the returns from the refactor. } @@ -212,6 +221,12 @@ namespace Content.Shared.GameObjects.Components.Pulling return false; } + if (_physics != null && _pullJoint != null) + { + _physics.RemoveJoint(_pullJoint); + } + + _pullJoint = null; Puller = null; return true; } @@ -246,12 +261,16 @@ namespace Content.Shared.GameObjects.Components.Pulling return false; } + /* if (!_physics.TryGetController(out PullController controller)) { return false; } + */ - return controller.TryMoveTo(Puller.Transform.Coordinates, to); + return true; + + //return controller.TryMoveTo(Puller.Transform.Coordinates, to); } public override ComponentState GetComponentState(ICommonSession player) diff --git a/Content.Shared/GameObjects/ContentNetIDs.cs b/Content.Shared/GameObjects/ContentNetIDs.cs index 122f688364..4094687206 100644 --- a/Content.Shared/GameObjects/ContentNetIDs.cs +++ b/Content.Shared/GameObjects/ContentNetIDs.cs @@ -14,8 +14,8 @@ namespace Content.Shared.GameObjects public const uint STORAGE = 1005; public const uint INVENTORY = 1006; public const uint POWER_DEBUG_TOOL = 1007; - // 1008 - // 1009 + public const uint PLAYER_MOB_MOVER = 1008; + public const uint TILE_FRICTION = 1009; public const uint RANGED_WEAPON = 1010; public const uint CAMERA_RECOIL = 1011; public const uint SOUND = 1012; @@ -60,7 +60,7 @@ namespace Content.Shared.GameObjects public const uint FLASHABLE = 1051; public const uint BUCKLE = 1052; public const uint PROJECTILE = 1053; - public const uint THROWN_ITEM = 1054; + // 1054 public const uint STRAP = 1055; public const uint DISPOSABLE = 1056; public const uint GAS_ANALYZER = 1057; diff --git a/Content.Shared/GameObjects/EntitySystems/SharedInteractionSystem.cs b/Content.Shared/GameObjects/EntitySystems/SharedInteractionSystem.cs index 5c7fe3c85f..6773cb51b3 100644 --- a/Content.Shared/GameObjects/EntitySystems/SharedInteractionSystem.cs +++ b/Content.Shared/GameObjects/EntitySystems/SharedInteractionSystem.cs @@ -9,6 +9,7 @@ using Robust.Shared.Localization; using Robust.Shared.Map; using Robust.Shared.Maths; using Robust.Shared.Physics; +using Robust.Shared.Physics.Broadphase; namespace Content.Shared.GameObjects.EntitySystems { @@ -18,8 +19,6 @@ namespace Content.Shared.GameObjects.EntitySystems [UsedImplicitly] public class SharedInteractionSystem : EntitySystem { - [Dependency] private readonly IPhysicsManager _physicsManager = default!; - public const float InteractionRange = 2; public const float InteractionRangeSquared = InteractionRange * InteractionRange; @@ -49,7 +48,7 @@ namespace Content.Shared.GameObjects.EntitySystems predicate ??= _ => false; var ray = new CollisionRay(origin.Position, dir.Normalized, collisionMask); - var rayResults = _physicsManager.IntersectRayWithPredicate(origin.MapId, ray, dir.Length, predicate.Invoke, false).ToList(); + var rayResults = Get().IntersectRayWithPredicate(origin.MapId, ray, dir.Length, predicate.Invoke, false).ToList(); if (rayResults.Count == 0) return dir.Length; return (rayResults[0].HitPos - origin.Position).Length; @@ -125,7 +124,7 @@ namespace Content.Shared.GameObjects.EntitySystems predicate ??= _ => false; var ray = new CollisionRay(origin.Position, dir.Normalized, (int) collisionMask); - var rayResults = _physicsManager.IntersectRayWithPredicate(origin.MapId, ray, dir.Length, predicate.Invoke, false).ToList(); + var rayResults = Get().IntersectRayWithPredicate(origin.MapId, ray, dir.Length, predicate.Invoke, false).ToList(); if (rayResults.Count == 0) return true; @@ -133,12 +132,12 @@ namespace Content.Shared.GameObjects.EntitySystems foreach (var result in rayResults) { - if (!result.HitEntity.TryGetComponent(out IPhysicsComponent p)) + if (!result.HitEntity.TryGetComponent(out IPhysBody p)) { continue; } - var bBox = p.WorldAABB; + var bBox = p.GetWorldAABB(); if (bBox.Contains(origin.Position) || bBox.Contains(other.Position)) { diff --git a/Content.Shared/GameObjects/EntitySystems/SharedMobMoverSystem.cs b/Content.Shared/GameObjects/EntitySystems/SharedMobMoverSystem.cs new file mode 100644 index 0000000000..353c1e3232 --- /dev/null +++ b/Content.Shared/GameObjects/EntitySystems/SharedMobMoverSystem.cs @@ -0,0 +1,38 @@ +#nullable enable +using Content.Shared.GameObjects.Components.Movement; +using Robust.Shared.GameObjects; +using Robust.Shared.Maths; +using Robust.Shared.Physics; +using Robust.Shared.Physics.Collision; + +namespace Content.Shared.GameObjects.EntitySystems +{ + public sealed class SharedMobMoverSystem : EntitySystem + { + public override void Initialize() + { + base.Initialize(); + Get().KinematicControllerCollision += HandleCollisionMessage; + } + + public override void Shutdown() + { + base.Shutdown(); + Get().KinematicControllerCollision -= HandleCollisionMessage; + } + + /// + /// Fake pushing for player collisions. + /// + private void HandleCollisionMessage(IPhysBody ourBody, IPhysBody otherBody, float frameTime, Manifold manifold) + { + if (otherBody.BodyType != BodyType.Dynamic) return; + + var normal = manifold.LocalNormal; + + if (!ourBody.Entity.TryGetComponent(out IMobMoverComponent? mobMover) || normal == Vector2.Zero) return; + + otherBody.ApplyLinearImpulse(-normal * mobMover.PushStrength * frameTime); + } + } +} diff --git a/Content.Shared/GameObjects/EntitySystems/SharedMoverSystem.cs b/Content.Shared/GameObjects/EntitySystems/SharedMoverSystem.cs index 4bb523b0a1..8b82552545 100644 --- a/Content.Shared/GameObjects/EntitySystems/SharedMoverSystem.cs +++ b/Content.Shared/GameObjects/EntitySystems/SharedMoverSystem.cs @@ -1,10 +1,11 @@ #nullable enable using System.Diagnostics.CodeAnalysis; -using Content.Shared.GameObjects.Components.Items; +using Content.Shared.GameObjects.Components.Mobs.State; using Content.Shared.GameObjects.Components.Movement; using Content.Shared.GameObjects.EntitySystems.ActionBlocker; using Content.Shared.Physics; using Content.Shared.Physics.Pull; +using Robust.Shared.Containers; using Robust.Shared.GameObjects; using Robust.Shared.Input; using Robust.Shared.Input.Binding; @@ -15,11 +16,11 @@ using Robust.Shared.Players; namespace Content.Shared.GameObjects.EntitySystems { - public abstract class SharedMoverSystem : EntitySystem + /// + /// Handles converting inputs into movement. + /// + public sealed class SharedMoverSystem : EntitySystem { - [Dependency] private readonly IEntityManager _entityManager = default!; - [Dependency] protected readonly IPhysicsManager PhysicsManager = default!; - public override void Initialize() { base.Initialize(); @@ -45,109 +46,9 @@ namespace Content.Shared.GameObjects.EntitySystems base.Shutdown(); } - //TODO: reorganize this to make more logical sense - protected void UpdateKinematics(ITransformComponent transform, IMoverComponent mover, IPhysicsComponent physics) - { - physics.EnsureController(); - - var weightless = transform.Owner.IsWeightless(); - - if (weightless) - { - // No gravity: is our entity touching anything? - var touching = IsAroundCollider(transform, mover, physics); - - if (!touching) - { - transform.LocalRotation = physics.LinearVelocity.GetDir().ToAngle(); - return; - } - } - - // TODO: movement check. - var (walkDir, sprintDir) = mover.VelocityDir; - var combined = walkDir + sprintDir; - if (combined.LengthSquared < 0.001 || !ActionBlockerSystem.CanMove(mover.Owner) && !weightless) - { - if (physics.TryGetController(out MoverController controller)) - { - controller.StopMoving(); - } - } - else if (ActionBlockerSystem.CanMove(mover.Owner)) - { - if (weightless) - { - if (physics.TryGetController(out MoverController controller)) - { - controller.Push(combined, mover.CurrentPushSpeed); - } - - transform.LocalRotation = physics.LinearVelocity.GetDir().ToAngle(); - return; - } - - var total = walkDir * mover.CurrentWalkSpeed + sprintDir * mover.CurrentSprintSpeed; - - { - if (physics.TryGetController(out MoverController controller)) - { - controller.Move(total, 1); - } - } - - transform.LocalRotation = total.GetDir().ToAngle(); - - HandleFootsteps(mover); - } - } - - protected virtual void HandleFootsteps(IMoverComponent mover) - { - - } - - private bool IsAroundCollider(ITransformComponent transform, IMoverComponent mover, - IPhysicsComponent collider) - { - foreach (var entity in _entityManager.GetEntitiesInRange(transform.Owner, mover.GrabRange, true)) - { - if (entity == transform.Owner) - { - continue; // Don't try to push off of yourself! - } - - if (!entity.TryGetComponent(out var otherCollider) || - !otherCollider.CanCollide || - (collider.CollisionMask & otherCollider.CollisionLayer) == 0) - { - continue; - } - - // Don't count pulled entities - if (otherCollider.HasController()) - { - continue; - } - - // TODO: Item check. - var touching = ((collider.CollisionMask & otherCollider.CollisionLayer) != 0x0 - || (otherCollider.CollisionMask & collider.CollisionLayer) != 0x0) // Ensure collision - && !entity.HasComponent(); // This can't be an item - - if (touching) - { - return true; - } - } - - return false; - } - - private static void HandleDirChange(ICommonSession? session, Direction dir, ushort subTick, bool state) { - if (!TryGetAttachedComponent(session, out var moverComp)) + if (!TryGetAttachedComponent(session, out var moverComp)) return; var owner = session?.AttachedEntity; @@ -158,6 +59,15 @@ namespace Content.Shared.GameObjects.EntitySystems { comp.MoveInputPressed(session); } + + // For stuff like "Moving out of locker" or the likes + if (owner.IsInContainer() && + (!owner.TryGetComponent(out IMobStateComponent? mobState) || + mobState.IsAlive())) + { + var relayEntityMoveMessage = new RelayMovementEntityMessage(owner); + owner.Transform.Parent!.Owner.SendMessage(owner.Transform, relayEntityMoveMessage); + } } moverComp.SetVelocityDirection(dir, subTick, state); diff --git a/Content.Shared/GameObjects/EntitySystems/SharedPullingSystem.cs b/Content.Shared/GameObjects/EntitySystems/SharedPullingSystem.cs index a692b51edb..f7212935ce 100644 --- a/Content.Shared/GameObjects/EntitySystems/SharedPullingSystem.cs +++ b/Content.Shared/GameObjects/EntitySystems/SharedPullingSystem.cs @@ -8,6 +8,7 @@ using JetBrains.Annotations; using Robust.Shared.GameObjects; using Robust.Shared.Input.Binding; using Robust.Shared.Map; +using Robust.Shared.Physics; using Robust.Shared.Players; namespace Content.Shared.GameObjects.EntitySystems @@ -58,7 +59,7 @@ namespace Content.Shared.GameObjects.EntitySystems return; } - if (!pulled.TryGetComponent(out IPhysicsComponent? physics)) + if (!pulled.TryGetComponent(out IPhysBody? physics)) { return; } diff --git a/Content.Shared/GameObjects/EntitySystems/ThrownItemSystem.cs b/Content.Shared/GameObjects/EntitySystems/ThrownItemSystem.cs new file mode 100644 index 0000000000..b4697e9225 --- /dev/null +++ b/Content.Shared/GameObjects/EntitySystems/ThrownItemSystem.cs @@ -0,0 +1,104 @@ +#nullable enable +using System.Collections.Generic; +using System.Linq; +using Content.Shared.GameObjects.Components.Items; +using Content.Shared.Interfaces.GameObjects.Components; +using Robust.Shared.GameObjects; +using Robust.Shared.Physics; + +namespace Content.Shared.GameObjects.EntitySystems +{ + /// + /// Handles throwing landing and collisions. + /// + public class ThrownItemSystem : EntitySystem + { + private List _throwCollide = new(); + + public override void Initialize() + { + base.Initialize(); + SubscribeLocalEvent(HandleSleep); + } + + public override void Shutdown() + { + base.Shutdown(); + UnsubscribeLocalEvent(); + } + + private void HandleSleep(PhysicsSleepMessage message) + { + // TODO: Sub to ThrownitemComponent + if (message.Body.Deleted || !message.Body.Owner.TryGetComponent(out ThrownItemComponent? thrownItem)) return; + + var user = thrownItem.Thrower; + var landing = message.Body.Owner; + var coordinates = landing.Transform.Coordinates; + + // LandInteraction + // TODO: Refactor these to system messages + var landMsg = new LandMessage(user, landing, coordinates); + RaiseLocalEvent(landMsg); + if (landMsg.Handled) + { + return; + } + + var comps = landing.GetAllComponents().ToArray(); + var landArgs = new LandEventArgs(user, coordinates); + + // Call Land on all components that implement the interface + foreach (var comp in comps) + { + if (landing.Deleted) break; + comp.Land(landArgs); + } + + ComponentManager.RemoveComponent(landing.Uid, thrownItem); + } + + /// + /// Calls ThrowCollide on all components that implement the IThrowCollide interface + /// on a thrown entity and the target entity it hit. + /// + public void ThrowCollideInteraction(IEntity? user, IPhysBody thrown, IPhysBody target) + { + // TODO: Just pass in the bodies directly + var collideMsg = new ThrowCollideMessage(user, thrown.Entity, target.Entity); + RaiseLocalEvent(collideMsg); + if (collideMsg.Handled) + { + return; + } + + var eventArgs = new ThrowCollideEventArgs(user, thrown.Entity, target.Entity); + + foreach (var comp in thrown.Entity.GetAllComponents()) + { + _throwCollide.Add(comp); + } + + foreach (var collide in _throwCollide) + { + if (thrown.Entity.Deleted) break; + collide.DoHit(eventArgs); + } + + _throwCollide.Clear(); + + foreach (var comp in target.Entity.GetAllComponents()) + { + _throwCollide.Add(comp); + } + + foreach (var collide in _throwCollide) + { + if (target.Entity.Deleted) break; + collide.HitBy(eventArgs); + } + + _throwCollide.Clear(); + } + } +} diff --git a/Content.Shared/Interfaces/GameObjects/Components/Interaction/ILand.cs b/Content.Shared/Interfaces/GameObjects/Components/Interaction/ILand.cs index 6ae20fbc2c..a296d58195 100644 --- a/Content.Shared/Interfaces/GameObjects/Components/Interaction/ILand.cs +++ b/Content.Shared/Interfaces/GameObjects/Components/Interaction/ILand.cs @@ -18,13 +18,13 @@ namespace Content.Shared.Interfaces.GameObjects.Components public class LandEventArgs : EventArgs { - public LandEventArgs(IEntity user, EntityCoordinates landingLocation) + public LandEventArgs(IEntity? user, EntityCoordinates landingLocation) { User = user; LandingLocation = landingLocation; } - public IEntity User { get; } + public IEntity? User { get; } public EntityCoordinates LandingLocation { get; } } @@ -42,7 +42,7 @@ namespace Content.Shared.Interfaces.GameObjects.Components /// /// Entity that threw the item. /// - public IEntity User { get; } + public IEntity? User { get; } /// /// Item that was thrown. @@ -54,7 +54,7 @@ namespace Content.Shared.Interfaces.GameObjects.Components /// public EntityCoordinates LandLocation { get; } - public LandMessage(IEntity user, IEntity thrown, EntityCoordinates landLocation) + public LandMessage(IEntity? user, IEntity thrown, EntityCoordinates landLocation) { User = user; Thrown = thrown; diff --git a/Content.Shared/Interfaces/GameObjects/Components/Interaction/IThrowCollide.cs b/Content.Shared/Interfaces/GameObjects/Components/Interaction/IThrowCollide.cs index d2392384e6..da811afe2d 100644 --- a/Content.Shared/Interfaces/GameObjects/Components/Interaction/IThrowCollide.cs +++ b/Content.Shared/Interfaces/GameObjects/Components/Interaction/IThrowCollide.cs @@ -18,7 +18,7 @@ namespace Content.Shared.Interfaces.GameObjects.Components /// /// The entity that threw and hit . /// - public IEntity User { get; } + public IEntity? User { get; } /// /// The entity thrown by that hit @@ -29,14 +29,12 @@ namespace Content.Shared.Interfaces.GameObjects.Components /// The entity hit with by /// public IEntity Target { get; } - public EntityCoordinates Location { get; } - public ThrowCollideEventArgs(IEntity user, IEntity thrown, IEntity target, EntityCoordinates location) + public ThrowCollideEventArgs(IEntity? user, IEntity thrown, IEntity target) { User = user; Thrown = thrown; Target = target; - Location = location; } } @@ -50,7 +48,7 @@ namespace Content.Shared.Interfaces.GameObjects.Components /// /// The entity that threw . /// - public IEntity User { get; } + public IEntity? User { get; } /// /// The entity thrown by that hit @@ -61,14 +59,12 @@ namespace Content.Shared.Interfaces.GameObjects.Components /// The entity hit with by /// public IEntity Target { get; } - public EntityCoordinates Location { get; } - public ThrowCollideMessage(IEntity user, IEntity thrown, IEntity target, EntityCoordinates location) + public ThrowCollideMessage(IEntity? user, IEntity thrown, IEntity target) { User = user; Thrown = thrown; Target = target; - Location = location; } } } diff --git a/Content.Shared/Maps/TurfHelpers.cs b/Content.Shared/Maps/TurfHelpers.cs index 379bfc2deb..6451324b7d 100644 --- a/Content.Shared/Maps/TurfHelpers.cs +++ b/Content.Shared/Maps/TurfHelpers.cs @@ -10,6 +10,7 @@ using Robust.Shared.IoC; using Robust.Shared.Map; using Robust.Shared.Maths; using Robust.Shared.Physics; +using Robust.Shared.Physics.Broadphase; namespace Content.Shared.Maps { @@ -181,7 +182,7 @@ namespace Content.Shared.Maps /// public static bool IsBlockedTurf(this TileRef turf, bool filterMobs) { - var physics = IoCManager.Resolve(); + var physics = EntitySystem.Get(); var worldBox = GetWorldTileBox(turf); diff --git a/Content.Shared/Physics/BulletController.cs b/Content.Shared/Physics/BulletController.cs deleted file mode 100644 index c54fc53553..0000000000 --- a/Content.Shared/Physics/BulletController.cs +++ /dev/null @@ -1,17 +0,0 @@ -#nullable enable -using Robust.Shared.GameObjects; -using Robust.Shared.Maths; -using Robust.Shared.Physics; - -namespace Content.Shared.Physics -{ - public class BulletController : VirtualController - { - public override IPhysicsComponent? ControlledComponent { protected get; set; } - - public void Push(Vector2 velocityDirection, float speed) - { - LinearVelocity = velocityDirection * speed; - } - } -} diff --git a/Content.Shared/Physics/ClimbController.cs b/Content.Shared/Physics/ClimbController.cs deleted file mode 100644 index a61be77317..0000000000 --- a/Content.Shared/Physics/ClimbController.cs +++ /dev/null @@ -1,89 +0,0 @@ -#nullable enable -using Robust.Shared.Maths; -using Robust.Shared.Physics; - -namespace Content.Shared.Physics -{ - /// - /// Movement controller used by the climb system. Lerps the player from A to B. - /// Also does checks to make sure the player isn't blocked. - /// - public class ClimbController : VirtualController - { - private Vector2? _movingTo = null; - private Vector2 _lastKnownPosition = default; - private int _numTicksBlocked = 0; - - /// - /// If 5 ticks have passed and our position has not changed then something is blocking us. - /// - public bool IsBlocked => _numTicksBlocked > 5 || _isMovingWrongDirection; - - /// - /// If the controller is currently moving the player somewhere, it is considered active. - /// - public bool IsActive => _movingTo.HasValue; - - private float _initialDist = default; - private bool _isMovingWrongDirection = false; - - public void TryMoveTo(Vector2 from, Vector2 to) - { - if (ControlledComponent == null) - { - return; - } - - _initialDist = (from - to).Length; - _numTicksBlocked = 0; - _lastKnownPosition = from; - _movingTo = to; - _isMovingWrongDirection = false; - } - - public override void UpdateAfterProcessing() - { - base.UpdateAfterProcessing(); - - if (ControlledComponent == null || _movingTo == null) - { - return; - } - - ControlledComponent.WakeBody(); - - if ((ControlledComponent.Owner.Transform.WorldPosition - _lastKnownPosition).Length <= 0.05f) - { - _numTicksBlocked++; - } - else - { - _numTicksBlocked = 0; - } - - _lastKnownPosition = ControlledComponent.Owner.Transform.WorldPosition; - - if ((ControlledComponent.Owner.Transform.WorldPosition - _movingTo.Value).Length <= 0.1f) - { - _movingTo = null; - } - - if (_movingTo.HasValue) - { - var dist = (_lastKnownPosition - _movingTo.Value).Length; - - if (dist > _initialDist) - { - _isMovingWrongDirection = true; - } - - var diff = _movingTo.Value - ControlledComponent.Owner.Transform.WorldPosition; - LinearVelocity = diff.Normalized * 5; - } - else - { - LinearVelocity = Vector2.Zero; - } - } - } -} diff --git a/Content.Shared/Physics/CollisionGroup.cs b/Content.Shared/Physics/CollisionGroup.cs index 1916e72dea..03be6c1fe9 100644 --- a/Content.Shared/Physics/CollisionGroup.cs +++ b/Content.Shared/Physics/CollisionGroup.cs @@ -2,6 +2,7 @@ using System; using JetBrains.Annotations; using Robust.Shared.Map; +using Robust.Shared.Physics.Dynamics; using Robust.Shared.Serialization; using RobustPhysics = Robust.Shared.Physics; @@ -11,7 +12,7 @@ namespace Content.Shared.Physics /// Defined collision groups for the physics system. /// [Flags, PublicAPI] - [FlagsFor(typeof(RobustPhysics.CollisionLayer)), FlagsFor(typeof(RobustPhysics.CollisionMask))] + [FlagsFor(typeof(CollisionLayer)), FlagsFor(typeof(CollisionMask))] public enum CollisionGroup { None = 0, diff --git a/Content.Shared/Physics/ContainmentFieldCollisionController.cs b/Content.Shared/Physics/ContainmentFieldCollisionController.cs deleted file mode 100644 index a9de254beb..0000000000 --- a/Content.Shared/Physics/ContainmentFieldCollisionController.cs +++ /dev/null @@ -1,10 +0,0 @@ -#nullable enable -using Robust.Shared.Physics; - -namespace Content.Shared.Physics -{ - public class ContainmentFieldCollisionController : VirtualController - { - - } -} diff --git a/Content.Shared/Physics/ContainmentFieldRepellController.cs b/Content.Shared/Physics/ContainmentFieldRepellController.cs deleted file mode 100644 index c878bf6f53..0000000000 --- a/Content.Shared/Physics/ContainmentFieldRepellController.cs +++ /dev/null @@ -1,13 +0,0 @@ -#nullable enable -using Robust.Shared.Maths; - -namespace Content.Shared.Physics -{ - public class ContainmentFieldRepellController : FrictionController - { - public void Repell(Direction dir, float speed) - { - LinearVelocity = dir.ToVec() * speed; - } - } -} diff --git a/Content.Shared/Physics/Controllers/SharedMoverController.cs b/Content.Shared/Physics/Controllers/SharedMoverController.cs new file mode 100644 index 0000000000..52ffecfe67 --- /dev/null +++ b/Content.Shared/Physics/Controllers/SharedMoverController.cs @@ -0,0 +1,143 @@ +#nullable enable +using Content.Shared.GameObjects.Components.Mobs.State; +using Content.Shared.GameObjects.Components.Movement; +using Content.Shared.GameObjects.Components.Pulling; +using Content.Shared.GameObjects.EntitySystems.ActionBlocker; +using Robust.Shared.GameObjects; +using Robust.Shared.IoC; +using Robust.Shared.Maths; +using Robust.Shared.Physics; +using Robust.Shared.Physics.Broadphase; +using Robust.Shared.Physics.Controllers; + +namespace Content.Shared.Physics.Controllers +{ + /// + /// Handles player and NPC mob movement. + /// NPCs are handled server-side only. + /// + public abstract class SharedMoverController : VirtualController + { + [Dependency] private readonly IPhysicsManager _physicsManager = default!; + + private SharedBroadPhaseSystem _broadPhaseSystem = default!; + + public override void Initialize() + { + base.Initialize(); + _broadPhaseSystem = EntitySystem.Get(); + } + + /// + /// A generic kinematic mover for entities. + /// + protected void HandleKinematicMovement(IMoverComponent mover, PhysicsComponent physicsComponent) + { + var (walkDir, sprintDir) = mover.VelocityDir; + + // Regular movement. + // Target velocity. + var total = (walkDir * mover.CurrentWalkSpeed + sprintDir * mover.CurrentSprintSpeed); + + if (total != Vector2.Zero) + { + mover.Owner.Transform.LocalRotation = total.GetDir().ToAngle(); + } + + physicsComponent.LinearVelocity = total; + } + + /// + /// Movement while considering actionblockers, weightlessness, etc. + /// + /// + /// + /// + protected void HandleMobMovement(IMoverComponent mover, PhysicsComponent physicsComponent, IMobMoverComponent mobMover) + { + // TODO: Look at https://gameworksdocs.nvidia.com/PhysX/4.1/documentation/physxguide/Manual/CharacterControllers.html?highlight=controller as it has some adviceo n kinematic controllersx + if (!UseMobMovement(_broadPhaseSystem, physicsComponent, _physicsManager)) + { + return; + } + + var transform = mover.Owner.Transform; + var (walkDir, sprintDir) = mover.VelocityDir; + + var weightless = transform.Owner.IsWeightless(_physicsManager); + + // Handle wall-pushes. + if (weightless) + { + // No gravity: is our entity touching anything? + var touching = IsAroundCollider(_broadPhaseSystem, transform, mobMover, physicsComponent); + + if (!touching) + { + transform.LocalRotation = physicsComponent.LinearVelocity.GetDir().ToAngle(); + return; + } + } + + // Regular movement. + // Target velocity. + var total = (walkDir * mover.CurrentWalkSpeed + sprintDir * mover.CurrentSprintSpeed); + + if (total != Vector2.Zero) + { + // This should have its event run during island solver soooo + transform.DeferUpdates = true; + transform.LocalRotation = total.GetDir().ToAngle(); + transform.DeferUpdates = false; + HandleFootsteps(mover, mobMover); + } + + physicsComponent.LinearVelocity = total; + } + + public static bool UseMobMovement(SharedBroadPhaseSystem broadPhaseSystem, PhysicsComponent body, IPhysicsManager? physicsManager = null) + { + return (body.BodyStatus == BodyStatus.OnGround) & + body.Owner.HasComponent() && + ActionBlockerSystem.CanMove(body.Owner) && + (!body.Owner.IsWeightless(physicsManager) || + body.Owner.TryGetComponent(out SharedPlayerMobMoverComponent? mover) && + IsAroundCollider(broadPhaseSystem, body.Owner.Transform, mover, body)); + } + + /// + /// Used for weightlessness to determine if we are near a wall. + /// + /// + /// + /// + /// + /// + public static bool IsAroundCollider(SharedBroadPhaseSystem broadPhaseSystem, ITransformComponent transform, IMobMoverComponent mover, IPhysBody collider) + { + var enlargedAABB = collider.GetWorldAABB().Enlarged(mover.GrabRange); + + foreach (var otherCollider in broadPhaseSystem.GetCollidingEntities(transform.MapID, enlargedAABB)) + { + if (otherCollider == collider) continue; // Don't try to push off of yourself! + + // Only allow pushing off of anchored things that have collision. + if (otherCollider.BodyType != BodyType.Static || + !otherCollider.CanCollide || + ((collider.CollisionMask & otherCollider.CollisionLayer) == 0 && + (otherCollider.CollisionMask & collider.CollisionLayer) == 0) || + (otherCollider.Entity.TryGetComponent(out SharedPullableComponent? pullable) && pullable.BeingPulled)) + { + continue; + } + + return true; + } + + return false; + } + + // TODO: Need a predicted client version that only plays for our own entity and then have server-side ignore our session (for that entity only) + protected virtual void HandleFootsteps(IMoverComponent mover, IMobMoverComponent mobMover) {} + } +} diff --git a/Content.Shared/Physics/Controllers/SharedTileFrictionController.cs b/Content.Shared/Physics/Controllers/SharedTileFrictionController.cs new file mode 100644 index 0000000000..6f0b89cee6 --- /dev/null +++ b/Content.Shared/Physics/Controllers/SharedTileFrictionController.cs @@ -0,0 +1,102 @@ +using System; +using Content.Shared.GameObjects.Components.Mobs.State; +using Content.Shared.GameObjects.Components.Movement; +using Content.Shared.GameObjects.EntitySystems.ActionBlocker; +using JetBrains.Annotations; +using Robust.Shared; +using Robust.Shared.Configuration; +using Robust.Shared.GameObjects; +using Robust.Shared.IoC; +using Robust.Shared.Map; +using Robust.Shared.Physics; +using Robust.Shared.Physics.Broadphase; +using Robust.Shared.Physics.Controllers; +using Robust.Shared.Physics.Dynamics; + +#nullable enable + +namespace Content.Shared.Physics.Controllers +{ + public sealed class SharedTileFrictionController : VirtualController + { + [Dependency] private readonly IConfigurationManager _configManager = default!; + [Dependency] private readonly IMapManager _mapManager = default!; + [Dependency] private readonly IPhysicsManager _physicsManager = default!; + [Dependency] private readonly ITileDefinitionManager _tileDefinitionManager = default!; + + private SharedBroadPhaseSystem _broadPhaseSystem = default!; + + private float _stopSpeed; + + private float _frictionModifier; + + public override void Initialize() + { + base.Initialize(); + _broadPhaseSystem = EntitySystem.Get(); + + _frictionModifier = _configManager.GetCVar(CCVars.TileFrictionModifier); + _configManager.OnValueChanged(CCVars.TileFrictionModifier, value => _frictionModifier = value); + + _stopSpeed = _configManager.GetCVar(CCVars.StopSpeed); + _configManager.OnValueChanged(CCVars.StopSpeed, value => _stopSpeed = value); + } + + public override void UpdateBeforeMapSolve(bool prediction, PhysicsMap map, float frameTime) + { + base.UpdateBeforeMapSolve(prediction, map, frameTime); + + foreach (var body in map.AwakeBodies) + { + if (prediction && !body.Predict) continue; + + var speed = body.LinearVelocity.Length; + + if (speed <= 0.0f || body.BodyStatus == BodyStatus.InAir) continue; + + // This is the *actual* amount that speed will drop by, we just do some multiplication around it to be easier. + var drop = 0.0f; + float control; + + // Only apply friction when it's not a mob (or the mob doesn't have control). + if (SharedMoverController.UseMobMovement(_broadPhaseSystem, body, _physicsManager)) continue; + + var surfaceFriction = GetTileFriction(body); + var bodyModifier = body.Owner.GetComponentOrNull()?.Modifier ?? 1.0f; + var friction = _frictionModifier * surfaceFriction * bodyModifier; + + if (friction > 0.0f) + { + // TBH I can't really tell if this makes a difference. + if (!prediction) + { + control = speed < _stopSpeed ? _stopSpeed : speed; + } + else + { + control = speed; + } + + drop += control * friction * frameTime; + } + + var newSpeed = MathF.Max(0.0f, speed - drop); + + newSpeed /= speed; + body.LinearVelocity *= newSpeed; + } + } + + [Pure] + private float GetTileFriction(IPhysBody body) + { + // TODO: Make IsWeightless event-based; we already have grid traversals tracked so just raise events + if (body.BodyStatus == BodyStatus.InAir || body.Owner.IsWeightless(_physicsManager) || !_mapManager.TryGetGrid(body.Owner.Transform.GridID, out var grid)) + return 0.0f; + + var tile = grid.GetTileRef(body.Owner.Transform.Coordinates); + var tileDef = _tileDefinitionManager[tile.Tile.TypeId]; + return tileDef.Friction; + } + } +} diff --git a/Content.Shared/Physics/ConveyedController.cs b/Content.Shared/Physics/ConveyedController.cs deleted file mode 100644 index 226b5335a3..0000000000 --- a/Content.Shared/Physics/ConveyedController.cs +++ /dev/null @@ -1,62 +0,0 @@ -#nullable enable -using Content.Shared.GameObjects.Components.Movement; -using Robust.Shared.GameObjects; -using Robust.Shared.Maths; -using Robust.Shared.Physics; - -namespace Content.Shared.Physics -{ - public class ConveyedController : VirtualController - { - public override IPhysicsComponent? ControlledComponent { protected get; set; } - - public void Move(Vector2 velocityDirection, float speed, Vector2 itemRelativeToConveyor) - { - if (ControlledComponent?.Owner.IsWeightless() ?? false) - { - return; - } - - if (ControlledComponent?.Status == BodyStatus.InAir) - { - return; - } - - LinearVelocity = velocityDirection * speed; - - //gravitating item towards center - //http://csharphelper.com/blog/2016/09/find-the-shortest-distance-between-a-point-and-a-line-segment-in-c/ - Vector2 centerPoint; - - var t = 0f; - if (velocityDirection.Length > 0) //if velocitydirection is 0, this calculation will divide by 0 - { - t = Vector2.Dot(itemRelativeToConveyor, velocityDirection) / - Vector2.Dot(velocityDirection, velocityDirection); - } - - if (t < 0) - { - centerPoint = new Vector2(); - } - else if(t > 1) - { - centerPoint = velocityDirection; - } - else - { - centerPoint = velocityDirection * t; - } - - var delta = centerPoint - itemRelativeToConveyor; - LinearVelocity += delta * (4 * delta.Length); - } - - public override void UpdateAfterProcessing() - { - base.UpdateAfterProcessing(); - - LinearVelocity = Vector2.Zero; - } - } -} diff --git a/Content.Shared/Physics/FrictionController.cs b/Content.Shared/Physics/FrictionController.cs deleted file mode 100644 index f4fd3c2964..0000000000 --- a/Content.Shared/Physics/FrictionController.cs +++ /dev/null @@ -1,24 +0,0 @@ -#nullable enable -using System; -using Robust.Shared.IoC; -using Robust.Shared.Physics; - -namespace Content.Shared.Physics -{ - public abstract class FrictionController : VirtualController - { - [Dependency] private readonly IPhysicsManager _physicsManager = default!; - - public override void UpdateAfterProcessing() - { - base.UpdateAfterProcessing(); - - if (ControlledComponent != null && !_physicsManager.IsWeightless(ControlledComponent.Owner.Transform.Coordinates)) - { - LinearVelocity *= 0.85f; - if (MathF.Abs(LinearVelocity.Length) < 1f) - Stop(); - } - } - } -} diff --git a/Content.Shared/Physics/MoverController.cs b/Content.Shared/Physics/MoverController.cs deleted file mode 100644 index 1124806330..0000000000 --- a/Content.Shared/Physics/MoverController.cs +++ /dev/null @@ -1,33 +0,0 @@ -#nullable enable -using Content.Shared.GameObjects.Components.Movement; -using Robust.Shared.GameObjects; -using Robust.Shared.Maths; -using Robust.Shared.Physics; - -namespace Content.Shared.Physics -{ - public class MoverController : VirtualController - { - public override IPhysicsComponent? ControlledComponent { protected get; set; } - - public void Move(Vector2 velocityDirection, float speed) - { - if (ControlledComponent?.Owner.IsWeightless() ?? false) - { - return; - } - - Push(velocityDirection, speed); - } - - public void Push(Vector2 velocityDirection, float speed) - { - LinearVelocity = velocityDirection * speed; - } - - public void StopMoving() - { - LinearVelocity = Vector2.Zero; - } - } -} diff --git a/Content.Shared/Physics/Pull/PullAttemptMessage.cs b/Content.Shared/Physics/Pull/PullAttemptMessage.cs index bc8870044f..945d58f678 100644 --- a/Content.Shared/Physics/Pull/PullAttemptMessage.cs +++ b/Content.Shared/Physics/Pull/PullAttemptMessage.cs @@ -1,11 +1,11 @@ #nullable enable -using Robust.Shared.GameObjects; +using Robust.Shared.Physics; namespace Content.Shared.Physics.Pull { public class PullAttemptMessage : PullMessage { - public PullAttemptMessage(IPhysicsComponent puller, IPhysicsComponent pulled) : base(puller, pulled) { } + public PullAttemptMessage(IPhysBody puller, IPhysBody pulled) : base(puller, pulled) { } public bool Cancelled { get; set; } } diff --git a/Content.Shared/Physics/Pull/PullController.cs b/Content.Shared/Physics/Pull/PullController.cs deleted file mode 100644 index b29643116d..0000000000 --- a/Content.Shared/Physics/Pull/PullController.cs +++ /dev/null @@ -1,190 +0,0 @@ -#nullable enable -using System; -using System.Linq; -using Robust.Shared.Containers; -using Robust.Shared.GameObjects; -using Robust.Shared.IoC; -using Robust.Shared.Map; -using Robust.Shared.Maths; -using Robust.Shared.Physics; -using Content.Shared.GameObjects.Components.Pulling; -using static Content.Shared.GameObjects.EntitySystems.SharedInteractionSystem; - -namespace Content.Shared.Physics.Pull -{ - /// - /// This is applied upon a Pullable object when that object is being pulled. - /// It lives only to serve that Pullable object. - /// - public class PullController : VirtualController - { - [Dependency] private readonly IEntityManager _entityManager = default!; - [Dependency] private readonly IPhysicsManager _physicsManager = default!; - - private const float DistBeforeStopPull = InteractionRange; - - private const float StopMoveThreshold = 0.25f; - - /// - /// The managing SharedPullableComponent of this PullController. - /// MUST BE SET! If you go attaching PullControllers yourself, YOU ARE DOING IT WRONG. - /// If you get a crash based on such, then, well, see previous note. - /// This is set by the SharedPullableComponent attaching the PullController. - /// - public SharedPullableComponent Manager = default!; - - private EntityCoordinates? _movingTo; - - public EntityCoordinates? MovingTo - { - get => _movingTo; - set - { - if (_movingTo == value || ControlledComponent == null) - { - return; - } - - _movingTo = value; - ControlledComponent.WakeBody(); - } - } - - private bool PullerMovingTowardsPulled() - { - var _puller = Manager.PullerPhysics; - if (_puller == null) - { - return false; - } - - if (ControlledComponent == null) - { - return false; - } - - if (_puller.LinearVelocity.EqualsApprox(Vector2.Zero)) - { - return false; - } - - var pullerTransform = _puller.Owner.Transform; - var origin = pullerTransform.Coordinates.Position; - var velocity = _puller.LinearVelocity.Normalized; - var mapId = pullerTransform.MapPosition.MapId; - var ray = new CollisionRay(origin, velocity, (int) CollisionGroup.AllMask); - bool Predicate(IEntity e) => e != ControlledComponent.Owner; - var rayResults = - _physicsManager.IntersectRayWithPredicate(mapId, ray, DistBeforeStopPull, Predicate); - - return rayResults.Any(); - } - - public bool TryMoveTo(EntityCoordinates from, EntityCoordinates to) - { - var _puller = Manager.PullerPhysics; - if (_puller == null || ControlledComponent == null) - { - return false; - } - - if (!_puller.Owner.Transform.Coordinates.InRange(_entityManager, from, InteractionRange)) - { - return false; - } - - if (!_puller.Owner.Transform.Coordinates.InRange(_entityManager, to, InteractionRange)) - { - return false; - } - - if (!from.InRange(_entityManager, to, InteractionRange)) - { - return false; - } - - if (from.Position.EqualsApprox(to.Position)) - { - return false; - } - - if (!_puller.Owner.Transform.Coordinates.TryDistance(_entityManager, to, out var distance) || - Math.Sqrt(distance) > DistBeforeStopPull || - Math.Sqrt(distance) < StopMoveThreshold) - { - return false; - } - - MovingTo = to; - return true; - } - - public override void UpdateBeforeProcessing() - { - var _puller = Manager.PullerPhysics; - if (_puller == null || ControlledComponent == null) - { - return; - } - - if (!_puller.Owner.IsInSameOrNoContainer(ControlledComponent.Owner)) - { - Manager.Puller = null; - return; - } - - var distance = _puller.Owner.Transform.WorldPosition - ControlledComponent.Owner.Transform.WorldPosition; - - if (distance.Length > DistBeforeStopPull) - { - Manager.Puller = null; - } - else if (MovingTo.HasValue) - { - var diff = MovingTo.Value.Position - ControlledComponent.Owner.Transform.Coordinates.Position; - LinearVelocity = diff.Normalized * 5; - } - else - { - if (PullerMovingTowardsPulled()) - { - LinearVelocity = Vector2.Zero; - return; - } - - var distanceAbs = Vector2.Abs(distance); - var totalAabb = _puller.AABB.Size + ControlledComponent.AABB.Size / 2; - if (distanceAbs.X < totalAabb.X && distanceAbs.Y < totalAabb.Y) - { - LinearVelocity = Vector2.Zero; - return; - } - - LinearVelocity = distance.Normalized * _puller.LinearVelocity.Length * 1.5f; - } - } - - public override void UpdateAfterProcessing() - { - base.UpdateAfterProcessing(); - - if (ControlledComponent == null) - { - MovingTo = null; - return; - } - - if (MovingTo != null && - ControlledComponent.Owner.Transform.Coordinates.Position.EqualsApprox(MovingTo.Value.Position, 0.01)) - { - MovingTo = null; - } - - if (LinearVelocity != Vector2.Zero) - { - var angle = LinearVelocity.ToAngle(); - ControlledComponent.Owner.Transform.LocalRotation = angle; - } - } - } -} diff --git a/Content.Shared/Physics/Pull/PullMessage.cs b/Content.Shared/Physics/Pull/PullMessage.cs index a65957bc84..d72e15d642 100644 --- a/Content.Shared/Physics/Pull/PullMessage.cs +++ b/Content.Shared/Physics/Pull/PullMessage.cs @@ -1,14 +1,15 @@ #nullable enable using Robust.Shared.GameObjects; +using Robust.Shared.Physics; namespace Content.Shared.Physics.Pull { public class PullMessage : ComponentMessage { - public readonly IPhysicsComponent Puller; - public readonly IPhysicsComponent Pulled; + public readonly IPhysBody Puller; + public readonly IPhysBody Pulled; - protected PullMessage(IPhysicsComponent puller, IPhysicsComponent pulled) + protected PullMessage(IPhysBody puller, IPhysBody pulled) { Puller = puller; Pulled = pulled; diff --git a/Content.Shared/Physics/Pull/PullStartedMessage.cs b/Content.Shared/Physics/Pull/PullStartedMessage.cs index 2dd84a84fd..0f138cf12c 100644 --- a/Content.Shared/Physics/Pull/PullStartedMessage.cs +++ b/Content.Shared/Physics/Pull/PullStartedMessage.cs @@ -1,11 +1,11 @@ #nullable enable -using Robust.Shared.GameObjects; +using Robust.Shared.Physics; namespace Content.Shared.Physics.Pull { public class PullStartedMessage : PullMessage { - public PullStartedMessage(IPhysicsComponent puller, IPhysicsComponent pulled) : + public PullStartedMessage(IPhysBody puller, IPhysBody pulled) : base(puller, pulled) { } diff --git a/Content.Shared/Physics/Pull/PullStoppedMessage.cs b/Content.Shared/Physics/Pull/PullStoppedMessage.cs index 215dae4aee..0b91a38d83 100644 --- a/Content.Shared/Physics/Pull/PullStoppedMessage.cs +++ b/Content.Shared/Physics/Pull/PullStoppedMessage.cs @@ -1,11 +1,11 @@ #nullable enable -using Robust.Shared.GameObjects; +using Robust.Shared.Physics; namespace Content.Shared.Physics.Pull { public class PullStoppedMessage : PullMessage { - public PullStoppedMessage(IPhysicsComponent puller, IPhysicsComponent pulled) : base(puller, pulled) + public PullStoppedMessage(IPhysBody puller, IPhysBody pulled) : base(puller, pulled) { } } diff --git a/Content.Shared/Physics/ShuttleController.cs b/Content.Shared/Physics/ShuttleController.cs deleted file mode 100644 index ed986d1e5e..0000000000 --- a/Content.Shared/Physics/ShuttleController.cs +++ /dev/null @@ -1,17 +0,0 @@ -#nullable enable -using Robust.Shared.GameObjects; -using Robust.Shared.Maths; -using Robust.Shared.Physics; - -namespace Content.Shared.Physics -{ - public class ShuttleController : VirtualController - { - public override IPhysicsComponent? ControlledComponent { protected get; set; } - - public void Push(Vector2 velocityDirection, float speed) - { - LinearVelocity = velocityDirection * speed; - } - } -} diff --git a/Content.Shared/Physics/SingularityController.cs b/Content.Shared/Physics/SingularityController.cs deleted file mode 100644 index c9dd44b1d2..0000000000 --- a/Content.Shared/Physics/SingularityController.cs +++ /dev/null @@ -1,18 +0,0 @@ -#nullable enable -using Robust.Shared.GameObjects; -using Robust.Shared.Maths; -using Robust.Shared.Physics; - -namespace Content.Shared.Physics -{ - public class SingularityController : VirtualController - { - public override IPhysicsComponent? ControlledComponent { protected get; set; } - - - public void Push(Vector2 velocityDirection, float speed) - { - LinearVelocity = velocityDirection * speed; - } - } -} diff --git a/Content.Shared/Physics/SingularityPullController.cs b/Content.Shared/Physics/SingularityPullController.cs deleted file mode 100644 index 66f4fa0c90..0000000000 --- a/Content.Shared/Physics/SingularityPullController.cs +++ /dev/null @@ -1,22 +0,0 @@ -#nullable enable -using Robust.Shared.GameObjects; -using Robust.Shared.Maths; -using Robust.Shared.Physics; - -namespace Content.Server.GameObjects.Components.Singularity -{ - public class SingularityPullController : VirtualController - { - public override IPhysicsComponent? ControlledComponent { protected get; set; } - - public void StopPull() - { - LinearVelocity = Vector2.Zero; - } - - public void Pull(Vector2 velocityDirection, float speed) - { - LinearVelocity = velocityDirection * speed; - } - } -} diff --git a/Content.Shared/Physics/SlipController.cs b/Content.Shared/Physics/SlipController.cs deleted file mode 100644 index bc64449a09..0000000000 --- a/Content.Shared/Physics/SlipController.cs +++ /dev/null @@ -1,44 +0,0 @@ -#nullable enable -using Robust.Shared.IoC; -using Robust.Shared.Maths; -using Robust.Shared.Physics; - -namespace Content.Shared.Physics -{ - public class SlipController : VirtualController - { - [Dependency] private readonly IPhysicsManager _physicsManager = default!; - - public SlipController() - { - IoCManager.InjectDependencies(this); - } - - private float Decay { get; set; } = 0.95f; - - public override void UpdateAfterProcessing() - { - if (ControlledComponent == null) - { - return; - } - - if (_physicsManager.IsWeightless(ControlledComponent.Owner.Transform.Coordinates)) - { - if (ControlledComponent.IsColliding(Vector2.Zero, false)) - { - Stop(); - } - - return; - } - - LinearVelocity *= Decay; - - if (LinearVelocity.Length < 0.001) - { - Stop(); - } - } - } -} diff --git a/Content.Shared/Physics/ThrowKnockbackController.cs b/Content.Shared/Physics/ThrowKnockbackController.cs deleted file mode 100644 index 6a7dc2ecb1..0000000000 --- a/Content.Shared/Physics/ThrowKnockbackController.cs +++ /dev/null @@ -1,50 +0,0 @@ -#nullable enable -using Content.Shared.GameObjects.Components.Movement; -using Content.Shared.GameObjects.EntitySystems.ActionBlocker; -using Robust.Shared.IoC; -using Robust.Shared.Maths; -using Robust.Shared.Physics; - -namespace Content.Shared.Physics -{ - public class ThrowKnockbackController : VirtualController - { - public ThrowKnockbackController() - { - IoCManager.InjectDependencies(this); - } - - public void Push(Vector2 velocityDirection, float speed) - { - LinearVelocity = velocityDirection * speed; - } - - private float Decay { get; set; } = 0.95f; - - public override void UpdateAfterProcessing() - { - if (ControlledComponent == null) - { - return; - } - - if (ControlledComponent.Owner.IsWeightless()) - { - if (ActionBlockerSystem.CanMove(ControlledComponent.Owner) - && ControlledComponent.IsColliding(Vector2.Zero, false)) - { - Stop(); - } - - return; - } - - LinearVelocity *= Decay; - - if (LinearVelocity.Length < 0.001) - { - Stop(); - } - } - } -} diff --git a/Content.Shared/Physics/ThrownController.cs b/Content.Shared/Physics/ThrownController.cs deleted file mode 100644 index 8b836b969b..0000000000 --- a/Content.Shared/Physics/ThrownController.cs +++ /dev/null @@ -1,17 +0,0 @@ -#nullable enable -using Robust.Shared.GameObjects; -using Robust.Shared.Maths; -using Robust.Shared.Physics; - -namespace Content.Shared.Physics -{ - public class ThrownController : VirtualController - { - public override IPhysicsComponent? ControlledComponent { protected get; set; } - - public void Push(Vector2 velocityDirection, float speed) - { - LinearVelocity = velocityDirection * speed; - } - } -} diff --git a/Content.Shared/Physics/VaporController.cs b/Content.Shared/Physics/VaporController.cs deleted file mode 100644 index b2cfa5c774..0000000000 --- a/Content.Shared/Physics/VaporController.cs +++ /dev/null @@ -1,14 +0,0 @@ -#nullable enable -using Robust.Shared.Maths; -using Robust.Shared.Physics; - -namespace Content.Shared.Physics -{ - public class VaporController : VirtualController - { - public void Move(Vector2 velocityDirection, float speed) - { - LinearVelocity = velocityDirection * speed; - } - } -} diff --git a/Content.Shared/Utility/EntitySystemExtensions.cs b/Content.Shared/Utility/EntitySystemExtensions.cs index b06d595583..6757021388 100644 --- a/Content.Shared/Utility/EntitySystemExtensions.cs +++ b/Content.Shared/Utility/EntitySystemExtensions.cs @@ -6,6 +6,7 @@ using Robust.Shared.IoC; using Robust.Shared.Map; using Robust.Shared.Maths; using Robust.Shared.Physics; +using Robust.Shared.Physics.Broadphase; namespace Content.Shared.Utility { @@ -17,9 +18,9 @@ namespace Content.Shared.Utility EntityCoordinates coordinates, CollisionGroup collisionLayer, in Box2? box = null, - IPhysicsManager? physicsManager = null) + SharedBroadPhaseSystem? physicsManager = null) { - physicsManager ??= IoCManager.Resolve(); + physicsManager ??= EntitySystem.Get(); var mapCoordinates = coordinates.ToMap(entityManager); return entityManager.SpawnIfUnobstructed(prototypeName, mapCoordinates, collisionLayer, box, physicsManager); @@ -31,18 +32,19 @@ namespace Content.Shared.Utility MapCoordinates coordinates, CollisionGroup collisionLayer, in Box2? box = null, - IPhysicsManager? physicsManager = null) + SharedBroadPhaseSystem? collision = null) { var boxOrDefault = box.GetValueOrDefault(Box2.UnitCentered); - physicsManager ??= IoCManager.Resolve(); + collision ??= EntitySystem.Get(); - foreach (var body in physicsManager.GetCollidingEntities(coordinates.MapId, in boxOrDefault)) + foreach (var body in collision.GetCollidingEntities(coordinates.MapId, in boxOrDefault)) { if (!body.Hard) { continue; } + // TODO: wtf fix this if (collisionLayer == 0 || (body.CollisionMask & (int) collisionLayer) == 0) { continue; @@ -61,7 +63,7 @@ namespace Content.Shared.Utility CollisionGroup collisionLayer, [NotNullWhen(true)] out IEntity? entity, Box2? box = null, - IPhysicsManager? physicsManager = null) + SharedBroadPhaseSystem? physicsManager = null) { entity = entityManager.SpawnIfUnobstructed(prototypeName, coordinates, collisionLayer, box, physicsManager); @@ -75,7 +77,7 @@ namespace Content.Shared.Utility CollisionGroup collisionLayer, [NotNullWhen(true)] out IEntity? entity, in Box2? box = null, - IPhysicsManager? physicsManager = null) + SharedBroadPhaseSystem? physicsManager = null) { entity = entityManager.SpawnIfUnobstructed(prototypeName, coordinates, collisionLayer, box, physicsManager); diff --git a/Content.Tools/test/0A.yml b/Content.Tools/test/0A.yml index d977df527a..9399d2d377 100644 --- a/Content.Tools/test/0A.yml +++ b/Content.Tools/test/0A.yml @@ -88,8 +88,9 @@ entities: type: Transform - index: 0 type: MapGrid - - shapes: - - !type:PhysShapeGrid - grid: 0 + - fixtures: + - shape: + !type:PhysShapeGrid + grid: 0 type: Physics diff --git a/Content.Tools/test/0B.yml b/Content.Tools/test/0B.yml index 27430439da..9d9c99e9c2 100644 --- a/Content.Tools/test/0B.yml +++ b/Content.Tools/test/0B.yml @@ -79,7 +79,7 @@ entities: type: Transform - index: 0 type: MapGrid - - shapes: + - fixtures: - !type:PhysShapeGrid grid: 0 type: Physics diff --git a/Content.Tools/test/0C.yml b/Content.Tools/test/0C.yml index 9d1634c44f..de44d5871b 100644 --- a/Content.Tools/test/0C.yml +++ b/Content.Tools/test/0C.yml @@ -98,8 +98,9 @@ entities: type: Transform - index: 0 type: MapGrid - - shapes: - - !type:PhysShapeGrid - grid: 0 + - fixtures: + - shape: + !type:PhysShapeGrid + grid: 0 type: Physics diff --git a/Resources/Maps/Test/Breathing/3by3-20oxy-80nit.yml b/Resources/Maps/Test/Breathing/3by3-20oxy-80nit.yml index a47f06d7ff..a84d8fd881 100644 --- a/Resources/Maps/Test/Breathing/3by3-20oxy-80nit.yml +++ b/Resources/Maps/Test/Breathing/3by3-20oxy-80nit.yml @@ -52,9 +52,10 @@ entities: type: Transform - index: 0 type: MapGrid - - shapes: - - !type:PhysShapeGrid - grid: 0 + - fixtures: + - shape: + !type:PhysShapeGrid + grid: 0 type: Physics - uniqueMixes: - volume: 2500 diff --git a/Resources/Maps/Test/empty.yml b/Resources/Maps/Test/empty.yml index 2309b1be44..e9979e70cf 100644 --- a/Resources/Maps/Test/empty.yml +++ b/Resources/Maps/Test/empty.yml @@ -47,8 +47,9 @@ entities: type: Transform - index: 0 type: MapGrid - - shapes: - - !type:PhysShapeGrid - grid: 0 + - fixtures: + - shape: + !type:PhysShapeGrid + grid: 0 type: Physics ... diff --git a/Resources/Maps/Test/singularity.yml b/Resources/Maps/Test/singularity.yml index 32355336d2..d0f0c444fe 100644 --- a/Resources/Maps/Test/singularity.yml +++ b/Resources/Maps/Test/singularity.yml @@ -77,9 +77,10 @@ entities: type: Transform - index: 0 type: MapGrid - - shapes: - - !type:PhysShapeGrid - grid: 0 + - fixtures: + - shape: + !type:PhysShapeGrid + grid: 0 type: Physics - uniqueMixes: - volume: 2500 diff --git a/Resources/Maps/saltern.yml b/Resources/Maps/saltern.yml index 76a2219e55..1372a8d8ef 100644 --- a/Resources/Maps/saltern.yml +++ b/Resources/Maps/saltern.yml @@ -615,7 +615,7 @@ entities: pos: 39.5,-1.5 rot: 4.371139006309477E-08 rad type: Transform - - anchored: False + - bodyType: Dynamic type: Physics - containers: PowerCellCharger-powerCellContainer: !type:ContainerSlot {} @@ -5115,7 +5115,7 @@ entities: pos: -8.5,8.5 rot: 1.5707963705062866 rad type: Transform - - anchored: False + - bodyType: Dynamic type: Physics - uid: 577 type: ChairOfficeDark @@ -5124,7 +5124,7 @@ entities: pos: -9.5,7.5 rot: 4.371139006309477E-08 rad type: Transform - - anchored: False + - bodyType: Dynamic type: Physics - uid: 578 type: TableR @@ -7933,9 +7933,10 @@ entities: type: Transform - index: 0 type: MapGrid - - shapes: - - !type:PhysShapeGrid - grid: 0 + - fixtures: + - shape: + !type:PhysShapeGrid + grid: 0 type: Physics - uniqueMixes: - volume: 2500 @@ -12661,7 +12662,7 @@ entities: pos: 10.5,17.5 rot: 4.71238902409608 rad type: Transform - - anchored: False + - bodyType: Dynamic type: Physics - uid: 955 type: Chair @@ -12670,7 +12671,7 @@ entities: pos: 8.5,17.5 rot: 1.5707963705062866 rad type: Transform - - anchored: False + - bodyType: Dynamic type: Physics - uid: 956 type: Table @@ -12712,7 +12713,7 @@ entities: pos: 0.5,31.5 rot: 3.141592697301183 rad type: Transform - - anchored: False + - bodyType: Dynamic type: Physics - uid: 961 type: ComputerMedicalRecords @@ -12728,7 +12729,7 @@ entities: pos: 7.5,31.5 rot: 3.141592697301183 rad type: Transform - - anchored: False + - bodyType: Dynamic type: Physics - uid: 963 type: ChairOfficeDark @@ -12737,7 +12738,7 @@ entities: pos: -2.5,25.5 rot: 1.5707963705062866 rad type: Transform - - anchored: False + - bodyType: Dynamic type: Physics - uid: 964 type: ChairOfficeDark @@ -12746,7 +12747,7 @@ entities: pos: -2.5,24.5 rot: 1.5707963705062866 rad type: Transform - - anchored: False + - bodyType: Dynamic type: Physics - uid: 965 type: ChairOfficeDark @@ -12755,7 +12756,7 @@ entities: pos: -0.5,25.5 rot: 4.71238902409608 rad type: Transform - - anchored: False + - bodyType: Dynamic type: Physics - uid: 966 type: ChairOfficeDark @@ -12764,7 +12765,7 @@ entities: pos: -0.5,24.5 rot: 4.71238902409608 rad type: Transform - - anchored: False + - bodyType: Dynamic type: Physics - uid: 967 type: TableWood @@ -12866,7 +12867,7 @@ entities: pos: 7.5,25.5 rot: 1.5707963705062866 rad type: Transform - - anchored: False + - bodyType: Dynamic type: Physics - uid: 979 type: ChairOfficeDark @@ -12875,7 +12876,7 @@ entities: pos: 9.5,25.5 rot: 4.71238902409608 rad type: Transform - - anchored: False + - bodyType: Dynamic type: Physics - uid: 980 type: ComputerComms @@ -12896,7 +12897,7 @@ entities: pos: 3.5,31.5 rot: 3.141592697301183 rad type: Transform - - anchored: False + - bodyType: Dynamic type: Physics - uid: 982 type: TableWood @@ -13017,7 +13018,7 @@ entities: pos: 22.5,-14.5 rot: 1.5707963705062866 rad type: Transform - - anchored: False + - bodyType: Dynamic type: Physics - uid: 997 type: ApcExtensionCable @@ -13404,7 +13405,7 @@ entities: pos: -8.5,-18.5 rot: 3.141592697301183 rad type: Transform - - anchored: False + - bodyType: Dynamic type: Physics - uid: 1046 type: ChairOfficeLight @@ -13413,7 +13414,7 @@ entities: pos: -9.5,-17.5 rot: 1.5707963705062866 rad type: Transform - - anchored: False + - bodyType: Dynamic type: Physics - uid: 1047 type: Table @@ -13436,7 +13437,7 @@ entities: pos: -5.5,-23.5 rot: 1.5707963705062866 rad type: Transform - - anchored: False + - bodyType: Dynamic type: Physics - uid: 1050 type: ChairOfficeLight @@ -13445,7 +13446,7 @@ entities: pos: -0.5,-14.5 rot: 1.5707963705062866 rad type: Transform - - anchored: False + - bodyType: Dynamic type: Physics - uid: 1051 type: BaseResearchAndDevelopmentPointSource @@ -13885,7 +13886,7 @@ entities: pos: 24.5,-14.5 rot: 4.71238902409608 rad type: Transform - - anchored: False + - bodyType: Dynamic type: Physics - uid: 1098 type: Table @@ -14440,7 +14441,7 @@ entities: pos: 28.5,1.5 rot: 4.371139006309477E-08 rad type: Transform - - anchored: False + - bodyType: Dynamic type: Physics - uid: 1166 type: Chair @@ -14449,7 +14450,7 @@ entities: pos: 26.5,1.5 rot: 4.371139006309477E-08 rad type: Transform - - anchored: False + - bodyType: Dynamic type: Physics - uid: 1167 type: LockerHeadOfSecurityFilled @@ -14539,7 +14540,7 @@ entities: pos: 6.5,-4.5 rot: 3.141592697301183 rad type: Transform - - anchored: False + - bodyType: Dynamic type: Physics - uid: 1178 type: Table @@ -14809,7 +14810,7 @@ entities: pos: -11.5,8.5 rot: 4.71238902409608 rad type: Transform - - anchored: False + - bodyType: Dynamic type: Physics - uid: 1209 type: Chair @@ -14818,7 +14819,7 @@ entities: pos: -13.5,8.5 rot: 1.5707963705062866 rad type: Transform - - anchored: False + - bodyType: Dynamic type: Physics - uid: 1210 type: Food4NoRaisins @@ -16250,7 +16251,7 @@ entities: pos: 10.5,-16.5 rot: 4.71238902409608 rad type: Transform - - anchored: False + - bodyType: Dynamic type: Physics - uid: 1339 type: ChairOfficeLight @@ -16259,7 +16260,7 @@ entities: pos: 14.5,0.5 rot: 4.71238902409608 rad type: Transform - - anchored: False + - bodyType: Dynamic type: Physics - uid: 1340 type: Poweredlight @@ -17857,7 +17858,7 @@ entities: pos: -3.5,-23.5 rot: 4.71238902409608 rad type: Transform - - anchored: False + - bodyType: Dynamic type: Physics - uid: 1536 type: Chair @@ -17866,7 +17867,7 @@ entities: pos: 38.5,-0.5 rot: 1.5707963705062866 rad type: Transform - - anchored: False + - bodyType: Dynamic type: Physics - uid: 1537 type: Table @@ -18119,7 +18120,7 @@ entities: pos: 30.5,-2.5 rot: 4.71238902409608 rad type: Transform - - anchored: False + - bodyType: Dynamic type: Physics - uid: 1572 type: Catwalk @@ -24174,7 +24175,7 @@ entities: pos: 40.5,-0.5 rot: 4.71238902409608 rad type: Transform - - anchored: False + - bodyType: Dynamic type: Physics - uid: 2428 type: solid_wall diff --git a/Resources/Prototypes/Entities/Constructible/Doors/airlock_base.yml b/Resources/Prototypes/Entities/Constructible/Doors/airlock_base.yml index aed87f266b..e7f8e5877a 100644 --- a/Resources/Prototypes/Entities/Constructible/Doors/airlock_base.yml +++ b/Resources/Prototypes/Entities/Constructible/Doors/airlock_base.yml @@ -24,9 +24,10 @@ - state: panel_open map: ["enum.WiresVisualLayers.MaintenancePanel"] - type: Physics - shapes: - - !type:PhysShapeAabb - bounds: "-0.49,-0.49,0.49,0.49" # don't want this colliding with walls or they won't close + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.49,-0.49,0.49,0.49" # don't want this colliding with walls or they won't close mask: - MobImpassable layer: diff --git a/Resources/Prototypes/Entities/Constructible/Doors/firelock.yml b/Resources/Prototypes/Entities/Constructible/Doors/firelock.yml index 4100d6dc85..94df24b331 100644 --- a/Resources/Prototypes/Entities/Constructible/Doors/firelock.yml +++ b/Resources/Prototypes/Entities/Constructible/Doors/firelock.yml @@ -34,18 +34,19 @@ map: ["enum.WiresVisualLayers.MaintenancePanel"] - type: Physics - on: false - shapes: - - !type:PhysShapeAabb - bounds: "-0.49,-0.49,0.49,0.49" # don't want this colliding with walls or they won't close - mask: - - MobImpassable - layer: - - Opaque - - Impassable - - MobImpassable - - VaultImpassable - - SmallImpassable + canCollide: false + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.49,-0.49,0.49,0.49" # don't want this colliding with walls or they won't close + mask: + - MobImpassable + layer: + - Opaque + - Impassable + - MobImpassable + - VaultImpassable + - SmallImpassable - type: Door closeTimeOne: 0.1 closeTimeTwo: 0.6 @@ -110,14 +111,15 @@ airBlockedDirection: - East - type: Physics - shapes: - - !type:PhysShapeRect - bounds: "0.49,-0.49,-0.49,-0.2" # don't want this colliding with walls or they won't close - mask: - - MobImpassable - layer: - - Opaque - - Impassable - - MobImpassable - - VaultImpassable - - SmallImpassable + fixtures: + - shape: + !type:PhysShapeRect + bounds: "0.49,-0.49,-0.49,-0.2" # don't want this colliding with walls or they won't close + mask: + - MobImpassable + layer: + - Opaque + - Impassable + - MobImpassable + - VaultImpassable + - SmallImpassable diff --git a/Resources/Prototypes/Entities/Constructible/Doors/firelock_frame.yml b/Resources/Prototypes/Entities/Constructible/Doors/firelock_frame.yml index 113b927d18..0ab2d1acbe 100644 --- a/Resources/Prototypes/Entities/Constructible/Doors/firelock_frame.yml +++ b/Resources/Prototypes/Entities/Constructible/Doors/firelock_frame.yml @@ -22,9 +22,10 @@ - !type:DoActsBehavior acts: ["Destruction"] - type: Physics - shapes: - - !type:PhysShapeAabb - bounds: "-0.49,-0.49,0.49,0.49" + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.49,-0.49,0.49,0.49" mask: - Impassable layer: diff --git a/Resources/Prototypes/Entities/Constructible/Furniture/beds.yml b/Resources/Prototypes/Entities/Constructible/Furniture/beds.yml index 7e0420ad04..80d537afc3 100644 --- a/Resources/Prototypes/Entities/Constructible/Furniture/beds.yml +++ b/Resources/Prototypes/Entities/Constructible/Furniture/beds.yml @@ -7,10 +7,11 @@ - type: InteractionOutline - type: Physics mass: 25 - anchored: true - shapes: - - !type:PhysShapeAabb - bounds: "-0.45, -0.45, 0.05, 0.45" + bodyType: Static + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.45, -0.45, 0.05, 0.45" mask: - Impassable - VaultImpassable diff --git a/Resources/Prototypes/Entities/Constructible/Furniture/bookshelf.yml b/Resources/Prototypes/Entities/Constructible/Furniture/bookshelf.yml index b45865c372..15e8f09ebc 100644 --- a/Resources/Prototypes/Entities/Constructible/Furniture/bookshelf.yml +++ b/Resources/Prototypes/Entities/Constructible/Furniture/bookshelf.yml @@ -11,8 +11,9 @@ - type: Sprite sprite: Constructible/Misc/bookshelf.rsi - type: Physics - shapes: - - !type:PhysShapeAabb + fixtures: + - shape: + !type:PhysShapeAabb {} layer: - Opaque - Impassable diff --git a/Resources/Prototypes/Entities/Constructible/Furniture/carpets.yml b/Resources/Prototypes/Entities/Constructible/Furniture/carpets.yml index 82800af63e..0a1921b789 100644 --- a/Resources/Prototypes/Entities/Constructible/Furniture/carpets.yml +++ b/Resources/Prototypes/Entities/Constructible/Furniture/carpets.yml @@ -16,9 +16,10 @@ key: full base: carpet_ - type: Physics - shapes: - - !type:PhysShapeAabb - bounds: "-0.5, -0.5, 0.5, 0.5" + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.5, -0.5, 0.5, 0.5" layer: [ Passable ] - type: Damageable - type: Destructible diff --git a/Resources/Prototypes/Entities/Constructible/Furniture/instruments.yml b/Resources/Prototypes/Entities/Constructible/Furniture/instruments.yml index bfa5aff82b..596fce5fdd 100644 --- a/Resources/Prototypes/Entities/Constructible/Furniture/instruments.yml +++ b/Resources/Prototypes/Entities/Constructible/Furniture/instruments.yml @@ -11,8 +11,9 @@ - type: InteractionOutline - type: Anchorable - type: Physics - shapes: - - !type:PhysShapeAabb + fixtures: + - shape: + !type:PhysShapeAabb {} layer: [MobMask] mask: - Impassable diff --git a/Resources/Prototypes/Entities/Constructible/Furniture/potted_plants.yml b/Resources/Prototypes/Entities/Constructible/Furniture/potted_plants.yml index 701bae83c5..bf11e317eb 100644 --- a/Resources/Prototypes/Entities/Constructible/Furniture/potted_plants.yml +++ b/Resources/Prototypes/Entities/Constructible/Furniture/potted_plants.yml @@ -6,10 +6,11 @@ - type: InteractionOutline - type: Physics mass: 25 - anchored: true - shapes: - - !type:PhysShapeAabb - bounds: "-0.5, -0.2, 0.5, 0.2" + bodyType: Static + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.5, -0.2, 0.5, 0.2" mask: - Impassable - MobImpassable @@ -58,9 +59,10 @@ - type: Sprite state: plant-25 - type: Physics - shapes: - - !type:PhysShapeAabb - bounds: "-0.47,-0.25,0.05,0.25" + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.47,-0.25,0.05,0.25" layer: [ Passable ] - type: entity diff --git a/Resources/Prototypes/Entities/Constructible/Furniture/seats.yml b/Resources/Prototypes/Entities/Constructible/Furniture/seats.yml index f9f4a0bf2d..cea66c414d 100644 --- a/Resources/Prototypes/Entities/Constructible/Furniture/seats.yml +++ b/Resources/Prototypes/Entities/Constructible/Furniture/seats.yml @@ -9,10 +9,11 @@ - type: Clickable - type: InteractionOutline - type: Physics - anchored: true - shapes: - - !type:PhysShapeAabb - bounds: "-0.5,-0.25,0.5,0.25" + bodyType: Static + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.5,-0.25,0.5,0.25" mask: - Impassable - VaultImpassable @@ -44,9 +45,10 @@ state: chair color: "#8e9799" - type: Physics - shapes: - - !type:PhysShapeAabb - bounds: "-0.45, -0.45, 0.05, 0.45" + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.45, -0.45, 0.05, 0.45" mask: - Impassable - VaultImpassable @@ -62,9 +64,10 @@ state: stool_base color: "#8e9799" - type: Physics - shapes: - - !type:PhysShapeAabb - bounds: "-0.5, -0.25, 0.05, 0.25" + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.5, -0.25, 0.05, 0.25" mask: - Impassable - VaultImpassable @@ -79,9 +82,10 @@ state: bar_stool color: "white" - type: Physics - shapes: - - !type:PhysShapeAabb - bounds: "-0.5, -0.2, 0.2, 0.25" + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.5, -0.2, 0.2, 0.25" mask: - Impassable - VaultImpassable @@ -97,9 +101,10 @@ - type: Sprite state: officechair_white - type: Physics - shapes: - - !type:PhysShapeAabb - bounds: "-0.49, -0.25, 0.37, 0.25" + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.49, -0.25, 0.37, 0.25" mask: - Impassable - VaultImpassable @@ -122,9 +127,10 @@ - type: Sprite state: comfychair_preview - type: Physics - shapes: - - !type:PhysShapeAabb - bounds: "-0.45, -0.3, 0.35, 0.3" + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.45, -0.3, 0.35, 0.3" mask: - Impassable - VaultImpassable @@ -139,9 +145,10 @@ state: wooden_chair color: "white" - type: Physics - shapes: - - !type:PhysShapeAabb - bounds: "-0.37, -0.25, 0.49, 0.24" + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.37, -0.25, 0.49, 0.24" mask: - Impassable - VaultImpassable diff --git a/Resources/Prototypes/Entities/Constructible/Furniture/storage.yml b/Resources/Prototypes/Entities/Constructible/Furniture/storage.yml index 24a72a3842..2b6b9ccb4a 100644 --- a/Resources/Prototypes/Entities/Constructible/Furniture/storage.yml +++ b/Resources/Prototypes/Entities/Constructible/Furniture/storage.yml @@ -12,10 +12,11 @@ state: rack - type: Physics mass: 25 - anchored: true - shapes: - - !type:PhysShapeAabb - bounds: "-0.4,-0.4,0.4,0.4" + bodyType: Static + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.4,-0.4,0.4,0.4" layer: - Opaque - Impassable @@ -60,10 +61,11 @@ state: shelf - type: Physics mass: 25 - anchored: true - shapes: - - !type:PhysShapeAabb - bounds: "-0.4,-0.4,0.4,0.4" + bodyType: Static + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.4,-0.4,0.4,0.4" layer: - Opaque - Impassable diff --git a/Resources/Prototypes/Entities/Constructible/Furniture/tables.yml b/Resources/Prototypes/Entities/Constructible/Furniture/tables.yml index 5f9721f36d..1ad9f0516a 100644 --- a/Resources/Prototypes/Entities/Constructible/Furniture/tables.yml +++ b/Resources/Prototypes/Entities/Constructible/Furniture/tables.yml @@ -17,8 +17,9 @@ key: state base: state_ - type: Physics - shapes: - - !type:PhysShapeAabb + fixtures: + - shape: + !type:PhysShapeAabb {} layer: - VaultImpassable - type: SnapGrid diff --git a/Resources/Prototypes/Entities/Constructible/Ground/catwalk.yml b/Resources/Prototypes/Entities/Constructible/Ground/catwalk.yml index 382d6addaa..ee28c18787 100644 --- a/Resources/Prototypes/Entities/Constructible/Ground/catwalk.yml +++ b/Resources/Prototypes/Entities/Constructible/Ground/catwalk.yml @@ -8,9 +8,10 @@ - type: Clickable - type: InteractionOutline - type: Physics - shapes: - - !type:PhysShapeAabb - bounds: "-0.5,-0.5,0.5,0.5" + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.5,-0.5,0.5,0.5" layer: [ Passable ] - type: Sprite netsync: false diff --git a/Resources/Prototypes/Entities/Constructible/Ground/kitchen.yml b/Resources/Prototypes/Entities/Constructible/Ground/kitchen.yml index e9d7cbd46a..67c3ae246c 100644 --- a/Resources/Prototypes/Entities/Constructible/Ground/kitchen.yml +++ b/Resources/Prototypes/Entities/Constructible/Ground/kitchen.yml @@ -8,8 +8,9 @@ - type: Clickable - type: InteractionOutline - type: Physics - shapes: - - !type:PhysShapeAabb + fixtures: + - shape: + !type:PhysShapeAabb {} mask: - Impassable layer: diff --git a/Resources/Prototypes/Entities/Constructible/Piping/gascanisters.yml b/Resources/Prototypes/Entities/Constructible/Piping/gascanisters.yml index cb908dc297..ed51d87af4 100644 --- a/Resources/Prototypes/Entities/Constructible/Piping/gascanisters.yml +++ b/Resources/Prototypes/Entities/Constructible/Piping/gascanisters.yml @@ -50,10 +50,11 @@ type: GasCanisterBoundUserInterface - type: Physics mass: 25 - anchored: false - shapes: - - !type:PhysShapeAabb - bounds: "-0.5,-0.25,0.5,0.25" + bodyType: Dynamic + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.5,-0.25,0.5,0.25" mask: - Impassable - MobImpassable diff --git a/Resources/Prototypes/Entities/Constructible/Piping/gasgenerator.yml b/Resources/Prototypes/Entities/Constructible/Piping/gasgenerator.yml index 17dd8c93d9..7d2fb359e7 100644 --- a/Resources/Prototypes/Entities/Constructible/Piping/gasgenerator.yml +++ b/Resources/Prototypes/Entities/Constructible/Piping/gasgenerator.yml @@ -7,10 +7,11 @@ - type: Clickable - type: InteractionOutline - type: Physics - anchored: true - shapes: - - !type:PhysShapeAabb - bounds: "-0.5,-0.5,0.5,0.5" + bodyType: Static + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.5,-0.5,0.5,0.5" layer: - Impassable - MobImpassable @@ -24,7 +25,7 @@ offset: Center - type: GasGenerator - type: PipeNetDevice - + - type: entity parent: GasGeneratorBase id: GasGenerator @@ -43,4 +44,4 @@ - !type:PipeNode nodeGroupID: Pipe pipeDirection: Fourway - + diff --git a/Resources/Prototypes/Entities/Constructible/Power/computers.yml b/Resources/Prototypes/Entities/Constructible/Power/computers.yml index 2acb426263..9f3958a06b 100644 --- a/Resources/Prototypes/Entities/Constructible/Power/computers.yml +++ b/Resources/Prototypes/Entities/Constructible/Power/computers.yml @@ -7,10 +7,11 @@ components: - type: Physics mass: 25 - anchored: true - shapes: - - !type:PhysShapeAabb - bounds: "-0.5,-0.25,0.5,0.25" + bodyType: Static + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.5,-0.25,0.5,0.25" layer: - Impassable - MobImpassable @@ -39,10 +40,11 @@ components: - type: Physics mass: 25 - anchored: true - shapes: - - !type:PhysShapeAabb - bounds: "-0.5,-0.25,0.5,0.25" + bodyType: Static + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.5,-0.25,0.5,0.25" layer: - Impassable - MobImpassable @@ -77,10 +79,11 @@ - type: Rotatable - type: Physics mass: 25 - anchored: true - shapes: - - !type:PhysShapeAabb - bounds: "-0.5,-0.25,0.5,0.25" + bodyType: Static + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.5,-0.25,0.5,0.25" layer: - Impassable - MobImpassable diff --git a/Resources/Prototypes/Entities/Constructible/Power/debug_power.yml b/Resources/Prototypes/Entities/Constructible/Power/debug_power.yml index 11e60743c0..b53810c169 100644 --- a/Resources/Prototypes/Entities/Constructible/Power/debug_power.yml +++ b/Resources/Prototypes/Entities/Constructible/Power/debug_power.yml @@ -12,9 +12,10 @@ - type: Clickable - type: InteractionOutline - type: Physics - shapes: - - !type:PhysShapeAabb - bounds: "-0.5, -0.5, 0.5, 0.5" + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.5, -0.5, 0.5, 0.5" layer: [MobMask, Opaque] - type: SnapGrid offset: Center @@ -48,9 +49,10 @@ - type: Clickable - type: InteractionOutline - type: Physics - shapes: - - !type:PhysShapeAabb - bounds: "-0.5, -0.5, 0.5, 0.5" + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.5, -0.5, 0.5, 0.5" layer: [MobMask, Opaque] - type: SnapGrid offset: Center @@ -75,9 +77,10 @@ - type: Clickable - type: InteractionOutline - type: Physics - shapes: - - !type:PhysShapeAabb - bounds: "-0.5, -0.5, 0.5, 0.5" + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.5, -0.5, 0.5, 0.5" layer: [MobMask, Opaque] - type: SnapGrid offset: Center @@ -117,9 +120,10 @@ - type: Clickable - type: InteractionOutline - type: Physics - shapes: - - !type:PhysShapeAabb - bounds: "-0.5, -0.5, 0.5, 0.5" + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.5, -0.5, 0.5, 0.5" layer: [MobMask, Opaque] - type: SnapGrid offset: Center diff --git a/Resources/Prototypes/Entities/Constructible/Power/lathe.yml b/Resources/Prototypes/Entities/Constructible/Power/lathe.yml index ff1f14657a..a4ca10b743 100644 --- a/Resources/Prototypes/Entities/Constructible/Power/lathe.yml +++ b/Resources/Prototypes/Entities/Constructible/Power/lathe.yml @@ -9,10 +9,11 @@ - type: InteractionOutline - type: Physics mass: 25 - anchored: true - shapes: - - !type:PhysShapeAabb - bounds: "-0.4,-0.4,0.4,0.4" + bodyType: Static + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.4,-0.4,0.4,0.4" mask: - Impassable - MobImpassable diff --git a/Resources/Prototypes/Entities/Constructible/Power/machine_frame.yml b/Resources/Prototypes/Entities/Constructible/Power/machine_frame.yml index e700bf2e8f..9340106f52 100644 --- a/Resources/Prototypes/Entities/Constructible/Power/machine_frame.yml +++ b/Resources/Prototypes/Entities/Constructible/Power/machine_frame.yml @@ -8,10 +8,11 @@ components: - type: Physics mass: 25 - anchored: true - shapes: - - !type:PhysShapeAabb - bounds: "-0.5,-0.25,0.5,0.25" + bodyType: Static + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.5,-0.25,0.5,0.25" layer: - Impassable - MobImpassable @@ -54,10 +55,11 @@ components: - type: Physics mass: 25 - anchored: true - shapes: - - !type:PhysShapeAabb - bounds: "-0.5,-0.25,0.5,0.25" + bodyType: Static + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.5,-0.25,0.5,0.25" layer: - Impassable - MobImpassable diff --git a/Resources/Prototypes/Entities/Constructible/Power/power_base.yml b/Resources/Prototypes/Entities/Constructible/Power/power_base.yml index 083cac2119..70703b996c 100644 --- a/Resources/Prototypes/Entities/Constructible/Power/power_base.yml +++ b/Resources/Prototypes/Entities/Constructible/Power/power_base.yml @@ -10,10 +10,11 @@ - type: InteractionOutline - type: Physics mass: 25 - anchored: true - shapes: - - !type:PhysShapeAabb - bounds: "-0.5, -0.4, 0.3, 0.4" + bodyType: Static + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.5, -0.4, 0.3, 0.4" mask: - Impassable - MobImpassable @@ -54,9 +55,10 @@ - type: InteractionOutline - type: Physics mass: 25 - anchored: true - shapes: - - !type:PhysShapeAabb + bodyType: Static + fixtures: + - shape: + !type:PhysShapeAabb {} mask: - Impassable - MobImpassable @@ -112,9 +114,10 @@ - type: InteractionOutline - type: Physics mass: 25 - anchored: true - shapes: - - !type:PhysShapeAabb + bodyType: Static + fixtures: + - shape: + !type:PhysShapeAabb {} mask: - Impassable - MobImpassable @@ -172,9 +175,10 @@ access: [["Engineering"]] - type: InteractionOutline - type: Physics - shapes: - - !type:PhysShapeAabb - bounds: "-0.25, -0.25, 0.25, 0.3" + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.25, -0.25, 0.25, 0.3" layer: [ Passable ] - type: SnapGrid offset: Center @@ -227,9 +231,10 @@ - type: InteractionOutline - type: Physics mass: 25 - anchored: false - shapes: - - !type:PhysShapeAabb + bodyType: Dynamic + fixtures: + - shape: + !type:PhysShapeAabb {} mask: - Impassable - MobImpassable diff --git a/Resources/Prototypes/Entities/Constructible/Power/seed_extractor.yml b/Resources/Prototypes/Entities/Constructible/Power/seed_extractor.yml index 3397231958..b1cdc79faf 100644 --- a/Resources/Prototypes/Entities/Constructible/Power/seed_extractor.yml +++ b/Resources/Prototypes/Entities/Constructible/Power/seed_extractor.yml @@ -12,10 +12,11 @@ state: seedextractor - type: Physics mass: 25 - anchored: true - shapes: - - !type:PhysShapeAabb - bounds: "-0.4,-0.25,0.4,0.25" + bodyType: Static + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.4,-0.25,0.4,0.25" layer: - Opaque - Impassable diff --git a/Resources/Prototypes/Entities/Constructible/Power/vending_machines.yml b/Resources/Prototypes/Entities/Constructible/Power/vending_machines.yml index c378ff584d..76812ded3b 100644 --- a/Resources/Prototypes/Entities/Constructible/Power/vending_machines.yml +++ b/Resources/Prototypes/Entities/Constructible/Power/vending_machines.yml @@ -12,10 +12,11 @@ sprite: Constructible/Power/VendingMachines/empty.rsi netsync: false - type: Physics - anchored: true - shapes: - - !type:PhysShapeAabb - bounds: "-0.5,-0.25,0.5,0.25" + bodyType: Static + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.5,-0.25,0.5,0.25" mask: - Impassable - MobImpassable diff --git a/Resources/Prototypes/Entities/Constructible/Power/wires.yml b/Resources/Prototypes/Entities/Constructible/Power/wires.yml index 32722b2ad0..a57ec3a6c8 100644 --- a/Resources/Prototypes/Entities/Constructible/Power/wires.yml +++ b/Resources/Prototypes/Entities/Constructible/Power/wires.yml @@ -6,10 +6,12 @@ components: - type: Clickable - type: Physics - shapes: - - !type:PhysShapeAabb - bounds: "-0.5, -0.5, 0.5, 0.5" - layer: [ Underplating ] + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.5, -0.5, 0.5, 0.5" + layer: + - Underplating - type: InteractionOutline - type: SnapGrid offset: Center diff --git a/Resources/Prototypes/Entities/Constructible/Specific/Conveyor/conveyor.yml b/Resources/Prototypes/Entities/Constructible/Specific/Conveyor/conveyor.yml index b2d43c0061..16f3244d5a 100644 --- a/Resources/Prototypes/Entities/Constructible/Specific/Conveyor/conveyor.yml +++ b/Resources/Prototypes/Entities/Constructible/Specific/Conveyor/conveyor.yml @@ -8,10 +8,11 @@ - type: Clickable - type: InteractionOutline - type: Physics - hard: false - shapes: - - !type:PhysShapeAabb - bounds: "-0.49,-0.49,0.49,0.49" + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.49,-0.49,0.49,0.49" + hard: false layer: [Passable] mask: - Impassable diff --git a/Resources/Prototypes/Entities/Constructible/Specific/Cooking/microwave.yml b/Resources/Prototypes/Entities/Constructible/Specific/Cooking/microwave.yml index ac4fa5ceb4..9feef45338 100644 --- a/Resources/Prototypes/Entities/Constructible/Specific/Cooking/microwave.yml +++ b/Resources/Prototypes/Entities/Constructible/Specific/Cooking/microwave.yml @@ -22,9 +22,10 @@ - key: enum.MicrowaveUiKey.Key type: MicrowaveBoundUserInterface - type: Physics - shapes: - - !type:PhysShapeAabb - bounds: "-0.16,-0.3,0.16,0.3" + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.16,-0.3,0.16,0.3" layer: - Opaque - Impassable diff --git a/Resources/Prototypes/Entities/Constructible/Specific/Cooking/reagent_grinder.yml b/Resources/Prototypes/Entities/Constructible/Specific/Cooking/reagent_grinder.yml index 2ffab8f32d..26c18fe7be 100644 --- a/Resources/Prototypes/Entities/Constructible/Specific/Cooking/reagent_grinder.yml +++ b/Resources/Prototypes/Entities/Constructible/Specific/Cooking/reagent_grinder.yml @@ -21,9 +21,10 @@ - type: PowerReceiver - type: LoopingSound - type: Physics - shapes: - - !type:PhysShapeAabb - bounds: "-0.35,-0.08,0.25,0.15" + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.35,-0.08,0.25,0.15" layer: - Opaque - Impassable diff --git a/Resources/Prototypes/Entities/Constructible/Specific/Dispensers/reagent_dispenser_base.yml b/Resources/Prototypes/Entities/Constructible/Specific/Dispensers/reagent_dispenser_base.yml index 0ee63db22b..a0e0582619 100644 --- a/Resources/Prototypes/Entities/Constructible/Specific/Dispensers/reagent_dispenser_base.yml +++ b/Resources/Prototypes/Entities/Constructible/Specific/Dispensers/reagent_dispenser_base.yml @@ -8,10 +8,11 @@ - type: InteractionOutline - type: Physics mass: 25 - anchored: true - shapes: - - !type:PhysShapeAabb - bounds: "-0.3,-0.4,0.3,0.4" + bodyType: Static + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.3,-0.4,0.3,0.4" mask: - Impassable - MobImpassable diff --git a/Resources/Prototypes/Entities/Constructible/Specific/Engines/AME/controller.yml b/Resources/Prototypes/Entities/Constructible/Specific/Engines/AME/controller.yml index 30d45968ce..a90fe00c79 100644 --- a/Resources/Prototypes/Entities/Constructible/Specific/Engines/AME/controller.yml +++ b/Resources/Prototypes/Entities/Constructible/Specific/Engines/AME/controller.yml @@ -13,8 +13,9 @@ - type: Physics # Mass of 1? Unmovable. Mass of 25? Fine. What on earth is going on? mass: 25 - shapes: - - !type:PhysShapeAabb + fixtures: + - shape: + !type:PhysShapeAabb {} layer: - Opaque - Impassable @@ -67,4 +68,4 @@ abstract: true components: - type: Physics - anchored: false + bodyType: Dynamic diff --git a/Resources/Prototypes/Entities/Constructible/Specific/Engines/AME/shielding.yml b/Resources/Prototypes/Entities/Constructible/Specific/Engines/AME/shielding.yml index dd8c060024..69bfe9c33b 100644 --- a/Resources/Prototypes/Entities/Constructible/Specific/Engines/AME/shielding.yml +++ b/Resources/Prototypes/Entities/Constructible/Specific/Engines/AME/shielding.yml @@ -12,8 +12,9 @@ sprite: Constructible/Power/ame_shielding.rsi state: shield_0 - type: Physics - shapes: - - !type:PhysShapeAabb + fixtures: + - shape: + !type:PhysShapeAabb {} layer: - Opaque - Impassable diff --git a/Resources/Prototypes/Entities/Constructible/Specific/Engines/PA/base.yml b/Resources/Prototypes/Entities/Constructible/Specific/Engines/PA/base.yml index e9abf244e6..57259e265d 100644 --- a/Resources/Prototypes/Entities/Constructible/Specific/Engines/PA/base.yml +++ b/Resources/Prototypes/Entities/Constructible/Specific/Engines/PA/base.yml @@ -9,15 +9,16 @@ snap: true - type: Physics mass: 25 - anchored: true - shapes: - - !type:PhysShapeAabb - bounds: "-0.49,-0.49,0.49,0.49" - layer: - - Opaque - - Impassable - - MobImpassable - - VaultImpassable + bodyType: Static + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.49,-0.49,0.49,0.49" + mask: + - Opaque + - Impassable + - MobImpassable + - VaultImpassable - type: SnapGrid offset: Center - type: Pullable diff --git a/Resources/Prototypes/Entities/Constructible/Specific/Engines/PA/control_box.yml b/Resources/Prototypes/Entities/Constructible/Specific/Engines/PA/control_box.yml index 6f0577f8d1..65e8d061cb 100644 --- a/Resources/Prototypes/Entities/Constructible/Specific/Engines/PA/control_box.yml +++ b/Resources/Prototypes/Entities/Constructible/Specific/Engines/PA/control_box.yml @@ -42,7 +42,7 @@ description: This controls the density of the particles. It looks unfinished. components: - type: Physics - anchored: false + bodyType: Dynamic - type: Sprite sprite: Constructible/Specific/Engines/PA/control_box.rsi state: box diff --git a/Resources/Prototypes/Entities/Constructible/Specific/Engines/PA/emitter.yml b/Resources/Prototypes/Entities/Constructible/Specific/Engines/PA/emitter.yml index dff77ecef7..83b24de757 100644 --- a/Resources/Prototypes/Entities/Constructible/Specific/Engines/PA/emitter.yml +++ b/Resources/Prototypes/Entities/Constructible/Specific/Engines/PA/emitter.yml @@ -83,7 +83,7 @@ description: This launchs the Alpha particles, might not want to stand near this end. It looks unfinished. components: - type: Physics - anchored: false + bodyType: Dynamic - type: Sprite sprite: Constructible/Specific/Engines/PA/emitter_left.rsi state: left @@ -100,7 +100,7 @@ description: This launchs the Alpha particles, might not want to stand near this end. It looks unfinished. components: - type: Physics - anchored: false + bodyType: Dynamic - type: Sprite sprite: Constructible/Specific/Engines/PA/emitter_center.rsi state: center @@ -117,7 +117,7 @@ description: This launchs the Alpha particles, might not want to stand near this end. It looks unfinished. components: - type: Physics - anchored: false + bodyType: Dynamic - type: Sprite sprite: Constructible/Specific/Engines/PA/emitter_right.rsi state: right diff --git a/Resources/Prototypes/Entities/Constructible/Specific/Engines/PA/end_cap.yml b/Resources/Prototypes/Entities/Constructible/Specific/Engines/PA/end_cap.yml index 0d80bd9137..fd97a8b0ac 100644 --- a/Resources/Prototypes/Entities/Constructible/Specific/Engines/PA/end_cap.yml +++ b/Resources/Prototypes/Entities/Constructible/Specific/Engines/PA/end_cap.yml @@ -22,7 +22,7 @@ description: Formally known as the Alpha Particle Generation Array. This is where Alpha particles are generated from [REDACTED]. It looks unfinished. components: - type: Physics - anchored: false + bodyType: Dynamic - type: Sprite sprite: Constructible/Specific/Engines/PA/end_cap.rsi state: cap diff --git a/Resources/Prototypes/Entities/Constructible/Specific/Engines/PA/fuel_chamber.yml b/Resources/Prototypes/Entities/Constructible/Specific/Engines/PA/fuel_chamber.yml index 7ee98d5a86..760ec86d34 100644 --- a/Resources/Prototypes/Entities/Constructible/Specific/Engines/PA/fuel_chamber.yml +++ b/Resources/Prototypes/Entities/Constructible/Specific/Engines/PA/fuel_chamber.yml @@ -32,7 +32,7 @@ description: Formally known as the EM Acceleration Chamber. This is where the Alpha particles are accelerated to radical speeds. It looks unfinished. components: - type: Physics - anchored: false + bodyType: Dynamic - type: Sprite sprite: Constructible/Specific/Engines/PA/fuel_chamber.rsi state: chamber diff --git a/Resources/Prototypes/Entities/Constructible/Specific/Engines/PA/particles.yml b/Resources/Prototypes/Entities/Constructible/Specific/Engines/PA/particles.yml index 06da36833b..04a252a4c9 100644 --- a/Resources/Prototypes/Entities/Constructible/Specific/Engines/PA/particles.yml +++ b/Resources/Prototypes/Entities/Constructible/Specific/Engines/PA/particles.yml @@ -15,10 +15,11 @@ damages: Radiation: 10 - type: Physics - hard: false - shapes: - - !type:PhysShapeAabb - bounds: "-0.48,-0.48,0.48,0.48" + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.48,-0.48,0.48,0.48" + hard: false layer: [None] mask: - MobMask diff --git a/Resources/Prototypes/Entities/Constructible/Specific/Engines/PA/power_box.yml b/Resources/Prototypes/Entities/Constructible/Specific/Engines/PA/power_box.yml index 112120ec17..f81138e37b 100644 --- a/Resources/Prototypes/Entities/Constructible/Specific/Engines/PA/power_box.yml +++ b/Resources/Prototypes/Entities/Constructible/Specific/Engines/PA/power_box.yml @@ -37,7 +37,7 @@ description: Formally known as the Particle Focusing EM Lens. This uses electromagnetic waves to focus the Alpha-Particles. It looks unfinished. components: - type: Physics - anchored: false + bodyType: Dynamic - type: Sprite sprite: Constructible/Specific/Engines/PA/power_box.rsi state: box diff --git a/Resources/Prototypes/Entities/Constructible/Specific/Engines/Singularity/collector.yml b/Resources/Prototypes/Entities/Constructible/Specific/Engines/Singularity/collector.yml index 1b2f4d3fb4..df860464ae 100644 --- a/Resources/Prototypes/Entities/Constructible/Specific/Engines/Singularity/collector.yml +++ b/Resources/Prototypes/Entities/Constructible/Specific/Engines/Singularity/collector.yml @@ -8,11 +8,12 @@ - type: Clickable - type: InteractionOutline - type: Physics - anchored: false + bodyType: Dynamic mass: 25 - shapes: - - !type:PhysShapeAabb - bounds: "-0.5, -0.5, 0.5, 0.5" + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.5, -0.5, 0.5, 0.5" layer: - Impassable - MobImpassable diff --git a/Resources/Prototypes/Entities/Constructible/Specific/Engines/Singularity/containment.yml b/Resources/Prototypes/Entities/Constructible/Specific/Engines/Singularity/containment.yml index 822cdb28b7..6fdabea35b 100644 --- a/Resources/Prototypes/Entities/Constructible/Specific/Engines/Singularity/containment.yml +++ b/Resources/Prototypes/Entities/Constructible/Specific/Engines/Singularity/containment.yml @@ -8,11 +8,12 @@ - type: InteractionOutline - type: Clickable - type: Physics - anchored: false + bodyType: Dynamic mass: 25 - shapes: - - !type:PhysShapeAabb - bounds: "-0.5, -0.5, 0.5, 0.5" + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.5, -0.5, 0.5, 0.5" layer: - Impassable - MobImpassable @@ -51,10 +52,11 @@ - type: InteractionOutline - type: Clickable - type: Physics - anchored: true - shapes: - - !type:PhysShapeAabb - bounds: "-0.5, -0.5, 0.5, 0.5" + bodyType: Static + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.5, -0.5, 0.5, 0.5" layer: - Impassable - MobImpassable diff --git a/Resources/Prototypes/Entities/Constructible/Specific/Engines/Singularity/emitter.yml b/Resources/Prototypes/Entities/Constructible/Specific/Engines/Singularity/emitter.yml index e435a5e3f2..d0cf67dfc2 100644 --- a/Resources/Prototypes/Entities/Constructible/Specific/Engines/Singularity/emitter.yml +++ b/Resources/Prototypes/Entities/Constructible/Specific/Engines/Singularity/emitter.yml @@ -8,11 +8,12 @@ - type: Clickable - type: InteractionOutline - type: Physics - anchored: false mass: 25 - shapes: - - !type:PhysShapeAabb - bounds: "-0.5, -0.5, 0.5, 0.5" + bodyType: Dynamic + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.5, -0.5, 0.5, 0.5" layer: - Impassable - MobImpassable diff --git a/Resources/Prototypes/Entities/Constructible/Specific/Engines/Singularity/generator.yml b/Resources/Prototypes/Entities/Constructible/Specific/Engines/Singularity/generator.yml index e03a9e50b7..94847d1dfb 100644 --- a/Resources/Prototypes/Entities/Constructible/Specific/Engines/Singularity/generator.yml +++ b/Resources/Prototypes/Entities/Constructible/Specific/Engines/Singularity/generator.yml @@ -12,11 +12,12 @@ - type: InteractionOutline - type: Clickable - type: Physics - anchored: false + bodyType: Dynamic mass: 25 - shapes: - - !type:PhysShapeAabb - bounds: "-0.5, -0.5, 0.5, 0.5" + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.5, -0.5, 0.5, 0.5" layer: - Opaque mask: diff --git a/Resources/Prototypes/Entities/Constructible/Specific/Engines/Singularity/singularity.yml b/Resources/Prototypes/Entities/Constructible/Specific/Engines/Singularity/singularity.yml index 8246655f22..1e24aa9656 100644 --- a/Resources/Prototypes/Entities/Constructible/Specific/Engines/Singularity/singularity.yml +++ b/Resources/Prototypes/Entities/Constructible/Specific/Engines/Singularity/singularity.yml @@ -5,10 +5,11 @@ components: - type: Clickable - type: Physics - anchored: false - shapes: - - !type:PhysShapeCircle - radius: 0.5 + bodyType: Dynamic + fixtures: + - shape: + !type:PhysShapeCircle + radius: 0.5 layer: [Impassable] mask: - AllMask diff --git a/Resources/Prototypes/Entities/Constructible/Specific/Medical/cloning_machine.yml b/Resources/Prototypes/Entities/Constructible/Specific/Medical/cloning_machine.yml index 3f07f2d0dc..168b373446 100644 --- a/Resources/Prototypes/Entities/Constructible/Specific/Medical/cloning_machine.yml +++ b/Resources/Prototypes/Entities/Constructible/Specific/Medical/cloning_machine.yml @@ -17,10 +17,11 @@ - type: InteractionOutline - type: Physics mass: 25 - anchored: true - shapes: - - !type:PhysShapeAabb - bounds: "-0.5,-0.25,0.5,0.25" + bodyType: Static + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.5,-0.25,0.5,0.25" layer: - Opaque - Impassable diff --git a/Resources/Prototypes/Entities/Constructible/Specific/Medical/medical_scanner.yml b/Resources/Prototypes/Entities/Constructible/Specific/Medical/medical_scanner.yml index 01bcd003ff..b2b4409890 100644 --- a/Resources/Prototypes/Entities/Constructible/Specific/Medical/medical_scanner.yml +++ b/Resources/Prototypes/Entities/Constructible/Specific/Medical/medical_scanner.yml @@ -19,13 +19,13 @@ - type: InteractionOutline - type: Physics mass: 25 - anchored: true - shapes: - - !type:PhysShapeAabb - mask: - - Impassable - - VaultImpassable - - SmallImpassable + bodyType: Static + fixtures: + - shape: + !type:PhysShapeAabb {} + layer: + - Impassable + - VaultImpassable - type: SnapGrid offset: Center - type: Anchorable diff --git a/Resources/Prototypes/Entities/Constructible/Specific/Research/research.yml b/Resources/Prototypes/Entities/Constructible/Specific/Research/research.yml index be404b783f..d9d8cd1d6c 100644 --- a/Resources/Prototypes/Entities/Constructible/Specific/Research/research.yml +++ b/Resources/Prototypes/Entities/Constructible/Specific/Research/research.yml @@ -12,10 +12,11 @@ - type: InteractionOutline - type: Physics mass: 25 - anchored: true - shapes: - - !type:PhysShapeAabb - bounds: "-0.4, -0.45, 0.45, 0.45" + bodyType: Static + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.4, -0.45, 0.45, 0.45" mask: - Impassable - MobImpassable @@ -54,9 +55,10 @@ - type: InteractionOutline - type: Physics mass: 25 - anchored: true - shapes: - - !type:PhysShapeAabb + bodyType: Static + fixtures: + - shape: + !type:PhysShapeAabb {} mask: - Impassable - MobImpassable diff --git a/Resources/Prototypes/Entities/Constructible/Specific/cargo_telepad.yml b/Resources/Prototypes/Entities/Constructible/Specific/cargo_telepad.yml index d6b17f6423..5322e47ada 100644 --- a/Resources/Prototypes/Entities/Constructible/Specific/cargo_telepad.yml +++ b/Resources/Prototypes/Entities/Constructible/Specific/cargo_telepad.yml @@ -9,9 +9,11 @@ - type: InteractionOutline - type: Physics mass: 25 - shapes: - - !type:PhysShapeAabb - bounds: "-0.45, -0.45, 0.00, 0.45" + bodyType: Dynamic + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.45, -0.45, 0.00, 0.45" layer: [ Passable ] - type: Sprite sprite: Constructible/Specific/Cargo/teleporter.rsi diff --git a/Resources/Prototypes/Entities/Constructible/Specific/chem_master.yml b/Resources/Prototypes/Entities/Constructible/Specific/chem_master.yml index 858cbeed69..7476c5e082 100644 --- a/Resources/Prototypes/Entities/Constructible/Specific/chem_master.yml +++ b/Resources/Prototypes/Entities/Constructible/Specific/chem_master.yml @@ -21,10 +21,11 @@ - type: Anchorable - type: Physics mass: 25 - anchored: true - shapes: - - !type:PhysShapeAabb - bounds: "-0.4,-0.25,0.4,0.25" + bodyType: Static + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.4,-0.25,0.4,0.25" layer: - Opaque - Impassable @@ -72,10 +73,11 @@ - type: Anchorable - type: Physics mass: 25 - anchored: true - shapes: - - !type:PhysShapeAabb - bounds: "-0.4,-0.25,0.4,0.25" + bodyType: Static + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.4,-0.25,0.4,0.25" layer: - Opaque - Impassable diff --git a/Resources/Prototypes/Entities/Constructible/Specific/disposal.yml b/Resources/Prototypes/Entities/Constructible/Specific/disposal.yml index 4248ef7196..5e713183c5 100644 --- a/Resources/Prototypes/Entities/Constructible/Specific/disposal.yml +++ b/Resources/Prototypes/Entities/Constructible/Specific/disposal.yml @@ -9,7 +9,7 @@ - type: Clickable - type: InteractionOutline - type: Physics - anchored: true + bodyType: Static - type: SnapGrid offset: Center - type: Anchorable @@ -51,9 +51,10 @@ state_anchored: pipe-s state_broken: pipe-b - type: Physics - shapes: - - !type:PhysShapeAabb - bounds: "-0.5,-0.25,0.5,0.25" + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.5,-0.25,0.5,0.25" layer: [ Underplating ] - type: entity @@ -78,9 +79,10 @@ - key: enum.DisposalTaggerUiKey.Key type: DisposalTaggerBoundUserInterface - type: Physics - shapes: - - !type:PhysShapeAabb - bounds: "-0.5,-0.25,0.5,0.25" + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.5,-0.25,0.5,0.25" layer: [ Underplating ] - type: entity @@ -101,9 +103,10 @@ state_anchored: pipe-t state_broken: pipe-b - type: Physics - shapes: - - !type:PhysShapeAabb - bounds: "-0.5,-0.25,0.4,0.25" + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.5,-0.25,0.4,0.25" layer: [ Underplating ] - type: entity @@ -131,10 +134,11 @@ - type: Clickable - type: InteractionOutline - type: Physics - anchored: true - shapes: - - !type:PhysShapeAabb - bounds: "-0.3,-0.35,0.3,0.35" + bodyType: Static + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.3,-0.35,0.3,0.35" mask: - Impassable - MobImpassable @@ -206,9 +210,10 @@ - key: enum.DisposalRouterUiKey.Key type: DisposalRouterBoundUserInterface - type: Physics - shapes: - - !type:PhysShapeAabb - bounds: "-0.5,-0.5,0.5,0.25" + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.5,-0.5,0.5,0.25" layer: [ Underplating ] - type: entity @@ -234,10 +239,11 @@ - type: Flippable entity: DisposalRouter - type: Physics - shapes: - - !type:PhysShapeAabb - bounds: "-0.5,-0.25,0.5,0.5" - layer: [ Underplating ] + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.5,-0.25,0.5,0.5" + layer: [ Underplating ] - type: entity id: DisposalJunction @@ -263,10 +269,11 @@ - type: Flippable entity: DisposalJunctionFlipped - type: Physics - shapes: - - !type:PhysShapeAabb - bounds: "-0.5,-0.5,0.5,0.25" - layer: [ Underplating ] + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.5,-0.5,0.5,0.25" + layer: [ Underplating ] - type: entity id: DisposalJunctionFlipped @@ -291,10 +298,11 @@ - type: Flippable entity: DisposalJunction - type: Physics - shapes: - - !type:PhysShapeAabb - bounds: "-0.5,-0.25,0.5,0.5" - layer: [ Underplating ] + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.5,-0.25,0.5,0.5" + layer: [ Underplating ] - type: entity id: DisposalYJunction @@ -318,10 +326,11 @@ state_anchored: pipe-y state_broken: pipe-b - type: Physics - shapes: - - !type:PhysShapeAabb - bounds: "-0.5,-0.5,0.25,0.5" - layer: [ Underplating ] + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.5,-0.5,0.25,0.5" + layer: [ Underplating ] - type: entity id: DisposalBend @@ -341,10 +350,11 @@ state_anchored: pipe-c state_broken: pipe-b - type: Physics - shapes: - - !type:PhysShapeAabb - bounds: "-0.5,-0.5,0.25,0.25" - layer: [ Underplating ] + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.5,-0.5,0.25,0.25" + layer: [ Underplating ] - type: entity id: DisposalMailingUnit @@ -374,10 +384,11 @@ - type: Clickable - type: InteractionOutline - type: Physics - anchored: true - shapes: - - !type:PhysShapeAabb - bounds: "-0.35,-0.3,0.35,0.3" + bodyType: Static + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.35,-0.3,0.35,0.3" mask: - Impassable - MobImpassable diff --git a/Resources/Prototypes/Entities/Constructible/Specific/gravity_generator.yml b/Resources/Prototypes/Entities/Constructible/Specific/gravity_generator.yml index aed6a268f9..f22aa08a90 100644 --- a/Resources/Prototypes/Entities/Constructible/Specific/gravity_generator.yml +++ b/Resources/Prototypes/Entities/Constructible/Specific/gravity_generator.yml @@ -18,14 +18,15 @@ - type: PowerReceiver powerLoad: 500 - type: Physics - shapes: - - !type:PhysShapeAabb - bounds: "-1.5,-1.5,1.5,1.5" - layer: - - Opaque - - Impassable - - MobImpassable - - VaultImpassable + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-1.5,-1.5,1.5,1.5" + layer: + - Opaque + - Impassable + - MobImpassable + - VaultImpassable - type: Clickable - type: InteractionOutline - type: Damageable diff --git a/Resources/Prototypes/Entities/Constructible/Specific/hydroponics.yml b/Resources/Prototypes/Entities/Constructible/Specific/hydroponics.yml index 0bbd53ae00..7573f6e2b5 100644 --- a/Resources/Prototypes/Entities/Constructible/Specific/hydroponics.yml +++ b/Resources/Prototypes/Entities/Constructible/Specific/hydroponics.yml @@ -8,11 +8,12 @@ - type: InteractionOutline - type: Physics mass: 25 - anchored: true - hard: false - shapes: - - !type:PhysShapeAabb - bounds: "-0.5, -0.5, 0.1, 0.5" + bodyType: Static + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.5, -0.5, 0.1, 0.5" + hard: false mask: - Impassable - MobImpassable @@ -55,7 +56,12 @@ components: - type: Physics mass: 25 - hard: true + fixtures: + - shape: + !type:PhysShapeAabb {} + hard: true + mask: + - Impassable - type: Anchorable snap: true - type: Pullable diff --git a/Resources/Prototypes/Entities/Constructible/Specific/recycler.yml b/Resources/Prototypes/Entities/Constructible/Specific/recycler.yml index 497cbcfd6a..83ce876c87 100644 --- a/Resources/Prototypes/Entities/Constructible/Specific/recycler.yml +++ b/Resources/Prototypes/Entities/Constructible/Specific/recycler.yml @@ -8,10 +8,11 @@ - type: Clickable - type: InteractionOutline - type: Physics - hard: false - shapes: - - !type:PhysShapeAabb - bounds: "-0.49,-0.49,0.49,0.49" + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.49,-0.49,0.49,0.49" + hard: false layer: - Opaque - Impassable diff --git a/Resources/Prototypes/Entities/Constructible/Storage/Closets/closet.yml b/Resources/Prototypes/Entities/Constructible/Storage/Closets/closet.yml index 9cd07d8e32..017559d927 100644 --- a/Resources/Prototypes/Entities/Constructible/Storage/Closets/closet.yml +++ b/Resources/Prototypes/Entities/Constructible/Storage/Closets/closet.yml @@ -21,20 +21,19 @@ soundHit: /Audio/Effects/bang.ogg - type: InteractionOutline - type: Physics - mass: 25 - anchored: false - shapes: - - !type:PhysShapeAabb - bounds: "-0.5,-0.25,0.5,0.25" + mass: 50 + bodyType: Dynamic + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.48,-0.25,0.48,0.25" mask: - Impassable - - MobImpassable - VaultImpassable - SmallImpassable layer: - Opaque - MobImpassable - - VaultImpassable - SmallImpassable - type: EntityStorage - type: PlaceableSurface diff --git a/Resources/Prototypes/Entities/Constructible/Storage/Crates/crate_base.yml b/Resources/Prototypes/Entities/Constructible/Storage/Crates/crate_base.yml index 61c50e31d0..ea29ed655e 100644 --- a/Resources/Prototypes/Entities/Constructible/Storage/Crates/crate_base.yml +++ b/Resources/Prototypes/Entities/Constructible/Storage/Crates/crate_base.yml @@ -18,13 +18,13 @@ - type: InteractionOutline - type: Physics mass: 25 - anchored: false - shapes: - - !type:PhysShapeAabb - bounds: "-0.4, -0.4, 0.29, 0.4" + bodyType: Dynamic + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.4, -0.4, 0.29, 0.4" mask: - Impassable - - MobImpassable - VaultImpassable - SmallImpassable layer: diff --git a/Resources/Prototypes/Entities/Constructible/Storage/StorageTanks/base_tank.yml b/Resources/Prototypes/Entities/Constructible/Storage/StorageTanks/base_tank.yml index f66eba078d..104a6b720c 100644 --- a/Resources/Prototypes/Entities/Constructible/Storage/StorageTanks/base_tank.yml +++ b/Resources/Prototypes/Entities/Constructible/Storage/StorageTanks/base_tank.yml @@ -7,11 +7,12 @@ - type: Clickable - type: InteractionOutline - type: Physics - mass: 15 - anchored: false - shapes: - - !type:PhysShapeAabb - bounds: "-0.5,-0.5,0.5,0.5" + mass: 100 + bodyType: Dynamic + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.5,-0.5,0.5,0.5" mask: - Impassable - MobImpassable diff --git a/Resources/Prototypes/Entities/Constructible/Walls/asteroid.yml b/Resources/Prototypes/Entities/Constructible/Walls/asteroid.yml index d4b61d585e..c2a204db4d 100644 --- a/Resources/Prototypes/Entities/Constructible/Walls/asteroid.yml +++ b/Resources/Prototypes/Entities/Constructible/Walls/asteroid.yml @@ -11,8 +11,9 @@ state: 0 - type: Physics - shapes: - - !type:PhysShapeAabb + fixtures: + - shape: + !type:PhysShapeAabb {} layer: [MobMask] - type: Damageable resistances: metallicResistances diff --git a/Resources/Prototypes/Entities/Constructible/Walls/atmos_plaque.yml b/Resources/Prototypes/Entities/Constructible/Walls/atmos_plaque.yml index cca5f22640..0b14d5319a 100644 --- a/Resources/Prototypes/Entities/Constructible/Walls/atmos_plaque.yml +++ b/Resources/Prototypes/Entities/Constructible/Walls/atmos_plaque.yml @@ -4,9 +4,10 @@ name: Atmos Plaque components: - type: Physics - shapes: - - !type:PhysShapeAabb - bounds: "-0.3,-0.3,0.3,0.3" + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.3,-0.3,0.3,0.3" layer: - Opaque - Impassable diff --git a/Resources/Prototypes/Entities/Constructible/Walls/bar_sign.yml b/Resources/Prototypes/Entities/Constructible/Walls/bar_sign.yml index 99f1d83ffe..ff9466f2c5 100644 --- a/Resources/Prototypes/Entities/Constructible/Walls/bar_sign.yml +++ b/Resources/Prototypes/Entities/Constructible/Walls/bar_sign.yml @@ -5,10 +5,11 @@ - type: Clickable - type: InteractionOutline - type: Physics - shapes: - - !type:PhysShapeAabb - bounds: "-0.45, -0.95, 0.45, 1" - layer: [ Passable ] + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.45, -0.95, 0.45, 1" + layer: [ Passable ] - type: Sprite drawdepth: WallTops sprite: Constructible/Misc/barsign.rsi diff --git a/Resources/Prototypes/Entities/Constructible/Walls/girder.yml b/Resources/Prototypes/Entities/Constructible/Walls/girder.yml index 23949e8a83..d74de07c29 100644 --- a/Resources/Prototypes/Entities/Constructible/Walls/girder.yml +++ b/Resources/Prototypes/Entities/Constructible/Walls/girder.yml @@ -15,9 +15,10 @@ state: wall_girder - type: Physics mass: 25 - anchored: true - shapes: - - !type:PhysShapeAabb + bodyType: Static + fixtures: + - shape: + !type:PhysShapeAabb {} layer: - Opaque - Impassable diff --git a/Resources/Prototypes/Entities/Constructible/Walls/lighting.yml b/Resources/Prototypes/Entities/Constructible/Walls/lighting.yml index 9bd69a5ab2..92ee1b8072 100644 --- a/Resources/Prototypes/Entities/Constructible/Walls/lighting.yml +++ b/Resources/Prototypes/Entities/Constructible/Walls/lighting.yml @@ -9,9 +9,10 @@ graph: lightFixture node: tubeLight - type: Physics - shapes: - - !type:PhysShapeAabb - bounds: "-0.45, -0.15, 0.45, 0.35" + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.45, -0.15, 0.45, 0.35" layer: [ Passable ] - type: LoopingSound - type: Sprite @@ -122,10 +123,11 @@ enabled: false offset: "0, -0.5" - type: Physics - shapes: - - !type:PhysShapeAabb - bounds: "0, 0.1, 0.25, 0.1" - layer: [ Passable ] + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "0, 0, 0.25, 0.1" + layer: [ Passable ] - type: PoweredLight bulb: Bulb - type: PowerReceiver diff --git a/Resources/Prototypes/Entities/Constructible/Walls/low_wall.yml b/Resources/Prototypes/Entities/Constructible/Walls/low_wall.yml index 0830167dc2..d429038da5 100644 --- a/Resources/Prototypes/Entities/Constructible/Walls/low_wall.yml +++ b/Resources/Prototypes/Entities/Constructible/Walls/low_wall.yml @@ -20,8 +20,9 @@ sprite: Constructible/Structures/Walls/low_wall.rsi state: metal - type: Physics - shapes: - - !type:PhysShapeAabb + fixtures: + - shape: + !type:PhysShapeAabb {} layer: - VaultImpassable - SmallImpassable diff --git a/Resources/Prototypes/Entities/Constructible/Walls/mirror.yml b/Resources/Prototypes/Entities/Constructible/Walls/mirror.yml index d51a0b5add..acb8b2972e 100644 --- a/Resources/Prototypes/Entities/Constructible/Walls/mirror.yml +++ b/Resources/Prototypes/Entities/Constructible/Walls/mirror.yml @@ -8,9 +8,10 @@ state: mirror - type: Physics mass: 25 - anchored: true - shapes: - - !type:PhysShapeAabb + bodyType: Static + fixtures: + - shape: + !type:PhysShapeAabb {} layer: [Clickable] - type: Clickable - type: InteractionOutline diff --git a/Resources/Prototypes/Entities/Constructible/Walls/signs.yml b/Resources/Prototypes/Entities/Constructible/Walls/signs.yml index d24fb79480..280ad330bb 100644 --- a/Resources/Prototypes/Entities/Constructible/Walls/signs.yml +++ b/Resources/Prototypes/Entities/Constructible/Walls/signs.yml @@ -6,8 +6,9 @@ - type: Clickable - type: InteractionOutline - type: Physics - shapes: - - !type:PhysShapeAabb + fixtures: + - shape: + !type:PhysShapeAabb {} - type: Damageable resistances: metallicResistances - type: Destructible @@ -34,9 +35,10 @@ description: Return to monky. components: - type: Physics - shapes: - - !type:PhysShapeAabb - bounds: "-0.1,-0.4,0.1,0.4" + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.1,-0.4,0.1,0.4" layer: - Opaque - Impassable @@ -57,9 +59,10 @@ components: - type: Rotatable - type: Physics - shapes: - - !type:PhysShapeAabb - bounds: "-0.1,-0.4,0.1,0.4" + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.1,-0.4,0.1,0.4" layer: - Opaque - Impassable @@ -78,9 +81,10 @@ components: - type: Rotatable - type: Physics - shapes: - - !type:PhysShapeAabb - bounds: "-0.1,-0.4,0.1,0.4" + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.1,-0.4,0.1,0.4" layer: - Opaque - Impassable @@ -100,9 +104,10 @@ components: - type: Rotatable - type: Physics - shapes: - - !type:PhysShapeAabb - bounds: "-0.1,-0.4,0.1,0.4" + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.1,-0.4,0.1,0.4" layer: - Opaque - Impassable @@ -122,9 +127,10 @@ components: - type: Rotatable - type: Physics - shapes: - - !type:PhysShapeAabb - bounds: "-0.1,-0.4,0.1,0.4" + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.1,-0.4,0.1,0.4" layer: - Opaque - Impassable @@ -144,9 +150,10 @@ components: - type: Rotatable - type: Physics - shapes: - - !type:PhysShapeAabb - bounds: "-0.1,-0.4,0.1,0.4" + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.1,-0.4,0.1,0.4" layer: - Opaque - Impassable @@ -165,9 +172,10 @@ components: - type: Rotatable - type: Physics - shapes: - - !type:PhysShapeAabb - bounds: "-0.1,-0.4,0.1,0.4" + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.1,-0.4,0.1,0.4" layer: - Opaque - Impassable @@ -186,9 +194,10 @@ components: - type: Rotatable - type: Physics - shapes: - - !type:PhysShapeAabb - bounds: "-0.1,-0.4,0.1,0.4" + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.1,-0.4,0.1,0.4" layer: - Opaque - Impassable @@ -208,9 +217,10 @@ name: armory sign components: - type: Physics - shapes: - - !type:PhysShapeAabb - bounds: "-0.4,-0.3,0.4,0.3" + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.4,-0.3,0.4,0.3" layer: - Opaque - Impassable @@ -228,9 +238,10 @@ name: tool storage sign components: - type: Physics - shapes: - - !type:PhysShapeAabb - bounds: "-0.4,-0.3,0.4,0.3" + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.4,-0.3,0.4,0.3" layer: - Opaque - Impassable @@ -248,9 +259,10 @@ name: anomaly lab sign components: - type: Physics - shapes: - - !type:PhysShapeAabb - bounds: "-0.4,-0.3,0.4,0.3" + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.4,-0.3,0.4,0.3" layer: - Opaque - Impassable @@ -268,9 +280,10 @@ name: atmos sign components: - type: Physics - shapes: - - !type:PhysShapeAabb - bounds: "-0.4,-0.3,0.4,0.3" + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.4,-0.3,0.4,0.3" layer: - Opaque - Impassable @@ -288,9 +301,10 @@ name: bar sign components: - type: Physics - shapes: - - !type:PhysShapeAabb - bounds: "-0.4,-0.3,0.4,0.3" + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.4,-0.3,0.4,0.3" layer: - Opaque - Impassable @@ -308,9 +322,10 @@ name: library sign components: - type: Physics - shapes: - - !type:PhysShapeAabb - bounds: "-0.4,-0.3,0.4,0.3" + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.4,-0.3,0.4,0.3" layer: - Opaque - Impassable @@ -328,9 +343,10 @@ name: chapel sign components: - type: Physics - shapes: - - !type:PhysShapeAabb - bounds: "-0.4,-0.3,0.4,0.3" + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.4,-0.3,0.4,0.3" layer: - Opaque - Impassable @@ -348,9 +364,10 @@ name: head sign components: - type: Physics - shapes: - - !type:PhysShapeAabb - bounds: "-0.4,-0.3,0.4,0.3" + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.4,-0.3,0.4,0.3" layer: - Opaque - Impassable @@ -368,9 +385,10 @@ name: conference room sign components: - type: Physics - shapes: - - !type:PhysShapeAabb - bounds: "-0.4,-0.3,0.4,0.3" + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.4,-0.3,0.4,0.3" layer: - Opaque - Impassable @@ -388,9 +406,10 @@ name: drones sign components: - type: Physics - shapes: - - !type:PhysShapeAabb - bounds: "-0.4,-0.3,0.4,0.3" + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.4,-0.3,0.4,0.3" layer: - Opaque - Impassable @@ -408,9 +427,10 @@ name: engine sign components: - type: Physics - shapes: - - !type:PhysShapeAabb - bounds: "-0.4,-0.3,0.4,0.3" + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.4,-0.3,0.4,0.3" layer: - Opaque - Impassable @@ -428,9 +448,10 @@ name: cloning sign components: - type: Physics - shapes: - - !type:PhysShapeAabb - bounds: "-0.4,-0.3,0.4,0.3" + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.4,-0.3,0.4,0.3" layer: - Opaque - Impassable @@ -448,9 +469,10 @@ name: interrogation sign components: - type: Physics - shapes: - - !type:PhysShapeAabb - bounds: "-0.4,-0.3,0.4,0.3" + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.4,-0.3,0.4,0.3" layer: - Opaque - Impassable @@ -468,9 +490,10 @@ name: surgery sign components: - type: Physics - shapes: - - !type:PhysShapeAabb - bounds: "-0.4,-0.3,0.4,0.3" + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.4,-0.3,0.4,0.3" layer: - Opaque - Impassable @@ -488,9 +511,10 @@ name: telecomms sign components: - type: Physics - shapes: - - !type:PhysShapeAabb - bounds: "-0.4,-0.3,0.4,0.3" + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.4,-0.3,0.4,0.3" layer: - Opaque - Impassable @@ -508,9 +532,10 @@ name: cargo sign components: - type: Physics - shapes: - - !type:PhysShapeAabb - bounds: "-0.4,-0.3,0.4,0.3" + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.4,-0.3,0.4,0.3" layer: - Opaque - Impassable @@ -528,9 +553,10 @@ name: cargo dock sign components: - type: Physics - shapes: - - !type:PhysShapeAabb - bounds: "-0.4,-0.3,0.4,0.3" + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.4,-0.3,0.4,0.3" layer: - Opaque - Impassable @@ -548,9 +574,10 @@ name: chemistry sign components: - type: Physics - shapes: - - !type:PhysShapeAabb - bounds: "-0.4,-0.3,0.4,0.3" + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.4,-0.3,0.4,0.3" layer: - Opaque - Impassable @@ -568,9 +595,10 @@ name: docking sign components: - type: Physics - shapes: - - !type:PhysShapeAabb - bounds: "-0.4,-0.3,0.4,0.3" + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.4,-0.3,0.4,0.3" layer: - Opaque - Impassable @@ -588,9 +616,10 @@ name: engineering sign components: - type: Physics - shapes: - - !type:PhysShapeAabb - bounds: "-0.4,-0.3,0.4,0.3" + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.4,-0.3,0.4,0.3" layer: - Opaque - Impassable @@ -608,9 +637,10 @@ name: EVA sign components: - type: Physics - shapes: - - !type:PhysShapeAabb - bounds: "-0.4,-0.3,0.4,0.3" + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.4,-0.3,0.4,0.3" layer: - Opaque - Impassable @@ -628,9 +658,10 @@ name: gravity sign components: - type: Physics - shapes: - - !type:PhysShapeAabb - bounds: "-0.4,-0.3,0.4,0.3" + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.4,-0.3,0.4,0.3" layer: - Opaque - Impassable @@ -648,9 +679,10 @@ name: medbay sign components: - type: Physics - shapes: - - !type:PhysShapeAabb - bounds: "-0.4,-0.3,0.4,0.3" + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.4,-0.3,0.4,0.3" layer: - Opaque - Impassable @@ -668,9 +700,10 @@ name: morgue sign components: - type: Physics - shapes: - - !type:PhysShapeAabb - bounds: "-0.4,-0.3,0.4,0.3" + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.4,-0.3,0.4,0.3" layer: - Opaque - Impassable @@ -688,9 +721,10 @@ name: prison sign components: - type: Physics - shapes: - - !type:PhysShapeAabb - bounds: "-0.4,-0.3,0.4,0.3" + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.4,-0.3,0.4,0.3" layer: - Opaque - Impassable @@ -708,9 +742,10 @@ name: research and development sign components: - type: Physics - shapes: - - !type:PhysShapeAabb - bounds: "-0.4,-0.3,0.4,0.3" + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.4,-0.3,0.4,0.3" layer: - Opaque - Impassable @@ -728,9 +763,10 @@ name: science sign components: - type: Physics - shapes: - - !type:PhysShapeAabb - bounds: "-0.4,-0.3,0.4,0.3" + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.4,-0.3,0.4,0.3" layer: - Opaque - Impassable @@ -748,9 +784,10 @@ name: toxins sign components: - type: Physics - shapes: - - !type:PhysShapeAabb - bounds: "-0.4,-0.3,0.4,0.3" + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.4,-0.3,0.4,0.3" layer: - Opaque - Impassable @@ -768,9 +805,10 @@ name: bridge sign components: - type: Physics - shapes: - - !type:PhysShapeAabb - bounds: "-0.4,-0.3,0.4,0.3" + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.4,-0.3,0.4,0.3" layer: - Opaque - Impassable @@ -791,9 +829,10 @@ description: WARNING! Air flow tube. Ensure the flow is disengaged before working. components: - type: Physics - shapes: - - !type:PhysShapeAabb - bounds: "-0.2,-0.3,0.2,0.3" + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.2,-0.3,0.2,0.3" layer: - Opaque - Impassable @@ -812,9 +851,10 @@ description: WARNING! CO2 flow tube. Ensure the flow is disengaged before working. components: - type: Physics - shapes: - - !type:PhysShapeAabb - bounds: "-0.2,-0.3,0.2,0.3" + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.2,-0.3,0.2,0.3" layer: - Opaque - Impassable @@ -833,9 +873,10 @@ description: WARNING! N2 flow tube. Ensure the flow is disengaged before working. components: - type: Physics - shapes: - - !type:PhysShapeAabb - bounds: "-0.2,-0.3,0.2,0.3" + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.2,-0.3,0.2,0.3" layer: - Opaque - Impassable @@ -854,9 +895,10 @@ description: WARNING! N2O flow tube. Ensure the flow is disengaged before working. components: - type: Physics - shapes: - - !type:PhysShapeAabb - bounds: "-0.2,-0.3,0.2,0.3" + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.2,-0.3,0.2,0.3" layer: - Opaque - Impassable @@ -875,9 +917,10 @@ description: WARNING! O2 flow tube. Ensure the flow is disengaged before working. components: - type: Physics - shapes: - - !type:PhysShapeAabb - bounds: "-0.2,-0.3,0.2,0.3" + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.2,-0.3,0.2,0.3" layer: - Opaque - Impassable @@ -896,9 +939,10 @@ description: WARNING! Plasma flow tube. Ensure the flow is disengaged before working. components: - type: Physics - shapes: - - !type:PhysShapeAabb - bounds: "-0.2,-0.3,0.2,0.3" + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.2,-0.3,0.2,0.3" layer: - Opaque - Impassable @@ -917,9 +961,10 @@ description: WARNING! Waste flow tube. Ensure the flow is disengaged before working. components: - type: Physics - shapes: - - !type:PhysShapeAabb - bounds: "-0.2,-0.3,0.2,0.3" + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.2,-0.3,0.2,0.3" layer: - Opaque - Impassable @@ -938,9 +983,10 @@ description: A warning sign which reads 'NO SMOKING' components: - type: Physics - shapes: - - !type:PhysShapeAabb - bounds: "-0.4,-0.3,0.4,0.3" + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.4,-0.3,0.4,0.3" layer: - Opaque - Impassable @@ -959,9 +1005,10 @@ description: Technical information of some sort, shame its too worn-out to read. components: - type: Physics - shapes: - - !type:PhysShapeAabb - bounds: "-0.4,-0.3,0.4,0.3" + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.4,-0.3,0.4,0.3" layer: - Opaque - Impassable @@ -980,9 +1027,10 @@ description: Looks like a planet crashing by some station above it. Its kinda scary. components: - type: Physics - shapes: - - !type:PhysShapeAabb - bounds: "-0.4,-0.3,0.4,0.3" + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.4,-0.3,0.4,0.3" layer: - Opaque - Impassable diff --git a/Resources/Prototypes/Entities/Constructible/Walls/walls.yml b/Resources/Prototypes/Entities/Constructible/Walls/walls.yml index 7d03b952c1..2def6a2cc3 100644 --- a/Resources/Prototypes/Entities/Constructible/Walls/walls.yml +++ b/Resources/Prototypes/Entities/Constructible/Walls/walls.yml @@ -20,8 +20,11 @@ - type: Icon state: full - type: Physics - shapes: - - !type:PhysShapeAabb + bodyType: Static + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.5, -0.5, 0.5, 0.5" layer: - Opaque - Impassable diff --git a/Resources/Prototypes/Entities/Constructible/Walls/windows.yml b/Resources/Prototypes/Entities/Constructible/Walls/windows.yml index 3df6bbd30f..cd7a56bfd0 100644 --- a/Resources/Prototypes/Entities/Constructible/Walls/windows.yml +++ b/Resources/Prototypes/Entities/Constructible/Walls/windows.yml @@ -19,8 +19,10 @@ sprite: Constructible/Structures/Windows/window.rsi state: full - type: Physics - shapes: - - !type:PhysShapeAabb + bodyType: Static + fixtures: + - shape: + !type:PhysShapeAabb {} layer: - Impassable - MobImpassable diff --git a/Resources/Prototypes/Entities/Constructible/Watercloset/toilet.yml b/Resources/Prototypes/Entities/Constructible/Watercloset/toilet.yml index cb73fef1f9..61012aaf3b 100644 --- a/Resources/Prototypes/Entities/Constructible/Watercloset/toilet.yml +++ b/Resources/Prototypes/Entities/Constructible/Watercloset/toilet.yml @@ -15,8 +15,9 @@ - type: SolutionContainer maxVol: 250 - type: Physics - shapes: - - !type:PhysShapeAabb + fixtures: + - shape: + !type:PhysShapeAabb {} layer: [ Passable ] - type: Construction graph: toilet diff --git a/Resources/Prototypes/Entities/Effects/chemistry_effects.yml b/Resources/Prototypes/Entities/Effects/chemistry_effects.yml index 0c242f2b3c..1b80370c3f 100644 --- a/Resources/Prototypes/Entities/Effects/chemistry_effects.yml +++ b/Resources/Prototypes/Entities/Effects/chemistry_effects.yml @@ -40,9 +40,10 @@ - type: SnapGrid offset: Center - type: Physics - shapes: - - !type:PhysShapeAabb - bounds: "-0.4,-0.4,0.4,0.4" + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.4,-0.4,0.4,0.4" layer: - MobImpassable - type: FoamSolutionAreaEffect @@ -104,14 +105,15 @@ netsync: false drawdepth: Walls - type: Physics - shapes: - - !type:PhysShapeAabb - layer: - - Opaque - - Impassable - - MobImpassable - - VaultImpassable - - SmallImpassable + fixtures: + - shape: + !type:PhysShapeAabb {} + mask: + - Opaque + - Impassable + - MobImpassable + - VaultImpassable + - SmallImpassable - type: Occluder sizeX: 32 sizeY: 32 diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/animals.yml b/Resources/Prototypes/Entities/Mobs/NPCs/animals.yml index a0bdefb634..84451c7186 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/animals.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/animals.yml @@ -14,11 +14,12 @@ state: monkey sprite: Mobs/Animals/monkey.rsi - type: Physics - anchored: false + bodyType: Dynamic mass: 50 - shapes: - - !type:PhysShapeAabb - bounds: "-0.30,-0.25,0.40,0.25" + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.30,-0.25,0.40,0.25" mask: - Impassable - VaultImpassable @@ -47,11 +48,12 @@ state: crawling sprite: Mobs/Animals/gorilla.rsi - type: Physics - anchored: false + bodyType: Dynamic mass: 90 - shapes: - - !type:PhysShapeAabb - bounds: "-0.90,-0.50,0.05,0.50" + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.90,-0.50,0.05,0.50" mask: - Impassable - VaultImpassable @@ -77,11 +79,12 @@ state: chicken-0 sprite: Mobs/Animals/chicken.rsi - type: Physics - anchored: false + bodyType: Dynamic mass: 20 - shapes: - - !type:PhysShapeAabb - bounds: "-0.45,-0.20,0.10,0.20" + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.45,-0.20,0.10,0.20" mask: - Impassable - VaultImpassable @@ -110,11 +113,12 @@ state: butterfly sprite: Mobs/Animals/butterfly.rsi - type: Physics - anchored: false + bodyType: Dynamic mass: 5 - shapes: - - !type:PhysShapeAabb - bounds: "-0.20,-0.20,0.20,0.20" + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.20,-0.20,0.20,0.20" mask: - Impassable - VaultImpassable @@ -153,11 +157,12 @@ state: bat sprite: Mobs/Animals/bat.rsi - type: Physics - anchored: false + bodyType: Dynamic mass: 5 - shapes: - - !type:PhysShapeAabb - bounds: "-0.20,-0.20,0.20,0.20" + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.20,-0.20,0.20,0.20" mask: - Impassable - VaultImpassable @@ -187,11 +192,12 @@ state: 0 sprite: Mobs/Animals/bee.rsi - type: Physics - anchored: false + bodyType: Dynamic mass: 5 - shapes: - - !type:PhysShapeAabb - bounds: "-0.10,-0.10,0.10,0.10" + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.10,-0.10,0.10,0.10" mask: - Impassable - VaultImpassable @@ -217,11 +223,12 @@ state: goat sprite: Mobs/Animals/goat.rsi - type: Physics - anchored: false + bodyType: Dynamic mass: 20 - shapes: - - !type:PhysShapeAabb - bounds: "-0.60,-0.50,0.05,0.50" + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.60,-0.50,0.05,0.50" mask: - Impassable - VaultImpassable @@ -248,11 +255,12 @@ state: goose sprite: Mobs/Animals/goose.rsi - type: Physics - anchored: false + bodyType: Dynamic mass: 20 - shapes: - - !type:PhysShapeAabb - bounds: "-0.45,-0.35,0.45,0.35" + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.45,-0.35,0.45,0.35" mask: - Impassable - VaultImpassable @@ -282,11 +290,12 @@ state: parrot sprite: Mobs/Animals/parrot.rsi - type: Physics - anchored: false + bodyType: Dynamic mass: 20 - shapes: - - !type:PhysShapeAabb - bounds: "-0.30,-0.35,0.35,0.35" + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.30,-0.35,0.35,0.35" mask: - Impassable - VaultImpassable @@ -312,11 +321,12 @@ state: snake sprite: Mobs/Animals/snake.rsi - type: Physics - anchored: false + bodyType: Dynamic mass: 10 - shapes: - - !type:PhysShapeAabb - bounds: "-0.30,-0.30,0.25,0.30" + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.30,-0.30,0.25,0.30" mask: - Impassable - VaultImpassable @@ -345,11 +355,12 @@ state: tarantula sprite: Mobs/Animals/spider.rsi - type: Physics - anchored: false + bodyType: Dynamic mass: 10 - shapes: - - !type:PhysShapeAabb - bounds: "-0.30,-0.40,0.45,0.40" + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.30,-0.40,0.45,0.40" mask: - Impassable - VaultImpassable @@ -375,11 +386,12 @@ state: crab sprite: Mobs/Animals/crab.rsi - type: Physics - anchored: false + bodyType: Dynamic mass: 10 - shapes: - - !type:PhysShapeAabb - bounds: "-0.40,-0.35,0.20,0.35" + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.40,-0.35,0.20,0.35" mask: - Impassable - VaultImpassable @@ -405,11 +417,12 @@ state: penguin sprite: Mobs/Animals/penguin.rsi - type: Physics - anchored: false + bodyType: Dynamic mass: 10 - shapes: - - !type:PhysShapeAabb - bounds: "-0.50,-0.30,0.35,0.30" + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.50,-0.30,0.35,0.30" mask: - Impassable - VaultImpassable diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/carp.yml b/Resources/Prototypes/Entities/Mobs/NPCs/carp.yml index a326dce431..a590dcb578 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/carp.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/carp.yml @@ -18,11 +18,12 @@ state: alive sprite: Mobs/Aliens/Carps/space.rsi - type: Physics - anchored: false + bodyType: Dynamic mass: 50 - shapes: - - !type:PhysShapeAabb - bounds: "-0.35,-0.35,0.35,0.35" + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.35,-0.35,0.35,0.35" mask: - Impassable - MobImpassable diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/mimic.yml b/Resources/Prototypes/Entities/Mobs/NPCs/mimic.yml index 7d602aeccd..759d626051 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/mimic.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/mimic.yml @@ -22,11 +22,12 @@ sprite: Constructible/Power/VendingMachines/cola.rsi state: normal - type: Physics - anchored: false + bodyType: Dynamic mass: 85 - shapes: - - !type:PhysShapeAabb - bounds: "-0.35,-0.35,0.35,0.35" + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.35,-0.35,0.35,0.35" mask: - Impassable - MobImpassable diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/pets.yml b/Resources/Prototypes/Entities/Mobs/NPCs/pets.yml index 310f55ce1e..99b904fd54 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/pets.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/pets.yml @@ -15,9 +15,10 @@ state: corgi - type: Physics mass: 10 - shapes: - - !type:PhysShapeAabb - bounds: "-0.50,-0.25,0.30,0.25" + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.50,-0.25,0.30,0.25" mask: - Impassable - VaultImpassable @@ -62,9 +63,10 @@ state: cat - type: Physics mass: 10 - shapes: - - !type:PhysShapeAabb - bounds: "-0.45,-0.20,0.30,0.20" + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.45,-0.20,0.30,0.20" mask: - Impassable - VaultImpassable @@ -112,9 +114,10 @@ state: sloth - type: Physics mass: 10 - shapes: - - !type:PhysShapeAabb - bounds: "-0.45,-0.35,0.15,0.35" + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.45,-0.35,0.15,0.35" mask: - Impassable - VaultImpassable diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/simplemob.yml b/Resources/Prototypes/Entities/Mobs/NPCs/simplemob.yml index 4f0669d52e..89832ec574 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/simplemob.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/simplemob.yml @@ -29,10 +29,11 @@ drawdepth: Mobs - type: Clickable - type: Physics - anchored: false + bodyType: Dynamic mass: 50 - shapes: - - !type:PhysShapeAabb + fixtures: + - shape: + !type:PhysShapeAabb {} mask: - Impassable # - MobImpassable Turns these off for now since humans don't have collisions either. diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/xeno.yml b/Resources/Prototypes/Entities/Mobs/NPCs/xeno.yml index cca996bacc..0580157e8a 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/xeno.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/xeno.yml @@ -20,11 +20,12 @@ state: running sprite: Mobs/Aliens/Xenos/xeno.rsi - type: Physics - anchored: false + bodyType: Dynamic mass: 85 - shapes: - - !type:PhysShapeAabb - bounds: "-1,-0.4,-0.2,0.4" + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-1,-0.4,-0.2,0.4" mask: - Impassable - MobImpassable diff --git a/Resources/Prototypes/Entities/Mobs/Player/admin_ghost.yml b/Resources/Prototypes/Entities/Mobs/Player/admin_ghost.yml index f559eaab3d..96818923ee 100644 --- a/Resources/Prototypes/Entities/Mobs/Player/admin_ghost.yml +++ b/Resources/Prototypes/Entities/Mobs/Player/admin_ghost.yml @@ -4,3 +4,16 @@ id: AdminObserver name: admin observer abstract: true + components: + - type: PlayerInputMover + - type: Physics + bodyType: Kinematic + mass: 5 + # TODO: Even need these? Don't think so but CBF checking right now. + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.35,-0.35,0.35,0.35" + mask: + - GhostImpassable + status: InAir diff --git a/Resources/Prototypes/Entities/Mobs/Player/human.yml b/Resources/Prototypes/Entities/Mobs/Player/human.yml index 1395b32226..3fc7d97753 100644 --- a/Resources/Prototypes/Entities/Mobs/Player/human.yml +++ b/Resources/Prototypes/Entities/Mobs/Player/human.yml @@ -9,6 +9,8 @@ showExamineInfo: true - type: Input context: "human" + - type: PlayerMobMover + - type: PlayerInputMover - type: Alerts - type: Actions innateActions: diff --git a/Resources/Prototypes/Entities/Mobs/Player/observer.yml b/Resources/Prototypes/Entities/Mobs/Player/observer.yml index c8ff82560a..52c9d35ebc 100644 --- a/Resources/Prototypes/Entities/Mobs/Player/observer.yml +++ b/Resources/Prototypes/Entities/Mobs/Player/observer.yml @@ -9,11 +9,12 @@ - type: Clickable - type: InteractionOutline - type: Physics - anchored: false + bodyType: KinematicController mass: 5 - shapes: - - !type:PhysShapeAabb - bounds: "-0.35,-0.35,0.35,0.35" + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.35,-0.35,0.35,0.35" mask: - GhostImpassable status: InAir diff --git a/Resources/Prototypes/Entities/Mobs/Species/human.yml b/Resources/Prototypes/Entities/Mobs/Species/human.yml index 595535889e..c7f9117bc3 100644 --- a/Resources/Prototypes/Entities/Mobs/Species/human.yml +++ b/Resources/Prototypes/Entities/Mobs/Species/human.yml @@ -116,11 +116,13 @@ - map: [ "enum.Slots.MASK" ] - map: [ "enum.Slots.HEAD" ] - type: Physics - anchored: false - mass: 85 - shapes: - - !type:PhysShapeAabb - bounds: "-0.35,-0.35,0.35,0.35" + bodyType: KinematicController + mass: 70 + fixtures: + - shape: + !type:PhysShapeCircle + radius: 0.35 + restitution: 0.0 mask: - Impassable - MobImpassable @@ -128,7 +130,6 @@ layer: - Opaque - MobImpassable - - type: PlayerInputMover - type: AtmosExposed - type: Flammable fireSpread: true @@ -298,11 +299,12 @@ - map: ["hand-left"] - map: ["hand-right"] - type: Physics - anchored: false + bodyType: Dynamic mass: 85 - shapes: - - !type:PhysShapeAabb - bounds: "-0.35,-0.35,0.35,0.35" + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.35,-0.35,0.35,0.35" mask: - Impassable - MobImpassable diff --git a/Resources/Prototypes/Entities/Mobs/Species/slime.yml b/Resources/Prototypes/Entities/Mobs/Species/slime.yml index fe10e531fc..c7bfa01566 100644 --- a/Resources/Prototypes/Entities/Mobs/Species/slime.yml +++ b/Resources/Prototypes/Entities/Mobs/Species/slime.yml @@ -114,11 +114,12 @@ - map: [ "enum.Slots.MASK" ] - map: [ "enum.Slots.HEAD" ] - type: Physics - anchored: false + bodyType: Dynamic mass: 85 - shapes: - - !type:PhysShapeAabb - bounds: "-0.35,-0.35,0.35,0.35" + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.35,-0.35,0.35,0.35" mask: - Impassable - MobImpassable diff --git a/Resources/Prototypes/Entities/Objects/Consumable/trash.yml b/Resources/Prototypes/Entities/Objects/Consumable/trash.yml index deabc3b5df..733c18ab5b 100644 --- a/Resources/Prototypes/Entities/Objects/Consumable/trash.yml +++ b/Resources/Prototypes/Entities/Objects/Consumable/trash.yml @@ -152,7 +152,7 @@ components: - type: Sprite sprite: Objects/Consumable/Trash/tastybread.rsi - + - type: entity name: tray (trash) @@ -183,8 +183,9 @@ - type: Slippery intersectPercentage: 0.2 - type: Physics - shapes: - - !type:PhysShapeAabb - bounds: "-0.2,-0.2,0.2,0.2" + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.2,-0.2,0.2,0.2" layer: - MobImpassable diff --git a/Resources/Prototypes/Entities/Objects/Devices/pda.yml b/Resources/Prototypes/Entities/Objects/Devices/pda.yml index 925fa649a3..7b06ab0acd 100644 --- a/Resources/Prototypes/Entities/Objects/Devices/pda.yml +++ b/Resources/Prototypes/Entities/Objects/Devices/pda.yml @@ -86,9 +86,10 @@ - type: Slippery paralyzeTime: 4 - type: Physics - shapes: - - !type:PhysShapeAabb - bounds: "-0.25,-0.25,0.25,0.25" + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.25,-0.25,0.25,0.25" layer: - MobImpassable diff --git a/Resources/Prototypes/Entities/Objects/Misc/fire_extinguisher.yml b/Resources/Prototypes/Entities/Objects/Misc/fire_extinguisher.yml index 77c85606d3..0069a1c5b5 100644 --- a/Resources/Prototypes/Entities/Objects/Misc/fire_extinguisher.yml +++ b/Resources/Prototypes/Entities/Objects/Misc/fire_extinguisher.yml @@ -48,14 +48,15 @@ - state: extinguish map: [ "enum.VaporVisualLayers.Base" ] - type: Physics - hard: false - shapes: - - !type:PhysShapeAabb - bounds: "-0.25,-0.25,0.25,0.25" - mask: - - Impassable - - MobImpassable - - SmallImpassable + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.25,-0.25,0.25,0.25" + hard: false + mask: + - Impassable + - MobImpassable + - SmallImpassable - type: Appearance visuals: - type: VaporVisualizer diff --git a/Resources/Prototypes/Entities/Objects/Misc/fluff_lights.yml b/Resources/Prototypes/Entities/Objects/Misc/fluff_lights.yml index cf65ad75aa..81b3b2c0c5 100644 --- a/Resources/Prototypes/Entities/Objects/Misc/fluff_lights.yml +++ b/Resources/Prototypes/Entities/Objects/Misc/fluff_lights.yml @@ -87,8 +87,9 @@ shader: unshaded visible: false - type: Physics - shapes: - - !type:PhysShapeAabb + fixtures: + - shape: + !type:PhysShapeAabb {} layer: - Opaque - Impassable @@ -149,8 +150,9 @@ - !type:DoActsBehavior acts: [ "Destruction" ] - type: Physics - shapes: - - !type:PhysShapeAabb + fixtures: + - shape: + !type:PhysShapeAabb {} layer: - Opaque - Impassable diff --git a/Resources/Prototypes/Entities/Objects/Misc/teleporters.yml b/Resources/Prototypes/Entities/Objects/Misc/teleporters.yml index c6b42d9d33..f53b0053bc 100644 --- a/Resources/Prototypes/Entities/Objects/Misc/teleporters.yml +++ b/Resources/Prototypes/Entities/Objects/Misc/teleporters.yml @@ -49,8 +49,9 @@ description: "Portal to another location." components: - type: Physics - shapes: - - !type:PhysShapeAabb + fixtures: + - shape: + !type:PhysShapeAabb {} mask: [Impassable, MobImpassable] - type: Portal - type: Sprite diff --git a/Resources/Prototypes/Entities/Objects/Power/powercells.yml b/Resources/Prototypes/Entities/Objects/Power/powercells.yml index ca78abb98f..640be828f2 100644 --- a/Resources/Prototypes/Entities/Objects/Power/powercells.yml +++ b/Resources/Prototypes/Entities/Objects/Power/powercells.yml @@ -7,10 +7,11 @@ parent: BaseItem components: - type: Physics - anchored: false - shapes: - - !type:PhysShapeAabb - bounds: "-0.15,-0.3,0.2,0.3" # TODO: these are placeholder values + bodyType: Dynamic + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.15,-0.3,0.2,0.3" # TODO: these are placeholder values layer: - Clickable - type: PowerCell @@ -322,9 +323,10 @@ - type: InteractionOutline - type: Physics mass: 5 - shapes: - - !type:PhysShapeAabb - bounds: "-0.25,-0.25,0.25,0.25" + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.25,-0.25,0.25,0.25" mask: [Impassable] layer: [Clickable] @@ -350,9 +352,10 @@ - type: InteractionOutline - type: Physics mass: 5 - shapes: - - !type:PhysShapeAabb - bounds: "-0.25,-0.25,0.25,0.25" + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.25,-0.25,0.25,0.25" mask: [Impassable] layer: [Clickable] @@ -377,8 +380,9 @@ - type: InteractionOutline - type: Physics mass: 5 - shapes: - - !type:PhysShapeAabb - bounds: "-0.25,-0.25,0.25,0.25" + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.25,-0.25,0.25,0.25" mask: [Impassable] layer: [Clickable] diff --git a/Resources/Prototypes/Entities/Objects/Specific/janitor.yml b/Resources/Prototypes/Entities/Objects/Specific/janitor.yml index 22e348823b..1a43a49a61 100644 --- a/Resources/Prototypes/Entities/Objects/Specific/janitor.yml +++ b/Resources/Prototypes/Entities/Objects/Specific/janitor.yml @@ -40,10 +40,11 @@ - type: Physics mass: 5 - anchored: false - shapes: - - !type:PhysShapeAabb - bounds: "-0.40,-0.25,0.25,0.25" + bodyType: Dynamic + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.40,-0.25,0.25,0.25" mask: - Impassable - Opaque @@ -70,10 +71,11 @@ maxVol: 500 - type: Physics mass: 5 - anchored: false - shapes: - - !type:PhysShapeAabb - bounds: "-0.25,-0.25,0.25,0.25" + bodyType: Dynamic + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.25,-0.25,0.25,0.25" mask: - Impassable - type: Spillable @@ -104,9 +106,10 @@ - type: Slippery paralyzeTime: 2.5 - type: Physics - shapes: - - !type:PhysShapeAabb - bounds: "-0.3,-0.4,0.3,0.4" + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.3,-0.4,0.3,0.4" layer: - MobImpassable @@ -178,15 +181,16 @@ - state: chempuff map: [ "enum.VaporVisualLayers.Base" ] - type: Physics - anchored: false - hard: false - shapes: - - !type:PhysShapeAabb - bounds: "-0.25,-0.25,0.25,0.25" - mask: - - Impassable - - MobImpassable - - SmallImpassable + bodyType: Dynamic + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.25,-0.25,0.25,0.25" + hard: false + mask: + - Impassable + - MobImpassable + - SmallImpassable - type: Appearance visuals: - type: VaporVisualizer diff --git a/Resources/Prototypes/Entities/Objects/Specific/morgue.yml b/Resources/Prototypes/Entities/Objects/Specific/morgue.yml index efbd62ae2c..c5b141c9b4 100644 --- a/Resources/Prototypes/Entities/Objects/Specific/morgue.yml +++ b/Resources/Prototypes/Entities/Objects/Specific/morgue.yml @@ -20,10 +20,11 @@ - type: MovedByPressure - type: Physics mass: 5 - anchored: false - shapes: - - !type:PhysShapeAabb - bounds: "-0.45,-0.5,0.1,0.5" + bodyType: Dynamic + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.45,-0.5,0.1,0.5" layer: - Clickable - type: BodyBagEntityStorage @@ -38,7 +39,7 @@ state_closed: bag - type: BodyBagVisualizer - type: Pullable - + - type: entity id: BodyBag_Item name: body bag @@ -53,8 +54,8 @@ # - type: Placeable # prototype: someId # snap: Center - - + + - type: entity id: Morgue name: morgue @@ -74,10 +75,11 @@ - type: InteractionOutline - type: Physics mass: 25 - anchored: true - shapes: - - !type:PhysShapeAabb - bounds: "-0.5, -0.5, 0.5, 0.5" + bodyType: Static + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.5, -0.5, 0.5, 0.5" mask: - Impassable - MobImpassable @@ -105,7 +107,7 @@ light_soul: morgue_soul_light - type: SnapGrid offset: Center - + - type: entity id: MorgueTray name: morgue tray @@ -119,10 +121,11 @@ - type: InteractionOutline - type: Physics mass: 15 - anchored: true - shapes: - - !type:PhysShapeAabb - bounds: "-0.5, -0.5, 0.5, 0.5" + bodyType: Static + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.5, -0.5, 0.5, 0.5" layer: - Clickable - type: MorgueTray @@ -147,10 +150,11 @@ - type: InteractionOutline - type: Physics mass: 25 - anchored: true - shapes: - - !type:PhysShapeAabb - bounds: "-0.5, -0.5, 0.5, 0.5" + bodyType: Static + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.5, -0.5, 0.5, 0.5" mask: - Impassable - MobImpassable @@ -179,7 +183,7 @@ light_burning: crema_active_light - type: SnapGrid offset: Center - + - type: entity id: CrematoriumTray name: crematorium tray @@ -199,4 +203,4 @@ - type: Sprite netsync: false sprite: Objects/Consumable/Trash/ash.rsi - state: icon \ No newline at end of file + state: icon diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Projectiles/projectiles.yml b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Projectiles/projectiles.yml index 7b4a09a261..bb917b9793 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Projectiles/projectiles.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Projectiles/projectiles.yml @@ -12,11 +12,12 @@ sprite: Objects/Weapons/Guns/Projectiles/bullet.rsi state: bullet - type: Physics - anchored: false - hard: false - shapes: - - !type:PhysShapeAabb - bounds: "-0.1,-0.1,0.1,0.1" + bodyType: Dynamic + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.1,-0.1,0.1,0.1" + hard: false layer: [Clickable] mask: - Impassable @@ -96,12 +97,12 @@ - state: spark shader: unshaded - type: Physics - anchored: false - - hard: false - shapes: - - !type:PhysShapeAabb - bounds: "-0.2,-0.2,0.2,0.2" + bodyType: Dynamic + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.2,-0.2,0.2,0.2" + hard: false layer: 32 mask: 30 diff --git a/Resources/Prototypes/Entities/base_item.yml b/Resources/Prototypes/Entities/base_item.yml index 4425aebf80..57a03f5c92 100644 --- a/Resources/Prototypes/Entities/base_item.yml +++ b/Resources/Prototypes/Entities/base_item.yml @@ -9,14 +9,23 @@ - type: InteractionOutline - type: MovedByPressure - type: DamageOnHighSpeedImpact + - type: CollisionWake + - type: TileFrictionModifier + modifier: 0.5 - type: Physics - anchored: false + bodyType: Dynamic mass: 5 - shapes: - - !type:PhysShapeAabb - bounds: "-0.25,-0.25,0.25,0.25" + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.25,-0.25,0.25,0.25" layer: - Clickable + mask: + - Impassable + - SmallImpassable + restitution: 0.8 # We want them items B O U N C Y + friction: 0.2 - type: Sprite drawdepth: Items - type: Pullable diff --git a/Resources/Prototypes/Entities/puddle.yml b/Resources/Prototypes/Entities/puddle.yml index 1cb3ec9b43..e6df04d03b 100644 --- a/Resources/Prototypes/Entities/puddle.yml +++ b/Resources/Prototypes/Entities/puddle.yml @@ -16,12 +16,13 @@ - type: Clickable - type: Slippery - type: Physics - shapes: - - !type:PhysShapeAabb - bounds: "-0.4,-0.4,0.4,0.4" + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.4,-0.4,0.4,0.4" + hard: false layer: - MobImpassable - hard: false - type: entity name: puddle diff --git a/Resources/Prototypes/Entities/traitordm.yml b/Resources/Prototypes/Entities/traitordm.yml index bdd92fe792..17c709729f 100644 --- a/Resources/Prototypes/Entities/traitordm.yml +++ b/Resources/Prototypes/Entities/traitordm.yml @@ -13,11 +13,12 @@ - type: Clickable - type: InteractionOutline - type: Physics - anchored: true + bodyType: Static mass: 1 - shapes: - - !type:PhysShapeAabb - bounds: "-0.25,-0.25,0.25,0.25" + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.25,-0.25,0.25,0.25" layer: - Clickable - type: TraitorDeathMatchRedemption