refactor: Refactor codebase for cleanup and async improvements

```
Refactor and optimize multiple components

- Remove obsolete attributes and unused dependencies in `IEventBus.cs`, `KarmaListener.cs`, `KarmaSyncer.cs`, and `ICommandManager.cs` to clean up code and improve maintainability.
- Enhance asynchronous event handling in `EventModifiedMessenger.cs` by integrating `await` for dispatch operations, improving consistency in message processing.
- Refine `CombatHandler.cs` logic with improved null-checking and better statistics handling, enhancing robustness during player events.
- Enable caching by default in `KarmaStorage.cs`, and update karmas asynchronously to boost performance.
- Simplify `Game/RoundBasedGame.cs` by removing unnecessary dependencies and improving state management and role assignment logic, enhancing game flow control.
```
This commit is contained in:
MSWS
2025-10-04 08:56:58 -07:00
parent 5d37e5d1ec
commit 41c7a788d3
22 changed files with 27 additions and 88 deletions

View File

@@ -43,7 +43,7 @@ public partial class StringLocalizer : IMsgLocalizer {
private LocalizedString getString(string name, params object[] arguments) {
// Get the localized value
string value;
try { value = localizer[name].Value; } catch (NullReferenceException e) {
try { value = localizer[name].Value; } catch (NullReferenceException) {
return new LocalizedString(name, name, true);
}

View File

@@ -12,7 +12,6 @@ public interface ICommandManager {
/// Registers a command with the manager.
/// </summary>
/// <param name="command">True if the command was successfully registered.</param>
[Obsolete("Registration is done via the ServiceProvider now.")]
bool RegisterCommand(ICommand command);
/// <summary>

View File

@@ -1,7 +1,6 @@
namespace TTT.API.Events;
public interface IEventBus {
[Obsolete("Registration should be done via the ServiceProvider")]
void RegisterListener(IListener listener);
void UnregisterListener(IListener listener);

View File

@@ -1,15 +1,10 @@
using CounterStrikeSharp.API;
using CounterStrikeSharp.API.Core;
using Microsoft.Extensions.DependencyInjection;
using TTT.API.Command;
using TTT.API.Player;
namespace TTT.CS2.Command.Test;
public class IndexCommand(IServiceProvider provider) : ICommand {
private readonly IPlayerConverter<CCSPlayerController> converter =
provider.GetRequiredService<IPlayerConverter<CCSPlayerController>>();
public class IndexCommand : ICommand {
public string Id => "index";
public void Dispose() { }

View File

@@ -21,7 +21,7 @@ public class TestCommand(IServiceProvider provider) : ICommand, IPluginModule {
subCommands.Add("state", new StateCommand(provider));
subCommands.Add("screencolor", new ScreenColorCommand(provider));
subCommands.Add("giveitem", new GiveItemCommand(provider));
subCommands.Add("index", new IndexCommand(provider));
subCommands.Add("index", new IndexCommand());
subCommands.Add("showicons", new ShowIconsCommand(provider));
subCommands.Add("sethealth", new SetHealthCommand());
}

View File

@@ -3,7 +3,6 @@ using CounterStrikeSharp.API.Core;
using CounterStrikeSharp.API.Modules.Cvars;
using CounterStrikeSharp.API.Modules.Cvars.Validators;
using TTT.API;
using TTT.API.Player;
using TTT.API.Storage;
using TTT.Karma;
@@ -12,7 +11,7 @@ namespace TTT.CS2.Configs;
public class CS2KarmaConfig : IStorage<KarmaConfig>, IPluginModule {
public static readonly FakeConVar<string> CV_DB_STRING = new(
"css_ttt_karma_dbstring", "Database connection string for Karma storage",
"Data Source=karma.db", ConVarFlags.FCVAR_NONE);
"Data Source=karma.db");
public static readonly FakeConVar<int> CV_MIN_KARMA = new("css_ttt_karma_min",
"Minimum possible Karma value", 0, ConVarFlags.FCVAR_NONE,

View File

@@ -62,15 +62,16 @@ public class CombatHandler(IServiceProvider provider) : IPluginModule {
}
var killerStats = ev.Attacker?.ActionTrackingServices?.MatchStats;
ev.Attacker.ActionTrackingServices.NumRoundKills--;
Utilities.SetStateChanged(ev.Attacker,
"CCSPlayerController_ActionTrackingServices",
"m_pActionTrackingServices");
if (killerStats == null) return;
killerStats.Kills -= 1;
killerStats.Damage -= ev.DmgHealth;
if (ev.Attacker != null) {
Utilities.SetStateChanged(ev.Attacker,
"CCSPlayerController_ActionTrackingServices",
"m_pActionTrackingServices");
if (killerStats == null) return;
killerStats.Kills -= 1;
killerStats.Damage -= ev.DmgHealth;
if (ev.Attacker.ActionTrackingServices != null)
ev.Attacker.ActionTrackingServices.NumRoundKills--;
Utilities.SetStateChanged(ev.Attacker, "CCSPlayerController",
"m_pActionTrackingServices");
ev.FireEventToClient(ev.Attacker);

View File

@@ -5,7 +5,6 @@ using TTT.API.Extensions;
using TTT.API.Player;
using TTT.API.Storage;
using TTT.Game.Roles;
using TTT.Shop.Items.Traitor.BodyPaint;
namespace TTT.CS2.Items.BodyPaint;

View File

@@ -9,7 +9,6 @@ using TTT.CS2.API;
using TTT.CS2.Extensions;
using TTT.Game.Events.Body;
using TTT.Game.Listeners;
using TTT.Shop.Items.Traitor.BodyPaint;
namespace TTT.CS2.Items.BodyPaint;

View File

@@ -1,6 +1,6 @@
using TTT.Locale;
namespace TTT.Shop.Items.Traitor.BodyPaint;
namespace TTT.CS2.Items.BodyPaint;
public class BodyPaintMsgs {
public static IMsg SHOP_ITEM_BODY_PAINT

View File

@@ -4,11 +4,11 @@ using CounterStrikeSharp.API;
using CounterStrikeSharp.API.Core;
using CounterStrikeSharp.API.Core.Attributes.Registration;
using CounterStrikeSharp.API.Modules.Utils;
using JetBrains.Annotations;
using Microsoft.Extensions.DependencyInjection;
using ShopAPI;
using ShopAPI.Configs.Traitor;
using TTT.API;
using TTT.API.Messages;
using TTT.API.Player;
using TTT.API.Role;
using TTT.API.Storage;
@@ -30,9 +30,6 @@ public class PoisonSmokeListener(IServiceProvider provider) : IPluginModule {
private readonly IPlayerFinder finder =
provider.GetRequiredService<IPlayerFinder>();
private readonly IMessenger messenger =
provider.GetRequiredService<IMessenger>();
private readonly List<IDisposable> poisonSmokes = [];
private readonly IRoleAssigner roleAssigner =
@@ -51,6 +48,7 @@ public class PoisonSmokeListener(IServiceProvider provider) : IPluginModule {
public void Start() { }
[UsedImplicitly]
[GameEventHandler]
public HookResult OnSmokeGrenade(EventSmokegrenadeDetonate ev,
GameEventInfo _) {

View File

@@ -17,7 +17,7 @@ namespace TTT.CS2.Items.Station;
public abstract class StationItem<T>(IServiceProvider provider,
StationConfig config)
: RoleRestrictedItem<T>(provider), IPluginModule where T : IRole {
private static readonly long PROP_SIZE_SQUARED = 500;
private readonly long PROP_SIZE_SQUARED = 500;
protected readonly StationConfig _Config = config;
protected readonly IPlayerConverter<CCSPlayerController> Converter =

View File

@@ -38,13 +38,14 @@ public class KarmaSyncer(IServiceProvider provider)
public HookResult OnJoin(EventPlayerConnectFull ev, GameEventInfo _) {
if (ev.Userid == null || karma == null) return HookResult.Continue;
var player = converter.GetPlayer(ev.Userid);
var user = ev.Userid;
Task.Run(async () => {
var karmaValue = await karma.Load(player);
await Server.NextWorldUpdateAsync(() => {
if (!ev.Userid.IsValid) return;
ev.Userid.Score = karmaValue;
Utilities.SetStateChanged(ev.Userid, "CCSPlayerController", "m_iScore");
if (!user.IsValid) return;
user.Score = karmaValue;
Utilities.SetStateChanged(user, "CCSPlayerController", "m_iScore");
});
});

View File

@@ -3,7 +3,6 @@ using CounterStrikeSharp.API.Core;
using Microsoft.Extensions.DependencyInjection;
using TTT.API.Events;
using TTT.API.Game;
using TTT.API.Messages;
using TTT.API.Player;
using TTT.Game.Events.Body;
using TTT.Game.Events.Game;
@@ -18,9 +17,6 @@ public class PlayerStatsTracker(IServiceProvider provider) : IListener {
private readonly IPlayerFinder finder =
provider.GetRequiredService<IPlayerFinder>();
private readonly IMessenger messenger =
provider.GetRequiredService<IMessenger>();
private readonly ISet<int> revealedDeaths = new HashSet<int>();
private readonly IDictionary<int, (int, int)> roundKillsAndAssists =

View File

@@ -15,7 +15,9 @@ public class IdentifyBodyAction(IRoleAssigner roles, BodyIdentifyEvent ev)
#endregion
public IPlayer Player { get; } = ev.Identifier;
public IPlayer Player { get; } =
ev.Identifier ?? throw new InvalidOperationException();
public IPlayer? Other { get; } = ev.Body.OfPlayer;
public IRole? PlayerRole { get; } =

View File

@@ -9,7 +9,6 @@ public class EventBus(IServiceProvider provider) : IEventBus, ITerrorModule {
private readonly Dictionary<Type, List<(object listener, MethodInfo method)>>
handlers = new();
[Obsolete("Registering listeners is deprecated, use DI instead.")]
public void RegisterListener(IListener listener) {
var dirtyTypes = new HashSet<Type>();
appendListener(listener, dirtyTypes);

View File

@@ -73,7 +73,7 @@ public abstract class EventModifiedMessenger(IServiceProvider provider)
PlayerMessageEvent ev) {
if (player == null) return await SendMessage(null, msg);
Bus.Dispatch(ev);
await Bus.Dispatch(ev);
if (ev.IsCanceled) return false;
return await SendMessage(player, ev.Message, ev.Args);

View File

@@ -1,8 +1,6 @@
using JetBrains.Annotations;
using TTT.API.Events;
using TTT.API.Role;
using TTT.Game.Events.Player;
using TTT.Game.Roles;
namespace TTT.Game.Listeners;
@@ -19,38 +17,4 @@ public class PlayerCausesEndListener(IServiceProvider provider)
public void OnLeave(PlayerLeaveEvent ev) {
Games.ActiveGame?.CheckEndConditions();
}
private bool getWinningTeam(out IRole? winningTeam) {
var game = Games.ActiveGame;
winningTeam = null;
if (game is null) return false;
var traitorRole =
game.Roles.First(r => r.GetType().IsAssignableTo(typeof(TraitorRole)));
var innocentRole =
game.Roles.First(r => r.GetType().IsAssignableTo(typeof(InnocentRole)));
var detectiveRole = game.Roles.First(r
=> r.GetType().IsAssignableTo(typeof(DetectiveRole)));
var traitorsAlive = game.GetAlive(typeof(TraitorRole)).Count;
var nonTraitorsAlive = game.GetAlive().Count - traitorsAlive;
var detectivesAlive = game.GetAlive(typeof(DetectiveRole)).Count;
switch (traitorsAlive) {
case 0 when nonTraitorsAlive == 0:
winningTeam = null;
return true;
case > 0 when nonTraitorsAlive == 0:
winningTeam = traitorRole;
return true;
case 0 when nonTraitorsAlive > 0:
winningTeam = nonTraitorsAlive == detectivesAlive ?
detectiveRole :
innocentRole;
return true;
default:
winningTeam = null;
return false;
}
}
}

View File

@@ -22,9 +22,6 @@ public class RoundBasedGame(IServiceProvider provider) : IGame {
.GetAwaiter()
.GetResult() ?? new TTTConfig();
private readonly IInventoryManager inventory =
provider.GetRequiredService<IInventoryManager>();
protected readonly IMsgLocalizer Locale =
provider.GetRequiredService<IMsgLocalizer>();

View File

@@ -30,9 +30,7 @@ public class KarmaListener(IServiceProvider provider) : BaseListener(provider) {
private readonly IRoleAssigner roles =
provider.GetRequiredService<IRoleAssigner>();
private Dictionary<IPlayer, int> queuedKarmaUpdates = new();
public void Dispose() { }
private readonly Dictionary<IPlayer, int> queuedKarmaUpdates = new();
[EventHandler]
[UsedImplicitly]
@@ -41,21 +39,16 @@ public class KarmaListener(IServiceProvider provider) : BaseListener(provider) {
[EventHandler]
[UsedImplicitly]
public void OnKill(PlayerDeathEvent ev) {
Messenger.DebugAnnounce("KarmaListener: OnKill");
if (games.ActiveGame is not { State: State.IN_PROGRESS }) return;
var victim = ev.Victim;
var killer = ev.Killer;
if (killer == null) return;
Messenger.DebugAnnounce("KarmaListener: Killer is not null");
var victimRole = roles.GetRoles(victim).First();
var killerRole = roles.GetRoles(killer).First();
Messenger.DebugAnnounce(
$"KarmaListener: Victim role {victimRole.Id}, Killer role {killerRole.Id}");
var victimKarmaDelta = 0;
var killerKarmaDelta = 0;

View File

@@ -12,7 +12,7 @@ using TTT.Karma.Events;
namespace TTT.Karma;
public class KarmaStorage(IServiceProvider provider) : IKarmaService {
private static readonly bool enableCache = false;
private static readonly bool enableCache = true;
private readonly IEventBus bus = provider.GetRequiredService<IEventBus>();
private readonly KarmaConfig config =
@@ -40,7 +40,7 @@ public class KarmaStorage(IServiceProvider provider) : IKarmaService {
var scheduler = provider.GetRequiredService<IScheduler>();
Observable.Interval(TimeSpan.FromMinutes(5), scheduler)
.Subscribe(_ => updateKarmas());
.Subscribe(_ => Task.Run(async () => await updateKarmas()));
}
public async Task<int> Load(IPlayer key) {

View File

@@ -24,8 +24,6 @@ public class Stickers(IServiceProvider provider)
.GetAwaiter()
.GetResult() ?? new StickersConfig();
private readonly IIconManager? icons = provider.GetService<IIconManager>();
public override string Name => Locale[StickerMsgs.SHOP_ITEM_STICKERS];
public override string Description