chore: cleanup
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
using Godot;
|
||||
using GodotHostTest.AetherBind;
|
||||
using GodotHostTest.Game.Level;
|
||||
using GodotHostTest.Game.Score;
|
||||
using GodotHostTest.Game.Target;
|
||||
@@ -6,7 +7,6 @@ using GodotHostTest.Interfaces;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using OwofGames.GodotHost.Observability;
|
||||
using OwofGames.GodotLume;
|
||||
using RootServiceSource = GodotHostTest.AetherBind.RootServiceSource;
|
||||
|
||||
namespace GodotHostTest.Game.Game;
|
||||
|
||||
@@ -17,9 +17,14 @@ public partial class GameServiceSource : RootServiceSource
|
||||
protected override void Configure(Builder builder)
|
||||
{
|
||||
builder
|
||||
// root scope services
|
||||
.AddSingleton<ITargetEventBus, TargetEventBus>()
|
||||
.AddSingleton<IScore, TotalScore>()
|
||||
.AddLevelServices(_levelsData);
|
||||
// current level / level data management
|
||||
.AddInstance<ILevelDataProvider, LevelsData>(_levelsData)
|
||||
.AddSingleton<ICurrentLevel, CurrentLevel>()
|
||||
// level scope services
|
||||
.AddLevelServices();
|
||||
}
|
||||
|
||||
protected override void ConfigureServices(IServiceCollection serviceCollection)
|
||||
|
||||
@@ -13,7 +13,8 @@ namespace GodotHostTest.Game.Level;
|
||||
|
||||
public partial class LevelServiceSource : ServiceSource
|
||||
{
|
||||
private Activity? _activityValue;
|
||||
private Activity? _levelActivity;
|
||||
|
||||
[Export] private TargetSpawner _targetSpawner = null!;
|
||||
|
||||
protected override void OnScopeCreated(IProvider serviceProvider)
|
||||
@@ -22,15 +23,13 @@ public partial class LevelServiceSource : ServiceSource
|
||||
}
|
||||
|
||||
[WithProvider]
|
||||
private void OnScopeCreated(IValueSetter<ITargetCollector> targetCollector,
|
||||
IValueSetter<ITargetSpawner> targetSpawner, IActivitySourceFactory activitySourceFactory,
|
||||
IValueSetter<Activity> activity)
|
||||
private void OnScopeCreated(IActivitySourceFactory activitySourceFactory,
|
||||
IValueSetter<ITargetCollector> targetCollector, IValueSetter<ITargetSpawner> targetSpawner)
|
||||
{
|
||||
// ReSharper disable once ExplicitCallerInfoArgument - the caller name is not significant in this case
|
||||
_activityValue = activitySourceFactory.ActivitySource.StartActivity("Level") ??
|
||||
_levelActivity = activitySourceFactory.ActivitySource.StartActivity("Level") ??
|
||||
throw new InvalidOperationException(
|
||||
"No listeners for the activity - is OpenTelemetry running?");
|
||||
activity.Set(_activityValue);
|
||||
targetCollector.Set(_targetSpawner);
|
||||
targetSpawner.Set(_targetSpawner);
|
||||
}
|
||||
@@ -38,6 +37,6 @@ public partial class LevelServiceSource : ServiceSource
|
||||
public override void _Ready()
|
||||
{
|
||||
// after 3 seconds, dispose the activity for simulation purposes
|
||||
GetTree().CreateTimer(3).Timeout += _activityValue!.Dispose;
|
||||
GetTree().CreateTimer(3).Timeout += _levelActivity!.Dispose;
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,3 @@
|
||||
using System.Diagnostics;
|
||||
using GodotHostTest.AetherBind;
|
||||
using GodotHostTest.Interfaces;
|
||||
using OwofGames.GodotLume;
|
||||
@@ -7,17 +6,12 @@ namespace GodotHostTest.Game.Level;
|
||||
|
||||
public static class LevelServices
|
||||
{
|
||||
public static void AddLevelServices(this Builder builder, LevelsData levelsData)
|
||||
public static void AddLevelServices(this Builder builder)
|
||||
{
|
||||
builder
|
||||
// current level / level data management
|
||||
.AddSingleton<ICurrentLevel, CurrentLevel>()
|
||||
.AddInstance<ILevelDataProvider, LevelsData>(levelsData)
|
||||
// value provider for activity
|
||||
.AddValueProvider<Activity, LevelScope>()
|
||||
// value providers to send data into level scope
|
||||
// value providers to send level data from root to level scope
|
||||
.AddValueProvider<ILevel, RootScope, LevelScope>()
|
||||
// value provider for level scope setup
|
||||
// value providers for level scope setup
|
||||
.AddValueProvider<ITargetCollector, LevelScope>()
|
||||
.AddValueProvider<ITargetSpawner, LevelScope>();
|
||||
}
|
||||
|
||||
+12
-4
@@ -9,16 +9,24 @@ namespace GodotHostTest.Game.Score;
|
||||
public partial class Score : Control
|
||||
{
|
||||
[Export] private AnimationPlayer _animationPlayer = null!;
|
||||
|
||||
[Inject] private ICurrentLevel _currentLevel = null!;
|
||||
[Export] private Label _label = null!;
|
||||
|
||||
[Inject] private IScore _score = null!;
|
||||
|
||||
public override void _Ready()
|
||||
{
|
||||
_score.Score.Subscribe(UpdateScore).AddTo(this);
|
||||
_score.Score.Chunk(2, 1).Where(values => values.Length == 2 && values[1] < values[0])
|
||||
.Subscribe(OnScoreDecreasing).AddTo(this);
|
||||
// update the score label whenever the score changes
|
||||
_score.Score
|
||||
.Subscribe(UpdateScore)
|
||||
.AddTo(this);
|
||||
|
||||
// run an animation whenever the score decreases
|
||||
_score.Score
|
||||
.Chunk(2, 1)
|
||||
.Where(values => values.Length == 2 && values[1] < values[0])
|
||||
.Subscribe(OnScoreDecreasing)
|
||||
.AddTo(this);
|
||||
}
|
||||
|
||||
private void OnScoreDecreasing<T>(T _)
|
||||
|
||||
@@ -6,24 +6,23 @@ namespace GodotHostTest.Game.Score;
|
||||
|
||||
public class TotalScore : IScore, IDisposable
|
||||
{
|
||||
private readonly IDisposable _connectedObservableDisposable;
|
||||
|
||||
public TotalScore(ITargetEventBus targetEventBus)
|
||||
{
|
||||
var connectedObservable = targetEventBus.Hit.Select(_ => 20)
|
||||
Score =
|
||||
// map every hit target to +20 points
|
||||
targetEventBus.Hit.Select(_ => 20)
|
||||
// map every missed target to -5 points
|
||||
.Merge(targetEventBus.TimedOut.Select(_ => -5))
|
||||
// sum them all (starting with 0)
|
||||
.Scan(0, (x1, x2) => x1 + x2)
|
||||
.Prepend(0)
|
||||
.Replay(1);
|
||||
_connectedObservableDisposable = connectedObservable.Connect();
|
||||
Score = connectedObservable.AsObservable();
|
||||
.ToReadOnlyReactiveProperty();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_connectedObservableDisposable.Dispose();
|
||||
Score.Dispose();
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
public Observable<int> Score { get; }
|
||||
public ReadOnlyReactiveProperty<int> Score { get; }
|
||||
}
|
||||
+13
-17
@@ -8,14 +8,14 @@ namespace GodotHostTest.Game.Target;
|
||||
public partial class Target : Node2D, ITarget
|
||||
{
|
||||
private readonly Subject<Unit> _hit = new();
|
||||
|
||||
private readonly Subject<Unit> _timedOut = new();
|
||||
|
||||
[Export] public required Area2D CollisionArea;
|
||||
[Export] public required Sprite2D Image;
|
||||
[Export] public required Timer TimeOutTimer;
|
||||
[Export] private PackedScene _explosionPackedScene = null!;
|
||||
[Inject] private ILevel _level = null!;
|
||||
|
||||
[Inject] private ILevel _level = null!;
|
||||
[Inject] private ITargetCollector _targetCollector = null!;
|
||||
|
||||
public Observable<Unit> TimedOut => _timedOut.AsObservable();
|
||||
@@ -30,26 +30,30 @@ public partial class Target : Node2D, ITarget
|
||||
TimeOutTimer.Start(_level.SpawnDuration.TotalSeconds);
|
||||
}
|
||||
|
||||
private void Disable()
|
||||
{
|
||||
Image.Visible = false;
|
||||
// can't set monitoring/monitorable when inside collision code, like during OnHit, so let's call them deferred
|
||||
CollisionArea.SetDeferred(Area2D.PropertyName.Monitoring, false);
|
||||
CollisionArea.SetDeferred(Area2D.PropertyName.Monitorable, false);
|
||||
TimeOutTimer.Stop();
|
||||
}
|
||||
|
||||
public override void _Ready()
|
||||
{
|
||||
_targetCollector.NewTarget(this);
|
||||
}
|
||||
|
||||
public override void _ExitTree()
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
base.Dispose(disposing);
|
||||
_timedOut.Dispose();
|
||||
_hit.Dispose();
|
||||
}
|
||||
|
||||
private void OnAreaEntered(Area2D _)
|
||||
{
|
||||
OnHit();
|
||||
}
|
||||
|
||||
private void OnHit()
|
||||
{
|
||||
Disable();
|
||||
TimeOutTimer.Stop();
|
||||
_hit.OnNext(Unit.Default);
|
||||
|
||||
var explosion = (GpuParticles2D)_explosionPackedScene.Instantiate();
|
||||
@@ -58,14 +62,6 @@ public partial class Target : Node2D, ITarget
|
||||
GetTree().CurrentScene.AddChild(explosion);
|
||||
}
|
||||
|
||||
private void Disable()
|
||||
{
|
||||
Image.Visible = false;
|
||||
// can't se monitoring/monitorable when inside the collision code, like during OnHit
|
||||
CollisionArea.SetDeferred(Area2D.PropertyName.Monitoring, false);
|
||||
CollisionArea.SetDeferred(Area2D.PropertyName.Monitorable, false);
|
||||
}
|
||||
|
||||
private void OnTimeout()
|
||||
{
|
||||
Disable();
|
||||
|
||||
@@ -10,31 +10,36 @@ namespace GodotHostTest.Game.Target;
|
||||
public partial class TargetSpawner : Node2D, ITargetCollector, ITargetSpawner
|
||||
{
|
||||
private readonly List<ITarget> _availableTargets = [];
|
||||
|
||||
private readonly Subject<ITarget> _targetSpawned = new();
|
||||
|
||||
[Export] public required Timer Timer;
|
||||
|
||||
[Inject] private ILevel _level = null!;
|
||||
[Inject] private ITargetEventBus _targetEventBus = null!;
|
||||
|
||||
/// <inheritdoc />
|
||||
public void NewTarget(ITarget target)
|
||||
{
|
||||
// record the target as available
|
||||
_availableTargets.Add(target);
|
||||
target.Hit.Merge(target.TimedOut).Select(_ => target).Subscribe(MakeTargetAvailable).AddTo(this);
|
||||
|
||||
// whenever the target gets disabled, mark it as available again
|
||||
target.Hit.Merge(target.TimedOut)
|
||||
.Select(_ => target)
|
||||
.Subscribe(_availableTargets.Add)
|
||||
.AddTo(this);
|
||||
}
|
||||
|
||||
public Observable<ITarget> TargetSpawned => _targetSpawned.AsObservable();
|
||||
|
||||
public override void _Ready()
|
||||
{
|
||||
// inform the target event bus that there's a new target spawner
|
||||
_targetEventBus.NewTargetSpawner(this);
|
||||
Spawn();
|
||||
Timer.Start(_level.TimeBetweenSpawns.TotalSeconds);
|
||||
}
|
||||
|
||||
private void MakeTargetAvailable(ITarget target)
|
||||
{
|
||||
_availableTargets.Add(target);
|
||||
// spawn every total seconds (and immediately spawn something at ready)
|
||||
Timer.Start(_level.TimeBetweenSpawns.TotalSeconds);
|
||||
Spawn();
|
||||
}
|
||||
|
||||
private void OnTimer()
|
||||
|
||||
@@ -11,7 +11,6 @@ public partial class Turret : Sprite2D
|
||||
|
||||
[Inject] private ILogger<Turret> _logger = null!;
|
||||
[Export] private PackedScene _projectilePackedScene = null!;
|
||||
|
||||
private double _rotationDirection;
|
||||
[Export] private double _rotationSpeed = 6;
|
||||
[Inject] private ISceneInstantiator _sceneInstantiator = null!;
|
||||
|
||||
@@ -16,4 +16,11 @@ public static class ObservableHelpers
|
||||
});
|
||||
return disposable;
|
||||
}
|
||||
|
||||
public static ConnectableObservable<T> Connect<T>(this ConnectableObservable<T> connectableObservable,
|
||||
out IDisposable disposable)
|
||||
{
|
||||
disposable = connectableObservable.Connect();
|
||||
return connectableObservable;
|
||||
}
|
||||
}
|
||||
@@ -2,8 +2,18 @@ using R3;
|
||||
|
||||
namespace GodotHostTest.Interfaces;
|
||||
|
||||
/// <summary>
|
||||
/// The object that handles the current level.
|
||||
/// </summary>
|
||||
public interface ICurrentLevel
|
||||
{
|
||||
/// <summary>
|
||||
/// The current level.
|
||||
/// </summary>
|
||||
public ReadOnlyReactiveProperty<int> LevelNumber { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Move to the next level.
|
||||
/// </summary>
|
||||
public void NextLevel();
|
||||
}
|
||||
@@ -2,6 +2,9 @@ using System;
|
||||
|
||||
namespace GodotHostTest.Interfaces;
|
||||
|
||||
/// <summary>
|
||||
/// Description of a single level.
|
||||
/// </summary>
|
||||
public interface ILevel
|
||||
{
|
||||
/// <summary>
|
||||
|
||||
@@ -1,6 +1,14 @@
|
||||
namespace GodotHostTest.Interfaces;
|
||||
|
||||
/// <summary>
|
||||
/// An object that provides the information about a certain level.
|
||||
/// </summary>
|
||||
public interface ILevelDataProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// Return the level data for a specific level.
|
||||
/// </summary>
|
||||
/// <param name="levelNumber">Level number.</param>
|
||||
/// <returns>The information about a certain level.</returns>
|
||||
public ILevel GetLevelData(int levelNumber);
|
||||
}
|
||||
@@ -10,5 +10,5 @@ public interface IScore
|
||||
/// <summary>
|
||||
/// The current score.
|
||||
/// </summary>
|
||||
public Observable<int> Score { get; }
|
||||
public ReadOnlyReactiveProperty<int> Score { get; }
|
||||
}
|
||||
@@ -3,18 +3,17 @@ using R3;
|
||||
namespace GodotHostTest.Interfaces;
|
||||
|
||||
/// <summary>
|
||||
/// A target for our projectiles.
|
||||
/// A target for our projectiles. Targets can be reused multiple times.
|
||||
/// </summary>
|
||||
public interface ITarget
|
||||
{
|
||||
/// <summary>
|
||||
/// The target hasn't been hit in the allotted time and has timed out; once this observable emits an event, both
|
||||
/// it and <see cref="Hit"/> complete.
|
||||
/// An observable that emits a <see cref="Unit"/> value when the target hasn't been hit in the allotted time and has timed out. Every time this observable emits, the target becomes disabled.
|
||||
/// </summary>
|
||||
Observable<Unit> TimedOut { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The target has been hit; once this observable emits an event, both it and <see cref="TimedOut"/> complete.
|
||||
/// An observable that emits a <see cref="Unit"/> value when the target has been hit in the allotted time. Every time this observable emits, the target becomes disabled.
|
||||
/// </summary>
|
||||
Observable<Unit> Hit { get; }
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
namespace GodotHostTest.Interfaces;
|
||||
|
||||
/// <summary>
|
||||
/// An object which collects targets as soon as they are created.
|
||||
/// An object which receives targets as soon as they are created.
|
||||
/// </summary>
|
||||
public interface ITargetCollector
|
||||
{
|
||||
|
||||
@@ -2,6 +2,9 @@ using R3;
|
||||
|
||||
namespace GodotHostTest.Interfaces;
|
||||
|
||||
/// <summary>
|
||||
/// An event bus that summarizes information from all <see cref="ITargetSpawner" />'s targets.
|
||||
/// </summary>
|
||||
public interface ITargetEventBus
|
||||
{
|
||||
/// <summary>
|
||||
@@ -15,8 +18,8 @@ public interface ITargetEventBus
|
||||
Observable<Unit> Hit { get; }
|
||||
|
||||
/// <summary>
|
||||
/// A new target spawner has been added.
|
||||
/// Callback method to invoke when a new target spawner has been added.
|
||||
/// </summary>
|
||||
/// <param name="targetSpawner"></param>
|
||||
/// <param name="targetSpawner">The new target spawner.</param>
|
||||
void NewTargetSpawner(ITargetSpawner targetSpawner);
|
||||
}
|
||||
@@ -3,7 +3,7 @@ using R3;
|
||||
namespace GodotHostTest.Interfaces;
|
||||
|
||||
/// <summary>
|
||||
/// An object that spawns targets.
|
||||
/// An object that spawns targets. A target is considered spawned whenever it's enabled, even if it was already present in the scene.
|
||||
/// </summary>
|
||||
public interface ITargetSpawner
|
||||
{
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
using JetBrains.Annotations;
|
||||
using OwofGames.GodotLume;
|
||||
|
||||
namespace GodotHostTest.AetherBind;
|
||||
|
||||
public static class BuilderExtensions
|
||||
{
|
||||
public static Builder AddValueProvider<TValueType, TSourceScope, TDestinationScope>(this Builder builder)
|
||||
public static Builder AddValueProvider<TValueType, [MeansImplicitUse] TSourceScope,
|
||||
[MeansImplicitUse] TDestinationScope>(this Builder builder)
|
||||
where TValueType : class
|
||||
where TSourceScope : RootScope
|
||||
where TDestinationScope : TSourceScope
|
||||
@@ -22,7 +24,7 @@ public static class BuilderExtensions
|
||||
provider => provider.Get<IValueGetter<TValueType>>().Value);
|
||||
}
|
||||
|
||||
public static Builder AddValueProvider<TValueType, TScope>(this Builder builder)
|
||||
public static Builder AddValueProvider<TValueType, [MeansImplicitUse] TScope>(this Builder builder)
|
||||
where TValueType : class
|
||||
where TScope : RootScope
|
||||
{
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="JetBrains.Annotations" Version="2026.2.0"/>
|
||||
<PackageReference Include="Microsoft.Extensions.Diagnostics" Version="10.0.0"/>
|
||||
<PackageReference Include="OpenTelemetry" Version="1.17.0"/>
|
||||
<PackageReference Include="OpenTelemetry.Exporter.OpenTelemetryProtocol" Version="1.17.0"/>
|
||||
|
||||
@@ -21,8 +21,10 @@
|
||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ALoggerInformation_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2026_002E2_003Fresharper_002Dhost_003FSourcesCache_003F58a2e8187d354ab2e42d1cca1ce63b1edb0381e3ac126b055eb2481382014_003FLoggerInformation_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ALogger_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2026_002E2_003Fresharper_002Dhost_003FSourcesCache_003F342e7081b95d68bdbbd320f210c35f9376e2b2b914a05d1cfef054c46bee58_003FLogger_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AMethodBaseInvoker_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2026_002E2_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F6cc9b871557b441baa469ce23b255f41dbb200_003F7b_003Fb6307b47_003FMethodBaseInvoker_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ANode_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2026_002E2_003Fresharper_002Dhost_003FSourcesCache_003Fcd2081581a57397285b1beba7fc14bdbc61c89e3ac09a962676d880d9dd3c_003FNode_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AOtlpHttpExportClient_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2026_002E2_003Fresharper_002Dhost_003FSourcesCache_003F4033dea463e391648d47bc0d947734cc9785594d32f2e63e7fdaa66dc6f69_003FOtlpHttpExportClient_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AProtobufOtlpLogSerializer_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2026_002E2_003Fresharper_002Dhost_003FSourcesCache_003Fc7a11e51b08d59f654af762b7dc9ef7158afab9213be73c87d181effe335_003FProtobufOtlpLogSerializer_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AReadOnlyReactiveProperty_00601_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2026_002E2_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F5c3b451e92d746ce859467e287bf9baf92400_003F9d_003F98b1b0ac_003FReadOnlyReactiveProperty_00601_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ARuntimeType_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2026_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F6cc9b871557b441baa469ce23b255f41dbb200_003F5e_003F88e82907_003FRuntimeType_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ASuppressInstrumentationScope_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2026_002E2_003Fresharper_002Dhost_003FSourcesCache_003Ffdb78768d9162cf6ca6280f1fa20f07dfc0fdd0d0352108d2d26c0cde1e0_003FSuppressInstrumentationScope_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AThrowHelpers_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2026_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F6cc9b871557b441baa469ce23b255f41dbb200_003F8e_003Fc3f51c26_003FThrowHelpers_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||
|
||||
Reference in New Issue
Block a user