mirror of
https://github.com/Facepunch/sbox-public.git
synced 2026-01-22 05:09:37 -05:00
This commit imports the C# engine code and game files, excluding C++ source code. [Source-Commit: ceb3d758046e50faa6258bc3b658a30c97743268]
267 lines
6.5 KiB
C#
267 lines
6.5 KiB
C#
namespace Sandbox.Engine;
|
|
|
|
/// <summary>
|
|
///
|
|
/// A collection of action binds.
|
|
///
|
|
/// BindCollection
|
|
/// - Action: attack1
|
|
/// - Slot0: mouse1
|
|
/// - Action: selectall
|
|
/// - Slot0: ctrl + a
|
|
///
|
|
/// The bind collection can be saved and loaded from disk via the BindSaveConfig class.
|
|
///
|
|
/// The bind collection can have a base collection which it will fall back to if it contains
|
|
/// the same binds. This allows us to have a "common" collection which can be shared between
|
|
/// all games, but can also let the games + users to override those binds if they choose.
|
|
///
|
|
/// </summary>
|
|
public class BindCollection
|
|
{
|
|
/// <summary>
|
|
/// The base collection. Game binds have this set to the common binds.
|
|
/// </summary>
|
|
public BindCollection Base { get; set; }
|
|
|
|
/// <summary>
|
|
/// Will be either "common" or the ident of the current game.
|
|
/// </summary>
|
|
public string CollectionName { get; set; }
|
|
|
|
/// <summary>
|
|
/// The location of the config file to load from in EngineFileSystem.Config
|
|
/// </summary>
|
|
public string ConfigPath { get; set; }
|
|
|
|
/// <summary>
|
|
/// The actual collection of binds.
|
|
/// </summary>
|
|
public CaseInsensitiveDictionary<ActionBind> Actions = new CaseInsensitiveDictionary<ActionBind>();
|
|
|
|
/// <summary>
|
|
/// Creates a collection and tries to load it from disk.
|
|
/// </summary>
|
|
public BindCollection( string name )
|
|
{
|
|
CollectionName = name;
|
|
ConfigPath = $"/input/{CollectionName}.json";
|
|
|
|
FillDefaultCommonInputs();
|
|
|
|
BindSaveConfig.Load( ConfigPath, this );
|
|
}
|
|
|
|
/// <summary>
|
|
/// If we're the common collection and have no binds (because we haven't
|
|
/// been able to load a customized config from disk) then we'll fill in
|
|
/// the defaults based on Input.CommonInputs.
|
|
/// </summary>
|
|
void FillDefaultCommonInputs()
|
|
{
|
|
if ( CollectionName != "common" ) return;
|
|
if ( Actions.Count != 0 ) return;
|
|
|
|
foreach ( var input in Input.CommonInputs )
|
|
{
|
|
if ( !string.IsNullOrWhiteSpace( input.KeyboardCode ) )
|
|
{
|
|
var bind = GetBind( input.Name );
|
|
bind.Set( 0, input.KeyboardCode );
|
|
bind.Default = input.KeyboardCode;
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get the bind, create if it doesn't exist
|
|
/// </summary>
|
|
public ActionBind GetBind( string actionName, bool create = true )
|
|
{
|
|
if ( !Actions.TryGetValue( actionName, out var bind ) )
|
|
{
|
|
if ( create )
|
|
{
|
|
bind = new ActionBind() { Name = actionName };
|
|
Actions[actionName] = bind;
|
|
}
|
|
}
|
|
|
|
return bind;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Set the bind value for this action. This will overwrite what's in this slot.
|
|
/// </summary>
|
|
public ActionBind Set( string actionName, int slot, string buttonName )
|
|
{
|
|
var bind = GetBind( actionName );
|
|
bind.Set( slot, buttonName );
|
|
return bind;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get the bind value at this slot
|
|
/// </summary>
|
|
public string Get( string actionName, int slot )
|
|
{
|
|
Actions.TryGetValue( actionName, out var bind );
|
|
if ( bind == null ) return null;
|
|
|
|
var entry = bind.Get( slot );
|
|
return entry.FullString;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Save the collection to disk
|
|
/// </summary>
|
|
public void SaveToDisk()
|
|
{
|
|
BindSaveConfig.Save( ConfigPath, this );
|
|
}
|
|
|
|
/// <summary>
|
|
/// Reset the collection to the default values.
|
|
/// </summary>
|
|
internal void ResetToDefaults()
|
|
{
|
|
if ( CollectionName == "common" )
|
|
{
|
|
Actions.Clear();
|
|
FillDefaultCommonInputs();
|
|
}
|
|
|
|
foreach ( var a in Actions )
|
|
{
|
|
a.Value.Set( 0, a.Value.Default );
|
|
a.Value.Set( 1, null );
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Enumerate all actions that contain this button
|
|
/// </summary>
|
|
internal IEnumerable<ActionBind> EnumerateWithButton( string button )
|
|
{
|
|
//
|
|
// No actions set (older project) fall back to use common binds
|
|
//
|
|
if ( Actions.Count == 0 )
|
|
{
|
|
if ( Base == null )
|
|
yield break;
|
|
|
|
foreach ( var action in Base.EnumerateWithButton( button ) )
|
|
{
|
|
yield return action;
|
|
}
|
|
|
|
yield break;
|
|
}
|
|
|
|
foreach ( var action in Actions )
|
|
{
|
|
//
|
|
// If this is a common action then check for the action set in the common collection instead.
|
|
//
|
|
// I'm commenting this out for now since it's not letting people override the default binds
|
|
// - Carson
|
|
//if ( Base != null && action.Value.IsCommon && Base.Actions.TryGetValue( action.Key, out var common ) )
|
|
//{
|
|
// if ( common.HasButton( button ) )
|
|
// yield return common;
|
|
|
|
// continue;
|
|
//}
|
|
|
|
if ( !action.Value.HasButton( button ) ) continue;
|
|
|
|
yield return action.Value;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// The action list has changed, we just got the config from the server.
|
|
/// Here we'll clear the actions, add all of the defaults from the new config
|
|
/// and then load the user config if it exists.
|
|
/// </summary>
|
|
internal void UpdateActions( List<InputAction> inputActions )
|
|
{
|
|
Actions.Clear();
|
|
|
|
foreach ( var action in inputActions )
|
|
{
|
|
// if this doesn't have a default bind, skip it
|
|
if ( string.IsNullOrEmpty( action.KeyboardCode ) ) continue;
|
|
|
|
var bind = GetBind( action.Name );
|
|
bind.Set( 0, action.KeyboardCode );
|
|
bind.Default = action.KeyboardCode;
|
|
bind.IsCommon = Base?.Actions.ContainsKey( action.Name ) ?? false;
|
|
}
|
|
|
|
BindSaveConfig.Load( ConfigPath, this );
|
|
}
|
|
|
|
public class ActionBind
|
|
{
|
|
public string Name { get; set; }
|
|
public BindEntry[] Slots = new BindEntry[2];
|
|
|
|
/// <summary>
|
|
/// If this is set then we want to read the value from the base collection
|
|
/// </summary>
|
|
public bool IsCommon { get; set; }
|
|
|
|
public string Default { get; set; }
|
|
|
|
internal BindEntry Get( int slot )
|
|
{
|
|
return Slots[slot];
|
|
}
|
|
|
|
internal void Set( int slot, string buttonString )
|
|
{
|
|
Slots[slot].Set( buttonString );
|
|
IsCommon = false;
|
|
}
|
|
|
|
internal bool HasButton( string button )
|
|
{
|
|
return Slots[0].HasButton( button ) || Slots[1].HasButton( button );
|
|
}
|
|
|
|
internal bool Test( string button, HashSet<string> activeButtons )
|
|
{
|
|
return Slots[0].Test( button, activeButtons ) || Slots[1].Test( button, activeButtons );
|
|
}
|
|
}
|
|
|
|
public struct BindEntry
|
|
{
|
|
public string FullString { get; set; }
|
|
|
|
HashSet<string> ButtonList;
|
|
|
|
internal bool HasButton( string button )
|
|
{
|
|
return ButtonList?.Contains( button ) ?? false;
|
|
}
|
|
|
|
internal void Set( string buttonString )
|
|
{
|
|
buttonString = buttonString ?? "";
|
|
FullString = buttonString;
|
|
ButtonList = FullString.Split( new[] { '+', ' ' }, StringSplitOptions.RemoveEmptyEntries ).ToHashSet( StringComparer.OrdinalIgnoreCase );
|
|
}
|
|
|
|
internal bool Test( string button, HashSet<string> activeButtons )
|
|
{
|
|
if ( ButtonList == null ) return false;
|
|
if ( !HasButton( button ) ) return false;
|
|
return ButtonList.IsSubsetOf( activeButtons );
|
|
}
|
|
}
|
|
|
|
}
|