Kick mines (real) (#8056)

Co-authored-by: metalgearsloth <comedian_vs_clown@hotmail.com>
This commit is contained in:
Pieter-Jan Briers
2022-05-18 06:07:35 +02:00
committed by GitHub
parent 2f604ce05c
commit ebfe5e888f
29 changed files with 635 additions and 220 deletions

View File

@@ -4,6 +4,7 @@ using Content.Shared.Chemistry.Reaction;
using Content.Shared.Chemistry.Reagent;
using Content.Shared.FixedPoint;
using Content.Shared.Slippery;
using Content.Shared.StepTrigger;
using JetBrains.Annotations;
using Robust.Shared.Map;
@@ -28,9 +29,10 @@ namespace Content.Server.Chemistry.TileReactions
if (puddle != null)
{
var slippery = IoCManager.Resolve<IEntityManager>().GetComponent<SlipperyComponent>(puddle.Owner);
var entityManager = IoCManager.Resolve<IEntityManager>();
var slippery = entityManager.GetComponent<SlipperyComponent>(puddle.Owner);
slippery.LaunchForwardsMultiplier = _launchForwardsMultiplier;
slippery.RequiredSlipSpeed = _requiredSlipSpeed;
EntitySystem.Get<StepTriggerSystem>().SetRequiredTriggerSpeed(puddle.Owner, _requiredSlipSpeed);
slippery.ParalyzeTime = _paralyzeTime;
return reactVolume;

View File

@@ -9,9 +9,11 @@ using Content.Server.Connection;
using Content.Server.Database;
using Content.Server.EUI;
using Content.Server.GameTicking;
using Content.Server.GhostKick;
using Content.Server.GuideGenerator;
using Content.Server.Info;
using Content.Server.IoC;
using Content.Server.LandMines;
using Content.Server.Maps;
using Content.Server.NodeContainer.NodeGroups;
using Content.Server.Preferences.Managers;
@@ -85,6 +87,8 @@ namespace Content.Server.Entry
IoCManager.Resolve<INodeGroupFactory>().Initialize();
IoCManager.Resolve<IGamePrototypeLoadManager>().Initialize();
IoCManager.Resolve<NetworkResourceManager>().Initialize();
IoCManager.Resolve<GhostKickManager>().Initialize();
_voteManager.Initialize();
}
}

View File

@@ -4,7 +4,7 @@ using Content.Shared.Chemistry.Components;
using Content.Shared.Examine;
using Content.Shared.FixedPoint;
using Content.Shared.Fluids;
using Content.Shared.Slippery;
using Content.Shared.StepTrigger;
using JetBrains.Annotations;
using Robust.Shared.Audio;
using Robust.Shared.Player;
@@ -16,6 +16,7 @@ namespace Content.Server.Fluids.EntitySystems
{
[Dependency] private readonly SolutionContainerSystem _solutionContainerSystem = default!;
[Dependency] private readonly FluidSpreaderSystem _fluidSpreaderSystem = default!;
[Dependency] private readonly StepTriggerSystem _stepTrigger = default!;
public override void Initialize()
{
@@ -71,20 +72,20 @@ namespace Content.Server.Fluids.EntitySystems
{
if ((puddleComponent.SlipThreshold == FixedPoint2.New(-1) ||
puddleComponent.CurrentVolume < puddleComponent.SlipThreshold) &&
EntityManager.TryGetComponent(entityUid, out SlipperyComponent? oldSlippery))
TryComp(entityUid, out StepTriggerComponent? stepTrigger))
{
oldSlippery.Slippery = false;
_stepTrigger.SetActive(entityUid, false, stepTrigger);
}
else if (puddleComponent.CurrentVolume >= puddleComponent.SlipThreshold)
{
var newSlippery = EntityManager.EnsureComponent<SlipperyComponent>(entityUid);
newSlippery.Slippery = true;
var comp = EnsureComp<StepTriggerComponent>(entityUid);
_stepTrigger.SetActive(entityUid, true, comp);
}
}
private void HandlePuddleExamined(EntityUid uid, PuddleComponent component, ExaminedEvent args)
{
if (EntityManager.TryGetComponent<SlipperyComponent>(uid, out var slippery) && slippery.Slippery)
if (TryComp<StepTriggerComponent>(uid, out var slippery) && slippery.Active)
{
args.PushText(Loc.GetString("puddle-component-examine-is-slipper-text"));
}

View File

@@ -0,0 +1,76 @@
using Content.Server.Administration;
using Content.Shared.Administration;
using Content.Shared.GhostKick;
using Robust.Server.Player;
using Robust.Shared.Console;
using Robust.Shared.Network;
using Robust.Shared.Timing;
namespace Content.Server.GhostKick;
// Handles logic for "ghost kicking".
// Basically we boot the client off the server without telling them, so the game shits itself.
// Hilariously isn't it?
public sealed class GhostKickManager
{
[Dependency] private readonly IServerNetManager _netManager = default!;
public void Initialize()
{
_netManager.RegisterNetMessage<MsgGhostKick>();
}
public void DoDisconnect(INetChannel channel, string reason)
{
Timer.Spawn(TimeSpan.FromMilliseconds(100), () =>
{
if (!channel.IsConnected)
return;
// We do this so the client can set net.fakeloss 1 before getting ghosted.
// This avoids it spamming messages at the server that cause warnings due to unconnected client.
channel.SendMessage(new MsgGhostKick());
Timer.Spawn(TimeSpan.FromMilliseconds(100), () =>
{
if (!channel.IsConnected)
return;
// Actually just remove the client entirely.
channel.Disconnect(reason, false);
});
});
}
}
[AdminCommand(AdminFlags.Admin)]
public sealed class GhostKickCommand : IConsoleCommand
{
public string Command => "ghostkick";
public string Description => "Kick a client from the server as if their network just dropped.";
public string Help => "Usage: ghostkick <Player> [Reason]";
public void Execute(IConsoleShell shell, string argStr, string[] args)
{
if (args.Length < 1)
{
shell.WriteError("Need at least one argument");
return;
}
var playerName = args[0];
var reason = args.Length > 1 ? args[1] : "Ghost kicked by console";
var players = IoCManager.Resolve<IPlayerManager>();
var ghostKick = IoCManager.Resolve<GhostKickManager>();
if (!players.TryGetSessionByUsername(playerName, out var player))
{
shell.WriteError($"Unable to find player: '{playerName}'.");
return;
}
ghostKick.DoDisconnect(player.ConnectedClient, reason);
}
}

View File

@@ -0,0 +1,7 @@
namespace Content.Server.GhostKick;
[RegisterComponent]
public sealed class GhostKickUserOnTriggerComponent : Component
{
}

View File

@@ -0,0 +1,24 @@
using Content.Server.Explosion.EntitySystems;
using Robust.Server.GameObjects;
namespace Content.Server.GhostKick;
public sealed class GhostKickUserOnTriggerSystem : EntitySystem
{
[Dependency] private readonly GhostKickManager _ghostKickManager = default!;
public override void Initialize()
{
SubscribeLocalEvent<GhostKickUserOnTriggerComponent, TriggerEvent>(HandleMineTriggered);
}
private void HandleMineTriggered(EntityUid uid, GhostKickUserOnTriggerComponent userOnTriggerComponent, TriggerEvent args)
{
if (!TryComp(args.User, out ActorComponent? actor))
return;
_ghostKickManager.DoDisconnect(
actor.PlayerSession.ConnectedClient,
"Tripped over a kick mine, crashed through the fourth wall");
}
}

View File

@@ -9,6 +9,7 @@ using Content.Server.Chat.Managers;
using Content.Server.Connection;
using Content.Server.Database;
using Content.Server.EUI;
using Content.Server.GhostKick;
using Content.Server.Info;
using Content.Server.Maps;
using Content.Server.Module;
@@ -52,6 +53,7 @@ namespace Content.Server.IoC
IoCManager.Register<RoleBanManager, RoleBanManager>();
IoCManager.Register<NetworkResourceManager>();
IoCManager.Register<IAdminNotesManager, AdminNotesManager>();
IoCManager.Register<GhostKickManager>();
}
}
}

View File

@@ -0,0 +1,7 @@
namespace Content.Server.LandMines;
[RegisterComponent]
public sealed class LandMineComponent : Component
{
}

View File

@@ -0,0 +1,40 @@
using Content.Server.Explosion.EntitySystems;
using Content.Shared.Popups;
using Content.Shared.StepTrigger;
using Robust.Shared.Player;
namespace Content.Server.LandMines;
public sealed class LandMineSystem : EntitySystem
{
[Dependency] private readonly SharedPopupSystem _popupSystem = default!;
[Dependency] private readonly TriggerSystem _trigger = default!;
public override void Initialize()
{
SubscribeLocalEvent<LandMineComponent, StepTriggeredEvent>(HandleTriggered);
SubscribeLocalEvent<LandMineComponent, StepTriggerAttemptEvent>(HandleTriggerAttempt);
}
private static void HandleTriggerAttempt(
EntityUid uid,
LandMineComponent component,
ref StepTriggerAttemptEvent args)
{
args.Continue = true;
}
private void HandleTriggered(EntityUid uid, LandMineComponent component, ref StepTriggeredEvent args)
{
_popupSystem.PopupCoordinates(
Loc.GetString("land-mine-triggered", ("mine", uid)),
Transform(uid).Coordinates,
Filter.Entities(args.Tripper));
_trigger.Trigger(uid, args.Tripper);
QueueDel(uid);
}
}