Skip to content

Commit

Permalink
Merge branch 'new-frontiers-14:master' into dragonfly
Browse files Browse the repository at this point in the history
  • Loading branch information
crystalHex authored Dec 15, 2023
2 parents 8c9b5c4 + fa2f5b0 commit ec28e17
Show file tree
Hide file tree
Showing 457 changed files with 13,201 additions and 16,574 deletions.
8 changes: 8 additions & 0 deletions Content.Server/Access/Systems/IdCardConsoleSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,14 @@ private void TryWriteToShuttleDeed(EntityUid uid,

if (!EntityManager.TryGetComponent<ShuttleDeedComponent>(targetId, out var shuttleDeed))
return;
else
{
if (Deleted(shuttleDeed!.ShuttleUid))
{
RemComp<ShuttleDeedComponent>(targetId);
return;
}
}

// Ensure the name is valid and follows the convention
var name = newShuttleName.Trim();
Expand Down
17 changes: 16 additions & 1 deletion Content.Server/Botany/Systems/MutationSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -228,14 +228,29 @@ private void MutateHarvestType(ref HarvestType val, int bits, int totalbits, flo

private void MutateGasses(ref Dictionary<Gas, float> gasses, float min, float max, int bits, int totalbits, float mult)
{
// Frontier - List of gasses
Gas[] gassesList =
{
Gas.Oxygen,
Gas.Nitrogen,
Gas.CarbonDioxide,
Gas.NitrousOxide,
Gas.Miasma,
Gas.Plasma,
Gas.Tritium,
Gas.WaterVapor,
};
// Frontier - List of gasses

float probModify = mult * bits / totalbits;
probModify = Math.Clamp(probModify, 0, 1);
if (!Random(probModify))
return;

// Add a random amount of a random gas to this gas dictionary
float amount = _robustRandom.NextFloat(min, max);
Gas gas = _robustRandom.Pick(Enum.GetValues(typeof(Gas)).Cast<Gas>().ToList());
//Gas gas = _robustRandom.Pick(Enum.GetValues(typeof(Gas)).Cast<Gas>().ToList()); // Frontier
Gas gas = _robustRandom.Pick(gassesList); // Frontier
if (gasses.ContainsKey(gas))
{
gasses[gas] += amount;
Expand Down
84 changes: 84 additions & 0 deletions Content.Server/Chat/Managers/ChatManager.RateLimit.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
using System.Runtime.InteropServices;
using Content.Shared.CCVar;
using Content.Shared.Database;
using Robust.Shared.Enums;
using Robust.Shared.Player;
using Robust.Shared.Timing;

namespace Content.Server.Chat.Managers;

internal sealed partial class ChatManager
{
private readonly Dictionary<ICommonSession, RateLimitDatum> _rateLimitData = new();

public bool HandleRateLimit(ICommonSession player)
{
ref var datum = ref CollectionsMarshal.GetValueRefOrAddDefault(_rateLimitData, player, out _);
var time = _gameTiming.RealTime;
if (datum.CountExpires < time)
{
// Period expired, reset it.
var periodLength = _configurationManager.GetCVar(CCVars.ChatRateLimitPeriod);
datum.CountExpires = time + TimeSpan.FromSeconds(periodLength);
datum.Count = 0;
datum.Announced = false;
}

var maxCount = _configurationManager.GetCVar(CCVars.ChatRateLimitCount);
datum.Count += 1;

if (datum.Count <= maxCount)
return true;

// Breached rate limits, inform admins if configured.
if (_configurationManager.GetCVar(CCVars.ChatRateLimitAnnounceAdmins))
{
if (datum.NextAdminAnnounce < time)
{
SendAdminAlert(Loc.GetString("chat-manager-rate-limit-admin-announcement", ("player", player.Name)));
var delay = _configurationManager.GetCVar(CCVars.ChatRateLimitAnnounceAdminsDelay);
datum.NextAdminAnnounce = time + TimeSpan.FromSeconds(delay);
}
}

if (!datum.Announced)
{
DispatchServerMessage(player, Loc.GetString("chat-manager-rate-limited"), suppressLog: true);
_adminLogger.Add(LogType.ChatRateLimited, LogImpact.Medium, $"Player {player} breached chat rate limits");

datum.Announced = true;
}

return false;
}

private void PlayerStatusChanged(object? sender, SessionStatusEventArgs e)
{
if (e.NewStatus == SessionStatus.Disconnected)
_rateLimitData.Remove(e.Session);
}

private struct RateLimitDatum
{
/// <summary>
/// Time stamp (relative to <see cref="IGameTiming.RealTime"/>) this rate limit period will expire at.
/// </summary>
public TimeSpan CountExpires;

/// <summary>
/// How many messages have been sent in the current rate limit period.
/// </summary>
public int Count;

/// <summary>
/// Have we announced to the player that they've been blocked in this rate limit period?
/// </summary>
public bool Announced;

/// <summary>
/// Time stamp (relative to <see cref="IGameTiming.RealTime"/>) of the
/// next time we can send an announcement to admins about rate limit breach.
/// </summary>
public TimeSpan NextAdminAnnounce;
}
}
15 changes: 12 additions & 3 deletions Content.Server/Chat/Managers/ChatManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,20 @@
using Content.Shared.Chat;
using Content.Shared.Database;
using Content.Shared.Mind;
using Robust.Server.Player;
using Robust.Shared.Configuration;
using Robust.Shared.Network;
using Robust.Shared.Player;
using Robust.Shared.Replays;
using Robust.Shared.Timing;
using Robust.Shared.Utility;

namespace Content.Server.Chat.Managers
{
/// <summary>
/// Dispatches chat messages to clients.
/// </summary>
internal sealed class ChatManager : IChatManager
internal sealed partial class ChatManager : IChatManager
{
private static readonly Dictionary<string, string> PatronOocColors = new()
{
Expand All @@ -41,6 +43,8 @@ internal sealed class ChatManager : IChatManager
[Dependency] private readonly IConfigurationManager _configurationManager = default!;
[Dependency] private readonly INetConfigurationManager _netConfigManager = default!;
[Dependency] private readonly IEntityManager _entityManager = default!;
[Dependency] private readonly IGameTiming _gameTiming = default!;
[Dependency] private readonly IPlayerManager _playerManager = default!;

/// <summary>
/// The maximum length a player-sent message can be sent
Expand All @@ -59,6 +63,8 @@ public void Initialize()

_configurationManager.OnValueChanged(CCVars.OocEnabled, OnOocEnabledChanged, true);
_configurationManager.OnValueChanged(CCVars.AdminOocEnabled, OnAdminOocEnabledChanged, true);

_playerManager.PlayerStatusChanged += PlayerStatusChanged;
}

private void OnOocEnabledChanged(bool val)
Expand Down Expand Up @@ -178,6 +184,9 @@ public void SendHookOOC(string sender, string message)
/// <param name="type">The type of message.</param>
public void TrySendOOCMessage(ICommonSession player, string message, OOCChatType type)
{
if (!HandleRateLimit(player))
return;

// Check if message exceeds the character limit
if (message.Length > MaxMessageLength)
{
Expand Down Expand Up @@ -215,7 +224,7 @@ private void SendOOC(ICommonSession player, string message)
}

Color? colorOverride = null;
var wrappedMessage = Loc.GetString("chat-manager-send-ooc-wrap-message", ("playerName",player.Name), ("message", FormattedMessage.EscapeText(message)));
var wrappedMessage = Loc.GetString("chat-manager-send-ooc-wrap-message", ("playerName", player.Name), ("message", FormattedMessage.EscapeText(message)));
if (_adminManager.HasAdminFlag(player, AdminFlags.Admin))
{
var prefs = _preferencesManager.GetPreferences(player.UserId);
Expand All @@ -224,7 +233,7 @@ private void SendOOC(ICommonSession player, string message)
if (player.ConnectedClient.UserData.PatronTier is { } patron &&
PatronOocColors.TryGetValue(patron, out var patronColor))
{
wrappedMessage = Loc.GetString("chat-manager-send-ooc-patron-wrap-message", ("patronColor", patronColor),("playerName", player.Name), ("message", FormattedMessage.EscapeText(message)));
wrappedMessage = Loc.GetString("chat-manager-send-ooc-patron-wrap-message", ("patronColor", patronColor), ("playerName", player.Name), ("message", FormattedMessage.EscapeText(message)));
}

//TODO: player.Name color, this will need to change the structure of the MsgChatMessage
Expand Down
8 changes: 8 additions & 0 deletions Content.Server/Chat/Managers/IChatManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,5 +41,13 @@ void ChatMessageToMany(ChatChannel channel, string message, string wrappedMessag

[return: NotNullIfNotNull(nameof(author))]
ChatUser? EnsurePlayer(NetUserId? author);

/// <summary>
/// Called when a player sends a chat message to handle rate limits.
/// Will update counts and do necessary actions if breached.
/// </summary>
/// <param name="player">The player sending a chat message.</param>
/// <returns>False if the player has violated rate limits and should be blocked from sending further messages.</returns>
bool HandleRateLimit(ICommonSession player);
}
}
8 changes: 7 additions & 1 deletion Content.Server/Chat/Systems/ChatSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,9 @@ public void TrySendInGameICMessage(
return;
}

if (player != null && !_chatManager.HandleRateLimit(player))
return;

// Sus
if (player?.AttachedEntity is { Valid: true } entity && source != entity)
{
Expand Down Expand Up @@ -213,7 +216,7 @@ public void TrySendInGameICMessage(
}

bool shouldCapitalize = (desiredType != InGameICChatType.Emote);
bool shouldPunctuate = _configurationManager.GetCVar(CCVars.ChatPunctuation);
bool shouldPunctuate = _configurationManager.GetCVar(CCVars.ChatPunctuation) && (desiredType != InGameICChatType.Emote);
// Capitalizing the word I only happens in English, so we check language here
bool shouldCapitalizeTheWordI = (!CultureInfo.CurrentCulture.IsNeutralCulture && CultureInfo.CurrentCulture.Parent.Name == "en")
|| (CultureInfo.CurrentCulture.IsNeutralCulture && CultureInfo.CurrentCulture.Name == "en");
Expand Down Expand Up @@ -267,6 +270,9 @@ public void TrySendInGameOOCMessage(
if (!CanSendInGame(message, shell, player))
return;

if (player != null && !_chatManager.HandleRateLimit(player))
return;

// It doesn't make any sense for a non-player to send in-game OOC messages, whereas non-players may be sending
// in-game IC messages.
if (player?.AttachedEntity is not { Valid: true } entity || source != entity)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
using Content.Server.DeltaV.Weapons.Ranged.Systems;

namespace Content.Server.DeltaV.Weapons.Ranged.Components;

/// <summary>
/// Allows for energy gun to switch between three modes. This also changes the sprite accordingly.
/// </summary>
/// <remarks>This is BatteryWeaponFireModesSystem with additional changes to allow for different sprites.</remarks>
[RegisterComponent]
[Access(typeof(EnergyGunSystem))]
[AutoGenerateComponentState]
public sealed partial class EnergyGunComponent : Component
{
/// <summary>
/// A list of the different firing modes the energy gun can switch between
/// </summary>
[DataField("fireModes", required: true)]
[AutoNetworkedField]
public List<EnergyWeaponFireMode> FireModes = new();

/// <summary>
/// The currently selected firing mode
/// </summary>
[DataField("currentFireMode")]
[AutoNetworkedField]
public EnergyWeaponFireMode? CurrentFireMode = default!;
}

[DataDefinition]
public sealed partial class EnergyWeaponFireMode
{
/// <summary>
/// The projectile prototype associated with this firing mode
/// </summary>
[DataField("proto", required: true, customTypeSerializer: typeof(PrototypeIdSerializer<EntityPrototype>))]
public string Prototype = default!;

/// <summary>
/// The battery cost to fire the projectile associated with this firing mode
/// </summary>
[DataField("fireCost")]
public float FireCost = 100;

/// <summary>
/// The name of the selected firemode
/// </summary>
[DataField("name")]
public string Name = string.Empty;

/// <summary>
/// What RsiState we use for that firemode if it needs to change.
/// </summary>
[DataField("state")]
public string State = string.Empty;
}
Loading

0 comments on commit ec28e17

Please sign in to comment.