mirror of
https://github.com/ppy/osu.git
synced 2024-12-05 02:53:21 +08:00
Compare commits
16 Commits
5651530325
...
1548f17aa7
Author | SHA1 | Date | |
---|---|---|---|
|
1548f17aa7 | ||
|
f09d8f097a | ||
|
457957d3b8 | ||
|
2ceb3f6f85 | ||
|
7ece8ec1dc | ||
|
68f4fa5a57 | ||
|
68f21709a8 | ||
|
fa3c95c296 | ||
|
fced254594 | ||
|
0a8ec4db2b | ||
|
5b63d725c5 | ||
|
f5a7716509 | ||
|
13d7c6a2d8 | ||
|
cd9b5927eb | ||
|
c57ace0b5f | ||
|
8f6e5c4754 |
@ -46,8 +46,59 @@ dotnet_diagnostic.IDE0130.severity = warning
|
|||||||
# IDE1006: Naming style
|
# IDE1006: Naming style
|
||||||
dotnet_diagnostic.IDE1006.severity = warning
|
dotnet_diagnostic.IDE1006.severity = warning
|
||||||
|
|
||||||
#Disable operator overloads requiring alternate named methods
|
# CA1305: Specify IFormatProvider
|
||||||
dotnet_diagnostic.CA2225.severity = none
|
# Too many noisy warnings for parsing/formatting numbers
|
||||||
|
dotnet_diagnostic.CA1305.severity = none
|
||||||
|
|
||||||
|
# CA1507: Use nameof to express symbol names
|
||||||
|
# Flaggs serialization name attributes
|
||||||
|
dotnet_diagnostic.CA1507.severity = suggestion
|
||||||
|
|
||||||
|
# CA1806: Do not ignore method results
|
||||||
|
# The usages for numeric parsing are explicitly optional
|
||||||
|
dotnet_diagnostic.CA1806.severity = suggestion
|
||||||
|
|
||||||
|
# CA1822: Mark members as static
|
||||||
|
# Potential false positive around reflection/too much noise
|
||||||
|
dotnet_diagnostic.CA1822.severity = none
|
||||||
|
|
||||||
|
# CA1826: Do not use Enumerable method on indexable collections
|
||||||
|
dotnet_diagnostic.CA1826.severity = suggestion
|
||||||
|
|
||||||
|
# CA1859: Use concrete types when possible for improved performance
|
||||||
|
# Involves design considerations
|
||||||
|
dotnet_diagnostic.CA1859.severity = suggestion
|
||||||
|
|
||||||
|
# CA1860: Avoid using 'Enumerable.Any()' extension method
|
||||||
|
dotnet_diagnostic.CA1860.severity = suggestion
|
||||||
|
|
||||||
|
# CA1861: Avoid constant arrays as arguments
|
||||||
|
# Outdated with collection expressions
|
||||||
|
dotnet_diagnostic.CA1861.severity = suggestion
|
||||||
|
|
||||||
|
# CA2007: Consider calling ConfigureAwait on the awaited task
|
||||||
|
dotnet_diagnostic.CA2007.severity = warning
|
||||||
|
|
||||||
|
# CA2016: Forward the 'CancellationToken' parameter to methods
|
||||||
|
# Some overloads are having special handling for debugger
|
||||||
|
dotnet_diagnostic.CA2016.severity = suggestion
|
||||||
|
|
||||||
|
# CA2021: Do not call Enumerable.Cast<T> or Enumerable.OfType<T> with incompatible types
|
||||||
|
# Causing a lot of false positives with generics
|
||||||
|
dotnet_diagnostic.CA2021.severity = none
|
||||||
|
|
||||||
|
# CA2101: Specify marshaling for P/Invoke string arguments
|
||||||
|
# Reports warning for all non-UTF16 usages on DllImport; consider migrating to LibraryImport
|
||||||
|
dotnet_diagnostic.CA2101.severity = none
|
||||||
|
|
||||||
|
# CA2201: Do not raise reserved exception types
|
||||||
|
dotnet_diagnostic.CA2201.severity = warning
|
||||||
|
|
||||||
|
# CA2208: Instantiate argument exceptions correctly
|
||||||
|
dotnet_diagnostic.CA2208.severity = suggestion
|
||||||
|
|
||||||
|
# CA2242: Test for NaN correctly
|
||||||
|
dotnet_diagnostic.CA2242.severity = warning
|
||||||
|
|
||||||
# Banned APIs
|
# Banned APIs
|
||||||
dotnet_diagnostic.RS0030.severity = error
|
dotnet_diagnostic.RS0030.severity = error
|
||||||
|
@ -14,10 +14,6 @@ M:Realms.CollectionExtensions.SubscribeForNotifications`1(System.Collections.Gen
|
|||||||
M:System.Threading.Tasks.Task.Wait();Don't use Task.Wait. Use Task.WaitSafely() to ensure we avoid deadlocks.
|
M:System.Threading.Tasks.Task.Wait();Don't use Task.Wait. Use Task.WaitSafely() to ensure we avoid deadlocks.
|
||||||
P:System.Threading.Tasks.Task`1.Result;Don't use Task.Result. Use Task.GetResultSafely() to ensure we avoid deadlocks.
|
P:System.Threading.Tasks.Task`1.Result;Don't use Task.Result. Use Task.GetResultSafely() to ensure we avoid deadlocks.
|
||||||
M:System.Threading.ManualResetEventSlim.Wait();Specify a timeout to avoid waiting forever.
|
M:System.Threading.ManualResetEventSlim.Wait();Specify a timeout to avoid waiting forever.
|
||||||
M:System.Char.ToLower(System.Char);char.ToLower() changes behaviour depending on CultureInfo.CurrentCulture. Use char.ToLowerInvariant() instead. If wanting culture-sensitive behaviour, explicitly provide CultureInfo.CurrentCulture.
|
|
||||||
M:System.Char.ToUpper(System.Char);char.ToUpper() changes behaviour depending on CultureInfo.CurrentCulture. Use char.ToUpperInvariant() instead. If wanting culture-sensitive behaviour, explicitly provide CultureInfo.CurrentCulture.
|
|
||||||
M:System.String.ToLower();string.ToLower() changes behaviour depending on CultureInfo.CurrentCulture. Use string.ToLowerInvariant() instead. If wanting culture-sensitive behaviour, explicitly provide CultureInfo.CurrentCulture or use LocalisableString.
|
|
||||||
M:System.String.ToUpper();string.ToUpper() changes behaviour depending on CultureInfo.CurrentCulture. Use string.ToUpperInvariant() instead. If wanting culture-sensitive behaviour, explicitly provide CultureInfo.CurrentCulture or use LocalisableString.
|
|
||||||
M:Humanizer.InflectorExtensions.Pascalize(System.String);Humanizer's .Pascalize() extension method changes behaviour depending on CultureInfo.CurrentCulture. Use StringDehumanizeExtensions.ToPascalCase() instead.
|
M:Humanizer.InflectorExtensions.Pascalize(System.String);Humanizer's .Pascalize() extension method changes behaviour depending on CultureInfo.CurrentCulture. Use StringDehumanizeExtensions.ToPascalCase() instead.
|
||||||
M:Humanizer.InflectorExtensions.Camelize(System.String);Humanizer's .Camelize() extension method changes behaviour depending on CultureInfo.CurrentCulture. Use StringDehumanizeExtensions.ToCamelCase() instead.
|
M:Humanizer.InflectorExtensions.Camelize(System.String);Humanizer's .Camelize() extension method changes behaviour depending on CultureInfo.CurrentCulture. Use StringDehumanizeExtensions.ToCamelCase() instead.
|
||||||
M:Humanizer.InflectorExtensions.Underscore(System.String);Humanizer's .Underscore() extension method changes behaviour depending on CultureInfo.CurrentCulture. Use StringDehumanizeExtensions.ToSnakeCase() instead.
|
M:Humanizer.InflectorExtensions.Underscore(System.String);Humanizer's .Underscore() extension method changes behaviour depending on CultureInfo.CurrentCulture. Use StringDehumanizeExtensions.ToSnakeCase() instead.
|
||||||
|
@ -1,58 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<RuleSet Name="osu! Rule Set" Description=" " ToolsVersion="16.0">
|
|
||||||
<Rules AnalyzerId="Microsoft.CodeQuality.Analyzers" RuleNamespace="Microsoft.CodeQuality.Analyzers">
|
|
||||||
<Rule Id="CA1016" Action="None" />
|
|
||||||
<Rule Id="CA1028" Action="None" />
|
|
||||||
<Rule Id="CA1031" Action="None" />
|
|
||||||
<Rule Id="CA1034" Action="None" />
|
|
||||||
<Rule Id="CA1036" Action="None" />
|
|
||||||
<Rule Id="CA1040" Action="None" />
|
|
||||||
<Rule Id="CA1044" Action="None" />
|
|
||||||
<Rule Id="CA1051" Action="None" />
|
|
||||||
<Rule Id="CA1054" Action="None" />
|
|
||||||
<Rule Id="CA1056" Action="None" />
|
|
||||||
<Rule Id="CA1062" Action="None" />
|
|
||||||
<Rule Id="CA1063" Action="None" />
|
|
||||||
<Rule Id="CA1067" Action="None" />
|
|
||||||
<Rule Id="CA1707" Action="None" />
|
|
||||||
<Rule Id="CA1710" Action="None" />
|
|
||||||
<Rule Id="CA1714" Action="None" />
|
|
||||||
<Rule Id="CA1716" Action="None" />
|
|
||||||
<Rule Id="CA1717" Action="None" />
|
|
||||||
<Rule Id="CA1720" Action="None" />
|
|
||||||
<Rule Id="CA1721" Action="None" />
|
|
||||||
<Rule Id="CA1724" Action="None" />
|
|
||||||
<Rule Id="CA1801" Action="None" />
|
|
||||||
<Rule Id="CA1806" Action="None" />
|
|
||||||
<Rule Id="CA1812" Action="None" />
|
|
||||||
<Rule Id="CA1814" Action="None" />
|
|
||||||
<Rule Id="CA1815" Action="None" />
|
|
||||||
<Rule Id="CA1819" Action="None" />
|
|
||||||
<Rule Id="CA1822" Action="None" />
|
|
||||||
<Rule Id="CA1823" Action="None" />
|
|
||||||
<Rule Id="CA2007" Action="Warning" />
|
|
||||||
<Rule Id="CA2214" Action="None" />
|
|
||||||
<Rule Id="CA2227" Action="None" />
|
|
||||||
</Rules>
|
|
||||||
<Rules AnalyzerId="Microsoft.CodeQuality.CSharp.Analyzers" RuleNamespace="Microsoft.CodeQuality.CSharp.Analyzers">
|
|
||||||
<Rule Id="CA1001" Action="None" />
|
|
||||||
<Rule Id="CA1032" Action="None" />
|
|
||||||
</Rules>
|
|
||||||
<Rules AnalyzerId="Microsoft.NetCore.Analyzers" RuleNamespace="Microsoft.NetCore.Analyzers">
|
|
||||||
<Rule Id="CA1303" Action="None" />
|
|
||||||
<Rule Id="CA1304" Action="None" />
|
|
||||||
<Rule Id="CA1305" Action="None" />
|
|
||||||
<Rule Id="CA1307" Action="None" />
|
|
||||||
<Rule Id="CA1308" Action="None" />
|
|
||||||
<Rule Id="CA1816" Action="None" />
|
|
||||||
<Rule Id="CA1826" Action="None" />
|
|
||||||
<Rule Id="CA2000" Action="None" />
|
|
||||||
<Rule Id="CA2008" Action="None" />
|
|
||||||
<Rule Id="CA2213" Action="None" />
|
|
||||||
<Rule Id="CA2235" Action="None" />
|
|
||||||
</Rules>
|
|
||||||
<Rules AnalyzerId="Microsoft.NetCore.CSharp.Analyzers" RuleNamespace="Microsoft.NetCore.CSharp.Analyzers">
|
|
||||||
<Rule Id="CA1309" Action="Warning" />
|
|
||||||
<Rule Id="CA2201" Action="Warning" />
|
|
||||||
</Rules>
|
|
||||||
</RuleSet>
|
|
@ -20,7 +20,17 @@
|
|||||||
<AdditionalFiles Include="$(MSBuildThisFileDirectory)CodeAnalysis\BannedSymbols.txt" />
|
<AdditionalFiles Include="$(MSBuildThisFileDirectory)CodeAnalysis\BannedSymbols.txt" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<PropertyGroup Label="Code Analysis">
|
<PropertyGroup Label="Code Analysis">
|
||||||
<CodeAnalysisRuleSet>$(MSBuildThisFileDirectory)CodeAnalysis\osu.ruleset</CodeAnalysisRuleSet>
|
<AnalysisMode>Default</AnalysisMode>
|
||||||
|
<AnalysisModeDesign>Default</AnalysisModeDesign>
|
||||||
|
<AnalysisModeDocumentation>Recommended</AnalysisModeDocumentation>
|
||||||
|
<AnalysisModeGlobalization>Recommended</AnalysisModeGlobalization>
|
||||||
|
<AnalysisModeInteroperability>Recommended</AnalysisModeInteroperability>
|
||||||
|
<AnalysisModeMaintainability>Recommended</AnalysisModeMaintainability>
|
||||||
|
<AnalysisModeNaming>Default</AnalysisModeNaming>
|
||||||
|
<AnalysisModePerformance>Minimum</AnalysisModePerformance>
|
||||||
|
<AnalysisModeReliability>Recommended</AnalysisModeReliability>
|
||||||
|
<AnalysisModeSecurity>Default</AnalysisModeSecurity>
|
||||||
|
<AnalysisModeUsage>Default</AnalysisModeUsage>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Label="Documentation">
|
<PropertyGroup Label="Documentation">
|
||||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||||
|
@ -164,7 +164,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.Argon
|
|||||||
|
|
||||||
case 1: return colour_cyan;
|
case 1: return colour_cyan;
|
||||||
|
|
||||||
default: throw new ArgumentOutOfRangeException();
|
default: throw new ArgumentOutOfRangeException(nameof(columnIndex));
|
||||||
}
|
}
|
||||||
|
|
||||||
case 3:
|
case 3:
|
||||||
@ -176,7 +176,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.Argon
|
|||||||
|
|
||||||
case 2: return colour_cyan;
|
case 2: return colour_cyan;
|
||||||
|
|
||||||
default: throw new ArgumentOutOfRangeException();
|
default: throw new ArgumentOutOfRangeException(nameof(columnIndex));
|
||||||
}
|
}
|
||||||
|
|
||||||
case 4:
|
case 4:
|
||||||
@ -190,7 +190,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.Argon
|
|||||||
|
|
||||||
case 3: return colour_purple;
|
case 3: return colour_purple;
|
||||||
|
|
||||||
default: throw new ArgumentOutOfRangeException();
|
default: throw new ArgumentOutOfRangeException(nameof(columnIndex));
|
||||||
}
|
}
|
||||||
|
|
||||||
case 5:
|
case 5:
|
||||||
@ -206,7 +206,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.Argon
|
|||||||
|
|
||||||
case 4: return colour_cyan;
|
case 4: return colour_cyan;
|
||||||
|
|
||||||
default: throw new ArgumentOutOfRangeException();
|
default: throw new ArgumentOutOfRangeException(nameof(columnIndex));
|
||||||
}
|
}
|
||||||
|
|
||||||
case 6:
|
case 6:
|
||||||
@ -224,7 +224,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.Argon
|
|||||||
|
|
||||||
case 5: return colour_pink;
|
case 5: return colour_pink;
|
||||||
|
|
||||||
default: throw new ArgumentOutOfRangeException();
|
default: throw new ArgumentOutOfRangeException(nameof(columnIndex));
|
||||||
}
|
}
|
||||||
|
|
||||||
case 7:
|
case 7:
|
||||||
@ -244,7 +244,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.Argon
|
|||||||
|
|
||||||
case 6: return colour_pink;
|
case 6: return colour_pink;
|
||||||
|
|
||||||
default: throw new ArgumentOutOfRangeException();
|
default: throw new ArgumentOutOfRangeException(nameof(columnIndex));
|
||||||
}
|
}
|
||||||
|
|
||||||
case 8:
|
case 8:
|
||||||
@ -266,7 +266,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.Argon
|
|||||||
|
|
||||||
case 7: return colour_purple;
|
case 7: return colour_purple;
|
||||||
|
|
||||||
default: throw new ArgumentOutOfRangeException();
|
default: throw new ArgumentOutOfRangeException(nameof(columnIndex));
|
||||||
}
|
}
|
||||||
|
|
||||||
case 9:
|
case 9:
|
||||||
@ -290,7 +290,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.Argon
|
|||||||
|
|
||||||
case 8: return colour_purple;
|
case 8: return colour_purple;
|
||||||
|
|
||||||
default: throw new ArgumentOutOfRangeException();
|
default: throw new ArgumentOutOfRangeException(nameof(columnIndex));
|
||||||
}
|
}
|
||||||
|
|
||||||
case 10:
|
case 10:
|
||||||
@ -316,7 +316,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.Argon
|
|||||||
|
|
||||||
case 9: return colour_purple;
|
case 9: return colour_purple;
|
||||||
|
|
||||||
default: throw new ArgumentOutOfRangeException();
|
default: throw new ArgumentOutOfRangeException(nameof(columnIndex));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -339,7 +339,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.Argon
|
|||||||
|
|
||||||
case 5: return colour_green;
|
case 5: return colour_green;
|
||||||
|
|
||||||
default: throw new ArgumentOutOfRangeException();
|
default: throw new ArgumentOutOfRangeException(nameof(columnIndex));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
7
osu.Game.Tests/CodeAnalysis.tests.globalconfig
Normal file
7
osu.Game.Tests/CodeAnalysis.tests.globalconfig
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
# Higher global_level has higher priority, the default global_level
|
||||||
|
# is 100 for root .globalconfig and 0 for others
|
||||||
|
# https://learn.microsoft.com/dotnet/fundamentals/code-analysis/configuration-files#precedence
|
||||||
|
is_global = true
|
||||||
|
global_level = 101
|
||||||
|
|
||||||
|
dotnet_diagnostic.CA2007.severity = none
|
@ -221,7 +221,7 @@ namespace osu.Game.Tests.Visual.Gameplay
|
|||||||
string? filePath = null;
|
string? filePath = null;
|
||||||
|
|
||||||
// Files starting with _ are temporary, created by CreateFileSafely call.
|
// Files starting with _ are temporary, created by CreateFileSafely call.
|
||||||
AddUntilStep("wait for export file", () => filePath = LocalStorage.GetFiles("exports").SingleOrDefault(f => !Path.GetFileName(f).StartsWith("_", StringComparison.Ordinal)), () => Is.Not.Null);
|
AddUntilStep("wait for export file", () => filePath = LocalStorage.GetFiles("exports").SingleOrDefault(f => !Path.GetFileName(f).StartsWith('_')), () => Is.Not.Null);
|
||||||
AddUntilStep("filesize is non-zero", () =>
|
AddUntilStep("filesize is non-zero", () =>
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
@ -198,7 +198,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
|
|
||||||
AddStep("make second user host", () => MultiplayerClient.TransferHost(3));
|
AddStep("make second user host", () => MultiplayerClient.TransferHost(3));
|
||||||
|
|
||||||
AddUntilStep("kick buttons not visible", () => this.ChildrenOfType<ParticipantPanel.KickButton>().Count(d => d.IsPresent) == 0);
|
AddUntilStep("kick buttons not visible", () => !this.ChildrenOfType<ParticipantPanel.KickButton>().Any(d => d.IsPresent));
|
||||||
|
|
||||||
AddStep("make local user host again", () => MultiplayerClient.TransferHost(API.LocalUser.Value.Id));
|
AddStep("make local user host again", () => MultiplayerClient.TransferHost(API.LocalUser.Value.Id));
|
||||||
|
|
||||||
|
@ -151,7 +151,7 @@ namespace osu.Game.Tests.Visual.UserInterface
|
|||||||
|
|
||||||
AddStep("click delete option", () =>
|
AddStep("click delete option", () =>
|
||||||
{
|
{
|
||||||
InputManager.MoveMouseTo(contextMenuContainer.ChildrenOfType<DrawableOsuMenuItem>().First(i => i.Item.Text.Value.ToString().ToLowerInvariant() == "delete"));
|
InputManager.MoveMouseTo(contextMenuContainer.ChildrenOfType<DrawableOsuMenuItem>().First(i => string.Equals(i.Item.Text.Value.ToString(), "delete", System.StringComparison.OrdinalIgnoreCase)));
|
||||||
InputManager.Click(MouseButton.Left);
|
InputManager.Click(MouseButton.Left);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -12,9 +12,9 @@
|
|||||||
<OutputType>WinExe</OutputType>
|
<OutputType>WinExe</OutputType>
|
||||||
<TargetFramework>net8.0</TargetFramework>
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Label="Code Analysis">
|
<ItemGroup Label="Code Analysis">
|
||||||
<CodeAnalysisRuleSet>tests.ruleset</CodeAnalysisRuleSet>
|
<GlobalAnalyzerConfigFiles Include="CodeAnalysis.tests.globalconfig" />
|
||||||
</PropertyGroup>
|
</ItemGroup>
|
||||||
<ItemGroup Label="Project References">
|
<ItemGroup Label="Project References">
|
||||||
<ProjectReference Include="..\osu.Game.Rulesets.Osu\osu.Game.Rulesets.Osu.csproj" />
|
<ProjectReference Include="..\osu.Game.Rulesets.Osu\osu.Game.Rulesets.Osu.csproj" />
|
||||||
<ProjectReference Include="..\osu.Game.Rulesets.Catch\osu.Game.Rulesets.Catch.csproj" />
|
<ProjectReference Include="..\osu.Game.Rulesets.Catch\osu.Game.Rulesets.Catch.csproj" />
|
||||||
|
@ -1,6 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<RuleSet Name="osu! Rule Set" Description=" " ToolsVersion="16.0">
|
|
||||||
<Rules AnalyzerId="Microsoft.CodeQuality.Analyzers" RuleNamespace="Microsoft.CodeQuality.Analyzers">
|
|
||||||
<Rule Id="CA2007" Action="None" />
|
|
||||||
</Rules>
|
|
||||||
</RuleSet>
|
|
@ -248,29 +248,30 @@ namespace osu.Game.Database
|
|||||||
return new RealmLive<T>(realmObject, realm);
|
return new RealmLive<T>(realmObject, realm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#pragma warning disable RS0030 // mentioning banned symbols in documentation
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Register a callback to be invoked each time this <see cref="T:Realms.IRealmCollection`1" /> changes.
|
/// Register a callback to be invoked each time this <see cref="IRealmCollection{T}" /> changes.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// <para>
|
/// <para>
|
||||||
/// This adds osu! specific thread and managed state safety checks on top of <see cref="IRealmCollection{T}.SubscribeForNotifications"/>.
|
/// This adds osu! specific thread and managed state safety checks on top of <see cref="IRealmCollection{T}.SubscribeForNotifications"/>.
|
||||||
/// </para>
|
/// </para>
|
||||||
/// <para>
|
/// <para>
|
||||||
/// The first callback will be invoked with the initial <see cref="T:Realms.IRealmCollection`1" /> after the asynchronous query completes,
|
/// The first callback will be invoked with the initial <see cref="IRealmCollection{T}" /> after the asynchronous query completes,
|
||||||
/// and then called again after each write transaction which changes either any of the objects in the collection, or
|
/// and then called again after each write transaction which changes either any of the objects in the collection, or
|
||||||
/// which objects are in the collection. The <c>changes</c> parameter will
|
/// which objects are in the collection. The <c>changes</c> parameter will
|
||||||
/// be <c>null</c> the first time the callback is invoked with the initial results. For each call after that,
|
/// be <c>null</c> the first time the callback is invoked with the initial results. For each call after that,
|
||||||
/// it will contain information about which rows in the results were added, removed or modified.
|
/// it will contain information about which rows in the results were added, removed or modified.
|
||||||
/// </para>
|
/// </para>
|
||||||
/// <para>
|
/// <para>
|
||||||
/// If a write transaction did not modify any objects in this <see cref="T:Realms.IRealmCollection`1" />, the callback is not invoked at all.
|
/// If a write transaction did not modify any objects in this <see cref="IRealmCollection{T}" />, the callback is not invoked at all.
|
||||||
/// If an error occurs the callback will be invoked with <c>null</c> for the <c>sender</c> parameter and a non-<c>null</c> <c>error</c>.
|
/// If an error occurs the callback will be invoked with <c>null</c> for the <c>sender</c> parameter and a non-<c>null</c> <c>error</c>.
|
||||||
/// Currently the only errors that can occur are when opening the <see cref="T:Realms.Realm" /> on the background worker thread.
|
/// Currently the only errors that can occur are when opening the <see cref="Realm" /> on the background worker thread.
|
||||||
/// </para>
|
/// </para>
|
||||||
/// <para>
|
/// <para>
|
||||||
/// At the time when the block is called, the <see cref="T:Realms.IRealmCollection`1" /> object will be fully evaluated
|
/// At the time when the block is called, the <see cref="IRealmCollection{T}" /> object will be fully evaluated
|
||||||
/// and up-to-date, and as long as you do not perform a write transaction on the same thread
|
/// and up-to-date, and as long as you do not perform a write transaction on the same thread
|
||||||
/// or explicitly call <see cref="M:Realms.Realm.Refresh" />, accessing it will never perform blocking work.
|
/// or explicitly call <see cref="Realm.Refresh" />, accessing it will never perform blocking work.
|
||||||
/// </para>
|
/// </para>
|
||||||
/// <para>
|
/// <para>
|
||||||
/// Notifications are delivered via the standard event loop, and so can't be delivered while the event loop is blocked by other activity.
|
/// Notifications are delivered via the standard event loop, and so can't be delivered while the event loop is blocked by other activity.
|
||||||
@ -279,13 +280,14 @@ namespace osu.Game.Database
|
|||||||
/// </para>
|
/// </para>
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
/// <param name="collection">The <see cref="IRealmCollection{T}"/> to observe for changes.</param>
|
/// <param name="collection">The <see cref="IRealmCollection{T}"/> to observe for changes.</param>
|
||||||
/// <param name="callback">The callback to be invoked with the updated <see cref="T:Realms.IRealmCollection`1" />.</param>
|
/// <param name="callback">The callback to be invoked with the updated <see cref="IRealmCollection{T}" />.</param>
|
||||||
/// <returns>
|
/// <returns>
|
||||||
/// A subscription token. It must be kept alive for as long as you want to receive change notifications.
|
/// A subscription token. It must be kept alive for as long as you want to receive change notifications.
|
||||||
/// To stop receiving notifications, call <see cref="M:System.IDisposable.Dispose" />.
|
/// To stop receiving notifications, call <see cref="IDisposable.Dispose" />.
|
||||||
/// </returns>
|
/// </returns>
|
||||||
/// <seealso cref="M:Realms.CollectionExtensions.SubscribeForNotifications``1(System.Collections.Generic.IList{``0},Realms.NotificationCallbackDelegate{``0})" />
|
/// <seealso cref="Realms.CollectionExtensions.SubscribeForNotifications{T}(IList{T}, NotificationCallbackDelegate{T})" />
|
||||||
/// <seealso cref="M:Realms.CollectionExtensions.SubscribeForNotifications``1(System.Linq.IQueryable{``0},Realms.NotificationCallbackDelegate{``0})" />
|
/// <seealso cref="Realms.CollectionExtensions.SubscribeForNotifications{T}(IQueryable{T}, NotificationCallbackDelegate{T})" />
|
||||||
|
#pragma warning restore RS0030
|
||||||
public static IDisposable QueryAsyncWithNotifications<T>(this IRealmCollection<T> collection, NotificationCallbackDelegate<T> callback)
|
public static IDisposable QueryAsyncWithNotifications<T>(this IRealmCollection<T> collection, NotificationCallbackDelegate<T> callback)
|
||||||
where T : RealmObjectBase
|
where T : RealmObjectBase
|
||||||
{
|
{
|
||||||
|
@ -60,7 +60,7 @@ namespace osu.Game.Extensions
|
|||||||
public static string ToCamelCase(this string input)
|
public static string ToCamelCase(this string input)
|
||||||
{
|
{
|
||||||
string word = input.ToPascalCase();
|
string word = input.ToPascalCase();
|
||||||
return word.Length > 0 ? word.Substring(0, 1).ToLowerInvariant() + word.Substring(1) : word;
|
return word.Length > 0 ? char.ToLowerInvariant(word[0]) + word.Substring(1) : word;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -44,6 +44,11 @@ namespace osu.Game.Localisation
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static LocalisableString CheckUpdate => new TranslatableString(getKey(@"check_update"), @"Check for updates");
|
public static LocalisableString CheckUpdate => new TranslatableString(getKey(@"check_update"), @"Check for updates");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// "Checking for updates"
|
||||||
|
/// </summary>
|
||||||
|
public static LocalisableString CheckingForUpdates => new TranslatableString(getKey(@"checking_for_updates"), @"Checking for updates");
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// "Open osu! folder"
|
/// "Open osu! folder"
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -363,7 +363,7 @@ namespace osu.Game.Online.Leaderboards
|
|||||||
return null;
|
return null;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw new ArgumentOutOfRangeException();
|
throw new ArgumentOutOfRangeException(nameof(state));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,7 +87,7 @@ namespace osu.Game.Online
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw new ArgumentOutOfRangeException();
|
throw new ArgumentOutOfRangeException(nameof(state.NewValue));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -126,7 +126,7 @@ namespace osu.Game.Overlays
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw new ArgumentOutOfRangeException();
|
throw new ArgumentOutOfRangeException(nameof(state.NewValue));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -386,10 +386,8 @@ namespace osu.Game.Overlays
|
|||||||
{
|
{
|
||||||
channelList.RemoveChannel(channel);
|
channelList.RemoveChannel(channel);
|
||||||
|
|
||||||
if (loadedChannels.ContainsKey(channel))
|
if (loadedChannels.Remove(channel, out var loaded))
|
||||||
{
|
{
|
||||||
DrawableChannel loaded = loadedChannels[channel];
|
|
||||||
loadedChannels.Remove(channel);
|
|
||||||
// DrawableChannel removed from cache must be manually disposed
|
// DrawableChannel removed from cache must be manually disposed
|
||||||
loaded.Dispose();
|
loaded.Dispose();
|
||||||
}
|
}
|
||||||
|
@ -244,7 +244,7 @@ namespace osu.Game.Overlays.Comments
|
|||||||
protected void OnSuccess(CommentBundle response)
|
protected void OnSuccess(CommentBundle response)
|
||||||
{
|
{
|
||||||
commentCounter.Current.Value = response.Total;
|
commentCounter.Current.Value = response.Total;
|
||||||
newCommentEditor.CommentableMeta.Value = response.CommentableMeta.SingleOrDefault(m => m.Id == id.Value && m.Type == type.Value.ToString().ToSnakeCase().ToLowerInvariant());
|
newCommentEditor.CommentableMeta.Value = response.CommentableMeta.SingleOrDefault(m => m.Id == id.Value && string.Equals(m.Type, type.Value.ToString().ToSnakeCase(), StringComparison.OrdinalIgnoreCase));
|
||||||
|
|
||||||
if (!response.Comments.Any())
|
if (!response.Comments.Any())
|
||||||
{
|
{
|
||||||
|
@ -4,7 +4,6 @@
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using osu.Framework;
|
using osu.Framework;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Extensions;
|
|
||||||
using osu.Framework.Graphics.Sprites;
|
using osu.Framework.Graphics.Sprites;
|
||||||
using osu.Framework.Localisation;
|
using osu.Framework.Localisation;
|
||||||
using osu.Framework.Logging;
|
using osu.Framework.Logging;
|
||||||
@ -13,6 +12,7 @@ using osu.Framework.Screens;
|
|||||||
using osu.Framework.Statistics;
|
using osu.Framework.Statistics;
|
||||||
using osu.Game.Configuration;
|
using osu.Game.Configuration;
|
||||||
using osu.Game.Localisation;
|
using osu.Game.Localisation;
|
||||||
|
using osu.Game.Online.Multiplayer;
|
||||||
using osu.Game.Overlays.Notifications;
|
using osu.Game.Overlays.Notifications;
|
||||||
using osu.Game.Overlays.Settings.Sections.Maintenance;
|
using osu.Game.Overlays.Settings.Sections.Maintenance;
|
||||||
using osu.Game.Updater;
|
using osu.Game.Updater;
|
||||||
@ -36,8 +36,11 @@ namespace osu.Game.Overlays.Settings.Sections.General
|
|||||||
[Resolved]
|
[Resolved]
|
||||||
private Storage storage { get; set; } = null!;
|
private Storage storage { get; set; } = null!;
|
||||||
|
|
||||||
|
[Resolved]
|
||||||
|
private OsuGame? game { get; set; }
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load(OsuConfigManager config, OsuGame? game)
|
private void load(OsuConfigManager config)
|
||||||
{
|
{
|
||||||
Add(new SettingsEnumDropdown<ReleaseStream>
|
Add(new SettingsEnumDropdown<ReleaseStream>
|
||||||
{
|
{
|
||||||
@ -50,23 +53,7 @@ namespace osu.Game.Overlays.Settings.Sections.General
|
|||||||
Add(checkForUpdatesButton = new SettingsButton
|
Add(checkForUpdatesButton = new SettingsButton
|
||||||
{
|
{
|
||||||
Text = GeneralSettingsStrings.CheckUpdate,
|
Text = GeneralSettingsStrings.CheckUpdate,
|
||||||
Action = () =>
|
Action = () => checkForUpdates().FireAndForget()
|
||||||
{
|
|
||||||
checkForUpdatesButton.Enabled.Value = false;
|
|
||||||
Task.Run(updateManager.CheckForUpdateAsync).ContinueWith(task => Schedule(() =>
|
|
||||||
{
|
|
||||||
if (!task.GetResultSafely())
|
|
||||||
{
|
|
||||||
notifications?.Post(new SimpleNotification
|
|
||||||
{
|
|
||||||
Text = GeneralSettingsStrings.RunningLatestRelease(game!.Version),
|
|
||||||
Icon = FontAwesome.Solid.CheckCircle,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
checkForUpdatesButton.Enabled.Value = true;
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -94,6 +81,44 @@ namespace osu.Game.Overlays.Settings.Sections.General
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task checkForUpdates()
|
||||||
|
{
|
||||||
|
if (updateManager == null || game == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
checkForUpdatesButton.Enabled.Value = false;
|
||||||
|
|
||||||
|
var checkingNotification = new ProgressNotification
|
||||||
|
{
|
||||||
|
Text = GeneralSettingsStrings.CheckingForUpdates,
|
||||||
|
};
|
||||||
|
notifications?.Post(checkingNotification);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
bool foundUpdate = await updateManager.CheckForUpdateAsync().ConfigureAwait(true);
|
||||||
|
|
||||||
|
if (!foundUpdate)
|
||||||
|
{
|
||||||
|
notifications?.Post(new SimpleNotification
|
||||||
|
{
|
||||||
|
Text = GeneralSettingsStrings.RunningLatestRelease(game.Version),
|
||||||
|
Icon = FontAwesome.Solid.CheckCircle,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
// This sequence allows the notification to be immediately dismissed.
|
||||||
|
checkingNotification.State = ProgressNotificationState.Cancelled;
|
||||||
|
checkingNotification.Close(false);
|
||||||
|
checkForUpdatesButton.Enabled.Value = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void exportLogs()
|
private void exportLogs()
|
||||||
{
|
{
|
||||||
ProgressNotification notification = new ProgressNotification
|
ProgressNotification notification = new ProgressNotification
|
||||||
|
@ -130,7 +130,7 @@ namespace osu.Game.Overlays.Toolbar
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw new ArgumentOutOfRangeException();
|
throw new ArgumentOutOfRangeException(nameof(state.NewValue));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -173,10 +173,10 @@ namespace osu.Game.Rulesets.Mods
|
|||||||
};
|
};
|
||||||
drawable.OnRevertResult += (_, result) =>
|
drawable.OnRevertResult += (_, result) =>
|
||||||
{
|
{
|
||||||
if (!ratesForRewinding.ContainsKey(result.HitObject)) return;
|
if (!ratesForRewinding.TryGetValue(result.HitObject, out double rate)) return;
|
||||||
if (!shouldProcessResult(result)) return;
|
if (!shouldProcessResult(result)) return;
|
||||||
|
|
||||||
recentRates.Insert(0, ratesForRewinding[result.HitObject]);
|
recentRates.Insert(0, rate);
|
||||||
ratesForRewinding.Remove(result.HitObject);
|
ratesForRewinding.Remove(result.HitObject);
|
||||||
|
|
||||||
recentRates.RemoveAt(recentRates.Count - 1);
|
recentRates.RemoveAt(recentRates.Count - 1);
|
||||||
|
@ -243,7 +243,7 @@ namespace osu.Game.Rulesets.Objects.Legacy
|
|||||||
return PathType.CATMULL;
|
return PathType.CATMULL;
|
||||||
|
|
||||||
case 'B':
|
case 'B':
|
||||||
if (input.Length > 1 && int.TryParse(input.Substring(1), out int degree) && degree > 0)
|
if (input.Length > 1 && int.TryParse(input.AsSpan(1), out int degree) && degree > 0)
|
||||||
return PathType.BSpline(degree);
|
return PathType.BSpline(degree);
|
||||||
|
|
||||||
return PathType.BEZIER;
|
return PathType.BEZIER;
|
||||||
|
@ -59,14 +59,14 @@ namespace osu.Game.Screens.Ranking.Statistics.User
|
|||||||
new SimpleStatisticTable.Spacer(),
|
new SimpleStatisticTable.Spacer(),
|
||||||
new PerformancePointsChangeRow { StatisticsUpdate = { BindTarget = StatisticsUpdate } },
|
new PerformancePointsChangeRow { StatisticsUpdate = { BindTarget = StatisticsUpdate } },
|
||||||
},
|
},
|
||||||
new Drawable[] { },
|
[],
|
||||||
new Drawable[]
|
new Drawable[]
|
||||||
{
|
{
|
||||||
new MaximumComboChangeRow { StatisticsUpdate = { BindTarget = StatisticsUpdate } },
|
new MaximumComboChangeRow { StatisticsUpdate = { BindTarget = StatisticsUpdate } },
|
||||||
new SimpleStatisticTable.Spacer(),
|
new SimpleStatisticTable.Spacer(),
|
||||||
new AccuracyChangeRow { StatisticsUpdate = { BindTarget = StatisticsUpdate } },
|
new AccuracyChangeRow { StatisticsUpdate = { BindTarget = StatisticsUpdate } },
|
||||||
},
|
},
|
||||||
new Drawable[] { },
|
[],
|
||||||
new Drawable[]
|
new Drawable[]
|
||||||
{
|
{
|
||||||
new RankedScoreChangeRow { StatisticsUpdate = { BindTarget = StatisticsUpdate } },
|
new RankedScoreChangeRow { StatisticsUpdate = { BindTarget = StatisticsUpdate } },
|
||||||
|
@ -37,7 +37,7 @@ namespace osu.Game.Skinning
|
|||||||
|
|
||||||
protected override string[] HashableFileTypes => new[] { ".ini", ".json" };
|
protected override string[] HashableFileTypes => new[] { ".ini", ".json" };
|
||||||
|
|
||||||
protected override bool ShouldDeleteArchive(string path) => Path.GetExtension(path).ToLowerInvariant() == @".osk";
|
protected override bool ShouldDeleteArchive(string path) => string.Equals(Path.GetExtension(path), @".osk", StringComparison.OrdinalIgnoreCase);
|
||||||
|
|
||||||
protected override SkinInfo CreateModel(ArchiveReader archive, ImportParameters parameters) => new SkinInfo { Name = archive.Name ?? @"No name" };
|
protected override SkinInfo CreateModel(ArchiveReader archive, ImportParameters parameters) => new SkinInfo { Name = archive.Name ?? @"No name" };
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
// See the LICENCE file in the repository root for full licence text.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
@ -91,7 +92,7 @@ namespace osu.Game.Storyboards
|
|||||||
// Importantly, do this after the NullOrEmpty because EF may have stored the non-nullable value as null to the database, bypassing compile-time constraints.
|
// Importantly, do this after the NullOrEmpty because EF may have stored the non-nullable value as null to the database, bypassing compile-time constraints.
|
||||||
backgroundPath = backgroundPath.ToLowerInvariant();
|
backgroundPath = backgroundPath.ToLowerInvariant();
|
||||||
|
|
||||||
return GetLayer("Background").Elements.Any(e => e.Path.ToLowerInvariant() == backgroundPath);
|
return GetLayer("Background").Elements.Any(e => string.Equals(e.Path, backgroundPath, StringComparison.OrdinalIgnoreCase));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,12 +78,12 @@ namespace osu.Game.Tests.Visual.Spectator
|
|||||||
/// <param name="state">The spectator state to end play with.</param>
|
/// <param name="state">The spectator state to end play with.</param>
|
||||||
public void SendEndPlay(int userId, SpectatedUserState state = SpectatedUserState.Quit)
|
public void SendEndPlay(int userId, SpectatedUserState state = SpectatedUserState.Quit)
|
||||||
{
|
{
|
||||||
if (!userBeatmapDictionary.TryGetValue(userId, out int value))
|
if (!userBeatmapDictionary.TryGetValue(userId, out int beatmapId))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
((ISpectatorClient)this).UserFinishedPlaying(userId, new SpectatorState
|
((ISpectatorClient)this).UserFinishedPlaying(userId, new SpectatorState
|
||||||
{
|
{
|
||||||
BeatmapID = value,
|
BeatmapID = beatmapId,
|
||||||
RulesetID = 0,
|
RulesetID = 0,
|
||||||
Mods = userModsDictionary[userId],
|
Mods = userModsDictionary[userId],
|
||||||
State = state
|
State = state
|
||||||
|
@ -666,10 +666,7 @@ namespace osu.Game.Utils
|
|||||||
{
|
{
|
||||||
// 2020-10-07 jbialogrodzki #730 Since this is public API we should probably
|
// 2020-10-07 jbialogrodzki #730 Since this is public API we should probably
|
||||||
// handle null arguments? It doesn't seem to have been done consistently in this class though.
|
// handle null arguments? It doesn't seem to have been done consistently in this class though.
|
||||||
if (coefficients == null)
|
ArgumentNullException.ThrowIfNull(coefficients);
|
||||||
{
|
|
||||||
throw new ArgumentNullException(nameof(coefficients));
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2020-10-07 jbialogrodzki #730 Zero polynomials need explicit handling.
|
// 2020-10-07 jbialogrodzki #730 Zero polynomials need explicit handling.
|
||||||
// Without this check, we attempted to peek coefficients at negative indices!
|
// Without this check, we attempted to peek coefficients at negative indices!
|
||||||
|
2
osu.sln
2
osu.sln
@ -60,7 +60,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
|
|||||||
Directory.Build.props = Directory.Build.props
|
Directory.Build.props = Directory.Build.props
|
||||||
osu.Android.props = osu.Android.props
|
osu.Android.props = osu.Android.props
|
||||||
osu.iOS.props = osu.iOS.props
|
osu.iOS.props = osu.iOS.props
|
||||||
CodeAnalysis\osu.ruleset = CodeAnalysis\osu.ruleset
|
global.json = global.json
|
||||||
osu.sln.DotSettings = osu.sln.DotSettings
|
osu.sln.DotSettings = osu.sln.DotSettings
|
||||||
osu.TestProject.props = osu.TestProject.props
|
osu.TestProject.props = osu.TestProject.props
|
||||||
EndProjectSection
|
EndProjectSection
|
||||||
|
Loading…
Reference in New Issue
Block a user