]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
Fix formatting to match .editorconfig (IDE0055 warnings) (#23301)
authorLordCarve <27449516+LordCarve@users.noreply.github.com>
Mon, 1 Jan 2024 02:20:02 +0000 (03:20 +0100)
committerGitHub <noreply@github.com>
Mon, 1 Jan 2024 02:20:02 +0000 (21:20 -0500)
Content.Shared/Climbing/Components/ClimbingComponent.cs
Content.Shared/Climbing/Systems/ClimbSystem.cs

index 9738c0cee9ba1d9de87f08a75f43b3b8e3f6b1b5..2af2c89feb50b783f5e1afd616746cb2e33ec67a 100644 (file)
@@ -16,7 +16,7 @@ public sealed partial class ClimbingComponent : Component
     /// <summary>
     /// Whether the owner is being moved onto the climbed entity.
     /// </summary>
-    [AutoNetworkedField, DataField(customTypeSerializer:typeof(TimeOffsetSerializer))]
+    [AutoNetworkedField, DataField(customTypeSerializer: typeof(TimeOffsetSerializer))]
     public TimeSpan? NextTransition;
 
     /// <summary>
index 081fb7fd8c4a1f050c4ccf79ad059e4c87d7f4df..21809f475637f98ac0164ecb690a6ed6c48558b1 100644 (file)
@@ -158,341 +158,341 @@ public sealed partial class ClimbSystem : VirtualController
         }
     }
 
-     private void OnCanDragDropOn(EntityUid uid, ClimbableComponent component, ref CanDropTargetEvent args)
-     {
-         if (args.Handled)
-             return;
-
-
-         var canVault = args.User == args.Dragged
-             ? CanVault(component, args.User, uid, out _)
-             : CanVault(component, args.User, args.Dragged, uid, out _);
-
-         args.CanDrop = canVault;
-
-         if (!HasComp<HandsComponent>(args.User))
-             args.CanDrop = false;
-
-         args.Handled = true;
-     }
-
-     private void AddClimbableVerb(EntityUid uid, ClimbableComponent component, GetVerbsEvent<AlternativeVerb> args)
-     {
-         if (!args.CanAccess || !args.CanInteract || !_actionBlockerSystem.CanMove(args.User))
-             return;
-
-         if (!TryComp(args.User, out ClimbingComponent? climbingComponent) || climbingComponent.IsClimbing)
-             return;
-
-         // TODO VERBS ICON add a climbing icon?
-         args.Verbs.Add(new AlternativeVerb
-         {
-             Act = () => TryClimb(args.User, args.User, args.Target, out _, component),
-             Text = Loc.GetString("comp-climbable-verb-climb")
-         });
-     }
-
-     private void OnClimbableDragDrop(EntityUid uid, ClimbableComponent component, ref DragDropTargetEvent args)
-     {
-         if (args.Handled)
-             return;
-
-         TryClimb(args.User, args.Dragged, uid, out _, component);
-     }
-
-     public bool TryClimb(
-         EntityUid user,
-         EntityUid entityToMove,
-         EntityUid climbable,
-         out DoAfterId? id,
-         ClimbableComponent? comp = null,
-         ClimbingComponent? climbing = null)
-     {
-         id = null;
-
-         if (!Resolve(climbable, ref comp) || !Resolve(entityToMove, ref climbing))
-             return false;
-
-         // Note, IsClimbing does not mean a DoAfter is active, it means the target has already finished a DoAfter and
-         // is currently on top of something..
-         if (climbing.IsClimbing)
-             return true;
-
-         var args = new DoAfterArgs(EntityManager, user, comp.ClimbDelay, new ClimbDoAfterEvent(),
-             entityToMove,
-             target: climbable,
-             used: entityToMove)
-         {
-             BreakOnTargetMove = true,
-             BreakOnUserMove = true,
-             BreakOnDamage = true
-         };
-
-         _audio.PlayPredicted(comp.StartClimbSound, climbable, user);
-         return _doAfterSystem.TryStartDoAfter(args, out id);
-     }
-
-     private void OnDoAfter(EntityUid uid, ClimbingComponent component, ClimbDoAfterEvent args)
-     {
-         if (args.Handled || args.Cancelled || args.Args.Target == null || args.Args.Used == null)
-             return;
-
-         Climb(uid, args.Args.User, args.Args.Target.Value, climbing: component);
-         args.Handled = true;
-     }
-
-     private void Climb(EntityUid uid, EntityUid user, EntityUid climbable, bool silent = false, ClimbingComponent? climbing = null,
-         PhysicsComponent? physics = null, FixturesComponent? fixtures = null, ClimbableComponent? comp = null)
-     {
-         if (!Resolve(uid, ref climbing, ref physics, ref fixtures, false))
-             return;
-
-         if (!Resolve(climbable, ref comp))
-             return;
-
-         if (!ReplaceFixtures(uid, climbing, fixtures))
-             return;
-
-         var xform = _xformQuery.GetComponent(uid);
-         var (worldPos, worldRot) = _xformSystem.GetWorldPositionRotation(xform);
-         var worldDirection = _xformSystem.GetWorldPosition(climbable) - worldPos;
-         var distance = worldDirection.Length();
-         var parentRot = (worldRot - xform.LocalRotation);
-         // Need direction relative to climber's parent.
-         var localDirection = (-parentRot).RotateVec(worldDirection);
-
-         // On top of it already so just do it in place.
-         if (localDirection.LengthSquared() < 0.01f)
-         {
-             climbing.NextTransition = null;
-         }
-         // VirtualController over to the thing.
-         else
-         {
-             var climbDuration = TimeSpan.FromSeconds(distance / climbing.TransitionRate);
-             climbing.NextTransition = _timing.CurTime + climbDuration;
-
-             climbing.Direction = localDirection.Normalized() * climbing.TransitionRate;
-             _actionBlockerSystem.UpdateCanMove(uid);
-         }
-
-         climbing.IsClimbing = true;
-         Dirty(uid, climbing);
-
-         _audio.PlayPredicted(comp.FinishClimbSound, climbable, user);
-
-         var startEv = new StartClimbEvent(climbable);
-         var climbedEv = new ClimbedOnEvent(uid, user);
-         RaiseLocalEvent(uid, ref startEv);
-         RaiseLocalEvent(climbable, ref climbedEv);
-
-         if (silent)
-             return;
-
-         string selfMessage;
-         string othersMessage;
-
-         if (user == uid)
-         {
-             othersMessage = Loc.GetString("comp-climbable-user-climbs-other",
-                 ("user", Identity.Entity(uid, EntityManager)),
-                 ("climbable", climbable));
-
-             selfMessage = Loc.GetString("comp-climbable-user-climbs", ("climbable", climbable));
-         }
-         else
-         {
-             othersMessage = Loc.GetString("comp-climbable-user-climbs-force-other",
-                 ("user", Identity.Entity(user, EntityManager)),
-                 ("moved-user", Identity.Entity(uid, EntityManager)), ("climbable", climbable));
-
-             selfMessage = Loc.GetString("comp-climbable-user-climbs-force", ("moved-user", Identity.Entity(uid, EntityManager)),
-                 ("climbable", climbable));
-         }
-
-         _popupSystem.PopupEntity(othersMessage, uid, Filter.PvsExcept(user, entityManager: EntityManager), true);
-         _popupSystem.PopupClient(selfMessage, uid, user);
-     }
-
-     /// <summary>
-     /// Replaces the current fixtures with non-climbing collidable versions so that climb end can be detected
-     /// </summary>
-     /// <returns>Returns whether adding the new fixtures was successful</returns>
-     private bool ReplaceFixtures(EntityUid uid, ClimbingComponent climbingComp, FixturesComponent fixturesComp)
-     {
-         // Swap fixtures
-         foreach (var (name, fixture) in fixturesComp.Fixtures)
-         {
-             if (climbingComp.DisabledFixtureMasks.ContainsKey(name)
-                 || fixture.Hard == false
-                 || (fixture.CollisionMask & ClimbingCollisionGroup) == 0)
-             {
-                 continue;
-             }
-
-             climbingComp.DisabledFixtureMasks.Add(name, fixture.CollisionMask & ClimbingCollisionGroup);
-             _physics.SetCollisionMask(uid, name, fixture, fixture.CollisionMask & ~ClimbingCollisionGroup, fixturesComp);
-         }
-
-         if (!_fixtureSystem.TryCreateFixture(
-                 uid,
-                 new PhysShapeCircle(0.35f),
-                 ClimbingFixtureName,
-                 collisionLayer: (int) CollisionGroup.None,
-                 collisionMask: ClimbingCollisionGroup,
-                 hard: false,
-                 manager: fixturesComp))
-         {
-             return false;
-         }
-
-         return true;
-     }
-
-     private void OnClimbEndCollide(EntityUid uid, ClimbingComponent component, ref EndCollideEvent args)
-     {
-         if (args.OurFixtureId != ClimbingFixtureName
-             || !component.IsClimbing
-             || component.NextTransition != null)
-         {
-             return;
-         }
-
-         foreach (var otherFixture in args.OurFixture.Contacts.Keys)
-         {
-             // If it's the other fixture then ignore em
-             if (otherFixture == args.OtherFixture)
-                 continue;
-
-             // If still colliding with a climbable, do not stop climbing
-             if (HasComp<ClimbableComponent>(otherFixture.Owner))
-                 return;
-         }
-
-         StopClimb(uid, component);
-     }
-
-     private void StopClimb(EntityUid uid, ClimbingComponent? climbing = null, FixturesComponent? fixtures = null)
-     {
-         if (!Resolve(uid, ref climbing, ref fixtures, false))
-             return;
-
-         foreach (var (name, fixtureMask) in climbing.DisabledFixtureMasks)
-         {
-             if (!fixtures.Fixtures.TryGetValue(name, out var fixture))
-             {
-                 continue;
-             }
-
-             _physics.SetCollisionMask(uid, name, fixture, fixture.CollisionMask | fixtureMask, fixtures);
-         }
-
-         climbing.DisabledFixtureMasks.Clear();
-         _fixtureSystem.DestroyFixture(uid, ClimbingFixtureName, manager: fixtures);
-         climbing.IsClimbing = false;
-         climbing.NextTransition = null;
-         var ev = new EndClimbEvent();
-         RaiseLocalEvent(uid, ref ev);
-         Dirty(uid, climbing);
-     }
-
-     /// <summary>
-     ///     Checks if the user can vault the target
-     /// </summary>
-     /// <param name="component">The component of the entity that is being vaulted</param>
-     /// <param name="user">The entity that wants to vault</param>
-     /// <param name="target">The object that is being vaulted</param>
-     /// <param name="reason">The reason why it cant be dropped</param>
-     public bool CanVault(ClimbableComponent component, EntityUid user, EntityUid target, out string reason)
-     {
-         if (!_actionBlockerSystem.CanInteract(user, target))
-         {
-             reason = Loc.GetString("comp-climbable-cant-interact");
-             return false;
-         }
-
-         if (!HasComp<ClimbingComponent>(user)
-             || !TryComp(user, out BodyComponent? body)
-             || !_bodySystem.BodyHasPartType(user, BodyPartType.Leg, body)
-             || !_bodySystem.BodyHasPartType(user, BodyPartType.Foot, body))
-         {
-             reason = Loc.GetString("comp-climbable-cant-climb");
-             return false;
-         }
-
-         if (!_interactionSystem.InRangeUnobstructed(user, target, component.Range))
-         {
-             reason = Loc.GetString("comp-climbable-cant-reach");
-             return false;
-         }
-
-         reason = string.Empty;
-         return true;
-     }
-
-     /// <summary>
-     ///     Checks if the user can vault the dragged entity onto the the target
-     /// </summary>
-     /// <param name="component">The climbable component of the object being vaulted onto</param>
-     /// <param name="user">The user that wants to vault the entity</param>
-     /// <param name="dragged">The entity that is being vaulted</param>
-     /// <param name="target">The object that is being vaulted onto</param>
-     /// <param name="reason">The reason why it cant be dropped</param>
-     /// <returns></returns>
-     public bool CanVault(ClimbableComponent component, EntityUid user, EntityUid dragged, EntityUid target,
-         out string reason)
-     {
-         if (!_actionBlockerSystem.CanInteract(user, dragged) || !_actionBlockerSystem.CanInteract(user, target))
-         {
-             reason = Loc.GetString("comp-climbable-cant-interact");
-             return false;
-         }
-
-         if (!HasComp<ClimbingComponent>(dragged))
-         {
-             reason = Loc.GetString("comp-climbable-cant-climb");
-             return false;
-         }
-
-         bool Ignored(EntityUid entity) => entity == target || entity == user || entity == dragged;
-
-         if (!_interactionSystem.InRangeUnobstructed(user, target, component.Range, predicate: Ignored)
-             || !_interactionSystem.InRangeUnobstructed(user, dragged, component.Range, predicate: Ignored))
-         {
-             reason = Loc.GetString("comp-climbable-cant-reach");
-             return false;
-         }
-
-         reason = string.Empty;
-         return true;
-     }
-
-     public void ForciblySetClimbing(EntityUid uid, EntityUid climbable, ClimbingComponent? component = null)
-     {
-         Climb(uid, uid, climbable, true, component);
-     }
-
-     private void OnBuckleChange(EntityUid uid, ClimbingComponent component, ref BuckleChangeEvent args)
-     {
-         if (!args.Buckling)
-             return;
-         StopClimb(uid, component);
-     }
-
-     private void OnGlassClimbed(EntityUid uid, GlassTableComponent component, ref ClimbedOnEvent args)
-     {
-         if (TryComp<PhysicsComponent>(args.Climber, out var physics) && physics.Mass <= component.MassLimit)
-             return;
-
-         _damageableSystem.TryChangeDamage(args.Climber, component.ClimberDamage, origin: args.Climber);
-         _damageableSystem.TryChangeDamage(uid, component.TableDamage, origin: args.Climber);
-         _stunSystem.TryParalyze(args.Climber, TimeSpan.FromSeconds(component.StunTime), true);
-
-         // Not shown to the user, since they already get a 'you climb on the glass table' popup
-         _popupSystem.PopupEntity(
-             Loc.GetString("glass-table-shattered-others", ("table", uid), ("climber", Identity.Entity(args.Climber, EntityManager))), args.Climber,
-             Filter.PvsExcept(args.Climber), true);
-     }
+    private void OnCanDragDropOn(EntityUid uid, ClimbableComponent component, ref CanDropTargetEvent args)
+    {
+        if (args.Handled)
+            return;
+
+
+        var canVault = args.User == args.Dragged
+            ? CanVault(component, args.User, uid, out _)
+            : CanVault(component, args.User, args.Dragged, uid, out _);
+
+        args.CanDrop = canVault;
+
+        if (!HasComp<HandsComponent>(args.User))
+            args.CanDrop = false;
+
+        args.Handled = true;
+    }
+
+    private void AddClimbableVerb(EntityUid uid, ClimbableComponent component, GetVerbsEvent<AlternativeVerb> args)
+    {
+        if (!args.CanAccess || !args.CanInteract || !_actionBlockerSystem.CanMove(args.User))
+            return;
+
+        if (!TryComp(args.User, out ClimbingComponent? climbingComponent) || climbingComponent.IsClimbing)
+            return;
+
+        // TODO VERBS ICON add a climbing icon?
+        args.Verbs.Add(new AlternativeVerb
+        {
+            Act = () => TryClimb(args.User, args.User, args.Target, out _, component),
+            Text = Loc.GetString("comp-climbable-verb-climb")
+        });
+    }
+
+    private void OnClimbableDragDrop(EntityUid uid, ClimbableComponent component, ref DragDropTargetEvent args)
+    {
+        if (args.Handled)
+            return;
+
+        TryClimb(args.User, args.Dragged, uid, out _, component);
+    }
+
+    public bool TryClimb(
+        EntityUid user,
+        EntityUid entityToMove,
+        EntityUid climbable,
+        out DoAfterId? id,
+        ClimbableComponent? comp = null,
+        ClimbingComponent? climbing = null)
+    {
+        id = null;
+
+        if (!Resolve(climbable, ref comp) || !Resolve(entityToMove, ref climbing))
+            return false;
+
+        // Note, IsClimbing does not mean a DoAfter is active, it means the target has already finished a DoAfter and
+        // is currently on top of something..
+        if (climbing.IsClimbing)
+            return true;
+
+        var args = new DoAfterArgs(EntityManager, user, comp.ClimbDelay, new ClimbDoAfterEvent(),
+            entityToMove,
+            target: climbable,
+            used: entityToMove)
+        {
+            BreakOnTargetMove = true,
+            BreakOnUserMove = true,
+            BreakOnDamage = true
+        };
+
+        _audio.PlayPredicted(comp.StartClimbSound, climbable, user);
+        return _doAfterSystem.TryStartDoAfter(args, out id);
+    }
+
+    private void OnDoAfter(EntityUid uid, ClimbingComponent component, ClimbDoAfterEvent args)
+    {
+        if (args.Handled || args.Cancelled || args.Args.Target == null || args.Args.Used == null)
+            return;
+
+        Climb(uid, args.Args.User, args.Args.Target.Value, climbing: component);
+        args.Handled = true;
+    }
+
+    private void Climb(EntityUid uid, EntityUid user, EntityUid climbable, bool silent = false, ClimbingComponent? climbing = null,
+        PhysicsComponent? physics = null, FixturesComponent? fixtures = null, ClimbableComponent? comp = null)
+    {
+        if (!Resolve(uid, ref climbing, ref physics, ref fixtures, false))
+            return;
+
+        if (!Resolve(climbable, ref comp))
+            return;
+
+        if (!ReplaceFixtures(uid, climbing, fixtures))
+            return;
+
+        var xform = _xformQuery.GetComponent(uid);
+        var (worldPos, worldRot) = _xformSystem.GetWorldPositionRotation(xform);
+        var worldDirection = _xformSystem.GetWorldPosition(climbable) - worldPos;
+        var distance = worldDirection.Length();
+        var parentRot = (worldRot - xform.LocalRotation);
+        // Need direction relative to climber's parent.
+        var localDirection = (-parentRot).RotateVec(worldDirection);
+
+        // On top of it already so just do it in place.
+        if (localDirection.LengthSquared() < 0.01f)
+        {
+            climbing.NextTransition = null;
+        }
+        // VirtualController over to the thing.
+        else
+        {
+            var climbDuration = TimeSpan.FromSeconds(distance / climbing.TransitionRate);
+            climbing.NextTransition = _timing.CurTime + climbDuration;
+
+            climbing.Direction = localDirection.Normalized() * climbing.TransitionRate;
+            _actionBlockerSystem.UpdateCanMove(uid);
+        }
+
+        climbing.IsClimbing = true;
+        Dirty(uid, climbing);
+
+        _audio.PlayPredicted(comp.FinishClimbSound, climbable, user);
+
+        var startEv = new StartClimbEvent(climbable);
+        var climbedEv = new ClimbedOnEvent(uid, user);
+        RaiseLocalEvent(uid, ref startEv);
+        RaiseLocalEvent(climbable, ref climbedEv);
+
+        if (silent)
+            return;
+
+        string selfMessage;
+        string othersMessage;
+
+        if (user == uid)
+        {
+            othersMessage = Loc.GetString("comp-climbable-user-climbs-other",
+                ("user", Identity.Entity(uid, EntityManager)),
+                ("climbable", climbable));
+
+            selfMessage = Loc.GetString("comp-climbable-user-climbs", ("climbable", climbable));
+        }
+        else
+        {
+            othersMessage = Loc.GetString("comp-climbable-user-climbs-force-other",
+                ("user", Identity.Entity(user, EntityManager)),
+                ("moved-user", Identity.Entity(uid, EntityManager)), ("climbable", climbable));
+
+            selfMessage = Loc.GetString("comp-climbable-user-climbs-force", ("moved-user", Identity.Entity(uid, EntityManager)),
+                ("climbable", climbable));
+        }
+
+        _popupSystem.PopupEntity(othersMessage, uid, Filter.PvsExcept(user, entityManager: EntityManager), true);
+        _popupSystem.PopupClient(selfMessage, uid, user);
+    }
+
+    /// <summary>
+    /// Replaces the current fixtures with non-climbing collidable versions so that climb end can be detected
+    /// </summary>
+    /// <returns>Returns whether adding the new fixtures was successful</returns>
+    private bool ReplaceFixtures(EntityUid uid, ClimbingComponent climbingComp, FixturesComponent fixturesComp)
+    {
+        // Swap fixtures
+        foreach (var (name, fixture) in fixturesComp.Fixtures)
+        {
+            if (climbingComp.DisabledFixtureMasks.ContainsKey(name)
+                || fixture.Hard == false
+                || (fixture.CollisionMask & ClimbingCollisionGroup) == 0)
+            {
+                continue;
+            }
+
+            climbingComp.DisabledFixtureMasks.Add(name, fixture.CollisionMask & ClimbingCollisionGroup);
+            _physics.SetCollisionMask(uid, name, fixture, fixture.CollisionMask & ~ClimbingCollisionGroup, fixturesComp);
+        }
+
+        if (!_fixtureSystem.TryCreateFixture(
+                uid,
+                new PhysShapeCircle(0.35f),
+                ClimbingFixtureName,
+                collisionLayer: (int) CollisionGroup.None,
+                collisionMask: ClimbingCollisionGroup,
+                hard: false,
+                manager: fixturesComp))
+        {
+            return false;
+        }
+
+        return true;
+    }
+
+    private void OnClimbEndCollide(EntityUid uid, ClimbingComponent component, ref EndCollideEvent args)
+    {
+        if (args.OurFixtureId != ClimbingFixtureName
+            || !component.IsClimbing
+            || component.NextTransition != null)
+        {
+            return;
+        }
+
+        foreach (var otherFixture in args.OurFixture.Contacts.Keys)
+        {
+            // If it's the other fixture then ignore em
+            if (otherFixture == args.OtherFixture)
+                continue;
+
+            // If still colliding with a climbable, do not stop climbing
+            if (HasComp<ClimbableComponent>(otherFixture.Owner))
+                return;
+        }
+
+        StopClimb(uid, component);
+    }
+
+    private void StopClimb(EntityUid uid, ClimbingComponent? climbing = null, FixturesComponent? fixtures = null)
+    {
+        if (!Resolve(uid, ref climbing, ref fixtures, false))
+            return;
+
+        foreach (var (name, fixtureMask) in climbing.DisabledFixtureMasks)
+        {
+            if (!fixtures.Fixtures.TryGetValue(name, out var fixture))
+            {
+                continue;
+            }
+
+            _physics.SetCollisionMask(uid, name, fixture, fixture.CollisionMask | fixtureMask, fixtures);
+        }
+
+        climbing.DisabledFixtureMasks.Clear();
+        _fixtureSystem.DestroyFixture(uid, ClimbingFixtureName, manager: fixtures);
+        climbing.IsClimbing = false;
+        climbing.NextTransition = null;
+        var ev = new EndClimbEvent();
+        RaiseLocalEvent(uid, ref ev);
+        Dirty(uid, climbing);
+    }
+
+    /// <summary>
+    ///     Checks if the user can vault the target
+    /// </summary>
+    /// <param name="component">The component of the entity that is being vaulted</param>
+    /// <param name="user">The entity that wants to vault</param>
+    /// <param name="target">The object that is being vaulted</param>
+    /// <param name="reason">The reason why it cant be dropped</param>
+    public bool CanVault(ClimbableComponent component, EntityUid user, EntityUid target, out string reason)
+    {
+        if (!_actionBlockerSystem.CanInteract(user, target))
+        {
+            reason = Loc.GetString("comp-climbable-cant-interact");
+            return false;
+        }
+
+        if (!HasComp<ClimbingComponent>(user)
+            || !TryComp(user, out BodyComponent? body)
+            || !_bodySystem.BodyHasPartType(user, BodyPartType.Leg, body)
+            || !_bodySystem.BodyHasPartType(user, BodyPartType.Foot, body))
+        {
+            reason = Loc.GetString("comp-climbable-cant-climb");
+            return false;
+        }
+
+        if (!_interactionSystem.InRangeUnobstructed(user, target, component.Range))
+        {
+            reason = Loc.GetString("comp-climbable-cant-reach");
+            return false;
+        }
+
+        reason = string.Empty;
+        return true;
+    }
+
+    /// <summary>
+    ///     Checks if the user can vault the dragged entity onto the the target
+    /// </summary>
+    /// <param name="component">The climbable component of the object being vaulted onto</param>
+    /// <param name="user">The user that wants to vault the entity</param>
+    /// <param name="dragged">The entity that is being vaulted</param>
+    /// <param name="target">The object that is being vaulted onto</param>
+    /// <param name="reason">The reason why it cant be dropped</param>
+    /// <returns></returns>
+    public bool CanVault(ClimbableComponent component, EntityUid user, EntityUid dragged, EntityUid target,
+        out string reason)
+    {
+        if (!_actionBlockerSystem.CanInteract(user, dragged) || !_actionBlockerSystem.CanInteract(user, target))
+        {
+            reason = Loc.GetString("comp-climbable-cant-interact");
+            return false;
+        }
+
+        if (!HasComp<ClimbingComponent>(dragged))
+        {
+            reason = Loc.GetString("comp-climbable-cant-climb");
+            return false;
+        }
+
+        bool Ignored(EntityUid entity) => entity == target || entity == user || entity == dragged;
+
+        if (!_interactionSystem.InRangeUnobstructed(user, target, component.Range, predicate: Ignored)
+            || !_interactionSystem.InRangeUnobstructed(user, dragged, component.Range, predicate: Ignored))
+        {
+            reason = Loc.GetString("comp-climbable-cant-reach");
+            return false;
+        }
+
+        reason = string.Empty;
+        return true;
+    }
+
+    public void ForciblySetClimbing(EntityUid uid, EntityUid climbable, ClimbingComponent? component = null)
+    {
+        Climb(uid, uid, climbable, true, component);
+    }
+
+    private void OnBuckleChange(EntityUid uid, ClimbingComponent component, ref BuckleChangeEvent args)
+    {
+        if (!args.Buckling)
+            return;
+        StopClimb(uid, component);
+    }
+
+    private void OnGlassClimbed(EntityUid uid, GlassTableComponent component, ref ClimbedOnEvent args)
+    {
+        if (TryComp<PhysicsComponent>(args.Climber, out var physics) && physics.Mass <= component.MassLimit)
+            return;
+
+        _damageableSystem.TryChangeDamage(args.Climber, component.ClimberDamage, origin: args.Climber);
+        _damageableSystem.TryChangeDamage(uid, component.TableDamage, origin: args.Climber);
+        _stunSystem.TryParalyze(args.Climber, TimeSpan.FromSeconds(component.StunTime), true);
+
+        // Not shown to the user, since they already get a 'you climb on the glass table' popup
+        _popupSystem.PopupEntity(
+            Loc.GetString("glass-table-shattered-others", ("table", uid), ("climber", Identity.Entity(args.Climber, EntityManager))), args.Climber,
+            Filter.PvsExcept(args.Climber), true);
+    }
 
     [Serializable, NetSerializable]
     private sealed partial class ClimbDoAfterEvent : SimpleDoAfterEvent