ClientPrefs-GoldKingZ.Shared 1.0.4

dotnet add package ClientPrefs-GoldKingZ.Shared --version 1.0.4
                    
NuGet\Install-Package ClientPrefs-GoldKingZ.Shared -Version 1.0.4
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="ClientPrefs-GoldKingZ.Shared" Version="1.0.4" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="ClientPrefs-GoldKingZ.Shared" Version="1.0.4" />
                    
Directory.Packages.props
<PackageReference Include="ClientPrefs-GoldKingZ.Shared" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add ClientPrefs-GoldKingZ.Shared --version 1.0.4
                    
#r "nuget: ClientPrefs-GoldKingZ.Shared, 1.0.4"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package ClientPrefs-GoldKingZ.Shared@1.0.4
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=ClientPrefs-GoldKingZ.Shared&version=1.0.4
                    
Install as a Cake Addin
#tool nuget:?package=ClientPrefs-GoldKingZ.Shared&version=1.0.4
                    
Install as a Cake Tool

🚀 Quick Start

1. Define your data class

public sealed class ClientPrefs
{
    public bool   ChatMuted  { get; set; } = false;
    public int    Volume     { get; set; } = 50;
    public float  XAxis      { get; set; } = 0f;
    public string FavPack    { get; set; } = "";
    public int    Mode       { get; set; } = 0;
}

Supported types: bool, int, long, ulong, float, double, string, DateTime

Reserved names (do NOT use): PlayerName, PlayerSteamID, DateAndTime — injected automatically by ClientPrefs

2. Register in your plugin

using ClientPrefs_GoldKingZ.Shared;

private IPrefsStore<ClientPrefs>? _prefs;

public override void OnAllPluginsLoaded(bool hotReload)
{
    var api = ClientPrefsApi.Get();
    if (api == null)
    {
        Logger.LogError("[MyPlugin] Missing cs2-ClientPrefs-GoldKingZ API !");
        return;
    }

    _prefs = api.CreatePrefs<ClientPrefs>(this, new ClientPrefsOptions
    {
        PrefsAPI_CookiesEnable = PrefsAPI_SaveMode.OnPlayerDisconnect,
    });

    if (hotReload)
    {
        _prefs?.Refresh();
    }

}

public override void Unload(bool hotReload)
{
    _prefs?.Unload();
}

3. Use it

if (_prefs?.TryGetValue(player.Slot, out var data) != true) return;

data.ChatMuted = !data.ChatMuted;
data.Volume = 75;

That's it. Changes are tracked automatically and saved on disconnect or map end.

Note: TryGetValue returns false while a player's data is still loading. The player automatically gets a chat message to wait, and another when everything is loaded. Just handle the false return and let the player retry.


🧩 Multiple Isolated Stores

One plugin can register more than one store — call CreatePrefs<T>() once per data class. Each store gets its own table and never shares rows or columns with the others.

private IPrefsStore<ClientPrefs>?    _prefs;
private IPrefsStore<ClientPrefsHud>? _hud;
 
public override void OnAllPluginsLoaded(bool hotReload)
{
    var api = ClientPrefsApi.Get();
    if (api == null) return;
 
    _prefs = api.CreatePrefs<ClientPrefs>(this, new ClientPrefsOptions { /* ... */ });
 
    _hud = api.CreatePrefs<ClientPrefsHud>(this, new ClientPrefsOptions
    {
        PrefsAPI_TableName = "test_hud",   // exact table name on SQLite AND MySQL
    });
}
 
public override void Unload(bool hotReload)
{
    _prefs?.Unload();
    _hud?.Unload();
}

Without PrefsAPI_TableName, each store auto-names its table <FolderName>_<ClassName> — so multiple stores never collide.


⚙️ Configuration Options

Option Values Default
PrefsAPI_CookiesEnable Disabled / OnPlayerDisconnect / OnMapEnd Disabled
PrefsAPI_CookiesAutoRemoveInactivePlayersOlderThanDays 0 = never delete, 1+ = days 7
PrefsAPI_MySqlEnable Disabled / OnPlayerDisconnect / OnMapEnd Disabled
PrefsAPI_MySqlAutoRemoveInactivePlayersOlderThanDays 0 = never delete, 1+ = days 7
PrefsAPI_MySqlConnectionTimeout seconds 30
PrefsAPI_MySqlRetryAttempts any positive integer 3
PrefsAPI_MySqlRetryDelay seconds between retries 2
PrefsAPI_TableName string or null for auto. Applies to both SQLite and MySQL null → <FolderName>_<ClassName>
PrefsAPI_MySqlConfig MySqlConfig { Server, Port, Database, Username, Password } or MySql_Servers list for failover empty
PrefsAPI_ReloadOnReconnect true = reload from storage / false = keep memory false
PrefsAPI_LoadDefaultAfterDrop true = give defaults after drop / false = empty until rejoin true
PrefsAPI_DebugEnable true = show all logs / false = errors only false

📖 API Methods

Read / Write Data (in-memory, instant)

Method Description
TryGetValue(player, out data) Get player data by controller. Returns false if not loaded
TryGetValue(slot, out data) Get player data by slot number
TryGetValue(steamId, out data) Get player data by SteamID64 (must be in memory)
TryGetValue(player, action) Run action if player is loaded (callback style)
TryGetValue(slot, action) Run action if slot is loaded (callback style)
TryGetValue(steamId, action) Run action if SteamID64 is in memory and loaded

Player Loaded Event

Method Description
OnPlayerLoaded(player, callback) Run callback ONCE when THIS store finishes loading the player
OnPlayerLoaded(player, callback, All_Plugins: true) Run callback ONCE when EVERY plugin finished loading the player

Call it anywhere (a connect event, etc). It fires once per call for the player you pass — it is not a registration. Call it twice = fires twice, you control it. Runs on the game thread.

DataBase (works for OFFLINE players)

Method Description
FetchPlayer(steamId, callback) Get one player's stored data (offline OK)
FetchPlayer<TResult>(steamId, callback, All_Plugins: true) Get one player from EVERY plugin into your own result class
SearchByField(field, value, callback) Find all players where a field equals a value
SearchByField<TResult>(field, value, callback, All_Plugins: true) Search EVERY plugin into your own result class
ModifyAndSave(steamId, modify, done) Modify one player's stored data and save it (offline OK, this plugin)

Reads cookies + MySQL per this store's config — newest data wins. In <TResult> results, result.Plugin and result.Table tell you which plugin / table each row came from.

Force Save

Method Description
ForceSave(player) / (slot) / (steamId) Save this player now — this plugin only
ForceSave(..., All_Plugins: true) Save this player across ALL plugins using ClientPrefs
ForceSave(..., done: saved => { }) Optional callback — true = saved OK

Drop Player (wipe memory + cookies.db + MySQL)

Method Description
DropPlayer(player) / (slot) / (steamId) Wipe this player — this plugin only
DropPlayer(..., All_Plugins: true) Wipe this player from ALL plugins using ClientPrefs
DropPlayer(..., done: dropped => { }) Optional callback — true = wiped

DropPlayer by steamId works even if the player is offline (deletes from storage). Wipes only the backends this store has enabled.

Lifecycle

Method Description
Refresh() Save all changed data + reload all players from storage
Unload() Save all changed data + close connections + clear memory

🔄 Auto-Migration

You can freely edit your data class at any time. ClientPrefs automatically updates your cookies.db and MySQL table to match — no need to delete the database.

Change What happens
Add a new field New column added, existing players keep their data
Remove a field Column dropped, other columns stay untouched
Change field type Column type updated (table rebuilt for cookies, MODIFY COLUMN for MySQL)

No data loss when adding or removing fields. Changing a field's type or renaming it (drop old + add new) resets that one column to its default — other columns are unaffected. Just edit your data class, rebuild your plugin, and reload.


📂 Folder Structure

After installation:

csgo/
└── addons/counterstrikesharp/
    ├── plugins/
    │   └── ClientPrefs-GoldKingZ/                       ← Core plugin
    │       ├── ClientPrefs-GoldKingZ.dll
    │       ├── ClientPrefs-GoldKingZ.Shared.dll
    │       ├── Microsoft.Data.Sqlite.dll
    │       ├── MySqlConnector.dll
    │       ├── SQLitePCLRaw.batteries_v2.dll
    │       ├── SQLitePCLRaw.core.dll
    │       ├── SQLitePCLRaw.provider.e_sqlite3.dll
    │       ├── e_sqlite3.dll                            ← Native SQLite (Windows)
    │       ├── libe_sqlite3.so                          ← Native SQLite (Linux)
    │       └── lang/
    │           └── en.json                              ← Chat messages
    └── shared/
        └── ClientPrefs-GoldKingZ.Shared/
            └── ClientPrefs-GoldKingZ.Shared.dll         ← API reference for developers

Each consumer plugin gets its own isolated storage inside the core folder:

plugins/
└── ClientPrefs-GoldKingZ/
    ├── YourPlugin/
    │   └── cookies.db                                   ← Created automatically
    └── AnotherPlugin/
        └── cookies.db
Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.4 117 8/26/2026
1.0.3 109 7/26/2026