mirror of
https://github.com/Pathoschild/SMAPI.git
synced 2026-10-12 02:08:51 +00:00
avoid Any() on warmer paths
This is typically much slower than equivalent manual checks.
This commit is contained in:
@@ -80,7 +80,7 @@ public class ChangeDescriptor
|
||||
this.Apply(values);
|
||||
|
||||
// format
|
||||
if (rawField == null && !values.Any())
|
||||
if (rawField == null && values.Count == 0)
|
||||
return null;
|
||||
return string.Join(", ", values);
|
||||
}
|
||||
@@ -91,7 +91,7 @@ public class ChangeDescriptor
|
||||
public void Apply(List<string> values)
|
||||
{
|
||||
// replace/remove values
|
||||
if (this.Replace.Any() || this.Remove.Any())
|
||||
if (this.Replace.Count > 0 || this.Remove.Count > 0)
|
||||
{
|
||||
for (int i = values.Count - 1; i >= 0; i--)
|
||||
{
|
||||
@@ -106,7 +106,7 @@ public class ChangeDescriptor
|
||||
}
|
||||
|
||||
// add values
|
||||
if (this.Add.Any())
|
||||
if (this.Add.Count > 0)
|
||||
{
|
||||
HashSet<string> curValues = new(values.Select(p => p.Trim()), StringComparer.OrdinalIgnoreCase);
|
||||
foreach (string add in this.Add)
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using StardewModdingAPI.Toolkit.Utilities;
|
||||
|
||||
namespace StardewModdingAPI.Toolkit.Framework;
|
||||
@@ -37,7 +36,7 @@ public static class ManifestValidator
|
||||
// validate EntryDll/ContentPackFor format
|
||||
if (hasDll)
|
||||
{
|
||||
if (manifest.EntryDll!.Intersect(Path.GetInvalidFileNameChars()).Any())
|
||||
if (manifest.EntryDll!.IndexOfAny(Path.GetInvalidFileNameChars()) > -1)
|
||||
{
|
||||
error = $"manifest has invalid filename '{manifest.EntryDll}' for the {nameof(IManifest.EntryDll)} field.";
|
||||
return false;
|
||||
@@ -63,7 +62,7 @@ public static class ManifestValidator
|
||||
if (string.IsNullOrWhiteSpace(manifest.UniqueID))
|
||||
missingFields.Add(nameof(IManifest.UniqueID));
|
||||
|
||||
if (missingFields.Any())
|
||||
if (missingFields.Count > 0)
|
||||
{
|
||||
error = $"manifest is missing required fields ({string.Join(", ", missingFields)}).";
|
||||
return false;
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
using System.Linq;
|
||||
|
||||
namespace StardewModdingAPI.Toolkit.Framework.ModData;
|
||||
|
||||
/// <summary>A versioned mod metadata field.</summary>
|
||||
@@ -66,7 +64,13 @@ public class ModDataField
|
||||
{
|
||||
// update key
|
||||
case ModDataFieldKey.UpdateKey:
|
||||
return manifest.UpdateKeys.Any(p => !string.IsNullOrWhiteSpace(p));
|
||||
foreach (string updateKey in manifest.UpdateKeys)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(updateKey))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
// non-manifest fields
|
||||
case ModDataFieldKey.StatusReasonPhrase:
|
||||
|
||||
@@ -138,7 +138,7 @@ public class ModScanner
|
||||
return new ModFolder(root, searchFolder, ModType.Invalid, null, ModParseError.EmptyVortexFolder, "it's an empty Vortex folder (is the mod disabled in Vortex?).");
|
||||
|
||||
// empty folder
|
||||
if (!relevantFiles.Any())
|
||||
if (relevantFiles.Length == 0)
|
||||
return new ModFolder(root, searchFolder, ModType.Invalid, null, ModParseError.EmptyFolder, "it's an empty folder.");
|
||||
|
||||
// XNB mod
|
||||
@@ -290,7 +290,7 @@ public class ModScanner
|
||||
|
||||
DirectoryInfo[] subfolders = folder.GetDirectories().Where(this.IsRelevant).ToArray();
|
||||
FileInfo[] files = folder.GetFiles().Where(this.IsRelevant).ToArray();
|
||||
return subfolders.Any() && !files.Any();
|
||||
return subfolders.Length > 0 && files.Length == 0;
|
||||
}
|
||||
|
||||
/// <summary>Recursively get all files in a folder.</summary>
|
||||
@@ -320,7 +320,13 @@ public class ModScanner
|
||||
return false;
|
||||
|
||||
// ignored entry name
|
||||
return !this.IgnoreFilesystemNames.Any(p => p.IsMatch(entry.Name));
|
||||
foreach (Regex rule in this.IgnoreFilesystemNames)
|
||||
{
|
||||
if (rule.IsMatch(entry.Name))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>Get whether a set of files looks like an XNB mod.</summary>
|
||||
|
||||
@@ -93,7 +93,7 @@ public static class PathUtilities
|
||||
}
|
||||
|
||||
// keep trailing separator
|
||||
if ((!hasRoot || segments.Any()) && PathUtilities.PossiblePathSeparators.Contains(path[path.Length - 1]))
|
||||
if ((!hasRoot || segments.Length > 0) && PathUtilities.PossiblePathSeparators.Contains(path[path.Length - 1]))
|
||||
newPath += PathUtilities.PreferredPathSeparator;
|
||||
|
||||
return newPath;
|
||||
|
||||
@@ -10,6 +10,7 @@ using StardewModdingAPI.Framework.ModLoading;
|
||||
using StardewModdingAPI.Toolkit.Framework;
|
||||
using StardewModdingAPI.Toolkit.Utilities;
|
||||
using StardewValley;
|
||||
using StardewValley.Extensions;
|
||||
|
||||
namespace StardewModdingAPI;
|
||||
|
||||
@@ -298,7 +299,7 @@ public static class Constants
|
||||
/// <param name="targetPlatform">The target game platform.</param>
|
||||
internal static PlatformAssemblyMap GetAssemblyMap(Platform targetPlatform)
|
||||
{
|
||||
var removeAssemblyReferences = new List<string>();
|
||||
var removeAssemblyReferences = new HashSet<string>();
|
||||
var targetAssemblies = new List<Assembly>();
|
||||
|
||||
// get assembly renamed in SMAPI 3.0
|
||||
|
||||
@@ -4,7 +4,6 @@ using System.Diagnostics.CodeAnalysis;
|
||||
using System.Diagnostics.Contracts;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using Microsoft.Xna.Framework.Content;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
@@ -199,7 +198,7 @@ internal abstract class BaseContentManager : LocalizedContentManager, IContentMa
|
||||
// throwing other types like ArgumentException here.
|
||||
if (string.IsNullOrWhiteSpace(assetName))
|
||||
throw new SContentLoadException(ContentLoadErrorType.InvalidName, "The asset key or local path is empty.");
|
||||
if (assetName.Intersect(Path.GetInvalidPathChars()).Any())
|
||||
if (assetName.IndexOfAny(Path.GetInvalidPathChars()) > -1)
|
||||
throw new SContentLoadException(ContentLoadErrorType.InvalidName, "The asset key or local path contains invalid characters.");
|
||||
|
||||
return this.Cache.NormalizeKey(assetName);
|
||||
|
||||
@@ -312,8 +312,13 @@ internal sealed class ModContentManager : BaseContentManager
|
||||
/// <exception cref="SContentLoadException">The <typeparamref name="TAsset"/> is not compatible with any of the <paramref name="validTypes"/>.</exception>
|
||||
private void AssertValidType<TAsset>(IAssetName assetName, FileInfo file, params Type[] validTypes)
|
||||
{
|
||||
if (!validTypes.Any(validType => validType.IsAssignableFrom(typeof(TAsset))))
|
||||
this.ThrowLoadError(assetName, ContentLoadErrorType.InvalidData, $"can't read file with extension '{file.Extension}' as type '{typeof(TAsset)}'; must be type '{string.Join("' or '", validTypes.Select(p => p.FullName))}'.");
|
||||
foreach (Type type in validTypes)
|
||||
{
|
||||
if (type.IsAssignableFrom(typeof(TAsset)))
|
||||
return;
|
||||
}
|
||||
|
||||
this.ThrowLoadError(assetName, ContentLoadErrorType.InvalidData, $"can't read file with extension '{file.Extension}' as type '{typeof(TAsset)}'; must be type '{string.Join("' or '", validTypes.Select(p => p.FullName))}'.");
|
||||
}
|
||||
|
||||
/// <summary>Throw an error which indicates that an asset couldn't be loaded.</summary>
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using StardewModdingAPI.Events;
|
||||
using StardewModdingAPI.Framework.Extensions;
|
||||
@@ -174,7 +173,17 @@ internal class ManagedEvent<TEventArgs> : IManagedEvent
|
||||
{
|
||||
// recheck priorities
|
||||
if (this.HasRemovedHandlers)
|
||||
this.HasPriorities = this.Handlers.Any(p => p.Priority != EventPriority.Normal);
|
||||
{
|
||||
this.HasPriorities = false;
|
||||
foreach (var handler in this.Handlers)
|
||||
{
|
||||
if (handler.Priority != EventPriority.Normal)
|
||||
{
|
||||
this.HasPriorities = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// sort by priority if needed
|
||||
if (this.HasPriorities)
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Input;
|
||||
using StardewValley;
|
||||
@@ -211,7 +210,13 @@ internal sealed class SInputState : InputState
|
||||
/// <param name="buttons">The buttons to check.</param>
|
||||
public bool IsAnyDown(InputButton[] buttons)
|
||||
{
|
||||
return buttons.Any(button => this.IsDown(button.ToSButton()));
|
||||
foreach (InputButton button in buttons)
|
||||
{
|
||||
if (this.IsDown(button.ToSButton()))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>Get the state of a button.</summary>
|
||||
|
||||
@@ -336,7 +336,7 @@ internal class AssemblyLoader : IDisposable
|
||||
for (int i = 0; i < module.AssemblyReferences.Count; i++)
|
||||
{
|
||||
// remove old assembly reference
|
||||
if (this.AssemblyMap.RemoveNames.Any(name => module.AssemblyReferences[i].Name == name))
|
||||
if (this.AssemblyMap.RemoveNames.Contains(module.AssemblyReferences[i].Name))
|
||||
{
|
||||
platformChanged = true;
|
||||
module.AssemblyReferences.RemoveAt(i);
|
||||
|
||||
@@ -267,14 +267,22 @@ internal static class RewriteHelper
|
||||
{
|
||||
if (reference.Name == ".ctor")
|
||||
{
|
||||
return type
|
||||
.GetConstructors(BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly | BindingFlags.Public)
|
||||
.Any(method => RewriteHelper.HasMatchingSignature(method, reference));
|
||||
foreach (ConstructorInfo constructor in type.GetConstructors(BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly | BindingFlags.Public))
|
||||
{
|
||||
if (RewriteHelper.HasMatchingSignature(constructor, reference))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (MethodInfo method in type.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly | BindingFlags.Public))
|
||||
{
|
||||
if (RewriteHelper.HasMatchingSignature(method, reference))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return type
|
||||
.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly | BindingFlags.Public)
|
||||
.Any(method => RewriteHelper.HasMatchingSignature(method, reference));
|
||||
return false;
|
||||
}
|
||||
|
||||
/****
|
||||
|
||||
@@ -241,14 +241,23 @@ internal class ModMetadata : IModMetadata
|
||||
/// <inheritdoc />
|
||||
public bool HasValidUpdateKeys()
|
||||
{
|
||||
return this.GetUpdateKeys(validOnly: true).Any();
|
||||
foreach (UpdateKey _ in this.GetUpdateKeys(validOnly: true))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool HasWarnings(params ModWarning[] warnings)
|
||||
{
|
||||
ModWarning curWarnings = this.Warnings;
|
||||
return warnings.Any(warning => curWarnings.HasFlag(warning));
|
||||
|
||||
foreach (ModWarning matchWarning in warnings)
|
||||
{
|
||||
if (curWarnings.HasFlag(matchWarning))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
||||
@@ -20,7 +20,7 @@ internal class PlatformAssemblyMap : IDisposable
|
||||
public readonly Platform TargetPlatform;
|
||||
|
||||
/// <summary>The short assembly names to remove as assembly reference, and replace with the <see cref="Targets"/>. These should be short names (like "Stardew Valley").</summary>
|
||||
public readonly IReadOnlyList<string> RemoveNames;
|
||||
public readonly HashSet<string> RemoveNames;
|
||||
|
||||
/****
|
||||
** Metadata
|
||||
@@ -42,7 +42,7 @@ internal class PlatformAssemblyMap : IDisposable
|
||||
/// <param name="targetPlatform">The target game platform.</param>
|
||||
/// <param name="removeAssemblyNames">The assembly short names to remove (like <c>Stardew Valley</c>).</param>
|
||||
/// <param name="targetAssemblies">The assemblies to target.</param>
|
||||
public PlatformAssemblyMap(Platform targetPlatform, IReadOnlyList<string> removeAssemblyNames, IReadOnlyList<Assembly> targetAssemblies)
|
||||
public PlatformAssemblyMap(Platform targetPlatform, HashSet<string> removeAssemblyNames, IReadOnlyList<Assembly> targetAssemblies)
|
||||
{
|
||||
// save data
|
||||
this.TargetPlatform = targetPlatform;
|
||||
|
||||
@@ -70,8 +70,13 @@ internal class HeuristicMethodRewriter : BaseInstructionHandler
|
||||
var loadInstructions = method.Parameters.Skip(methodRef.Parameters.Count)
|
||||
.Select(p => RewriteHelper.GetLoadValueInstruction(p.Constant))
|
||||
.ToArray();
|
||||
if (loadInstructions.Any(p => p == null))
|
||||
return false; // SMAPI needs to load the value onto the stack before the method call, but the optional parameter type wasn't recognized
|
||||
|
||||
// skip if invalid
|
||||
foreach (Instruction? loadInstruction in loadInstructions)
|
||||
{
|
||||
if (loadInstruction is null)
|
||||
return false; // SMAPI needs to load the value onto the stack before the method call, but the optional parameter type wasn't recognized
|
||||
}
|
||||
|
||||
// rewrite method reference
|
||||
foreach (Instruction? loadInstruction in loadInstructions)
|
||||
|
||||
@@ -1011,8 +1011,8 @@ internal class SCore : IDisposable
|
||||
|
||||
if (verbose)
|
||||
{
|
||||
string addedText = added.Any() ? string.Join(", ", added.Select(p => p.Name)) : "none";
|
||||
string removedText = removed.Any() ? string.Join(", ", removed.Select(p => p.Name)) : "none";
|
||||
string addedText = added.Count > 0 ? string.Join(", ", added.Select(p => p.Name)) : "none";
|
||||
string removedText = removed.Count > 0 ? string.Join(", ", removed.Select(p => p.Name)) : "none";
|
||||
this.Monitor.Log($"Context: location list changed (added {addedText}; removed {removedText}).", Monitor.ContextLogLevel);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.Xna.Framework;
|
||||
using StardewModdingAPI.Framework.StateTracking.FieldWatchers;
|
||||
using StardewValley;
|
||||
@@ -20,6 +19,9 @@ internal class LocationTracker : IWatcher
|
||||
/// <summary>The underlying watchers.</summary>
|
||||
private readonly List<IWatcher> Watchers = [];
|
||||
|
||||
/// <summary>Whether any of the <see cref="Watchers"/> changed.</summary>
|
||||
private bool WatchersHaveChanges;
|
||||
|
||||
|
||||
/*********
|
||||
** Accessors
|
||||
@@ -28,7 +30,7 @@ internal class LocationTracker : IWatcher
|
||||
public string Name { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool IsChanged => this.Watchers.Any(p => p.IsChanged);
|
||||
public bool IsChanged => this.WatchersHaveChanges;
|
||||
|
||||
/// <summary>The tracked location.</summary>
|
||||
public GameLocation Location { get; }
|
||||
@@ -93,9 +95,15 @@ internal class LocationTracker : IWatcher
|
||||
/// <inheritdoc />
|
||||
public void Update()
|
||||
{
|
||||
this.WatchersHaveChanges = false;
|
||||
foreach (IWatcher watcher in this.Watchers)
|
||||
{
|
||||
watcher.Update();
|
||||
|
||||
if (watcher.IsChanged)
|
||||
this.WatchersHaveChanges = true;
|
||||
}
|
||||
|
||||
this.UpdateChestWatcherList(added: this.ObjectsWatcher.Added, removed: this.ObjectsWatcher.Removed);
|
||||
|
||||
foreach (var watcher in this.ChestWatchers)
|
||||
@@ -105,6 +113,8 @@ internal class LocationTracker : IWatcher
|
||||
/// <inheritdoc />
|
||||
public void Reset()
|
||||
{
|
||||
this.WatchersHaveChanges = false;
|
||||
|
||||
foreach (IWatcher watcher in this.Watchers)
|
||||
watcher.Reset();
|
||||
|
||||
@@ -118,7 +128,7 @@ internal class LocationTracker : IWatcher
|
||||
foreach (IWatcher watcher in this.Watchers)
|
||||
watcher.Dispose();
|
||||
|
||||
foreach (var watcher in this.ChestWatchers.Values)
|
||||
foreach (ChestTracker watcher in this.ChestWatchers.Values)
|
||||
watcher.Dispose();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using StardewModdingAPI.Framework.StateTracking.Comparers;
|
||||
using StardewModdingAPI.Framework.StateTracking.FieldWatchers;
|
||||
using StardewValley;
|
||||
@@ -33,6 +32,9 @@ internal class WorldLocationsTracker : IWatcher
|
||||
/// <summary>The pooled list instance for <see cref="GetLocationsWhoseBuildingsChanged"/>.</summary>
|
||||
private static readonly List<LocationTracker> PooledLocationsWithBuildingsChanged = [];
|
||||
|
||||
/// <summary>Whether any of the <see cref="Locations"/> have content changes.</summary>
|
||||
private bool LocationsHaveChanges;
|
||||
|
||||
|
||||
/*********
|
||||
** Accessors
|
||||
@@ -44,7 +46,7 @@ internal class WorldLocationsTracker : IWatcher
|
||||
public bool IsLocationListChanged => this.Added.Count > 0 || this.Removed.Count > 0;
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool IsChanged => this.IsLocationListChanged || this.Locations.Any(p => p.IsChanged);
|
||||
public bool IsChanged => this.IsLocationListChanged || this.LocationsHaveChanges;
|
||||
|
||||
/// <summary>The tracked locations.</summary>
|
||||
public IEnumerable<LocationTracker> Locations => this.LocationDict.Values;
|
||||
@@ -77,8 +79,15 @@ internal class WorldLocationsTracker : IWatcher
|
||||
this.LocationListWatcher.Update();
|
||||
this.MineLocationListWatcher.Update();
|
||||
this.VolcanoLocationListWatcher.Update();
|
||||
|
||||
// update location content watchers
|
||||
this.LocationsHaveChanges = false;
|
||||
foreach (LocationTracker watcher in this.Locations)
|
||||
{
|
||||
watcher.Update();
|
||||
if (watcher.IsChanged)
|
||||
this.LocationsHaveChanges = true;
|
||||
}
|
||||
|
||||
// detect added/removed locations
|
||||
if (this.LocationListWatcher.IsChanged)
|
||||
@@ -131,6 +140,8 @@ internal class WorldLocationsTracker : IWatcher
|
||||
/// <inheritdoc />
|
||||
public void Reset()
|
||||
{
|
||||
this.LocationsHaveChanges = false;
|
||||
|
||||
this.ResetLocationList();
|
||||
foreach (IWatcher watcher in this.GetWatchers())
|
||||
watcher.Reset();
|
||||
|
||||
@@ -177,7 +177,18 @@ internal class CoreAssetPropagator
|
||||
this.UpdateMap(info);
|
||||
var newWarps = GetWarpSet(location);
|
||||
|
||||
changedWarpRoutes = changedWarpRoutes || oldWarps.Count != newWarps.Count || oldWarps.Any(p => !newWarps.Contains(p));
|
||||
changedWarpRoutes = changedWarpRoutes || oldWarps.Count != newWarps.Count;
|
||||
if (!changedWarpRoutes)
|
||||
{
|
||||
foreach (string oldWarp in oldWarps)
|
||||
{
|
||||
if (!newWarps.Contains(oldWarp))
|
||||
{
|
||||
changedWarpRoutes = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
+20
-3
@@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Microsoft.Xna.Framework.Input;
|
||||
using StardewValley;
|
||||
|
||||
@@ -697,13 +696,31 @@ public static class SButtonExtensions
|
||||
/// <summary>Get whether the given button is equivalent to <see cref="Options.useToolButton"/>.</summary>
|
||||
public bool IsUseToolButton()
|
||||
{
|
||||
return input == SButton.ControllerX || Game1.options.useToolButton.Any(p => p.ToSButton() == input);
|
||||
if (input is SButton.ControllerX)
|
||||
return true;
|
||||
|
||||
foreach (InputButton button in Game1.options.useToolButton)
|
||||
{
|
||||
if (button.ToSButton() == input)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>Get whether the given button is equivalent to <see cref="Options.actionButton"/>.</summary>
|
||||
public bool IsActionButton()
|
||||
{
|
||||
return input == SButton.ControllerA || Game1.options.actionButton.Any(p => p.ToSButton() == input);
|
||||
if (input is SButton.ControllerA)
|
||||
return true;
|
||||
|
||||
foreach (InputButton button in Game1.options.actionButton)
|
||||
{
|
||||
if (button.ToSButton() == input)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
using StardewModdingAPI.Framework;
|
||||
|
||||
namespace StardewModdingAPI.Utilities;
|
||||
@@ -36,7 +35,15 @@ public class Keybind
|
||||
public Keybind(params SButton[] buttons)
|
||||
{
|
||||
this.Buttons = buttons;
|
||||
this.IsBound = buttons.Any(p => p != SButton.None);
|
||||
|
||||
foreach (SButton button in buttons)
|
||||
{
|
||||
if (button != SButton.None)
|
||||
{
|
||||
this.IsBound = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Parse a keybind string, if it's valid.</summary>
|
||||
|
||||
Reference in New Issue
Block a user