_nextAudio = TimeSpan.MaxValue;
SetupAmbientSounds();
- _proto.PrototypesReloaded += OnProtoReload;
+ SubscribeLocalEvent<PrototypesReloadedEventArgs>(OnProtoReload);
_state.OnStateChanged += OnStateChange;
// On round end summary OR lobby cut audio.
SubscribeNetworkEvent<RoundEndMessageEvent>(OnRoundEndMessage);
private void ShutdownAmbientMusic()
{
_configManager.UnsubValueChanged(CCVars.AmbientMusicVolume, AmbienceCVarChanged);
- _proto.PrototypesReloaded -= OnProtoReload;
_state.OnStateChanged -= OnStateChange;
_ambientMusicStream = _audio.Stop(_ambientMusicStream);
}
private void OnProtoReload(PrototypesReloadedEventArgs obj)
{
- if (!obj.ByType.ContainsKey(typeof(AmbientMusicPrototype)) &&
- !obj.ByType.ContainsKey(typeof(RulesPrototype)))
- {
- return;
- }
-
- _ambientSounds.Clear();
- SetupAmbientSounds();
+ if (obj.WasModified<AmbientMusicPrototype>() || obj.WasModified<RulesPrototype>())
+ SetupAmbientSounds();
}
private void OnStateChange(StateChangedEventArgs obj)
private void SetupAmbientSounds()
{
+ _ambientSounds.Clear();
foreach (var ambience in _proto.EnumeratePrototypes<AmbientMusicPrototype>())
{
var tracks = _ambientSounds.GetOrNew(ambience.ID);
SubscribeLocalEvent<ChameleonClothingComponent, AfterAutoHandleStateEvent>(HandleState);
PrepareAllVariants();
- _proto.PrototypesReloaded += OnProtoReloaded;
+ SubscribeLocalEvent<PrototypesReloadedEventArgs>(OnProtoReloaded);
}
- public override void Shutdown()
+ private void OnProtoReloaded(PrototypesReloadedEventArgs args)
{
- base.Shutdown();
- _proto.PrototypesReloaded -= OnProtoReloaded;
- }
-
- private void OnProtoReloaded(PrototypesReloadedEventArgs _)
- {
- PrepareAllVariants();
+ if (args.WasModified<EntityPrototype>())
+ PrepareAllVariants();
}
private void HandleState(EntityUid uid, ChameleonClothingComponent component, ref AfterAutoHandleStateEvent args)
-using Content.Client.GameTicking.Managers;
using Content.Shared.CrewManifest;
using Content.Shared.Roles;
using Robust.Shared.Prototypes;
base.Initialize();
BuildDepartmentLookup();
- _prototypeManager.PrototypesReloaded += OnPrototypesReload;
- }
-
- public override void Shutdown()
- {
- _prototypeManager.PrototypesReloaded -= OnPrototypesReload;
+ SubscribeLocalEvent<PrototypesReloadedEventArgs>(OnPrototypesReload);
}
/// <summary>
RaiseNetworkEvent(new RequestCrewManifestMessage(netEntity));
}
- private void OnPrototypesReload(PrototypesReloadedEventArgs _)
+ private void OnPrototypesReload(PrototypesReloadedEventArgs args)
{
- _jobDepartmentLookup.Clear();
- _departments.Clear();
-
- BuildDepartmentLookup();
+ if (args.WasModified<DepartmentPrototype>())
+ BuildDepartmentLookup();
}
private void BuildDepartmentLookup()
{
+ _jobDepartmentLookup.Clear();
+ _departments.Clear();
foreach (var department in _prototypeManager.EnumeratePrototypes<DepartmentPrototype>())
{
_departments.Add(department.ID);
{
base.Initialize();
_overlay.AddOverlay(new ParallaxOverlay());
- _protoManager.PrototypesReloaded += OnReload;
-
+ SubscribeLocalEvent<PrototypesReloadedEventArgs>(OnReload);
SubscribeLocalEvent<ParallaxComponent, AfterAutoHandleStateEvent>(OnAfterAutoHandleState);
}
private void OnReload(PrototypesReloadedEventArgs obj)
{
- if (!obj.ByType.ContainsKey(typeof(ParallaxPrototype)))
+ if (!obj.WasModified<ParallaxPrototype>())
return;
_parallax.UnloadParallax(Fallback);
{
base.Shutdown();
_overlay.RemoveOverlay<ParallaxOverlay>();
- _protoManager.PrototypesReloaded -= OnReload;
}
private void OnAfterAutoHandleState(EntityUid uid, ParallaxComponent component, ref AfterAutoHandleStateEvent args)
private void OnPrototypesReloaded(PrototypesReloadedEventArgs obj)
{
- ReloadPrototypes();
+ if (obj.WasModified<DecalPrototype>())
+ ReloadPrototypes();
}
private void ReloadPrototypes()
public override void Initialize()
{
SubscribeLocalEvent<StationInitializedEvent>(OnStationInitialize);
-
- _prototypeManager.PrototypesReloaded += OnPrototypeReload;
- }
-
- public override void Shutdown()
- {
- base.Shutdown();
-
- _prototypeManager.PrototypesReloaded -= OnPrototypeReload;
+ SubscribeLocalEvent<PrototypesReloadedEventArgs>(OnPrototypeReload);
}
public override void Update(float time)
using Content.Shared.GameTicking;
using Robust.Server.Audio;
using Robust.Shared.Audio;
-using Robust.Shared.Audio.Components;
using Robust.Shared.Prototypes;
namespace Content.Server.Audio;
public sealed class ContentAudioSystem : SharedContentAudioSystem
{
[Dependency] private readonly AudioSystem _serverAudio = default!;
- [Dependency] private readonly IPrototypeManager _protoManager = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<RoundRestartCleanupEvent>(OnRoundCleanup);
SubscribeLocalEvent<RoundStartingEvent>(OnRoundStart);
- _protoManager.PrototypesReloaded += OnProtoReload;
+ SubscribeLocalEvent<PrototypesReloadedEventArgs>(OnProtoReload);
}
private void OnRoundCleanup(RoundRestartCleanupEvent ev)
private void OnProtoReload(PrototypesReloadedEventArgs obj)
{
- if (!obj.ByType.ContainsKey(typeof(AudioPresetPrototype)))
- return;
-
- _serverAudio.ReloadPresets();
- }
-
- public override void Shutdown()
- {
- base.Shutdown();
- _protoManager.PrototypesReloaded -= OnProtoReload;
+ if (obj.WasModified<AudioPresetPrototype>())
+ _serverAudio.ReloadPresets();
}
private void OnRoundStart(RoundStartingEvent ev)
+using System.Collections.Frozen;
using Content.Shared.Chat.Prototypes;
using Robust.Shared.Prototypes;
using Robust.Shared.Random;
// emotes using emote prototype
public partial class ChatSystem
{
- private readonly Dictionary<string, EmotePrototype> _wordEmoteDict = new();
+ private FrozenDictionary<string, EmotePrototype> _wordEmoteDict = FrozenDictionary<string, EmotePrototype>.Empty;
- private void InitializeEmotes()
+ protected override void OnPrototypeReload(PrototypesReloadedEventArgs obj)
{
- _prototypeManager.PrototypesReloaded += OnPrototypeReloadEmotes;
- CacheEmotes();
- }
-
- private void ShutdownEmotes()
- {
- _prototypeManager.PrototypesReloaded -= OnPrototypeReloadEmotes;
- }
-
- private void OnPrototypeReloadEmotes(PrototypesReloadedEventArgs obj)
- {
- CacheEmotes();
+ base.OnPrototypeReload(obj);
+ if (obj.WasModified<EmotePrototype>())
+ CacheEmotes();
}
private void CacheEmotes()
{
- _wordEmoteDict.Clear();
+ var dict = new Dictionary<string, EmotePrototype>();
var emotes = _prototypeManager.EnumeratePrototypes<EmotePrototype>();
foreach (var emote in emotes)
{
foreach (var word in emote.ChatTriggers)
{
var lowerWord = word.ToLower();
- if (_wordEmoteDict.ContainsKey(lowerWord))
+ if (dict.TryGetValue(lowerWord, out var value))
{
- var existingId = _wordEmoteDict[lowerWord].ID;
- var errMsg = $"Duplicate of emote word {lowerWord} in emotes {emote.ID} and {existingId}";
- Logger.Error(errMsg);
+ var errMsg = $"Duplicate of emote word {lowerWord} in emotes {emote.ID} and {value.ID}";
+ Log.Error(errMsg);
continue;
}
- _wordEmoteDict.Add(lowerWord, emote);
+ dict.Add(lowerWord, emote);
}
}
+
+ _wordEmoteDict = dict.ToFrozenDictionary();
}
/// <summary>
public override void Initialize()
{
base.Initialize();
- InitializeEmotes();
+ CacheEmotes();
_configurationManager.OnValueChanged(CCVars.LoocEnabled, OnLoocEnabledChanged, true);
_configurationManager.OnValueChanged(CCVars.DeadLoocEnabled, OnDeadLoocEnabledChanged, true);
_configurationManager.OnValueChanged(CCVars.CritLoocEnabled, OnCritLoocEnabledChanged, true);
public override void Shutdown()
{
base.Shutdown();
- ShutdownEmotes();
_configurationManager.UnsubValueChanged(CCVars.LoocEnabled, OnLoocEnabledChanged);
_configurationManager.UnsubValueChanged(CCVars.DeadLoocEnabled, OnDeadLoocEnabledChanged);
_configurationManager.UnsubValueChanged(CCVars.CritLoocEnabled, OnCritLoocEnabledChanged);
return ev.Message;
}
-
+
public bool CheckIgnoreSpeechBlocker(EntityUid sender, bool ignoreBlocker)
{
if (ignoreBlocker)
{
base.Initialize();
- PrototypeManager.PrototypesReloaded += PrototypeManagerReload;
-
+ SubscribeLocalEvent<PrototypesReloadedEventArgs>(PrototypeManagerReload);
_player.PlayerStatusChanged += OnPlayerStatusChanged;
InitializeServerRegistry();
/// <inheritdoc/>
public override void Initialize()
{
- _prototype.PrototypesReloaded += OnPrototypesReloaded;
+ SubscribeLocalEvent<PrototypesReloadedEventArgs>(OnPrototypesReloaded);
SubscribeLocalEvent<RandomGiftComponent, MapInitEvent>(OnGiftMapInit);
SubscribeLocalEvent<RandomGiftComponent, UseInHandEvent>(OnUseInHand);
SubscribeLocalEvent<RandomGiftComponent, ExaminedEvent>(OnExamined);
private void OnPrototypesReloaded(PrototypesReloadedEventArgs obj)
{
- BuildIndex();
+ if (obj.WasModified<EntityPrototype>())
+ BuildIndex();
}
private void BuildIndex()
using Content.Shared.Mobs;
using Content.Shared.NPC;
using JetBrains.Annotations;
-using Robust.Server.GameObjects;
using Robust.Shared.Player;
using Robust.Shared.Prototypes;
using Robust.Shared.Utility;
SubscribeLocalEvent<HTNComponent, PlayerDetachedEvent>(_npc.OnPlayerNPCDetach);
SubscribeLocalEvent<HTNComponent, ComponentShutdown>(OnHTNShutdown);
SubscribeNetworkEvent<RequestHTNMessage>(OnHTNMessage);
-
- _prototypeManager.PrototypesReloaded += OnPrototypeLoad;
+ SubscribeLocalEvent<PrototypesReloadedEventArgs>(OnPrototypeLoad);
OnLoad();
}
_subscribers.Remove(args.SenderSession);
}
- public override void Shutdown()
- {
- base.Shutdown();
- _prototypeManager.PrototypesReloaded -= OnPrototypeLoad;
- }
-
private void OnLoad()
{
// Clear all NPCs in case they're hanging onto stale tasks
+using System.Collections.Frozen;
using System.Linq;
using Content.Server.NPC.Components;
using JetBrains.Annotations;
/// <summary>
/// To avoid prototype mutability we store an intermediary data class that gets used instead.
/// </summary>
- private Dictionary<string, FactionData> _factions = new();
+ private FrozenDictionary<string, FactionData> _factions = FrozenDictionary<string, FactionData>.Empty;
public override void Initialize()
{
base.Initialize();
_sawmill = Logger.GetSawmill("faction");
SubscribeLocalEvent<NpcFactionMemberComponent, ComponentStartup>(OnFactionStartup);
- _protoManager.PrototypesReloaded += OnProtoReload;
+ SubscribeLocalEvent<PrototypesReloadedEventArgs>(OnProtoReload);
InitializeException();
RefreshFactions();
}
- public override void Shutdown()
- {
- base.Shutdown();
- _protoManager.PrototypesReloaded -= OnProtoReload;
- }
-
private void OnProtoReload(PrototypesReloadedEventArgs obj)
{
- if (!obj.ByType.ContainsKey(typeof(NpcFactionPrototype)))
- return;
-
- RefreshFactions();
+ if (obj.WasModified<NpcFactionPrototype>())
+ RefreshFactions();
}
private void OnFactionStartup(EntityUid uid, NpcFactionMemberComponent memberComponent, ComponentStartup args)
private void RefreshFactions()
{
- _factions.Clear();
- foreach (var faction in _protoManager.EnumeratePrototypes<NpcFactionPrototype>())
- {
- _factions[faction.ID] = new FactionData()
+ _factions = _protoManager.EnumeratePrototypes<NpcFactionPrototype>().ToFrozenDictionary(
+ faction => faction.ID,
+ faction => new FactionData
{
Friendly = faction.Friendly.ToHashSet(),
- Hostile = faction.Hostile.ToHashSet(),
- };
- }
+ Hostile = faction.Hostile.ToHashSet()
+
+ });
foreach (var comp in EntityQuery<NpcFactionMemberComponent>(true))
{
SubscribeLocalEvent<NameIdentifierComponent, MapInitEvent>(OnMapInit);
SubscribeLocalEvent<NameIdentifierComponent, ComponentShutdown>(OnComponentShutdown);
SubscribeLocalEvent<RoundRestartCleanupEvent>(CleanupIds);
+ SubscribeLocalEvent<PrototypesReloadedEventArgs>(OnReloadPrototypes);
InitialSetupPrototypes();
- _prototypeManager.PrototypesReloaded += OnReloadPrototypes;
}
private void OnComponentShutdown(EntityUid uid, NameIdentifierComponent component, ComponentShutdown args)
}
}
- public override void Shutdown()
- {
- base.Shutdown();
-
- _prototypeManager.PrototypesReloaded -= OnReloadPrototypes;
- }
-
/// <summary>
/// Generates a new unique name/suffix for a given entity and adds it to <see cref="CurrentIds"/>
/// but does not set the entity's name.
SubscribeLocalEvent<ShuttleFlattenEvent>(OnShuttleFlatten);
_configManager.OnValueChanged(CVars.NetMaxUpdateRange, SetLoadRange, true);
InitializeCommands();
- ProtoManager.PrototypesReloaded += ProtoReload;
+ SubscribeLocalEvent<PrototypesReloadedEventArgs>(ProtoReload);
}
public override void Shutdown()
{
base.Shutdown();
_configManager.UnsubValueChanged(CVars.NetMaxUpdateRange, SetLoadRange);
- ProtoManager.PrototypesReloaded -= ProtoReload;
}
private void ProtoReload(PrototypesReloadedEventArgs obj)
_console.RegisterCommand("dungen", Loc.GetString("cmd-dungen-desc"), Loc.GetString("cmd-dungen-help"), GenerateDungeon, CompletionCallback);
_console.RegisterCommand("dungen_preset_vis", Loc.GetString("cmd-dungen_preset_vis-desc"), Loc.GetString("cmd-dungen_preset_vis-help"), DungeonPresetVis, PresetCallback);
_console.RegisterCommand("dungen_pack_vis", Loc.GetString("cmd-dungen_pack_vis-desc"), Loc.GetString("cmd-dungen_pack_vis-help"), DungeonPackVis, PackCallback);
- _prototype.PrototypesReloaded += PrototypeReload;
+ SubscribeLocalEvent<PrototypesReloadedEventArgs>(PrototypeReload);
SubscribeLocalEvent<RoundRestartCleanupEvent>(OnRoundCleanup);
SubscribeLocalEvent<RoundStartingEvent>(OnRoundStart);
}
public override void Shutdown()
{
base.Shutdown();
- _prototype.PrototypesReloaded -= PrototypeReload;
-
foreach (var token in _dungeonJobs.Values)
{
token.Cancel();
/// <summary>
/// Remaining number of updates per grid & prototype.
/// </summary>
+ // TODO PERFORMANCE Assign each prototype to an index and convert dictionary to array
private Dictionary<EntityUid, Dictionary<string, int>> _gridUpdates = new();
public const float SpreadCooldownSeconds = 1;
{
SubscribeLocalEvent<AirtightChanged>(OnAirtightChanged);
SubscribeLocalEvent<GridInitializeEvent>(OnGridInit);
+ SubscribeLocalEvent<PrototypesReloadedEventArgs>(OnPrototypeReload);
SubscribeLocalEvent<EdgeSpreaderComponent, EntityTerminatingEvent>(OnTerminating);
SetupPrototypes();
- _prototype.PrototypesReloaded += OnPrototypeReload;
- }
-
- public override void Shutdown()
- {
- base.Shutdown();
- _prototype.PrototypesReloaded -= OnPrototypeReload;
}
private void OnPrototypeReload(PrototypesReloadedEventArgs obj)
{
- if (!obj.ByType.ContainsKey(typeof(EdgeSpreaderPrototype)))
- return;
-
- SetupPrototypes();
+ if (obj.WasModified<EdgeSpreaderPrototype>())
+ SetupPrototypes();
}
private void SetupPrototypes()
+using System.Collections.Frozen;
using System.Diagnostics.CodeAnalysis;
using Robust.Shared.Player;
using Robust.Shared.Prototypes;
public abstract class AlertsSystem : EntitySystem
{
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
- private readonly Dictionary<AlertType, AlertPrototype> _typeToAlert = new();
+
+ private FrozenDictionary<AlertType, AlertPrototype> _typeToAlert = default!;
public IReadOnlyDictionary<AlertKey, AlertState>? GetActiveAlerts(EntityUid euid)
{
SubscribeLocalEvent<AlertsComponent, PlayerAttachedEvent>(OnPlayerAttached);
SubscribeNetworkEvent<ClickAlertEvent>(HandleClickAlert);
-
+ SubscribeLocalEvent<PrototypesReloadedEventArgs>(HandlePrototypesReloaded);
LoadPrototypes();
- _prototypeManager.PrototypesReloaded += HandlePrototypesReloaded;
}
protected virtual void HandleComponentShutdown(EntityUid uid, AlertsComponent component, ComponentShutdown args)
RaiseLocalEvent(uid, new AlertSyncEvent(uid), true);
}
- public override void Shutdown()
- {
- _prototypeManager.PrototypesReloaded -= HandlePrototypesReloaded;
-
- base.Shutdown();
- }
-
private void HandlePrototypesReloaded(PrototypesReloadedEventArgs obj)
{
- LoadPrototypes();
+ if (obj.WasModified<AlertPrototype>())
+ LoadPrototypes();
}
protected virtual void LoadPrototypes()
{
- _typeToAlert.Clear();
+ var dict = new Dictionary<AlertType, AlertPrototype>();
foreach (var alert in _prototypeManager.EnumeratePrototypes<AlertPrototype>())
{
- if (!_typeToAlert.TryAdd(alert.AlertType, alert))
+ if (!dict.TryAdd(alert.AlertType, alert))
{
Log.Error("Found alert with duplicate alertType {0} - all alerts must have" +
" a unique alerttype, this one will be skipped", alert.AlertType);
}
}
+
+ _typeToAlert = dict.ToFrozenDictionary();
}
/// <summary>
+using System.Collections.Frozen;
using Content.Shared.Popups;
using Content.Shared.Radio;
using Content.Shared.Speech;
/// <summary>
/// Cache of the keycodes for faster lookup.
/// </summary>
- private Dictionary<char, RadioChannelPrototype> _keyCodes = new();
+ private FrozenDictionary<char, RadioChannelPrototype> _keyCodes = default!;
public override void Initialize()
{
base.Initialize();
DebugTools.Assert(_prototypeManager.HasIndex<RadioChannelPrototype>(CommonChannel));
- _prototypeManager.PrototypesReloaded += OnPrototypeReload;
+ SubscribeLocalEvent<PrototypesReloadedEventArgs>(OnPrototypeReload);
CacheRadios();
}
- private void OnPrototypeReload(PrototypesReloadedEventArgs obj)
+ protected virtual void OnPrototypeReload(PrototypesReloadedEventArgs obj)
{
- if (obj.ByType.ContainsKey(typeof(RadioChannelPrototype)))
+ if (obj.WasModified<RadioChannelPrototype>())
CacheRadios();
}
private void CacheRadios()
{
- _keyCodes.Clear();
-
- foreach (var proto in _prototypeManager.EnumeratePrototypes<RadioChannelPrototype>())
- {
- _keyCodes.Add(proto.KeyCode, proto);
- }
- }
-
- public override void Shutdown()
- {
- _prototypeManager.PrototypesReloaded -= OnPrototypeReload;
+ _keyCodes = _prototypeManager.EnumeratePrototypes<RadioChannelPrototype>()
+ .ToFrozenDictionary(x => x.KeyCode);
}
/// <summary>
+using System.Collections.Frozen;
using System.Linq;
using Content.Shared.Administration.Logs;
using Content.Shared.Chemistry.Components;
using Robust.Shared.Audio;
using Robust.Shared.Audio.Systems;
using Robust.Shared.Prototypes;
+using Robust.Shared.Utility;
namespace Content.Shared.Chemistry.Reaction
{
[Dependency] private readonly ISharedAdminLogManager _adminLogger = default!;
/// <summary>
- /// A cache of all existant chemical reactions indexed by one of their
- /// required reactants.
+ /// A cache of all reactions indexed by at most ONE of their required reactants.
+ /// I.e., even if a reaction has more than one reagent, it will only ever appear once in this dictionary.
/// </summary>
- private IDictionary<string, List<ReactionPrototype>> _reactions = default!;
+ private FrozenDictionary<string, List<ReactionPrototype>> _reactionsSingle = default!;
+
+ /// <summary>
+ /// A cache of all reactions indexed by one of their required reactants.
+ /// </summary>
+ private FrozenDictionary<string, List<ReactionPrototype>> _reactions = default!;
public override void Initialize()
{
base.Initialize();
InitializeReactionCache();
- _prototypeManager.PrototypesReloaded += OnPrototypesReloaded;
- }
-
- public override void Shutdown()
- {
- base.Shutdown();
- _prototypeManager.PrototypesReloaded -= OnPrototypesReloaded;
+ SubscribeLocalEvent<PrototypesReloadedEventArgs>(OnPrototypesReloaded);
}
/// <summary>
/// </summary>
private void InitializeReactionCache()
{
- _reactions = new Dictionary<string, List<ReactionPrototype>>();
-
- var reactions = _prototypeManager.EnumeratePrototypes<ReactionPrototype>();
- foreach(var reaction in reactions)
+ // Construct single-reaction dictionary.
+ var dict = new Dictionary<string, List<ReactionPrototype>>();
+ foreach(var reaction in _prototypeManager.EnumeratePrototypes<ReactionPrototype>())
{
- CacheReaction(reaction);
+ // For this dictionary we only need to cache based on the first reagent.
+ var reagent = reaction.Reactants.Keys.First();
+ var list = dict.GetOrNew(reagent);
+ list.Add(reaction);
}
- }
+ _reactionsSingle = dict.ToFrozenDictionary();
- /// <summary>
- /// Caches a reaction by its first required reagent.
- /// Used to build the reaction cache.
- /// </summary>
- /// <param name="reaction">A reaction prototype to cache.</param>
- private void CacheReaction(ReactionPrototype reaction)
- {
- var reagents = reaction.Reactants.Keys;
- foreach(var reagent in reagents)
+ dict.Clear();
+ foreach(var reaction in _prototypeManager.EnumeratePrototypes<ReactionPrototype>())
{
- if(!_reactions.TryGetValue(reagent, out var cache))
+ foreach (var reagent in reaction.Reactants.Keys)
{
- cache = new List<ReactionPrototype>();
- _reactions.Add(reagent, cache);
+ var list = dict.GetOrNew(reagent);
+ list.Add(reaction);
}
-
- cache.Add(reaction);
- return; // Only need to cache based on the first reagent.
}
+ _reactions = dict.ToFrozenDictionary();
}
/// <summary>
/// <param name="eventArgs">The set of modified prototypes.</param>
private void OnPrototypesReloaded(PrototypesReloadedEventArgs eventArgs)
{
- if (!eventArgs.ByType.TryGetValue(typeof(ReactionPrototype), out var set))
- return;
-
- foreach (var (reactant, cache) in _reactions)
- {
- cache.RemoveAll((reaction) => set.Modified.ContainsKey(reaction.ID));
- if (cache.Count == 0)
- _reactions.Remove(reactant);
- }
-
- foreach (var prototype in set.Modified.Values)
- {
- CacheReaction((ReactionPrototype) prototype);
- }
+ if (eventArgs.WasModified<ReactionPrototype>())
+ InitializeReactionCache();
}
/// <summary>
SortedSet<ReactionPrototype> reactions = new();
foreach (var reactant in solution.Contents)
{
- if (_reactions.TryGetValue(reactant.Reagent.Prototype, out var reactantReactions))
+ if (_reactionsSingle.TryGetValue(reactant.Reagent.Prototype, out var reactantReactions))
reactions.UnionWith(reactantReactions);
}
return;
}
- Logger.Error($"{nameof(Solution)} {owner} could not finish reacting in under {MaxReactionIterations} loops.");
+ Log.Error($"{nameof(Solution)} {owner} could not finish reacting in under {MaxReactionIterations} loops.");
}
}
private void PrototypeReload(PrototypesReloadedEventArgs obj)
{
+ if (!obj.WasModified<ContentTileDefinition>())
+ return;
+
// Need to re-allocate tiledefs due to how prototype reloads work
foreach (var def in _prototypeManager.EnumeratePrototypes<ContentTileDefinition>())
{
+using System.Collections.Frozen;
using System.Diagnostics.CodeAnalysis;
+using System.Linq;
using Content.Shared.Humanoid.Prototypes;
using Robust.Shared.Prototypes;
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
private readonly List<MarkingPrototype> _index = new();
- private readonly Dictionary<MarkingCategories, Dictionary<string, MarkingPrototype>> _markingDict = new();
- private readonly Dictionary<string, MarkingPrototype> _markings = new();
+ public FrozenDictionary<MarkingCategories, FrozenDictionary<string, MarkingPrototype>> CategorizedMarkings = default!;
+ public FrozenDictionary<string, MarkingPrototype> Markings = default!;
public void Initialize()
{
_prototypeManager.PrototypesReloaded += OnPrototypeReload;
+ CachePrototypes();
+ }
+
+ private void CachePrototypes()
+ {
+ _index.Clear();
+ var markingDict = new Dictionary<MarkingCategories, Dictionary<string, MarkingPrototype>>();
foreach (var category in Enum.GetValues<MarkingCategories>())
{
- _markingDict.Add(category, new Dictionary<string, MarkingPrototype>());
+ markingDict.Add(category, new());
}
foreach (var prototype in _prototypeManager.EnumeratePrototypes<MarkingPrototype>())
{
_index.Add(prototype);
- _markingDict[prototype.MarkingCategory].Add(prototype.ID, prototype);
- _markings.Add(prototype.ID, prototype);
+ markingDict[prototype.MarkingCategory].Add(prototype.ID, prototype);
}
- }
- public IReadOnlyDictionary<string, MarkingPrototype> Markings => _markings;
- public IReadOnlyDictionary<MarkingCategories, Dictionary<string, MarkingPrototype>> CategorizedMarkings => _markingDict;
+ Markings = _prototypeManager.EnumeratePrototypes<MarkingPrototype>().ToFrozenDictionary(x => x.ID);
+ CategorizedMarkings = markingDict.ToFrozenDictionary(
+ x => x.Key,
+ x => x.Value.ToFrozenDictionary());
+ }
- public IReadOnlyDictionary<string, MarkingPrototype> MarkingsByCategory(MarkingCategories category)
+ public FrozenDictionary<string, MarkingPrototype> MarkingsByCategory(MarkingCategories category)
{
// all marking categories are guaranteed to have a dict entry
- return _markingDict[category];
+ return CategorizedMarkings[category];
}
/// <summary>
public bool TryGetMarking(Marking marking, [NotNullWhen(true)] out MarkingPrototype? markingResult)
{
- return _markings.TryGetValue(marking.MarkingId, out markingResult);
+ return Markings.TryGetValue(marking.MarkingId, out markingResult);
}
/// <summary>
private void OnPrototypeReload(PrototypesReloadedEventArgs args)
{
- if(!args.ByType.TryGetValue(typeof(MarkingPrototype), out var set))
- return;
-
-
- _index.RemoveAll(i => set.Modified.ContainsKey(i.ID));
-
- foreach (var prototype in set.Modified.Values)
- {
- var markingPrototype = (MarkingPrototype) prototype;
- _index.Add(markingPrototype);
- }
+ if (args.WasModified<MarkingPrototype>())
+ CachePrototypes();
}
public bool CanBeApplied(string species, Sex sex, Marking marking, IPrototypeManager? prototypeManager = null)
public override void Initialize()
{
base.Initialize();
- _protoManager.PrototypesReloaded += OnProtoReload;
+ SubscribeLocalEvent<PrototypesReloadedEventArgs>(OnProtoReload);
SetupTrackerLookup();
}
- public override void Shutdown()
- {
- base.Shutdown();
- _protoManager.PrototypesReloaded -= OnProtoReload;
- }
-
private void OnProtoReload(PrototypesReloadedEventArgs obj)
{
- SetupTrackerLookup();
+ if (obj.WasModified<JobPrototype>())
+ SetupTrackerLookup();
}
private void SetupTrackerLookup()