diff --git a/XPSystem.Console/App.config b/XPSystem.Console/App.config
index ddb81eb..1a71491 100644
--- a/XPSystem.Console/App.config
+++ b/XPSystem.Console/App.config
@@ -15,7 +15,7 @@
-
+
diff --git a/XPSystem.Console/Program.cs b/XPSystem.Console/Program.cs
index c233ac0..4239324 100644
--- a/XPSystem.Console/Program.cs
+++ b/XPSystem.Console/Program.cs
@@ -139,8 +139,6 @@ public static void Main(string[] args)
foreach ((int level, int xp) kvp in new[]
{
(0, 0),
- (1, 151),
- (1245, 1674575),
(random.Next(0, 100), -1),
(random.Next(100, 1000), -1),
(random.Next(1000, 1000), -1),
diff --git a/XPSystem.Console/XPSystem.Console.csproj b/XPSystem.Console/XPSystem.Console.csproj
index b99414f..4fdce23 100644
--- a/XPSystem.Console/XPSystem.Console.csproj
+++ b/XPSystem.Console/XPSystem.Console.csproj
@@ -43,44 +43,44 @@
- ..\packages\ExMod.Exiled.9.6.0\lib\net48\Assembly-CSharp-Publicized.dll
+ ..\packages\ExMod.Exiled.9.6.3\lib\net48\Assembly-CSharp-Publicized.dll
- ..\packages\ExMod.Exiled.9.6.0\lib\net48\CommandSystem.Core.dll
+ ..\packages\ExMod.Exiled.9.6.3\lib\net48\CommandSystem.Core.dll
-
- ..\packages\ExMod.Exiled.9.6.0\lib\net48\Exiled.API.dll
+
+ ..\packages\ExMod.Exiled.9.6.3\lib\net48\Exiled.API.dll
-
- ..\packages\ExMod.Exiled.9.6.0\lib\net48\Exiled.CreditTags.dll
+
+ ..\packages\ExMod.Exiled.9.6.3\lib\net48\Exiled.CreditTags.dll
-
- ..\packages\ExMod.Exiled.9.6.0\lib\net48\Exiled.CustomItems.dll
+
+ ..\packages\ExMod.Exiled.9.6.3\lib\net48\Exiled.CustomItems.dll
-
- ..\packages\ExMod.Exiled.9.6.0\lib\net48\Exiled.CustomRoles.dll
+
+ ..\packages\ExMod.Exiled.9.6.3\lib\net48\Exiled.CustomRoles.dll
-
- ..\packages\ExMod.Exiled.9.6.0\lib\net48\Exiled.Events.dll
+
+ ..\packages\ExMod.Exiled.9.6.3\lib\net48\Exiled.Events.dll
-
- ..\packages\ExMod.Exiled.9.6.0\lib\net48\Exiled.Loader.dll
+
+ ..\packages\ExMod.Exiled.9.6.3\lib\net48\Exiled.Loader.dll
-
- ..\packages\ExMod.Exiled.9.6.0\lib\net48\Exiled.Permissions.dll
+
+ ..\packages\ExMod.Exiled.9.6.3\lib\net48\Exiled.Permissions.dll
-
- ..\packages\ExMod.Exiled.9.6.0\lib\net48\LabApi.dll
+
+ ..\packages\ExMod.Exiled.9.6.3\lib\net48\LabApi.dll
- ..\packages\ExMod.Exiled.9.6.0\lib\net48\NorthwoodLib.dll
+ ..\packages\ExMod.Exiled.9.6.3\lib\net48\NorthwoodLib.dll
- ..\packages\ExMod.Exiled.9.6.0\lib\net48\YamlDotNet.dll
+ ..\packages\ExMod.Exiled.9.6.3\lib\net48\YamlDotNet.dll
diff --git a/XPSystem.Console/packages.config b/XPSystem.Console/packages.config
index 603f1d9..02e0314 100644
--- a/XPSystem.Console/packages.config
+++ b/XPSystem.Console/packages.config
@@ -1,4 +1,4 @@
-
+
\ No newline at end of file
diff --git a/XPSystem/API/Badge.cs b/XPSystem/API/Badge.cs
index c81842b..74d7c67 100644
--- a/XPSystem/API/Badge.cs
+++ b/XPSystem/API/Badge.cs
@@ -1,7 +1,8 @@
-namespace XPSystem.Config.Models
+// ReSharper disable PropertyCanBeMadeInitOnly.Global
+#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring as nullable.
+namespace XPSystem.API
{
using System;
- using XPSystem.API;
public class Badge
{
diff --git a/XPSystem/API/DisplayProviders/IXPDisplayProvider.cs b/XPSystem/API/DisplayProviders/IXPDisplayProvider.cs
index 6c7b4ea..a246afa 100644
--- a/XPSystem/API/DisplayProviders/IXPDisplayProvider.cs
+++ b/XPSystem/API/DisplayProviders/IXPDisplayProvider.cs
@@ -1,6 +1,6 @@
namespace XPSystem.API
{
- using System;
+ using XPSystem.API.Player;
using XPSystem.API.StorageProviders;
///
@@ -10,10 +10,8 @@ public interface IXPDisplayProvider
{
void Enable();
void Disable();
- void RefreshTo(XPPlayer player);
- void RefreshOf(XPPlayer player, PlayerInfoWrapper playerInfo);
+ void RefreshTo(BaseXPPlayer player);
+ void RefreshOf(BaseXPPlayer player, PlayerInfoWrapper? playerInfo = null);
void RefreshAll();
- IXPDisplayProviderConfig ConfigPropertyInternal { get; set; }
- Type ConfigTypeInternal { get; }
}
}
\ No newline at end of file
diff --git a/XPSystem/API/DisplayProviders/SyncVarXPDisplayProvider.cs b/XPSystem/API/DisplayProviders/SyncVarXPDisplayProvider.cs
index 3d8100b..aa5b56f 100644
--- a/XPSystem/API/DisplayProviders/SyncVarXPDisplayProvider.cs
+++ b/XPSystem/API/DisplayProviders/SyncVarXPDisplayProvider.cs
@@ -1,6 +1,7 @@
namespace XPSystem.API.DisplayProviders
{
using System;
+ using XPSystem.API.Player;
using XPSystem.API.StorageProviders;
using static XPAPI;
@@ -19,7 +20,7 @@
///
/// Gets the sync vars to use.
///
- protected abstract (Type typeName, string methodName, Func getFakeSyncVar, Func getResyncVar)[] SyncVars { get; }
+ protected abstract (Type typeName, string methodName, Func getFakeSyncVar, Func getResyncVar)[] SyncVars { get; }
///
/// Creates the object for the player.
@@ -27,28 +28,30 @@
/// The player to create the object for.
/// The player's info to create the object from.
/// The created object.
- protected abstract TObject CreateObject(XPPlayer player, PlayerInfoWrapper playerInfo);
+ protected abstract TObject? CreateObject(BaseXPPlayer player, PlayerInfoWrapper? playerInfo);
- protected override void RefreshToEnabled(XPPlayer player)
+ protected override void RefreshToEnabled(BaseXPPlayer player)
{
int count = 0;
- foreach (var kvp in XPPlayer.Players)
+ foreach (BaseXPPlayer player2 in XPPlayer.PlayersRealConnected)
{
- if (kvp.Value.IsNPC)
+ if (player == player2)
continue;
- if (player == kvp.Value)
- continue;
- if (!ShouldEdit(kvp.Value))
+ if (!ShouldEdit(player2))
continue;
- TObject obj = GetObject(kvp.Value);
+ TObject? obj = GetObject(player2);
if (obj == null)
continue;
foreach (var syncVar in SyncVars)
{
- player.SendFakeSyncVar(kvp.Value.NetworkIdentity, syncVar.typeName, syncVar.methodName, syncVar.getFakeSyncVar(kvp.Value, obj));
+ object? value = syncVar.getFakeSyncVar(player2, obj);
+ if (value == null)
+ continue;
+
+ player.SendFakeSyncVar(player2.NetworkIdentity, syncVar.typeName, syncVar.methodName, value);
count++;
}
}
@@ -56,22 +59,24 @@ protected override void RefreshToEnabled(XPPlayer player)
LogDebug(GetType().Name + " sent all (" + count + ") to " + player.Nickname + " (enabled)");
}
- protected override void RefreshToDisabled(XPPlayer player)
+ protected override void RefreshToDisabled(BaseXPPlayer player)
{
int count = 0;
- foreach (var kvp in XPPlayer.Players)
+ foreach (BaseXPPlayer player2 in XPPlayer.PlayersRealConnected)
{
- if (kvp.Value.IsNPC)
- continue;
- if (player == kvp.Value)
+ if (player == player2)
continue;
- if (!ShouldEdit(kvp.Value))
+ if (!ShouldEdit(player2))
continue;
foreach (var syncVar in SyncVars)
{
- player.SendFakeSyncVar(kvp.Value.NetworkIdentity, syncVar.typeName, syncVar.methodName, syncVar.getResyncVar(player));
+ object? value = syncVar.getResyncVar(player2);
+ if (value == null)
+ continue;
+
+ player.SendFakeSyncVar(player2.NetworkIdentity, syncVar.typeName, syncVar.methodName, value);
count++;
}
}
@@ -79,23 +84,29 @@ protected override void RefreshToDisabled(XPPlayer player)
LogDebug(GetType().Name + " sent all (" + count + ") to " + player.Nickname + " (disabled)");
}
- protected override void RefreshOfEnabled(XPPlayer player, PlayerInfoWrapper playerInfo)
+ protected override void RefreshOfEnabled(BaseXPPlayer player, PlayerInfoWrapper? playerInfo)
{
if (!ShouldEdit(player))
return;
- TObject obj = GetObject(player, playerInfo, true);
+ TObject? obj = GetObject(player, playerInfo, true);
if (obj == null)
return;
int count = 0;
foreach (var syncVar in SyncVars)
- count += player.SendFakeSyncVars(x => ShouldShowTo(player, x), syncVar.typeName, syncVar.methodName, syncVar.getFakeSyncVar(player, obj));
+ {
+ object? value = syncVar.getFakeSyncVar(player, obj);
+ if (value == null)
+ continue;
+
+ count += player.SendFakeSyncVars(x => ShouldShowTo(player, x), syncVar.typeName, syncVar.methodName, value);
+ }
LogDebug(GetType().Name + " of " + player.Nickname + " sent to all (" + count + ") (enabled)");
}
- protected override void RefreshOfDisabled(XPPlayer player)
+ protected override void RefreshOfDisabled(BaseXPPlayer player)
{
if (!ShouldEdit(player))
return;
@@ -113,15 +124,15 @@ protected override void RefreshOfDisabled(XPPlayer player)
/// The player's info to create the object from.
/// Whether or not to force creation of a new object, even if one already exists.
/// The object for the player.
- protected virtual TObject GetObject(XPPlayer player, PlayerInfoWrapper playerInfo = null, bool update = false)
+ protected virtual TObject? GetObject(BaseXPPlayer player, PlayerInfoWrapper? playerInfo = null, bool update = false)
{
- if (VariableKey == null)
- return default;
-
- if (update || !player.Variables.TryGet(VariableKey, out TObject obj))
+ if (update || !player.Variables.TryGet(VariableKey, out TObject? obj))
{
- obj = CreateObject(player, playerInfo ?? player.GetPlayerInfo());
- player.Variables.Set(VariableKey, obj);
+ if (playerInfo == null && player is XPPlayer xpPlayer)
+ playerInfo = xpPlayer.GetPlayerInfo();
+
+ obj = CreateObject(player, playerInfo);
+ player.Variables.Set(VariableKey, obj!);
}
return obj;
@@ -132,7 +143,7 @@ protected virtual TObject GetObject(XPPlayer player, PlayerInfoWrapper playerInf
///
/// The player to check.
/// Whether or not the player's data should be displayed.
- protected virtual bool ShouldEdit(XPPlayer player) => true;
+ protected virtual bool ShouldEdit(BaseXPPlayer player) => true;
///
/// Whether or not the player's data should be shown to the target player.
@@ -140,6 +151,6 @@ protected virtual TObject GetObject(XPPlayer player, PlayerInfoWrapper playerInf
/// The player to show the data of.
/// The target player to show the data to.
/// Whether or not the player's data should be shown to the target player.
- protected virtual bool ShouldShowTo(XPPlayer player, XPPlayer target) => !target.IsNPC;
+ protected virtual bool ShouldShowTo(BaseXPPlayer player, BaseXPPlayer target) => true;
}
}
\ No newline at end of file
diff --git a/XPSystem/API/DisplayProviders/XPDisplayProvider.cs b/XPSystem/API/DisplayProviders/XPDisplayProvider.cs
index 92be478..0e56f5e 100644
--- a/XPSystem/API/DisplayProviders/XPDisplayProvider.cs
+++ b/XPSystem/API/DisplayProviders/XPDisplayProvider.cs
@@ -1,24 +1,27 @@
namespace XPSystem.API
{
using System;
+ using System.IO;
using XPSystem.API.DisplayProviders;
+ using XPSystem.API.Player;
using XPSystem.API.StorageProviders;
+ using static XPAPI;
///
- /// Base class for xp display providers, shows the xp/lvl of a player to others.
+ /// Base class for XP display providers, shows the XP/level of a player to others.
///
- public abstract class XPDisplayProvider : IXPDisplayProvider where T : IXPDisplayProviderConfig, new()
+ public abstract class XPDisplayProvider : ConfigXPDisplayProvider where T : IXPDisplayProviderConfig, new()
{
///
/// Gets the patch category.
/// Null to disable patching.
///
- protected virtual string PatchCategory => null;
+ protected virtual string? PatchCategory => null;
///
/// Enables the display provider.
///
- public virtual void Enable()
+ public override void Enable()
{
if (PatchCategory != null)
{
@@ -32,7 +35,7 @@ public virtual void Enable()
///
/// Disables the display provider.
///
- public virtual void Disable()
+ public override void Disable()
{
if (PatchCategory != null)
{
@@ -50,20 +53,18 @@ public virtual void Disable()
///
/// implementation when enabled.
///
- protected virtual void RefreshToEnabled(XPPlayer player) {}
+ protected virtual void RefreshToEnabled(BaseXPPlayer player) {}
///
/// implementation when disabled.
///
- protected virtual void RefreshToDisabled(XPPlayer player) {}
+ protected virtual void RefreshToDisabled(BaseXPPlayer player) {}
/// See .
- public virtual void RefreshTo(XPPlayer player)
+ public override void RefreshTo(BaseXPPlayer player)
{
if (!Config.Enabled && !HasSet)
return;
- if (player.IsNPC)
- return;
if (Config.Enabled)
{
@@ -79,22 +80,24 @@ public virtual void RefreshTo(XPPlayer player)
///
/// implementation when enabled.
///
- protected virtual void RefreshOfEnabled(XPPlayer player, PlayerInfoWrapper playerInfo) {}
+ protected virtual void RefreshOfEnabled(BaseXPPlayer player, PlayerInfoWrapper? playerInfo) {}
///
/// implementation when disabled.
///
- protected virtual void RefreshOfDisabled(XPPlayer player) {}
+ protected virtual void RefreshOfDisabled(BaseXPPlayer player) {}
/// See .
- public virtual void RefreshOf(XPPlayer player, PlayerInfoWrapper playerInfo = null)
+ public override void RefreshOf(BaseXPPlayer player, PlayerInfoWrapper? playerInfo = null)
{
if (!Config.Enabled && !HasSet)
return;
if (Config.Enabled)
{
- RefreshOfEnabled(player, playerInfo ?? player.GetPlayerInfo());
+ if (player is XPPlayer xpPlayer)
+ playerInfo ??= xpPlayer.GetPlayerInfo();
+ RefreshOfEnabled(player, playerInfo);
HasSet = true;
}
else
@@ -106,13 +109,13 @@ public virtual void RefreshOf(XPPlayer player, PlayerInfoWrapper playerInfo = nu
///
/// Refreshes the displays of all players.
///
- public virtual void RefreshAll()
+ public override void RefreshAll()
{
if (!Config.Enabled && !HasSet)
return;
- foreach (var kvp in XPPlayer.Players)
- RefreshOf(kvp.Value, kvp.Value.GetPlayerInfo());
+ foreach (BaseXPPlayer player in XPPlayer.PlayersRealConnected)
+ RefreshOf(player, player is XPPlayer xpPlayer ? xpPlayer.GetPlayerInfo() : null);
HasSet = Config.Enabled;
}
@@ -120,21 +123,45 @@ public virtual void RefreshAll()
///
/// The config instance.
///
- protected T Config { get; set; }
+ public T Config { get; private set; } = default!;
+ internal override IXPDisplayProviderConfig ConfigPropertyInternal => Config;
///
- /// Ignore this, used by loader.
+ /// Ignore, used by loader.
///
- IXPDisplayProviderConfig IXPDisplayProvider.ConfigPropertyInternal
+ internal override void LoadConfig(string folder)
{
- get => Config ?? new T();
- set => Config = (T)value;
+ string name = GetType().Name;
+ string file = Path.Combine(folder, name + ".yml");
+
+ if (File.Exists(file))
+ {
+ try
+ {
+ Config = Deserializer.Deserialize(File.ReadAllText(file));
+ }
+ catch (Exception e)
+ {
+ LogError($"Error loading display provider config for {name}: {e}");
+ }
+ }
+ else
+ {
+ Config = new T();
+ File.WriteAllText(file, Serializer.Serialize(Config));
+ }
}
+ }
- ///
- /// Ignore this, used by loader.
- /// Type of .
- ///
- public Type ConfigTypeInternal { get; } = typeof(T);
+ public abstract class ConfigXPDisplayProvider : IXPDisplayProvider
+ {
+ public abstract void Enable();
+ public abstract void Disable();
+ public abstract void RefreshTo(BaseXPPlayer player);
+ public abstract void RefreshOf(BaseXPPlayer player, PlayerInfoWrapper? playerInfo = null);
+ public abstract void RefreshAll();
+
+ internal abstract IXPDisplayProviderConfig ConfigPropertyInternal { get; }
+ internal abstract void LoadConfig(string folder);
}
}
\ No newline at end of file
diff --git a/XPSystem/API/DisplayProviders/XPDisplayProviderCollection.cs b/XPSystem/API/DisplayProviders/XPDisplayProviderCollection.cs
index 0bb6408..42ae8ef 100644
--- a/XPSystem/API/DisplayProviders/XPDisplayProviderCollection.cs
+++ b/XPSystem/API/DisplayProviders/XPDisplayProviderCollection.cs
@@ -3,8 +3,8 @@
using System;
using System.Collections;
using System.Collections.Generic;
- using System.IO;
using System.Linq;
+ using XPSystem.API.Player;
using XPSystem.API.StorageProviders;
using static XPAPI;
@@ -47,7 +47,7 @@ public void RefreshTo(XPPlayer player)
///
/// The player to refresh the displays of.
/// The player's info to refresh the displays using.
- public void RefreshOf(XPPlayer player, PlayerInfoWrapper playerInfo = null)
+ public void RefreshOf(XPPlayer player, PlayerInfoWrapper? playerInfo = null)
{
playerInfo ??= player.GetPlayerInfo();
@@ -97,7 +97,7 @@ public void Enable()
{
foreach (IXPDisplayProvider provider in _providers)
{
- if (provider.ConfigPropertyInternal?.Enabled == true)
+ if (provider is not ConfigXPDisplayProvider config || config.ConfigPropertyInternal?.Enabled == true)
{
try
{
@@ -119,28 +119,8 @@ public void LoadConfigs(string folder)
{
foreach (IXPDisplayProvider provider in Providers)
{
- string name = provider.GetType().Name;
- string file = Path.Combine(folder, name + ".yml");
-
- if (File.Exists(file))
- {
- try
- {
- provider.ConfigPropertyInternal = (IXPDisplayProviderConfig)
- Deserializer.Deserialize(File.ReadAllText(file), provider.ConfigTypeInternal);
- }
- catch (Exception e)
- {
- LogError($"Error loading xpdisplayprovider config for {name}: {e}");
- }
- }
- else
- {
- IXPDisplayProviderConfig obj = provider.ConfigPropertyInternal;
-
- File.WriteAllText(file, XPAPI.Serializer.Serialize(obj));
- provider.ConfigPropertyInternal = obj;
- }
+ if (provider is ConfigXPDisplayProvider config)
+ config.LoadConfig(folder);
}
}
diff --git a/XPSystem/API/Exceptions/InvalidPlayerIdException.cs b/XPSystem/API/Exceptions/InvalidPlayerIdException.cs
deleted file mode 100644
index 2277c8b..0000000
--- a/XPSystem/API/Exceptions/InvalidPlayerIdException.cs
+++ /dev/null
@@ -1,11 +0,0 @@
-namespace XPSystem.API.Exceptions
-{
- using System;
-
- public class InvalidPlayerIdException : Exception
- {
- public InvalidPlayerIdException() : base("The PlayerId for the specified player is invalid! Are you trying to modify the xp for the host?")
- {
- }
- }
-}
\ No newline at end of file
diff --git a/XPSystem/API/IMessagingProvider.cs b/XPSystem/API/IMessagingProvider.cs
index e0fb0b1..f6f6d85 100644
--- a/XPSystem/API/IMessagingProvider.cs
+++ b/XPSystem/API/IMessagingProvider.cs
@@ -1,10 +1,12 @@
namespace XPSystem.API
{
+ using XPSystem.API.Player;
+
///
/// Interface for a messaging provider, used to display messages to players.
///
public interface IMessagingProvider
{
- void DisplayMessage(XPPlayer player, string message, float duration);
+ void DisplayMessage(BaseXPPlayer player, string message, float duration);
}
}
\ No newline at end of file
diff --git a/XPSystem/API/Legacy/LiteDBMigrator.cs b/XPSystem/API/Legacy/LiteDBMigrator.cs
index 12fdf1e..4016ea6 100644
--- a/XPSystem/API/Legacy/LiteDBMigrator.cs
+++ b/XPSystem/API/Legacy/LiteDBMigrator.cs
@@ -76,7 +76,7 @@ public static int ImportLegacyDB(LiteDatabase db)
XP = log.XP + LevelCalculator.GetXP(log.LVL)
};
- StorageProvider.SetPlayerInfo(playerInfo);
+ StorageProvider!.SetPlayerInfo(playerInfo);
count++;
if (count % 100 == 0) LogInfo($"Imported {count}/{total} players.");
diff --git a/XPSystem/API/Legacy/PlayerLog.cs b/XPSystem/API/Legacy/PlayerLog.cs
index 4b6a152..68345ef 100644
--- a/XPSystem/API/Legacy/PlayerLog.cs
+++ b/XPSystem/API/Legacy/PlayerLog.cs
@@ -12,6 +12,6 @@ public class PlayerLog
public int LVL { get; set; }
public int XP { get; set; }
[BsonId]
- public string ID { get; set; }
+ public string ID { get; set; } = null!;
}
}
\ No newline at end of file
diff --git a/XPSystem/API/LevelCalculator.cs b/XPSystem/API/LevelCalculator.cs
index 8db1b27..e5fdb9b 100644
--- a/XPSystem/API/LevelCalculator.cs
+++ b/XPSystem/API/LevelCalculator.cs
@@ -14,17 +14,17 @@ public static class LevelCalculator
///
/// Gets the used for the s.
///
- public static ExpressionContext Context { get; private set; }
+ public static ExpressionContext Context { get; private set; } = null!;
///
/// Gets the used to calculate the level.
///
- public static IGenericExpression Expression { get; private set; }
+ public static IGenericExpression Expression { get; private set; } = null!;
///
/// Gets the inverse of the . Used to calculate the XP needed for a level.
///
- public static IGenericExpression InverseExpression { get; private set; }
+ public static IGenericExpression InverseExpression { get; private set; } = null!;
///
/// Gets the level of the specified .
diff --git a/XPSystem/API/LoaderSpecific.cs b/XPSystem/API/LoaderSpecific.cs
index 952f945..7448bde 100644
--- a/XPSystem/API/LoaderSpecific.cs
+++ b/XPSystem/API/LoaderSpecific.cs
@@ -33,7 +33,7 @@ public static class LoaderSpecific
///
/// The player's nickname, user ID, or player ID.
/// The if found, otherwise null.
- public static ReferenceHub GetHub(string data)
+ public static ReferenceHub? GetHub(string data)
{
if (string.IsNullOrWhiteSpace(data))
return null;
diff --git a/XPSystem/API/XPPlayer.cs b/XPSystem/API/Player/BaseXPPlayer.cs
similarity index 58%
rename from XPSystem/API/XPPlayer.cs
rename to XPSystem/API/Player/BaseXPPlayer.cs
index 7acf339..ddc321e 100644
--- a/XPSystem/API/XPPlayer.cs
+++ b/XPSystem/API/Player/BaseXPPlayer.cs
@@ -1,31 +1,22 @@
-namespace XPSystem.API
+namespace XPSystem.API.Player
{
using System;
- using System.Collections.Generic;
- using System.Diagnostics;
- using CommandSystem;
using Hints;
using Mirror;
using PlayerRoles;
- using RemoteAdmin;
- using XPSystem.API.StorageProviders.Models;
using XPSystem.API.Variables;
- using XPSystem.Config.Models;
using static LoaderSpecific;
///
- /// wrapper.
+ /// wrapper. Kinda like the one found in plugin frameworks.
///
- /// Multiple instances of this class can exist for the same player, instances are not saved, there is no constructor logic.
- public partial class XPPlayer
+ public class BaseXPPlayer
{
- public static IReadOnlyDictionary Players => PlayersValue;
- internal static readonly Dictionary PlayersValue = new();
-
///
/// The player's .
///
public readonly ReferenceHub Hub;
+ internal BaseXPPlayer(ReferenceHub hub) => Hub = hub;
///
/// Gets the player's user ID.
@@ -37,17 +28,6 @@ public partial class XPPlayer
///
public readonly VariableCollection Variables = new();
- ///
- /// Gets the player's .
- ///
- public IPlayerId PlayerId { get; }
-
- ///
- /// Gets whether or not the player is a npc.
- /// AddXP will return unless forced, if this is true.
- ///
- public bool IsNPC { get; }
-
///
/// Gets the player's nickname.
///
@@ -56,7 +36,7 @@ public partial class XPPlayer
///
/// Gets the player's display name.
///
- public string DisplayName => Hub.nicknameSync.Network_displayName;
+ public string? DisplayName => Hub.nicknameSync.Network_displayName;
///
/// Gets the name that will be displayed to other players.
@@ -71,17 +51,23 @@ public partial class XPPlayer
///
/// Gets whether or not the player is connected to the server.
///
- public bool IsConnected => GetIsConnectedSafe();
+ public bool IsConnected => Hub && Hub.gameObject;
+
+ ///
+ /// Gets whether or not the player is a NPC.
+ ///
+ public bool IsNPC => Hub.IsHost || CheckNPC(Hub);
///
/// Gets whether or not the player has do not track enabled.
+ /// Should always be false unless the creation was forced (which you shouldn't do).
///
public bool DNT => Hub.authManager.DoNotTrack;
///
/// Gets the player's group.
///
- public UserGroup Group => Hub.serverRoles.Group;
+ public UserGroup? Group => Hub.serverRoles.Group;
///
/// Gets whether or not the player has a badge.
@@ -101,12 +87,12 @@ public partial class XPPlayer
///
/// Gets the player's badge text.
///
- public string BadgeText => Hub.serverRoles.Network_myText;
+ public string? BadgeText => Hub.serverRoles.Network_myText;
///
/// Gets the player's badge color.
///
- public string BadgeColor => Hub.serverRoles.Network_myColor;
+ public string? BadgeColor => Hub.serverRoles.Network_myColor;
///
/// Gets whether or not the player can view hidden badges.
@@ -125,12 +111,6 @@ public partial class XPPlayer
///
public RoundSummary.LeadingTeam LeadingTeam => Role.GetTeam().GetLeadingTeam();
- ///
- /// Gets or sets the player's XP multiplier.
- /// All XP added by methods (all built-in except for directly via non-wrapper) that respect this value will be multiplied by this value.
- ///
- public float XPMultiplier { get; set; } = 1f;
-
public void ShowHint(string message, float duration = 3f)
{
Hub.hints.Show(new TextHint(message, new HintParameter[]
@@ -169,164 +149,8 @@ public bool CheckPermission(string permission)
{
return LoaderSpecific.CheckPermission(Hub, permission);
}
-
- ///
- /// Creates a new instance of for the specified .
- ///
- /// The player's to wrap.
- private XPPlayer(ReferenceHub referenceHub)
- {
- if (referenceHub == null)
- throw new ArgumentNullException(nameof(referenceHub));
-
-#if DEBUG
- if (referenceHub.IsHost)
- {
- var stackTrace = new StackTrace();
- LogInfo("XPPlayer for Dedicated Server was created: " + stackTrace);
- }
-#endif
-
- Hub = referenceHub;
- IsNPC = referenceHub.IsHost || CheckNPC(referenceHub);
-
- if (UserId.TryParseUserId(out var playerId))
- {
- PlayerId = playerId;
- }
- else if (!IsNPC)
- {
- LogWarn("PlayerId "
- + (string.IsNullOrWhiteSpace(UserId) ? "(empty)" : UserId)
- + " could not be parsed for player "
- + DisplayedName);
- }
-
- PlayersValue.Add(referenceHub, this);
- }
-
- ///
- /// Gets a player from their .
- ///
- /// The of the player.
- /// The player.
- public static XPPlayer Get(ReferenceHub hub)
- {
- if (Players.TryGetValue(hub, out XPPlayer player))
- return player;
-
- player = new XPPlayer(hub);
- return player;
- }
-
- ///
- /// Attempts to get a player using a .
- ///
- /// The of the player.
- /// The player, if on the server.
- /// Whether or not the playerid is valid and player is on the server.
- public static bool TryGet(IPlayerId playerId, out XPPlayer player)
- {
- return TryGet(playerId.ToString(), out player);
- }
-
- public static bool TryGet(ICommandSender sender, out XPPlayer player)
- {
- if (sender is not PlayerCommandSender playerSender)
- {
- player = null;
- return false;
- }
-
- player = Get(playerSender.ReferenceHub);
- return true;
- }
-
- ///
- /// Just with extra return.
- ///
- public static bool TryGet(string data, out XPPlayer player)
- {
- player = null;
- if (string.IsNullOrWhiteSpace(data))
- return false;
-
- ReferenceHub hub = GetHub(data);
- if (hub == null)
- return false;
-
- player = Get(hub);
- return true;
- }
-
- ///
- /// Attempts to get a player of a and checks if they have a permission.
- ///
- /// The sender to get the player from.
- /// The permission to check for.
- /// The player if found, otherwise null.
- /// Whether or not the player was found and has the permission.
- public static bool TryGetAndCheckPermission(ICommandSender sender, string permission, out XPPlayer player)
- {
- return TryGet(sender, out player) && player.CheckPermission(permission);
- }
-
- ///
- /// Sets the player's badge.
- ///
- /// The badge to set.
- /// Whether or not the badge is actually set on the server and not just synced to the clients.
- public void SetBadge(Badge badge, bool fakeSyncVar)
- {
- if (badge == null)
- throw new ArgumentNullException(nameof(badge));
-
- if (fakeSyncVar)
- {
- SendFakeSyncVars(typeof(ServerRoles), nameof(ServerRoles.Network_myText), badge.Text);
- SendFakeSyncVars(typeof(ServerRoles), nameof(ServerRoles.Network_myColor), badge.Color);
- }
- else
- {
- Hub.serverRoles.SetText(badge.Text);
- Hub.serverRoles.SetColor(badge.Color);
- }
- }
-
- ///
- /// Sets the player's nickname.
- ///
- /// The nickname to set.
- /// Whether or not the nickname is actually set on the server and not just synced to the clients.
- public void SetNick(string nick, bool fakeSyncVar)
- {
- if (string.IsNullOrWhiteSpace(nick))
- throw new ArgumentNullException(nameof(nick));
-
- if (fakeSyncVar)
- {
- SendFakeSyncVars(typeof(NicknameSync), nameof(NicknameSync.Network_displayName), nick);
- }
- else
- {
- Hub.nicknameSync.DisplayName = nick;
- }
- }
-
- // Because unity do be like that
- private bool GetIsConnectedSafe()
- {
- try
- {
- return Hub.gameObject != null;
- }
- catch (NullReferenceException)
- {
- return false;
- }
- }
-
-#region Exiled sync stuff (Source: https://github.com/Exiled-Team/EXILED/blob/master/Exiled.API/Extensions/MirrorExtensions.cs)
+
+ #region Exiled sync stuff (Source: https://github.com/Exiled-Team/EXILED/blob/master/Exiled.API/Extensions/MirrorExtensions.cs)
///
/// Send fake values to the client's .
///
@@ -380,12 +204,12 @@ public int SendFakeSyncVars(Type targetType, string propertyName, object value,
payload = writer.ToArraySegment(),
};
- foreach (ReferenceHub referenceHub in ReferenceHub.AllHubs)
+ foreach (ReferenceHub hub in ReferenceHub.AllHubs)
{
- if (skipSelf && referenceHub == Hub)
+ if (skipSelf && hub == Hub)
continue;
- referenceHub.connectionToClient.Send(message);
+ hub.connectionToClient.Send(message);
count++;
}
@@ -410,7 +234,7 @@ void CustomSyncVarGenerator(NetworkWriter targetWriter)
/// Value to send to people who don't match the condition.
/// Whether or not to skip sending to self.
/// The amount of people the first value was sent to.
- public int SendFakeSyncVars(Func condition, Type targetType, string propertyName, object value, object value2 = null, bool skipSelf = false)
+ public int SendFakeSyncVars(Func condition, Type targetType, string propertyName, object value, object value2 = null!, bool skipSelf = false)
{
if (!IsConnected)
return -1;
@@ -420,7 +244,7 @@ public int SendFakeSyncVars(Func condition, Type targetType, str
MakeCustomSyncWriter(Hub.networkIdentity, targetType, CustomSyncVarGenerator, writer);
EntityStateMessage message2 = default;
- if (value2 != null)
+ if (value2 != null!)
{
NetworkWriterPooled writer2 = NetworkWriterPool.Get();
MakeCustomSyncWriter(Hub.networkIdentity, targetType, CustomSyncVarGeneratorValue2, writer2);
@@ -440,19 +264,19 @@ public int SendFakeSyncVars(Func condition, Type targetType, str
payload = writer.ToArraySegment(),
};
- foreach (var kvp in Players)
+ foreach (BaseXPPlayer player in XPPlayer.PlayersRealConnected)
{
- if (skipSelf && kvp.Value == this)
+ if (skipSelf && player == this)
continue;
- if (condition(kvp.Value))
+ if (condition(player))
{
- kvp.Value.Hub.connectionToClient.Send(message);
+ player.Hub.connectionToClient.Send(message);
count++;
}
else if (value2 != null)
{
- kvp.Value.Hub.connectionToClient.Send(message2);
+ player.Hub.connectionToClient.Send(message2);
}
}
@@ -484,10 +308,10 @@ public void ResyncSyncVar(Type targetType, string propertyName) =>
Hub.gameObject.GetComponent(targetType),
new object[] { SyncVarDirtyBits[$"{targetType.Name}.{propertyName}"] });
- private static void MakeCustomSyncWriter(NetworkIdentity behaviorOwner, Type targetType, Action customSyncVar, NetworkWriter owner)
+ private static void MakeCustomSyncWriter(NetworkIdentity behaviorOwner, Type targetType, Action? customSyncVar, NetworkWriter owner)
{
ulong value = 0;
- NetworkBehaviour behaviour = null;
+ NetworkBehaviour behaviour = null!;
// Get NetworkBehaviors index (behaviorDirty use index)
for (int i = 0; i < behaviorOwner.NetworkBehaviours.Length; i++)
@@ -522,17 +346,17 @@ private static void MakeCustomSyncWriter(NetworkIdentity behaviorOwner, Type tar
}
#endregion
- ///
- public static implicit operator XPPlayer(ReferenceHub hub) => Get(hub);
-
+ ///
+ public static implicit operator BaseXPPlayer(ReferenceHub hub) => XPPlayer.Get(hub);
///
- public static implicit operator ReferenceHub(XPPlayer player) => player.Hub;
-
+ public static implicit operator ReferenceHub(BaseXPPlayer player) => player.Hub;
+
#if EXILED
- ///
- public static implicit operator XPPlayer(Exiled.API.Features.Player player) => Get(player.ReferenceHub);
+ ///
+ public static implicit operator BaseXPPlayer(Exiled.API.Features.Player player) => XPPlayer.Get(player.ReferenceHub);
#else
- public static implicit operator XPPlayer(LabApi.Features.Wrappers.Player player) => Get(player.ReferenceHub);
+ ///
+ public static implicit operator BaseXPPlayer(LabApi.Features.Wrappers.Player player) => XPPlayer.Get(player.ReferenceHub);
#endif
}
}
\ No newline at end of file
diff --git a/XPSystem/API/Player/XPPlayer.cs b/XPSystem/API/Player/XPPlayer.cs
new file mode 100644
index 0000000..43819fd
--- /dev/null
+++ b/XPSystem/API/Player/XPPlayer.cs
@@ -0,0 +1,171 @@
+namespace XPSystem.API.Player
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Diagnostics.CodeAnalysis;
+ using System.Linq;
+ using CommandSystem;
+ using RemoteAdmin;
+ using XPSystem.API.StorageProviders.Models;
+ using static LoaderSpecific;
+
+ ///
+ /// Extended , for players that can actually gain XP.
+ ///
+ public class XPPlayer : BaseXPPlayer
+ {
+ public static IEnumerable Players => PlayersValue.Values;
+ public static IEnumerable PlayersRealConnected => PlayersValue.Values
+ .Where(x => x.IsConnected && !x.IsNPC);
+ public static IEnumerable XPPlayers => PlayersRealConnected
+ .Where(x => x is XPPlayer)
+ .Cast();
+
+ internal static readonly Dictionary PlayersValue = new();
+
+ ///
+ /// Gets the player's .
+ ///
+ public IPlayerId PlayerId { get; }
+
+ ///
+ /// Gets or sets the player's XP multiplier.
+ /// All XP added by methods (all built-in except for directly via non-wrapper) that respect this value will be multiplied by this value.
+ ///
+ public float XPMultiplier { get; set; } = 1f;
+
+ ///
+ /// Checks if the player can create an instance.
+ /// This is true if the player is not the host and is not an NPC and does not have DNT enabled.
+ ///
+ /// The player to check.
+ /// Whether or not the player can create an instance.
+ private static bool CanCreate(BaseXPPlayer player)
+ {
+ if (player is not { IsConnected: true })
+ return false;
+ return player is { IsNPC: false, DNT: false };
+ }
+
+ private XPPlayer(BaseXPPlayer player, IPlayerId playerId) : base(player.Hub) => PlayerId = playerId;
+ ///
+ /// Attempts to get a player using a .
+ /// Will return a if a cannot be created (see ).
+ ///
+ /// The of the player.
+ /// The (or derivative) instance of the player.
+ /// Thrown if is null.
+ public static BaseXPPlayer Get(ReferenceHub hub)
+ {
+ if (!hub)
+ throw new ArgumentNullException(nameof(hub));
+
+ if (PlayersValue.TryGetValue(hub, out BaseXPPlayer player))
+ return player;
+
+ player = new BaseXPPlayer(hub);
+ if (CanCreate(player))
+ {
+ if (player.UserId.TryParseUserId(out IPlayerId? playerId))
+ player = new XPPlayer(player, playerId);
+ else
+ LogError("Could not parse user ID of player to player ID: " + player.UserId);
+ }
+
+ PlayersValue.Add(hub, player);
+ return player;
+ }
+
+ ///
+ /// but with extra cast.
+ /// Also won't throw on null hub! (Dummies and patching do that)
+ ///
+ public static bool TryGetXP(ReferenceHub? hub, [NotNullWhen(true)] out XPPlayer? player)
+ {
+ player = null;
+ if (!hub)
+ return false;
+
+ player = Get(hub) as XPPlayer;
+ return player != null;
+ }
+
+ ///
+ /// Attempts to get a player using an .
+ ///
+ /// The of the player.
+ /// The player, if on the server.
+ /// Whether or not the player ID is valid and player is on the server.
+ public static bool TryGet(IPlayerId playerId, [NotNullWhen(true)] out BaseXPPlayer? player)
+ {
+ return TryGet(playerId.ToString(), out player);
+ }
+
+ ///
+ /// but extra cast.
+ ///
+ public static bool TryGetXP(IPlayerId playerId, [NotNullWhen(true)] out XPPlayer? player)
+ {
+ player = null;
+ return TryGet(playerId, out BaseXPPlayer? basePlayer)
+ && basePlayer is XPPlayer xpPlayer
+ && (player = xpPlayer) != null;
+ }
+
+ ///
+ /// I wonder...
+ ///
+ public static bool TryGet(ICommandSender sender, [NotNullWhen(true)] out BaseXPPlayer? player)
+ {
+ player = null;
+ if (sender is not PlayerCommandSender playerSender)
+ return false;
+
+ player = Get(playerSender.ReferenceHub);
+ return true;
+ }
+
+ ///
+ /// Just with extra conversion.
+ ///
+ public static bool TryGet(string data, [NotNullWhen(true)] out BaseXPPlayer? player)
+ {
+ player = null;
+ if (string.IsNullOrWhiteSpace(data))
+ return false;
+
+ ReferenceHub? hub = GetHub(data);
+ if (!hub)
+ return false;
+
+ player = Get(hub);
+ return true;
+ }
+
+ ///
+ /// Attempts to get a player of a and checks if they have a permission.
+ ///
+ /// The sender to get the player from.
+ /// The permission to check for.
+ /// The player if found, otherwise null.
+ /// Whether or not the player was found and has the permission.
+ public static bool TryGetAndCheckPermission(ICommandSender sender, string permission, [NotNullWhen(true)] out BaseXPPlayer? player)
+ {
+ return TryGet(sender, out player) && player.CheckPermission(permission);
+ }
+
+ ///
+ public static implicit operator XPPlayer?(ReferenceHub hub) => Get(hub) as XPPlayer;
+
+ ///
+ public static implicit operator ReferenceHub(XPPlayer player) => player.Hub;
+
+#if EXILED
+ ///
+ public static implicit operator XPPlayer?(Exiled.API.Features.Player player) => Get(player.ReferenceHub) as XPPlayer;
+#else
+ ///
+ public static implicit operator XPPlayer?(LabApi.Features.Wrappers.Player player) => Get(player.ReferenceHub) as XPPlayer;
+#endif
+ }
+}
\ No newline at end of file
diff --git a/XPSystem/API/StorageProviders/IStorageProvider.cs b/XPSystem/API/StorageProviders/IStorageProvider.cs
index 0f2dd5c..9b938ae 100644
--- a/XPSystem/API/StorageProviders/IStorageProvider.cs
+++ b/XPSystem/API/StorageProviders/IStorageProvider.cs
@@ -1,6 +1,7 @@
namespace XPSystem.API.StorageProviders
{
using System.Collections.Generic;
+ using System.Diagnostics.CodeAnalysis;
using System.IO;
using XPSystem.API.StorageProviders.Models;
@@ -11,7 +12,7 @@ public interface IStorageProvider
{
void Initialize();
void Dispose();
- bool TryGetPlayerInfo(IPlayerId playerId, out PlayerInfoWrapper playerInfo);
+ bool TryGetPlayerInfo(IPlayerId playerId, [NotNullWhen(true)] out PlayerInfoWrapper? playerInfo);
PlayerInfoWrapper GetPlayerInfoAndCreateOfNotExist(IPlayerId playerId);
IEnumerable GetTopPlayers(int count);
void SetPlayerInfo(PlayerInfoWrapper playerInfo);
diff --git a/XPSystem/API/StorageProviders/Models/PlayerInfo.cs b/XPSystem/API/StorageProviders/Models/PlayerInfo.cs
index f4b6fd7..605f673 100644
--- a/XPSystem/API/StorageProviders/Models/PlayerInfo.cs
+++ b/XPSystem/API/StorageProviders/Models/PlayerInfo.cs
@@ -6,10 +6,10 @@
///
public class PlayerInfo
{
- public IPlayerId Player { get; set; }
+ public IPlayerId Player { get; set; } = null!;
public int XP { get; set; }
#if STORENICKS
- public string Nickname { get; set; }
+ public string? Nickname { get; set; }
#endif
}
}
\ No newline at end of file
diff --git a/XPSystem/API/StorageProviders/PlayerInfoWrapper.cs b/XPSystem/API/StorageProviders/PlayerInfoWrapper.cs
index 9334a02..fe631d3 100644
--- a/XPSystem/API/StorageProviders/PlayerInfoWrapper.cs
+++ b/XPSystem/API/StorageProviders/PlayerInfoWrapper.cs
@@ -23,7 +23,7 @@ public class PlayerInfoWrapper
///
/// Gets the stored nickname of the player.
///
- public string Nickname => PlayerInfo.Nickname;
+ public string? Nickname => PlayerInfo.Nickname;
///
/// Gets or sets the amount of XP of the player has.
diff --git a/XPSystem/API/StorageProviders/StorageProvider.cs b/XPSystem/API/StorageProviders/StorageProvider.cs
index 8deedf1..ed08fb5 100644
--- a/XPSystem/API/StorageProviders/StorageProvider.cs
+++ b/XPSystem/API/StorageProviders/StorageProvider.cs
@@ -1,9 +1,12 @@
-namespace XPSystem.API.StorageProviders
+// ReSharper disable MemberCanBePrivate.Global
+namespace XPSystem.API.StorageProviders
{
using System;
using System.Collections.Generic;
+ using System.Diagnostics.CodeAnalysis;
+ using System.IO;
+ using XPSystem.API.Player;
using XPSystem.API.StorageProviders.Models;
- using XPSystem.EventHandlers;
using static XPAPI;
///
@@ -18,19 +21,19 @@ public abstract class StorageProvider : IStorageProvider
///
public virtual void Dispose() => ClearCache();
- public virtual bool TryGetPlayerInfo(IPlayerId playerId, out PlayerInfoWrapper playerInfo)
+ public virtual bool TryGetPlayerInfo(IPlayerId playerId, [NotNullWhen(true)] out PlayerInfoWrapper? playerInfo)
{
if (TryGetFromCache(playerId, out playerInfo))
return true;
- bool result = TryGetPlayerInfoNoCache(playerId, out PlayerInfo playerInfo3);
- playerInfo = playerInfo3;
+ bool result = TryGetPlayerInfoNoCache(playerId, out PlayerInfo? playerInfo3);
+ playerInfo = playerInfo3!;
return result;
}
public virtual PlayerInfoWrapper GetPlayerInfoAndCreateOfNotExist(IPlayerId playerId)
{
- if (TryGetFromCache(playerId, out PlayerInfoWrapper playerInfo))
+ if (TryGetFromCache(playerId, out PlayerInfoWrapper? playerInfo))
return playerInfo;
return GetPlayerInfoAndCreateOfNotExistNoCache(playerId);
@@ -38,7 +41,7 @@ public virtual PlayerInfoWrapper GetPlayerInfoAndCreateOfNotExist(IPlayerId play
public virtual void SetPlayerInfo(PlayerInfoWrapper playerInfo)
{
- if (XPPlayer.TryGet(playerInfo.Player, out XPPlayer player))
+ if (XPPlayer.TryGetXP(playerInfo.Player, out XPPlayer? player))
player.Variables.Set(VariableKey, playerInfo);
SetPlayerInfoNoCache(playerInfo);
@@ -46,7 +49,7 @@ public virtual void SetPlayerInfo(PlayerInfoWrapper playerInfo)
public virtual bool DeletePlayerInfo(IPlayerId playerId)
{
- if (XPPlayer.TryGet(playerId, out XPPlayer player))
+ if (XPPlayer.TryGetXP(playerId, out XPPlayer? player))
player.Variables.Remove(VariableKey);
return DeletePlayerInfoNoCache(playerId);
@@ -58,18 +61,18 @@ public virtual void DeleteAllPlayerInfo()
DeleteAllPlayerInfoNoCache();
}
- protected virtual bool TryGetFromCache(IPlayerId playerId, out PlayerInfoWrapper playerInfo)
+ protected virtual bool TryGetFromCache(IPlayerId playerId, [NotNullWhen(true)] out PlayerInfoWrapper? playerInfo)
{
playerInfo = null;
- if (!XPPlayer.TryGet(playerId, out XPPlayer player))
+ if (!XPPlayer.TryGetXP(playerId, out XPPlayer? player))
{
LogDebug("Player not in server: " + playerId);
playerInfo = null;
return false;
}
- if (!player.Variables.TryGet(VariableKey, out object playerInfoObj))
+ if (!player.Variables.TryGet(VariableKey, out object? playerInfoObj))
{
LogDebug("Player variable cache not found - adding " + playerId);
@@ -89,48 +92,58 @@ protected virtual bool TryGetFromCache(IPlayerId playerId, out PlayerInfoWrapper
public virtual void ClearCache()
{
- foreach (var kvp in XPPlayer.Players)
- kvp.Value.Variables.Remove(VariableKey);
+ foreach (BaseXPPlayer player in XPPlayer.PlayersRealConnected)
+ player.Variables.Remove(VariableKey);
}
public abstract void Initialize();
public abstract IEnumerable GetTopPlayers(int count);
- protected abstract bool TryGetPlayerInfoNoCache(IPlayerId playerId, out PlayerInfo playerInfo);
+ protected abstract bool TryGetPlayerInfoNoCache(IPlayerId playerId, [NotNullWhen(true)] out PlayerInfo? playerInfo);
protected abstract PlayerInfo GetPlayerInfoAndCreateOfNotExistNoCache(IPlayerId playerId);
protected abstract void SetPlayerInfoNoCache(PlayerInfo playerInfo);
protected abstract bool DeletePlayerInfoNoCache(IPlayerId playerId);
protected abstract void DeleteAllPlayerInfoNoCache();
///
- /// Ignore this.
- /// Used by loader when combined with .
- ///
- public virtual object ConfigPropertyInternal { get; set; }
-
- ///
- /// Ignore this.
- /// Used by loader when combined with .
- /// Type of .
+ /// Ignore, used by loader in case of .
///
- public virtual Type ConfigTypeInternal { get; } = null;
+ internal virtual void LoadConfig()
+ {
+ }
}
///
/// template with config.
///
/// The type of the config.
- public abstract class StorageProvider : StorageProvider where T : new()
+ public abstract class StorageProvider : StorageProvider where T : class, new()
{
- public T Config;
+ public T Config { get; private set; } = null!;
- ///
- public override object ConfigPropertyInternal
+ ///
+ /// Ignore, used by loader.
+ ///
+ internal override void LoadConfig()
{
- get => Config ?? new T();
- set => Config = (T)value;
- }
+ string name = GetType().Name;
+ string file = Path.Combine(XPAPI.Config.ExtendedConfigPath, name + ".yml");
- ///
- public override Type ConfigTypeInternal { get; } = typeof(T);
+ if (File.Exists(file))
+ {
+ try
+ {
+ Config = Deserializer.Deserialize(File.ReadAllText(file));
+ }
+ catch (Exception e)
+ {
+ LogError($"Error loading storageprovider config for {name}: {e}");
+ }
+ }
+ else
+ {
+ Config = new T();
+ File.WriteAllText(file, Serializer.Serialize(Config));
+ }
+ }
}
}
\ No newline at end of file
diff --git a/XPSystem/API/Variables/Variable.cs b/XPSystem/API/Variables/Variable.cs
index e6bbc3f..e0269f5 100644
--- a/XPSystem/API/Variables/Variable.cs
+++ b/XPSystem/API/Variables/Variable.cs
@@ -10,7 +10,7 @@ public class Variable
///
/// Gets or sets value of the variable.
///
- public object Value { get; set; }
+ public object? Value { get; set; }
///
/// Gets or sets the expiry time of the variable.
@@ -61,7 +61,7 @@ public T As()
if (Value is T value)
return value;
- throw new InvalidCastException($"Cannot cast {Value.GetType()} to {typeof(T)}");
+ throw new InvalidCastException($"Cannot cast {Value?.GetType().ToString() ?? "null"} to {typeof(T)}");
}
///
diff --git a/XPSystem/API/Variables/VariableCollection.cs b/XPSystem/API/Variables/VariableCollection.cs
index da8c40b..c8dc037 100644
--- a/XPSystem/API/Variables/VariableCollection.cs
+++ b/XPSystem/API/Variables/VariableCollection.cs
@@ -3,13 +3,14 @@
using System;
using System.Collections;
using System.Collections.Generic;
+ using System.Diagnostics.CodeAnalysis;
///
/// Represents a collection of variables.
///
public class VariableCollection : IEnumerable>
{
- private Dictionary _variables = new();
+ private readonly Dictionary _variables = new();
///
/// Gets the number of variables in the collection.
@@ -69,7 +70,7 @@ public void Set(string key, object value, DateTime? expiryTime = null)
/// The key of the variable.
/// The variable with the specified key, if found; otherwise, null.
/// Whether or not the variable was found.
- public bool TryGet(string key, out Variable variable)
+ public bool TryGet(string key, [NotNullWhen(true)] out Variable? variable)
{
if (_variables.TryGetValue(key, out variable))
{
@@ -91,11 +92,11 @@ public bool TryGet(string key, out Variable variable)
/// The type to cast the variable to.
/// Whether or not the variable was found and casted.
/// Will throw if the cast fails.
- public bool TryGet(string key, out T value)
+ public bool TryGet(string key, [NotNullWhen(true)] out T? value)
{
- if (TryGet(key, out Variable variable))
+ if (TryGet(key, out Variable? variable))
{
- value = variable.As();
+ value = variable.As()!;
return true;
}
@@ -114,12 +115,12 @@ public bool TryGet(string key, out T value)
/// Gets or sets the variable with the specified key.
///
/// The key of the variable.
- public Variable this[string key]
+ public Variable? this[string key]
{
- get => TryGet(key, out Variable variable)
+ get => TryGet(key, out Variable? variable)
? variable
: null;
- set => _variables[key] = value;
+ set => _variables[key] = value!;
}
///
diff --git a/XPSystem/API/XPAPI.cs b/XPSystem/API/XPAPI.cs
index d1db833..b87c2ce 100644
--- a/XPSystem/API/XPAPI.cs
+++ b/XPSystem/API/XPAPI.cs
@@ -1,14 +1,16 @@
-namespace XPSystem.API
+// ReSharper disable MemberCanBePrivate.Global
+namespace XPSystem.API
{
using System;
using System.Collections.Generic;
- using System.IO;
+ using System.Diagnostics.CodeAnalysis;
using System.Text;
using NorthwoodLib.Pools;
using PlayerRoles;
using XPSystem.API.DisplayProviders;
using XPSystem.API.Enums;
using XPSystem.API.Exceptions;
+ using XPSystem.API.Player;
using XPSystem.API.StorageProviders;
using XPSystem.API.StorageProviders.Models;
using XPSystem.Config;
@@ -26,6 +28,7 @@ public static class XPAPI
///
/// Whether the plugin is enabled or not.
///
+ // ReSharper disable once UnusedAutoPropertyAccessor.Global
public static bool PluginEnabled { get; internal set; } = false;
///
@@ -35,18 +38,18 @@ public static class XPAPI
///
/// The display provider for the plugin.
- /// May be null ( or uninitialized).
+ /// Null if ( or uninitialized).
///
- public static IMessagingProvider MessagingProvider;
+ public static IMessagingProvider? MessagingProvider;
///
/// The storage provider for the plugin.
/// Change it using .
///
- public static IStorageProvider StorageProvider { get; private set; }
+ public static IStorageProvider? StorageProvider { get; private set; }
///
- /// The xp display providers.
+ /// The XP display providers.
///
public static readonly XPDisplayProviderCollection DisplayProviders = new();
@@ -122,13 +125,12 @@ public static class XPAPI
///
public static Action LogError = LoaderSpecific.LogError;
#endregion
-
#region Storage
///
/// Sets the storage provider for the plugin.
///
/// The storage provider to set.
- public static void SetStorageProvider(IStorageProvider provider)
+ public static void SetStorageProvider(IStorageProvider? provider)
{
try
{
@@ -141,14 +143,15 @@ public static void SetStorageProvider(IStorageProvider provider)
if (provider == null)
{
- LogDebug("Disposed storage provider. No data will be read or saved!");
+ StorageProvider = null;
+ LogInfo("Storage provider set to null, no data will be read or saved!");
return;
}
try
{
- if (provider is StorageProvider { ConfigTypeInternal: not null } storageProvider)
- LoadStorageProviderConfig(storageProvider);
+ if (provider is StorageProvider storageProvider)
+ storageProvider.LoadConfig();
provider.Initialize();
}
@@ -175,7 +178,7 @@ public static void SetStorageProvider(string typeName)
return;
}
- if (Main.TryCreate(typeName, out Exception e, out IStorageProvider provider))
+ if (Main.TryCreate(typeName, out Exception? e, out IStorageProvider? provider))
{
SetStorageProvider(provider);
return;
@@ -185,36 +188,6 @@ public static void SetStorageProvider(string typeName)
LogError("No data will be read or saved!");
}
- ///
- /// Loads the storage providers config.
- ///
- /// The storage provider whose config is to be loaded.
- public static void LoadStorageProviderConfig(StorageProvider provider)
- {
- string name = provider.GetType().Name;
- string file = Path.Combine(Config.ExtendedConfigPath, name + ".yml");
-
- if (File.Exists(file))
- {
- try
- {
- provider.ConfigPropertyInternal =
- Deserializer.Deserialize(File.ReadAllText(file), provider.ConfigTypeInternal);
- }
- catch (Exception e)
- {
- LogError($"Error loading storageprovider config for {name}: {e}");
- }
- }
- else
- {
- object obj = provider.ConfigPropertyInternal;
-
- File.WriteAllText(file, Serializer.Serialize(obj));
- provider.ConfigPropertyInternal = obj;
- }
- }
-
///
/// Ensures that the storage provider is valid.
///
@@ -234,7 +207,7 @@ public static void EnsureStorageProviderValid()
public static PlayerInfoWrapper GetPlayerInfo(IPlayerId playerId)
{
EnsureStorageProviderValid();
- return StorageProvider.GetPlayerInfoAndCreateOfNotExist(playerId);
+ return StorageProvider!.GetPlayerInfoAndCreateOfNotExist(playerId);
}
///
@@ -253,12 +226,12 @@ public static PlayerInfoWrapper GetPlayerInfo(XPPlayer player)
///
/// The player to update the nickname of.
/// The player's . Optional, only pass if you already have it, saves barely any time.
- public static void UpdateNickname(XPPlayer player, PlayerInfoWrapper playerInfo = null)
+ public static void UpdateNickname(XPPlayer player, PlayerInfoWrapper? playerInfo = null)
{
playerInfo ??= GetPlayerInfo(player);
playerInfo.PlayerInfo.Nickname = player.DisplayedName;
- StorageProvider.SetPlayerInfo(playerInfo);
+ StorageProvider!.SetPlayerInfo(playerInfo);
LogDebug("Updated nick of " + player.PlayerId + " to " + player.DisplayedName);
}
#endif
@@ -268,38 +241,32 @@ public static void UpdateNickname(XPPlayer player, PlayerInfoWrapper playerInfo
///
/// The player to add XP to.
/// The amount of XP to add.
- /// Whether to force the addition of XP,
- /// even if
- /// or the player has enabled
- /// or is true.
+ /// Whether to force the addition of XP, even if .
/// The player's . Optional, only pass if you already have it, saves barely any time.
- /// Whether or not the XP was added.
- public static bool AddXP(XPPlayer player, int amount, bool force = false, PlayerInfoWrapper playerInfo = null)
+ /// Whether or not the player leveled up.
+ public static bool AddXP(XPPlayer player, int amount, bool force = false, PlayerInfoWrapper? playerInfo = null)
{
if (amount == 0)
return false;
- if (!force && (XPGainPaused || player.DNT) || player.IsNPC)
+ if (!force && XPGainPaused)
return false;
- playerInfo ??= GetPlayerInfo(player.PlayerId);
-
- AddXP(playerInfo, amount, player);
- return true;
+ return AddXP(playerInfo ?? GetPlayerInfo(player.PlayerId), amount, player);
}
///
/// The method that actually adds XP to a player.
/// Beware: No checks!
///
- internal static bool AddXP(PlayerInfoWrapper playerInfo, int amount, XPPlayer player = null)
+ internal static bool AddXP(PlayerInfoWrapper playerInfo, int amount, XPPlayer? player = null)
{
if (player == null)
- XPPlayer.TryGet(playerInfo.Player, out player);
+ XPPlayer.TryGetXP(playerInfo.Player, out player);
int prevLevel = playerInfo.Level;
float floatAmount = amount;
- bool connected = player?.IsConnected ?? false;
+ bool connected = player != null;
if (amount > 0 || Config.XPMultiplierForXPLoss)
{
@@ -313,10 +280,13 @@ internal static bool AddXP(PlayerInfoWrapper playerInfo, int amount, XPPlayer pl
amount = (int)floatAmount;
playerInfo.PlayerInfo.XP += amount;
- StorageProvider.SetPlayerInfo(playerInfo);
+ StorageProvider!.SetPlayerInfo(playerInfo);
+
+ if (playerInfo.Level == prevLevel)
+ return false;
- if (connected && playerInfo.Level != prevLevel)
- HandleLevelUp(player, playerInfo, prevLevel);
+ if (connected)
+ HandleLevelUp(player!, playerInfo, prevLevel);
return true;
}
@@ -328,9 +298,9 @@ internal static bool AddXP(PlayerInfoWrapper playerInfo, int amount, XPPlayer pl
/// The player to display the message to.
/// The message to display.
/// If is null, it will not be displayed.
- public static void DisplayMessage(XPPlayer player, string message)
+ public static void DisplayMessage(BaseXPPlayer player, string? message)
{
- if (string.IsNullOrWhiteSpace(message) || player.IsNPC)
+ if (string.IsNullOrWhiteSpace(message))
return;
MessagingProvider?.DisplayMessage(player, Config.TextPrefix + message + Config.TextSuffix, Config.DisplayDuration);
@@ -338,34 +308,21 @@ public static void DisplayMessage(XPPlayer player, string message)
#endregion
#region Mixed
///
- /// Adds XP to a player and displays it's corresponding message.
- /// Respects role overrides, DNT, and .
+ /// Tries to add XP to a player and display it's corresponding message.
+ /// Respects limits, role overrides, and .
///
/// The player to affect.
/// The key of the .
/// The subkeys of the .
- /// Whether or not the XP was added and the message was sent (can be forced with
- ///
- /// and ).
- /// Uses .
- public static bool AddXPAndDisplayMessage(XPPlayer player, string key, params object[] subkeys)
- {
- return AddXPAndDisplayMessage(player, XPECManager.GetItem(key, player.Role, subkeys));
- }
-
- ///
- /// Tries to add XP to a player and display it's corresponding message.
- /// Respects limits, role overrides, DNT, and .
- ///
- ///
+ /// Whether or not the XP was added.
/// Uses .
- public static bool TryAddXPAndDisplayMessage(XPPlayer player, string key, params object[] subkeys)
+ public static bool TryAddXPAndDisplayMessage(XPPlayer? player, string key, params object?[] subkeys)
{
- if (!player.IsConnected)
+ if (player is not { IsConnected: true })
return false;
- XPECFile file = XPECManager.GetFile(key, player.Role);
- XPECItem item = file?.Get(subkeys);
+ XPECFile? file = XPECManager.GetFile(key, player.Role);
+ XPECItem? item = file?.Get(subkeys);
if (item == null)
return false;
@@ -380,49 +337,100 @@ public static bool TryAddXPAndDisplayMessage(XPPlayer player, string key, params
///
/// Adds XP to a player and displays it's corresponding message.
- /// Respects role overrides, DNT, and .
+ /// Respects role overrides and .
///
/// The player to affect.
/// The containing the amount and the message.
- /// Whether or not the XP was added and the message was sent (can be forced with
- ///
- /// and ).
- public static bool AddXPAndDisplayMessage(XPPlayer player, XPECItem xpecItem)
+ /// Whether or not the XP was added.
+ public static bool AddXPAndDisplayMessage(XPPlayer player, XPECItem? xpecItem)
{
- if (xpecItem == null || xpecItem.Amount == 0 || player.DNT || XPGainPaused)
+ if (xpecItem == null)
+ return false;
+
+ return AddXPAndDisplayMessage(player, xpecItem.Amount, xpecItem.Translation);
+ }
+
+ ///
+ /// Adds XP to a player and displays it's corresponding message.
+ ///
+ /// The player to affect.
+ /// The amount of XP to add.
+ /// The message to display.
+ /// Whether to force the addition of XP, even if amount = 0 or .
+ /// Whether or not XP was added.
+ public static bool AddXPAndDisplayMessage(XPPlayer player, int amount, string? message, bool force = false)
+ {
+ if (amount == 0 && !force || XPGainPaused)
return false;
PlayerInfoWrapper playerInfo = GetPlayerInfo(player.PlayerId);
- AddXP(player, xpecItem.Amount, playerInfo: playerInfo);
+ bool levelup = AddXP(player, amount, force: true, playerInfo: playerInfo);
+
+ if (levelup && !Config.ShowXPOnLevelUp)
+ return true;
- string message = xpecItem.Translation;
- if (message != null && Config.UseAddedXPTemplate)
+ if (!string.IsNullOrWhiteSpace(message))
{
- message = Config.AddedXPTemplate
+ if (Config.UseAddedXPTemplate)
+ message = FormatMessage(message!, playerInfo);
+ DisplayMessage(player, message);
+ }
+
+ return true;
+ }
+
+ ///
+ /// Formats a message according to the for a player.
+ ///
+ /// The message to format.
+ /// The of the player to format the message for.
+ /// The formatted message.
+ public static string FormatMessage(string message, PlayerInfoWrapper playerInfo)
+ {
+ message = Config.AddedXPTemplate
.Replace("%message%", message)
.Replace("%currentlevel%", playerInfo.Level.ToString())
.Replace("%nextlevel%", (playerInfo.Level + 1).ToString());
- if (Config.UseTotalXP)
+ message = message
+ .Replace("%currentxp%",
+ (Config.UseTotalXP
+ ? playerInfo.XP
+ : playerInfo.XP - playerInfo.NeededXPCurrent)
+ .ToString())
+ .Replace("%neededxp%",
+ (Config.UseTotalXP
+ ? playerInfo.NeededXPNext
+ : playerInfo.NeededXPNext - playerInfo.NeededXPCurrent)
+ .ToString());
+
+ if (Config.AddedXPTemplate.Contains("%progressbarfilled%") ||
+ Config.AddedXPTemplate.Contains("%progressbarremaining%"))
+ {
+ if (string.IsNullOrEmpty(Config.AddedXPProgressBarChars) || Config.AddedXPProgressBarChars.Length < 2)
{
+ LogWarn("Template contains progress bar, but no/not enough characters are set for it!");
message = message
- .Replace("%currentxp%", playerInfo.XP.ToString())
- .Replace("%neededxp%", playerInfo.NeededXPNext.ToString());
+ .Replace("%progressbarfilled%", string.Empty)
+ .Replace("%progressbarremaining%", string.Empty);
}
else
{
+ char filledChar = Config.AddedXPProgressBarChars[0];
+ char remainingChar = Config.AddedXPProgressBarChars[1];
+ double fillPercentage = (double)(playerInfo.XP - playerInfo.NeededXPCurrent) /
+ (playerInfo.NeededXPNext - playerInfo.NeededXPCurrent);
+ int fill = (int)(Config.AddedXPProgressBarLength * fillPercentage);
+
message = message
- .Replace("%currentxp%",
- (playerInfo.XP - playerInfo.NeededXPCurrent)
- .ToString())
- .Replace("%neededxp%",
- (playerInfo.NeededXPNext - playerInfo.NeededXPCurrent)
- .ToString());
+ .Replace("%progressbarfilled%",
+ new string(filledChar, fill))
+ .Replace("%progressbarremaining%",
+ new string(remainingChar, Config.AddedXPProgressBarLength - fill));
}
}
- DisplayMessage(player, message);
- return true;
+ return message;
}
#endregion
#region Misc
@@ -451,9 +459,9 @@ public static void HandleLevelUp(XPPlayer player, PlayerInfoWrapper wrapper, int
/// The id value.
/// The of the id.
/// If successful, the created. Otherwise, null.
- public static IPlayerId CreateUserId(object id, AuthType authType)
+ public static IPlayerId? CreateUserId(object id, AuthType authType)
{
- bool EnsureIs(out T obj)
+ bool EnsureIs([NotNullWhen(true)] out T? obj)
{
if (id is T t)
{
@@ -482,7 +490,7 @@ bool EnsureIs(out T obj)
LogDebug("UserId creating failed (not ulong)");
return null;
case AuthType.Northwood:
- if (EnsureIs(out string stringId))
+ if (EnsureIs(out string? stringId))
return new StringPlayerId(stringId, authType);
LogDebug("UserId creating failed (not string)");
@@ -498,7 +506,7 @@ bool EnsureIs(out T obj)
/// The string to parse.
/// The equivalent .
/// Whether or not the parsing was successful.
- public static bool TryParseUserId(string @string, out IPlayerId playerId)
+ public static bool TryParseUserId(string? @string, [NotNullWhen(true)] out IPlayerId? playerId)
{
playerId = null;
if (@string == null)
diff --git a/XPSystem/API/XPExtensions.cs b/XPSystem/API/XPExtensions.cs
index e934bc4..8e012ae 100644
--- a/XPSystem/API/XPExtensions.cs
+++ b/XPSystem/API/XPExtensions.cs
@@ -2,7 +2,9 @@
{
using System;
using System.Collections.Generic;
+ using System.Diagnostics.CodeAnalysis;
using CommandSystem;
+ using XPSystem.API.Player;
using XPSystem.API.StorageProviders;
using XPSystem.API.StorageProviders.Models;
using XPSystem.Config.Events.Types;
@@ -10,7 +12,7 @@
public static class XPExtensions
{
///
- public static bool TryParseUserId(this string @string, out IPlayerId playerId) => XPAPI.TryParseUserId(@string, out playerId);
+ public static bool TryParseUserId(this string @string, [NotNullWhen(true)] out IPlayerId? playerId) => XPAPI.TryParseUserId(@string, out playerId);
///
public static string FormatLeaderboard(this IEnumerable players) => XPAPI.FormatLeaderboard(players);
@@ -27,17 +29,17 @@ public static class XPExtensions
///
public static PlayerInfoWrapper GetPlayerInfo(this XPPlayer player) => XPAPI.GetPlayerInfo(player);
- ///
- public static void DisplayMessage(this XPPlayer player, string message) => XPAPI.DisplayMessage(player, message);
+ ///
+ public static void DisplayMessage(this BaseXPPlayer player, string message) => XPAPI.DisplayMessage(player, message);
///
- public static bool AddXP(this XPPlayer player, int amount, bool notify = false) => XPAPI.AddXP(player, amount, notify);
+ public static bool AddXP(this XPPlayer player, int amount, bool force = false) => XPAPI.AddXP(player, amount, force);
///
- public static void AddXPAndDisplayMessage(this XPPlayer player, XPECItem item) => XPAPI.AddXPAndDisplayMessage(player, item);
+ public static void AddXPAndDisplayMessage(this XPPlayer player, XPECItem? item) => XPAPI.AddXPAndDisplayMessage(player, item);
///
- public static void TryAddXPAndDisplayMessage(this XPPlayer player, string key, params object[] args) => XPAPI.TryAddXPAndDisplayMessage(player, key, args);
+ public static void TryAddXPAndDisplayMessage(this XPPlayer? player, string key, params object?[] args) => XPAPI.TryAddXPAndDisplayMessage(player, key, args);
///
public static string FormatType(this Type type) => XPAPI.FormatType(type);
diff --git a/XPSystem/BuiltInProviders/Display/Patch/MyNickPatchXPDisplayProvider.cs b/XPSystem/BuiltInProviders/Display/Patch/MyNickPatchXPDisplayProvider.cs
index 068aec5..ea63375 100644
--- a/XPSystem/BuiltInProviders/Display/Patch/MyNickPatchXPDisplayProvider.cs
+++ b/XPSystem/BuiltInProviders/Display/Patch/MyNickPatchXPDisplayProvider.cs
@@ -3,18 +3,19 @@
using System.ComponentModel;
using HarmonyLib;
using XPSystem.API;
+ using XPSystem.API.Player;
public class MyNickPatchXPDisplayProvider : XPDisplayProvider
{
public override void RefreshAll() {}
- public override void RefreshTo(XPPlayer player) {}
+ public override void RefreshTo(BaseXPPlayer player) {}
[HarmonyPatch(typeof(NicknameSync), nameof(NicknameSync.Network_myNickSync), MethodType.Setter)]
internal static class NicknamePatch
{
public static void Prefix(NicknameSync __instance, ref string value)
{
- if (!__instance._hub || __instance._hub.IsHost || __instance._hub.IsDummy)
+ if (!XPPlayer.TryGetXP(__instance._hub, out XPPlayer? player))
return;
foreach (IXPDisplayProvider provider in XPAPI.DisplayProviders)
@@ -25,7 +26,7 @@ public static void Prefix(NicknameSync __instance, ref string value)
return;
value = nickProvider.Config.NickStructure
- .Replace("%lvl%", XPAPI.GetPlayerInfo(__instance._hub).Level.ToString())
+ .Replace("%lvl%", XPAPI.GetPlayerInfo(player).Level.ToString())
.Replace("%name%", value);
return;
diff --git a/XPSystem/BuiltInProviders/Display/Patch/NickPatchXPDisplayProvider.cs b/XPSystem/BuiltInProviders/Display/Patch/NickPatchXPDisplayProvider.cs
index e929a98..0439ba3 100644
--- a/XPSystem/BuiltInProviders/Display/Patch/NickPatchXPDisplayProvider.cs
+++ b/XPSystem/BuiltInProviders/Display/Patch/NickPatchXPDisplayProvider.cs
@@ -4,17 +4,21 @@
using System.ComponentModel;
using HarmonyLib;
using XPSystem.API;
+ using XPSystem.API.Player;
using XPSystem.API.StorageProviders;
public class NickPatchXPDisplayProvider : XPDisplayProvider
{
public Dictionary DisplayNameOverrides { get; } = new();
- protected override void RefreshOfEnabled(XPPlayer player, PlayerInfoWrapper playerInfo) => Refresh(player);
- protected override void RefreshOfDisabled(XPPlayer player) => Refresh(player);
+ protected override void RefreshOfEnabled(BaseXPPlayer player, PlayerInfoWrapper? playerInfo) => Refresh(player);
+ protected override void RefreshOfDisabled(BaseXPPlayer player) => Refresh(player);
- private void Refresh(XPPlayer player)
+ private void Refresh(BaseXPPlayer player)
{
+ if (player is not XPPlayer)
+ return;
+
player.Hub.nicknameSync.DisplayName = DisplayNameOverrides.TryGetValue(player.UserId, out string cached)
? cached
: player.DisplayedName;
@@ -25,7 +29,7 @@ internal static class DisplayNamePatch
{
public static void Prefix(NicknameSync __instance, ref string value)
{
- if (!__instance._hub || __instance._hub.IsHost || __instance._hub.IsDummy)
+ if (!XPPlayer.TryGetXP(__instance._hub, out XPPlayer? player))
return;
foreach (IXPDisplayProvider provider in XPAPI.DisplayProviders)
@@ -35,9 +39,9 @@ public static void Prefix(NicknameSync __instance, ref string value)
if (!nickProvider.Config.Enabled)
return;
- nickProvider.DisplayNameOverrides[__instance._hub.authManager.UserId] = value;
+ nickProvider.DisplayNameOverrides[player.UserId] = value;
value = nickProvider.Config.NickStructure
- .Replace("%lvl%", XPAPI.GetPlayerInfo(__instance._hub).Level.ToString())
+ .Replace("%lvl%", XPAPI.GetPlayerInfo(player).Level.ToString())
.Replace("%name%", value);
return;
diff --git a/XPSystem/BuiltInProviders/Display/Patch/RankSetXPDisplayProvider.cs b/XPSystem/BuiltInProviders/Display/Patch/RankSetXPDisplayProvider.cs
index 5a35fd9..f1bfad3 100644
--- a/XPSystem/BuiltInProviders/Display/Patch/RankSetXPDisplayProvider.cs
+++ b/XPSystem/BuiltInProviders/Display/Patch/RankSetXPDisplayProvider.cs
@@ -6,17 +6,17 @@
using HarmonyLib;
using MEC;
using XPSystem.API;
+ using XPSystem.API.Player;
using XPSystem.API.StorageProviders;
- using XPSystem.Config.Models;
using XPSystem.EventHandlers;
using YamlDotNet.Serialization;
public class RankSetXPDisplayProvider : XPDisplayProvider
{
public override void RefreshAll() {}
- public override void RefreshTo(XPPlayer player) {}
+ public override void RefreshTo(BaseXPPlayer player) {}
- private Badge GetBadge(XPPlayer player, PlayerInfoWrapper playerInfo)
+ private Badge? GetBadge(BaseXPPlayer player, PlayerInfoWrapper? playerInfo)
{
if (Config.SkipGlobalBadges && player.HasGlobalBadge)
return null;
@@ -26,17 +26,20 @@ private Badge GetBadge(XPPlayer player, PlayerInfoWrapper playerInfo)
if (player.DNT)
{
- if (player.HasBadge && !player.HasHiddenBadge)
- return null;
-
- return Config.DNTBadge;
+ return player is { HasBadge: true, HasHiddenBadge: false }
+ ? null
+ : Config.DNTBadge;
}
- Badge badge = null;
+ if (player is not XPPlayer xpPlayer)
+ return null;
+ playerInfo ??= xpPlayer.GetPlayerInfo();
+
+ Badge? badge = null;
string format = !player.HasBadge || player.HasHiddenBadge
? Config.BadgeStructureNoBadge
: Config.BadgeStructure;
- string color = "default";
+ string? color = null;
foreach (var kvp in Config.SortedBadges)
{
@@ -59,13 +62,13 @@ private Badge GetBadge(XPPlayer player, PlayerInfoWrapper playerInfo)
.Replace("%lvl%", playerInfo.Level.ToString())
.Replace("%badge%", badge.Text)
.Replace("%oldbadge%", player.BadgeText),
- Color = color
+ Color = color ?? "default"
};
}
- private void Refresh(XPPlayer player, PlayerInfoWrapper playerInfo = null)
+ private void Refresh(BaseXPPlayer player, PlayerInfoWrapper? playerInfo = null)
{
- Badge badge = GetBadge(player, playerInfo ?? XPAPI.GetPlayerInfo(player));
+ Badge? badge = GetBadge(player, playerInfo);
if (badge == null)
return;
@@ -114,13 +117,16 @@ public class HiddenBadgePatchHide
private static void Refresh(ServerRoles instance)
{
+ if (!XPPlayer.TryGetXP(instance._hub, out XPPlayer? player))
+ return;
+
foreach (IXPDisplayProvider provider in XPAPI.DisplayProviders)
{
- if (provider is RankSetXPDisplayProvider rankProvider && rankProvider.Config.Enabled && rankProvider.Config.PatchBadgeCommands)
+ if (provider is RankSetXPDisplayProvider { Config: { Enabled: true, PatchBadgeCommands: true } } rankProvider)
{
Timing.CallDelayed(.5f + XPAPI.Config.ExtraDelay, () =>
{
- rankProvider.Refresh(instance._hub);
+ rankProvider.Refresh(player);
});
return;
@@ -156,10 +162,10 @@ public class RankConfig : IXPDisplayProviderConfig
public Badge DNTBadge { get; set; } = new()
{
Text = "(DNT) anonymous man????",
- Color = Misc.PlayerInfoColorTypes.Nickel.ToString()
+ Color = nameof(Misc.PlayerInfoColorTypes.Nickel)
};
- private Dictionary _sortedBadges;
+ private Dictionary? _sortedBadges = null!;
[YamlIgnore]
public Dictionary SortedBadges => _sortedBadges ??= Badges
.OrderBy(x => x.Key)
@@ -171,27 +177,27 @@ public class RankConfig : IXPDisplayProviderConfig
[0] = new Badge
{
Text = "Visitor",
- Color = Misc.PlayerInfoColorTypes.Cyan.ToString().ToLower()
+ Color = nameof(Misc.PlayerInfoColorTypes.Cyan).ToLower()
},
[1] = new Badge
{
Text = "Junior",
- Color = Misc.PlayerInfoColorTypes.Orange.ToString().ToLower()
+ Color = nameof(Misc.PlayerInfoColorTypes.Orange).ToLower()
},
[5] = new Badge
{
Text = "Senior",
- Color = Misc.PlayerInfoColorTypes.Yellow.ToString().ToLower()
+ Color = nameof(Misc.PlayerInfoColorTypes.Yellow).ToLower()
},
[10] = new Badge
{
Text = "Veteran",
- Color = Misc.PlayerInfoColorTypes.Red.ToString().ToLower()
+ Color = nameof(Misc.PlayerInfoColorTypes.Red).ToLower()
},
[50] = new Badge
{
Text = "Nerd",
- Color = Misc.PlayerInfoColorTypes.Lime.ToString().ToLower()
+ Color = nameof(Misc.PlayerInfoColorTypes.Lime).ToLower()
}
};
}
diff --git a/XPSystem/BuiltInProviders/Display/SyncVar/NickXPDisplayProvider.cs b/XPSystem/BuiltInProviders/Display/SyncVar/NickXPDisplayProvider.cs
index cbd7977..630d24a 100644
--- a/XPSystem/BuiltInProviders/Display/SyncVar/NickXPDisplayProvider.cs
+++ b/XPSystem/BuiltInProviders/Display/SyncVar/NickXPDisplayProvider.cs
@@ -6,19 +6,28 @@
using MEC;
using XPSystem.API;
using XPSystem.API.DisplayProviders;
+ using XPSystem.API.Player;
using XPSystem.API.StorageProviders;
public class NickXPDisplayProvider : SyncVarXPDisplayProvider
{
protected override string VariableKey { get; } = "NickXPDisplayProvider_nick";
- protected override (Type typeName, string methodName, Func getFakeSyncVar, Func getResyncVar)[] SyncVars { get; } =
+ protected override (Type typeName, string methodName, Func getFakeSyncVar, Func getResyncVar)[] SyncVars { get; } =
{
(typeof(NicknameSync), nameof(NicknameSync.Network_displayName), (_, obj) => obj, player => player.DisplayedName)
};
- protected override string CreateObject(XPPlayer player, PlayerInfoWrapper playerInfo)
+ protected override string? CreateObject(BaseXPPlayer player, PlayerInfoWrapper? playerInfo)
{
+ if (playerInfo == null)
+ {
+ if (player is XPPlayer xpPlayer)
+ playerInfo = xpPlayer.GetPlayerInfo();
+ else
+ return null;
+ }
+
return Config.NickStructure
.Replace("%lvl%", playerInfo.Level.ToString())
.Replace("%name%", player.DisplayedName);
@@ -29,16 +38,17 @@ internal static class NickCommandPatch
{
public static void Postfix(NicknameSync __instance)
{
- if (__instance._hub.IsDummy)
+ XPPlayer? player = __instance._hub;
+ if (player == null)
return;
foreach (IXPDisplayProvider provider in XPAPI.DisplayProviders)
{
- if (provider is NickXPDisplayProvider nickProvider && nickProvider.Config.PatchNickCommand)
+ if (provider is NickXPDisplayProvider { Config: { PatchNickCommand: true } } nickProvider)
{
Timing.CallDelayed(.5f + XPAPI.Config.ExtraDelay, () =>
{
- nickProvider.RefreshOf(__instance._hub);
+ nickProvider.RefreshOf(player);
});
return;
diff --git a/XPSystem/BuiltInProviders/Display/SyncVar/RankXPDisplayProvider.cs b/XPSystem/BuiltInProviders/Display/SyncVar/RankXPDisplayProvider.cs
index d856383..41ec43c 100644
--- a/XPSystem/BuiltInProviders/Display/SyncVar/RankXPDisplayProvider.cs
+++ b/XPSystem/BuiltInProviders/Display/SyncVar/RankXPDisplayProvider.cs
@@ -8,35 +8,39 @@
using MEC;
using XPSystem.API;
using XPSystem.API.DisplayProviders;
+ using XPSystem.API.Player;
using XPSystem.API.StorageProviders;
- using XPSystem.Config.Models;
using YamlDotNet.Serialization;
public class RankXPDisplayProvider : SyncVarXPDisplayProvider
{
protected override string VariableKey { get; } = "RankXPDisplayProvider_badge";
- protected override (Type typeName, string methodName, Func getFakeSyncVar, Func getResyncVar)[] SyncVars { get; } =
+ protected override (Type typeName, string methodName, Func getFakeSyncVar, Func getResyncVar)[] SyncVars { get; } =
{
(typeof(ServerRoles), nameof(ServerRoles.Network_myText), (_, obj) => obj.Text, player => player.BadgeText),
(typeof(ServerRoles), nameof(ServerRoles.Network_myColor), (_, obj) => obj.Color, player => player.BadgeColor)
};
- protected override Badge CreateObject(XPPlayer player, PlayerInfoWrapper playerInfo)
+ protected override Badge? CreateObject(BaseXPPlayer player, PlayerInfoWrapper? playerInfo)
{
if (player.DNT)
{
- if (player.HasBadge && !player.HasHiddenBadge)
+ if (player is { HasBadge: true, HasHiddenBadge: false })
return null;
return Config.DNTBadge;
}
- Badge badge = null;
+ if (player is not XPPlayer xpPlayer)
+ return null;
+ playerInfo ??= xpPlayer.GetPlayerInfo();
+
+ Badge? badge = null;
string format = !player.HasBadge || player.HasHiddenBadge
? Config.BadgeStructureNoBadge
: Config.BadgeStructure;
- string color = "default";
+ string? color = null;
foreach (var kvp in Config.SortedBadges)
{
@@ -59,11 +63,11 @@ protected override Badge CreateObject(XPPlayer player, PlayerInfoWrapper playerI
.Replace("%lvl%", playerInfo.Level.ToString())
.Replace("%badge%", badge.Text)
.Replace("%oldbadge%", player.BadgeText),
- Color = color
+ Color = color ?? "default"
};
}
- protected override bool ShouldEdit(XPPlayer player)
+ protected override bool ShouldEdit(BaseXPPlayer player)
{
if (Config.SkipGlobalBadges && player.HasGlobalBadge)
return false;
@@ -74,7 +78,7 @@ protected override bool ShouldEdit(XPPlayer player)
return true;
}
- protected override bool ShouldShowTo(XPPlayer player, XPPlayer target)
+ protected override bool ShouldShowTo(BaseXPPlayer player, BaseXPPlayer target)
{
if (!base.ShouldShowTo(player, target))
return false;
@@ -151,10 +155,10 @@ public class RankConfig : IXPDisplayProviderConfig
public Badge DNTBadge { get; set; } = new()
{
Text = "(DNT) anonymous man????",
- Color = Misc.PlayerInfoColorTypes.Nickel.ToString()
+ Color = nameof(Misc.PlayerInfoColorTypes.Nickel)
};
- private Dictionary _sortedBadges;
+ private Dictionary _sortedBadges = null!;
[YamlIgnore]
public Dictionary SortedBadges => _sortedBadges ??= Badges
.OrderBy(x => x.Key)
@@ -166,27 +170,27 @@ public class RankConfig : IXPDisplayProviderConfig
[0] = new Badge
{
Text = "Visitor",
- Color = Misc.PlayerInfoColorTypes.Cyan.ToString().ToLower()
+ Color = nameof(Misc.PlayerInfoColorTypes.Cyan).ToLower()
},
[1] = new Badge
{
Text = "Junior",
- Color = Misc.PlayerInfoColorTypes.Orange.ToString().ToLower()
+ Color = nameof(Misc.PlayerInfoColorTypes.Orange).ToLower()
},
[5] = new Badge
{
Text = "Senior",
- Color = Misc.PlayerInfoColorTypes.Yellow.ToString().ToLower()
+ Color = nameof(Misc.PlayerInfoColorTypes.Yellow).ToLower()
},
[10] = new Badge
{
Text = "Veteran",
- Color = Misc.PlayerInfoColorTypes.Red.ToString().ToLower()
+ Color = nameof(Misc.PlayerInfoColorTypes.Red).ToLower()
},
[50] = new Badge
{
Text = "Nerd",
- Color = Misc.PlayerInfoColorTypes.Lime.ToString().ToLower()
+ Color = nameof(Misc.PlayerInfoColorTypes.Lime).ToLower()
}
};
}
diff --git a/XPSystem/BuiltInProviders/LiteDB/LiteDBPlayerInfo.cs b/XPSystem/BuiltInProviders/LiteDB/LiteDBPlayerInfo.cs
index a9110ea..a8ed596 100644
--- a/XPSystem/BuiltInProviders/LiteDB/LiteDBPlayerInfo.cs
+++ b/XPSystem/BuiltInProviders/LiteDB/LiteDBPlayerInfo.cs
@@ -25,7 +25,7 @@ public override T SetId(IPlayerId id)
public class LiteDBStringPlayerInfo : LiteDBPlayerInfo
{
[BsonId]
- public string Id { get; set; }
+ public string Id { get; set; } = null!;
public override T SetId(IPlayerId id)
{
@@ -43,7 +43,7 @@ public abstract class LiteDBPlayerInfo
{
public int XP { get; set; }
#if STORENICKS
- public string Nickname { get; set; }
+ public string? Nickname { get; set; }
#endif
public abstract T SetId(IPlayerId id) where T : LiteDBPlayerInfo;
diff --git a/XPSystem/BuiltInProviders/LiteDB/LiteDBProvider.cs b/XPSystem/BuiltInProviders/LiteDB/LiteDBProvider.cs
index 72cdd98..34cdaf7 100644
--- a/XPSystem/BuiltInProviders/LiteDB/LiteDBProvider.cs
+++ b/XPSystem/BuiltInProviders/LiteDB/LiteDBProvider.cs
@@ -2,6 +2,7 @@
{
using System;
using System.Collections.Generic;
+ using System.Diagnostics.CodeAnalysis;
using System.Linq;
using global::LiteDB;
using XPSystem.API.Enums;
@@ -10,11 +11,11 @@
public class LiteDBProvider : StorageProvider
{
- public ILiteCollection SteamCollection { get; private set; }
- public ILiteCollection DiscordCollection { get; private set; }
- public ILiteCollection NWCollection { get; private set; }
+ public ILiteCollection? SteamCollection { get; private set; }
+ public ILiteCollection? DiscordCollection { get; private set; }
+ public ILiteCollection? NWCollection { get; private set; }
- private LiteDatabase database;
+ private LiteDatabase? database;
public override void Initialize()
{
@@ -45,30 +46,30 @@ public override void Dispose()
DiscordCollection = null;
NWCollection = null;
- database.Dispose();
+ database?.Dispose();
database = null;
}
- public LiteDBPlayerInfo TryGetPlayerInfo(IPlayerId playerId) => TryGetPlayerInfo(playerId);
- public T TryGetPlayerInfo(IPlayerId playerId) where T : LiteDBPlayerInfo
+ public LiteDBPlayerInfo? TryGetPlayerInfo(IPlayerId playerId) => TryGetPlayerInfo(playerId);
+ public T? TryGetPlayerInfo(IPlayerId playerId) where T : LiteDBPlayerInfo
{
switch (playerId.AuthType)
{
// FindById no work; BsonValue converts ulong to decimal, key is different; retarded conversion
case AuthType.Steam when playerId is NumberPlayerId numberPlayerId:
- return (T)(object)SteamCollection.FindOne(x => x.Id == numberPlayerId.IdNumber);
+ return (T)(object)SteamCollection!.FindOne(x => x.Id == numberPlayerId.IdNumber);
case AuthType.Discord when playerId is NumberPlayerId numberPlayerId:
- return (T)(object)DiscordCollection.FindOne(x => x.Id == numberPlayerId.IdNumber);
+ return (T)(object)DiscordCollection!.FindOne(x => x.Id == numberPlayerId.IdNumber);
case AuthType.Northwood when playerId is StringPlayerId stringPlayerId:
- return (T)(object)NWCollection.FindOne(x => x.Id == stringPlayerId.IdString);
+ return (T)(object)NWCollection!.FindOne(x => x.Id == stringPlayerId.IdString);
default:
throw new ArgumentOutOfRangeException(nameof(playerId.AuthType), playerId.AuthType, null);
}
}
- protected override bool TryGetPlayerInfoNoCache(IPlayerId playerId, out PlayerInfo playerInfo)
+ protected override bool TryGetPlayerInfoNoCache(IPlayerId playerId, [NotNullWhen(true)] out PlayerInfo? playerInfo)
{
- LiteDBPlayerInfo existing = TryGetPlayerInfo(playerId);
+ LiteDBPlayerInfo? existing = TryGetPlayerInfo(playerId);
if (existing == null)
{
playerInfo = null;
@@ -81,18 +82,18 @@ protected override bool TryGetPlayerInfoNoCache(IPlayerId playerId, out PlayerIn
protected override PlayerInfo GetPlayerInfoAndCreateOfNotExistNoCache(IPlayerId playerId)
{
- LiteDBPlayerInfo existing = TryGetPlayerInfo(playerId);
+ LiteDBPlayerInfo? existing = TryGetPlayerInfo(playerId);
if (existing != null)
return existing.ToPlayerInfo(playerId.AuthType);
switch (playerId.AuthType)
{
case AuthType.Steam:
- return GetPlayerInfoAndCreateOfNotExistNoCache(playerId, SteamCollection);
+ return GetPlayerInfoAndCreateOfNotExistNoCache(playerId, SteamCollection!);
case AuthType.Discord:
- return GetPlayerInfoAndCreateOfNotExistNoCache(playerId, DiscordCollection);
+ return GetPlayerInfoAndCreateOfNotExistNoCache(playerId, DiscordCollection!);
case AuthType.Northwood:
- return GetPlayerInfoAndCreateOfNotExistNoCache(playerId, NWCollection);
+ return GetPlayerInfoAndCreateOfNotExistNoCache(playerId, NWCollection!);
default:
throw new ArgumentOutOfRangeException(nameof(playerId.AuthType), playerId.AuthType, null);
}
@@ -109,20 +110,20 @@ protected override PlayerInfo GetPlayerInfoAndCreateOfNotExistNoCache(IPlayerId
public override IEnumerable GetTopPlayers(int count)
{
- var result = SteamCollection.Query()
+ var result = SteamCollection!.Query()
.OrderByDescending(x => x.XP)
.Limit(count)
.ToEnumerable()
.Select(x => x.ToPlayerInfo(AuthType.Steam))
.ToList();
- result.AddRange(DiscordCollection.Query()
+ result.AddRange(DiscordCollection!.Query()
.OrderByDescending(x => x.XP)
.Limit(count)
.ToEnumerable()
.Select(x => x.ToPlayerInfo(AuthType.Discord)));
- result.AddRange(NWCollection.Query()
+ result.AddRange(NWCollection!.Query()
.OrderByDescending(x => x.XP)
.Limit(count)
.ToEnumerable()
@@ -139,13 +140,13 @@ protected override void SetPlayerInfoNoCache(PlayerInfo playerInfo)
switch (playerInfo.Player.AuthType)
{
case AuthType.Steam:
- SetPlayerInfoNoCache(playerInfo, SteamCollection);
+ SetPlayerInfoNoCache(playerInfo, SteamCollection!);
break;
case AuthType.Discord:
- SetPlayerInfoNoCache(playerInfo, DiscordCollection);
+ SetPlayerInfoNoCache(playerInfo, DiscordCollection!);
break;
case AuthType.Northwood:
- SetPlayerInfoNoCache(playerInfo, NWCollection);
+ SetPlayerInfoNoCache(playerInfo, NWCollection!);
break;
default:
throw new ArgumentOutOfRangeException(nameof(playerInfo.Player.AuthType), playerInfo.Player.AuthType, null);
@@ -153,7 +154,7 @@ protected override void SetPlayerInfoNoCache(PlayerInfo playerInfo)
}
protected void SetPlayerInfoNoCache(PlayerInfo playerInfo, ILiteCollection collection) where T : LiteDBPlayerInfo, new()
{
- T existing = TryGetPlayerInfo(playerInfo.Player);
+ T? existing = TryGetPlayerInfo(playerInfo.Player);
if (existing == null)
{
collection.Insert(new T()
@@ -179,11 +180,11 @@ protected override bool DeletePlayerInfoNoCache(IPlayerId playerId)
switch (playerId.AuthType)
{
case AuthType.Steam when playerId is NumberPlayerId numberPlayerId:
- return SteamCollection.Delete(numberPlayerId.IdNumber);
+ return SteamCollection!.Delete(numberPlayerId.IdNumber);
case AuthType.Discord when playerId is NumberPlayerId numberPlayerId:
- return DiscordCollection.Delete(numberPlayerId.IdNumber);
+ return DiscordCollection!.Delete(numberPlayerId.IdNumber);
case AuthType.Northwood when playerId is StringPlayerId stringPlayerId:
- return NWCollection.Delete(stringPlayerId.IdString);
+ return NWCollection!.Delete(stringPlayerId.IdString);
default:
throw new ArgumentOutOfRangeException(nameof(playerId.AuthType), playerId.AuthType, null);
}
@@ -191,9 +192,9 @@ protected override bool DeletePlayerInfoNoCache(IPlayerId playerId)
protected override void DeleteAllPlayerInfoNoCache()
{
- SteamCollection.DeleteAll();
- DiscordCollection.DeleteAll();
- NWCollection.DeleteAll();
+ SteamCollection!.DeleteAll();
+ DiscordCollection!.DeleteAll();
+ NWCollection!.DeleteAll();
}
public class LiteDBProviderConfig
diff --git a/XPSystem/BuiltInProviders/MySql/MySqlProvider.cs b/XPSystem/BuiltInProviders/MySql/MySqlProvider.cs
index 2bb7f5b..02ac72b 100644
--- a/XPSystem/BuiltInProviders/MySql/MySqlProvider.cs
+++ b/XPSystem/BuiltInProviders/MySql/MySqlProvider.cs
@@ -2,6 +2,7 @@
{
using System;
using System.Collections.Generic;
+ using System.Diagnostics.CodeAnalysis;
using System.Linq;
using MySqlConnector;
using XPSystem.API;
@@ -68,7 +69,7 @@ public override IEnumerable GetTopPlayers(int count)
.Select(x => new PlayerInfoWrapper(x));
}
- protected override bool TryGetPlayerInfoNoCache(IPlayerId playerId, out PlayerInfo playerInfo)
+ protected override bool TryGetPlayerInfoNoCache(IPlayerId playerId, [NotNullWhen(true)] out PlayerInfo? playerInfo)
{
using MySqlConnection connection = GetConnection();
using MySqlCommand command = connection.CreateCommand();
@@ -159,14 +160,16 @@ protected override void DeleteAllPlayerInfoNoCache()
}
}
- private PlayerInfo FromReader(MySqlDataReader reader, IPlayerId playerId = null)
+ private PlayerInfo FromReader(MySqlDataReader reader, IPlayerId playerId)
{
return new PlayerInfo
{
Player = playerId,
XP = reader.GetInt32(1),
#if STORENICKS
- Nickname = reader.IsDBNull(2) ? null : reader.GetString(2)
+ Nickname = reader.IsDBNull(2)
+ ? null
+ : reader.GetString(2)
#endif
};
}
@@ -195,7 +198,7 @@ public MySqlConnection GetConnection()
public class MySqlProviderConfig
{
- public string ConnectionString { get; set; }
+ public string ConnectionString { get; set; } = null!;
public bool LogQueries { get; set; } = false;
}
}
diff --git a/XPSystem/Commands/Admin/DatabasePlayerCommand.cs b/XPSystem/Commands/Admin/DatabasePlayerCommand.cs
index 8180f06..f551a5c 100644
--- a/XPSystem/Commands/Admin/DatabasePlayerCommand.cs
+++ b/XPSystem/Commands/Admin/DatabasePlayerCommand.cs
@@ -1,8 +1,8 @@
namespace XPSystem.Commands.Admin
{
using System;
- using CommandSystem;
using XPSystem.API;
+ using XPSystem.API.Player;
using XPSystem.API.StorageProviders;
using XPSystem.API.StorageProviders.Models;
@@ -17,49 +17,55 @@ public abstract class DatabasePlayerCommand : SanitizedInputCommand
///
/// The command arguments.
/// The index of the argument that would specify the targeted player.
- /// The player that executed the command.
+ /// The player that executed the command.
/// The response to be sent back to the player.
/// The targeted player's info, if found, otherwise default.
/// The targeted player's id, if found, otherwise 0.
/// Whether the operation was successful (whether or not to return immediately after).
/// If the argument count and the target player's argument position don't match, the sender will become the targeted player.
- protected bool DoThingWithArgs(ref ArraySegment arguments, byte targetPlayerArgumentIndex, XPPlayer player, ref string response, out PlayerInfoWrapper playerInfo, out IPlayerId playerId)
+ protected bool DoThingWithArgs(ref ArraySegment arguments, byte targetPlayerArgumentIndex, BaseXPPlayer? sender, ref string response, out PlayerInfoWrapper playerInfo, out IPlayerId playerId)
{
- playerId = default;
- playerInfo = default;
+ playerId = null!;
+ playerInfo = null!;
// If player is specified.
if (arguments.Count > targetPlayerArgumentIndex)
{
string arg = arguments.At(targetPlayerArgumentIndex);
// Try to get player by name or user id.
- if (XPPlayer.TryGet(arg, out player))
+ if (XPPlayer.TryGet(arg, out BaseXPPlayer? basePlayer))
{
+ if (basePlayer is not XPPlayer player)
+ {
+ response = "Player is not a xp player, can't do that.";
+ return false;
+ }
+
playerId = player.PlayerId;
}
else
{
// if player isn't online, try to parse user id.
- if (!arg.TryParseUserId(out playerId))
+ if (!arg.TryParseUserId(out playerId!))
{
- response = "Invalid player.";
+ response = "Invalid player ID.";
return false;
}
}
}
// Player not specified, use sender.
- else
+ else if (sender is XPPlayer player)
{
playerId = player.PlayerId;
}
-
- if (player.PlayerId == playerId && player.IsNPC)
+ else
{
- response = "Player is not actual player, can't do that.";
+ response = "You must specify a player (sender not a XPPlayer).";
return false;
}
- if (XPAPI.StorageProvider.TryGetPlayerInfo(playerId, out playerInfo))
+ // XPAPI.EnsureStorageProviderValid(); - called in calling command(s)
+ if (XPAPI.StorageProvider!.TryGetPlayerInfo(playerId, out playerInfo!))
return true;
response = "Player does not exist within database.";
diff --git a/XPSystem/Commands/Admin/Subcommands/GetCommandAdmin.cs b/XPSystem/Commands/Admin/Subcommands/GetCommandAdmin.cs
index a6112f1..86ba558 100644
--- a/XPSystem/Commands/Admin/Subcommands/GetCommandAdmin.cs
+++ b/XPSystem/Commands/Admin/Subcommands/GetCommandAdmin.cs
@@ -3,22 +3,24 @@
using System;
using CommandSystem;
using XPSystem.API;
+ using XPSystem.API.Player;
using XPSystem.API.StorageProviders;
+ using XPSystem.API.StorageProviders.Models;
public class GetCommandAdmin : DatabasePlayerCommand
{
public override bool Execute(ArraySegment arguments, ICommandSender sender, out string response)
{
- if (!XPPlayer.TryGetAndCheckPermission(sender, "xps.get", out XPPlayer player))
+ if (!XPPlayer.TryGetAndCheckPermission(sender, "xps.get", out BaseXPPlayer? player))
{
response = "You don't have permission (xps.get) to use this command.";
return false;
}
+ response = "temp";
XPAPI.EnsureStorageProviderValid();
- response = null;
- if (!DoThingWithArgs(ref arguments, 0, player, ref response, out PlayerInfoWrapper playerInfo, out var playerId))
+ if (!DoThingWithArgs(ref arguments, 0, player, ref response, out PlayerInfoWrapper playerInfo, out IPlayerId playerId))
return false;
response = $"{playerId.ToString()} ({playerInfo.Nickname})] XP: {playerInfo.XP} (Level {playerInfo.Level})";
diff --git a/XPSystem/Commands/Admin/Subcommands/GiveCommand.cs b/XPSystem/Commands/Admin/Subcommands/GiveCommand.cs
index d41f674..5eb3255 100644
--- a/XPSystem/Commands/Admin/Subcommands/GiveCommand.cs
+++ b/XPSystem/Commands/Admin/Subcommands/GiveCommand.cs
@@ -3,13 +3,15 @@
using System;
using CommandSystem;
using XPSystem.API;
+ using XPSystem.API.Player;
using XPSystem.API.StorageProviders;
+ using XPSystem.API.StorageProviders.Models;
public class GiveCommand : DatabasePlayerCommand
{
public override bool Execute(ArraySegment arguments, ICommandSender sender, out string response)
{
- if (!XPPlayer.TryGetAndCheckPermission(sender, "xps.give", out XPPlayer player))
+ if (!XPPlayer.TryGetAndCheckPermission(sender, "xps.give", out BaseXPPlayer? player))
{
response = "You don't have permission (xps.give) to use this command.";
return false;
@@ -28,8 +30,10 @@ public override bool Execute(ArraySegment arguments, ICommandSender send
return false;
}
- response = null;
- if (!DoThingWithArgs(ref arguments, 1, player, ref response, out PlayerInfoWrapper playerInfo, out var playerId))
+ response = "temp";
+ XPAPI.EnsureStorageProviderValid();
+
+ if (!DoThingWithArgs(ref arguments, 1, player, ref response, out PlayerInfoWrapper playerInfo, out IPlayerId playerId))
return false;
playerInfo.XP += amount;
diff --git a/XPSystem/Commands/Admin/Subcommands/LeaderboardCommandAdmin.cs b/XPSystem/Commands/Admin/Subcommands/LeaderboardCommandAdmin.cs
index d59726d..0e74f36 100644
--- a/XPSystem/Commands/Admin/Subcommands/LeaderboardCommandAdmin.cs
+++ b/XPSystem/Commands/Admin/Subcommands/LeaderboardCommandAdmin.cs
@@ -32,7 +32,7 @@ public override bool Execute(ArraySegment arguments, ICommandSender send
}
}
- response = XPAPI.StorageProvider.GetTopPlayers(amount)
+ response = XPAPI.StorageProvider!.GetTopPlayers(amount)
.FormatLeaderboard();
return true;
}
diff --git a/XPSystem/Commands/Admin/Subcommands/MultiplierCommand.cs b/XPSystem/Commands/Admin/Subcommands/MultiplierCommand.cs
index c003ba5..0c58b68 100644
--- a/XPSystem/Commands/Admin/Subcommands/MultiplierCommand.cs
+++ b/XPSystem/Commands/Admin/Subcommands/MultiplierCommand.cs
@@ -3,6 +3,7 @@
using System;
using CommandSystem;
using XPSystem.API;
+ using XPSystem.API.Player;
public class MultiplierCommand : SanitizedInputCommand
{
@@ -36,20 +37,19 @@ public override bool Execute(ArraySegment arguments, ICommandSender send
return true;
case "p":
case "player":
- XPPlayer player;
+ BaseXPPlayer? basePlayer;
int intArgLocation;
if (arguments.Count > 2)
{
intArgLocation = 2;
-
- if (!XPPlayer.TryGet(arguments.At(1), out player))
+ if (!XPPlayer.TryGet(arguments.At(1), out basePlayer))
{
response = "Invalid player.";
return false;
}
}
- else if (XPPlayer.TryGet(sender, out player))
+ else if (XPPlayer.TryGet(sender, out basePlayer))
{
intArgLocation = 1;
}
@@ -59,6 +59,12 @@ public override bool Execute(ArraySegment arguments, ICommandSender send
return false;
}
+ if (basePlayer is not XPPlayer player)
+ {
+ response = "Player not XPPlayer.";
+ return false;
+ }
+
if (!float.TryParse(arguments.At(intArgLocation), out multiplier))
{
response = $"{player.DisplayedName}'s multiplier: {player.XPMultiplier}.";
diff --git a/XPSystem/Commands/Admin/Subcommands/SetCommand.cs b/XPSystem/Commands/Admin/Subcommands/SetCommand.cs
index 5844729..751fbf9 100644
--- a/XPSystem/Commands/Admin/Subcommands/SetCommand.cs
+++ b/XPSystem/Commands/Admin/Subcommands/SetCommand.cs
@@ -3,13 +3,15 @@
using System;
using CommandSystem;
using XPSystem.API;
+ using XPSystem.API.Player;
using XPSystem.API.StorageProviders;
+ using XPSystem.API.StorageProviders.Models;
public class SetCommand : DatabasePlayerCommand
{
public override bool Execute(ArraySegment arguments, ICommandSender sender, out string response)
{
- if (!XPPlayer.TryGetAndCheckPermission(sender, "xps.set", out XPPlayer player))
+ if (!XPPlayer.TryGetAndCheckPermission(sender, "xps.set", out BaseXPPlayer? player))
{
response = "You don't have permission (xps.set) to use this command.";
return false;
@@ -30,8 +32,10 @@ public override bool Execute(ArraySegment arguments, ICommandSender send
return false;
}
- response = null;
- if (!DoThingWithArgs(ref arguments, 1, player, ref response, out PlayerInfoWrapper playerInfo, out var playerId))
+ response = "temp";
+ XPAPI.EnsureStorageProviderValid();
+
+ if (!DoThingWithArgs(ref arguments, 1, player, ref response, out PlayerInfoWrapper playerInfo, out IPlayerId playerId))
return false;
playerInfo.XP = amount;
diff --git a/XPSystem/Commands/Admin/Subcommands/SetLevelCommand.cs b/XPSystem/Commands/Admin/Subcommands/SetLevelCommand.cs
index fe07b81..5d99973 100644
--- a/XPSystem/Commands/Admin/Subcommands/SetLevelCommand.cs
+++ b/XPSystem/Commands/Admin/Subcommands/SetLevelCommand.cs
@@ -3,13 +3,15 @@
using System;
using CommandSystem;
using XPSystem.API;
+ using XPSystem.API.Player;
using XPSystem.API.StorageProviders;
+ using XPSystem.API.StorageProviders.Models;
public class SetLevelCommand : DatabasePlayerCommand
{
public override bool Execute(ArraySegment arguments, ICommandSender sender, out string response)
{
- if (!XPPlayer.TryGetAndCheckPermission(sender, "xps.setlevel", out XPPlayer player))
+ if (!XPPlayer.TryGetAndCheckPermission(sender, "xps.setlevel", out BaseXPPlayer? player))
{
response = "You don't have permission (xps.setlevel) to use this command.";
return false;
@@ -30,8 +32,10 @@ public override bool Execute(ArraySegment arguments, ICommandSender send
return false;
}
- response = null;
- if (!DoThingWithArgs(ref arguments, 1, player, ref response, out PlayerInfoWrapper playerInfo, out var playerId))
+ response = "temp";
+ XPAPI.EnsureStorageProviderValid();
+
+ if (!DoThingWithArgs(ref arguments, 1, player, ref response, out PlayerInfoWrapper playerInfo, out IPlayerId playerId))
return false;
playerInfo.Level = level;
diff --git a/XPSystem/Commands/Admin/Subcommands/ShowMessageCommand.cs b/XPSystem/Commands/Admin/Subcommands/ShowMessageCommand.cs
index afa23c1..a9b7654 100644
--- a/XPSystem/Commands/Admin/Subcommands/ShowMessageCommand.cs
+++ b/XPSystem/Commands/Admin/Subcommands/ShowMessageCommand.cs
@@ -9,6 +9,7 @@
using NorthwoodLib.Pools;
using PlayerRoles;
using XPSystem.API;
+ using XPSystem.API.Player;
using XPSystem.Config.Events;
using XPSystem.Config.Events.Types;
@@ -24,6 +25,13 @@ public override bool Execute(ArraySegment arguments, ICommandSender send
if (arguments.Count < 1)
{
+ if (XPPlayer.TryGet(sender, out BaseXPPlayer? player) && player is XPPlayer xpPlayer)
+ {
+ XPAPI.AddXPAndDisplayMessage(xpPlayer, 1, "debug");
+ response = "done.";
+ return true;
+ }
+
response = "Usage: showmessage (key) or showmessage (key) (subkeys)";
return false;
}
@@ -33,10 +41,10 @@ public override bool Execute(ArraySegment arguments, ICommandSender send
if (key.StartsWith("default_"))
key = key.Substring(8);
- else if (XPPlayer.TryGet(sender, out XPPlayer player))
+ else if (XPPlayer.TryGet(sender, out BaseXPPlayer? player))
role = player.Role;
- XPECFile file = XPECManager.GetFile(key, role);
+ XPECFile? file = XPECManager.GetFile(key, role);
if (file == null)
{
response = "No such XPEC file.";
@@ -61,7 +69,7 @@ public override bool Execute(ArraySegment arguments, ICommandSender send
}
bool success = false;
- Exception e = null;
+ Exception? e = null;
var argTypes = types[i];
foreach (Type type in argTypes)
{
@@ -93,7 +101,7 @@ public override bool Execute(ArraySegment arguments, ICommandSender send
}
}
- XPECItem item = file.Get(subkeys.ToArray());
+ XPECItem? item = file.Get(subkeys.ToArray());
if (item == null)
{
response = "Item null.";
diff --git a/XPSystem/Commands/Admin/Subcommands/VariablesCommand.cs b/XPSystem/Commands/Admin/Subcommands/VariablesCommand.cs
index 0848f1b..ee494c6 100644
--- a/XPSystem/Commands/Admin/Subcommands/VariablesCommand.cs
+++ b/XPSystem/Commands/Admin/Subcommands/VariablesCommand.cs
@@ -5,12 +5,13 @@
using CommandSystem;
using NorthwoodLib.Pools;
using XPSystem.API;
+ using XPSystem.API.Player;
public class VariablesCommand : SanitizedInputCommand
{
public override bool Execute(ArraySegment arguments, ICommandSender sender, out string response)
{
- if (!XPPlayer.TryGetAndCheckPermission(sender, "xps.variables", out XPPlayer player))
+ if (!XPPlayer.TryGetAndCheckPermission(sender, "xps.variables", out BaseXPPlayer? player))
{
response = "You don't have permission (xps.variables) to use this command.";
return false;
diff --git a/XPSystem/Commands/Client/Subcommands/GetCommandClient.cs b/XPSystem/Commands/Client/Subcommands/GetCommandClient.cs
index 53dcffe..605981c 100644
--- a/XPSystem/Commands/Client/Subcommands/GetCommandClient.cs
+++ b/XPSystem/Commands/Client/Subcommands/GetCommandClient.cs
@@ -3,20 +3,20 @@
using System;
using CommandSystem;
using XPSystem.API;
+ using XPSystem.API.Player;
using XPSystem.API.StorageProviders;
public class GetCommandClient : SanitizedInputCommand, IAliasableCommand
{
public override bool Execute(ArraySegment arguments, ICommandSender sender, out string response)
{
- if (!XPPlayer.TryGet(sender, out XPPlayer player))
+ if (!XPPlayer.TryGet(sender, out BaseXPPlayer? basePlayer) || basePlayer is not XPPlayer player)
{
response = "This command is player only.";
return false;
}
PlayerInfoWrapper log = player.GetPlayerInfo();
-
response = $"LVL: {log.Level} | XP: {log.XP} | Needed XP: {log.NeededXPNext}";
return true;
}
diff --git a/XPSystem/Commands/Client/Subcommands/LeaderboardCommandClient.cs b/XPSystem/Commands/Client/Subcommands/LeaderboardCommandClient.cs
index 3366e2d..07fc72c 100644
--- a/XPSystem/Commands/Client/Subcommands/LeaderboardCommandClient.cs
+++ b/XPSystem/Commands/Client/Subcommands/LeaderboardCommandClient.cs
@@ -32,7 +32,7 @@ public override bool Execute(ArraySegment arguments, ICommandSender send
}
}
- response = XPAPI.StorageProvider.GetTopPlayers(amount)
+ response = XPAPI.StorageProvider!.GetTopPlayers(amount)
.FormatLeaderboard();
return true;
}
diff --git a/XPSystem/Commands/Console/Subcommands/DeleteEverythingCommand.cs b/XPSystem/Commands/Console/Subcommands/DeleteEverythingCommand.cs
index 47b9aca..dcff76a 100644
--- a/XPSystem/Commands/Console/Subcommands/DeleteEverythingCommand.cs
+++ b/XPSystem/Commands/Console/Subcommands/DeleteEverythingCommand.cs
@@ -20,7 +20,7 @@ public override bool Execute(ArraySegment arguments, ICommandSender send
if ((DateTime.Now - _lastUsed).TotalSeconds < 10)
{
- XPAPI.StorageProvider.DeleteAllPlayerInfo();
+ XPAPI.StorageProvider!.DeleteAllPlayerInfo();
response = "Everything deleted.";
return true;
diff --git a/XPSystem/Commands/Console/Subcommands/ReloadConfigsCommand.cs b/XPSystem/Commands/Console/Subcommands/ReloadConfigsCommand.cs
index 7578b04..25a1bd8 100644
--- a/XPSystem/Commands/Console/Subcommands/ReloadConfigsCommand.cs
+++ b/XPSystem/Commands/Console/Subcommands/ReloadConfigsCommand.cs
@@ -7,7 +7,7 @@ public class ReloadConfigsCommand : SanitizedInputCommand
{
public override bool Execute(ArraySegment arguments, ICommandSender sender, out string response)
{
- Main.Instance.LoadExtraConfigs();
+ Main.Instance!.LoadExtraConfigs();
response = "Extra (non main, use your pluginloader to reload) configs reloaded.";
return true;
}
diff --git a/XPSystem/Config/Config.cs b/XPSystem/Config/Config.cs
index 9f4a214..ea5a3e4 100644
--- a/XPSystem/Config/Config.cs
+++ b/XPSystem/Config/Config.cs
@@ -9,34 +9,35 @@ public abstract class Config
[Description("Print debug messages?")]
public bool Debug { get; set; } = false;
- [Description("The function to calculate level for given xp. Parameter: xp. Available functions: https://learn.microsoft.com/en-us/dotnet/api/system.math?view=net-8.0#methods.")]
- public string LevelFunction { get; set; } = "Ceiling(-50 + Sqrt((4 * xp / a) + 9800) / 2)";
+ [Description("The function to calculate XP needed for a level. The inverse of the LevelFunction. Parameter: level. Available functions: https://learn.microsoft.com/en-us/dotnet/api/system.math?view=net-8.0#methods.")]
+ public string XPFunction { get; set; } = "Floor((level^a) * b)";
- [Description("The function to calculate xp needed for a level. The inverse of the LevelFunction. Parameter: level. Available functions: https://learn.microsoft.com/en-us/dotnet/api/system.math?view=net-8.0#methods.")]
- public string XPFunction { get; set; } = "Ceiling((level^2 + 100 * level + 50) * a)";
+ [Description("The function to calculate level for given XP. Parameter: xp. Available functions: https://learn.microsoft.com/en-us/dotnet/api/system.math?view=net-8.0#methods.")]
+ public string LevelFunction { get; set; } = "Floor((xp/b)^(1/a))";
- [Description("Additional parameters for the level/xp functions.")]
+ [Description("Additional parameters for the level/XP functions.")]
public Dictionary AdditionalFunctionParameters { get; set; } = new()
{
- { "a", 1 },
+ { "a", 2 },
+ { "b", 100 }
};
- [Description("Override xp required for specific levels. Key: level, Value: xp.")]
+ [Description("Override XP required for specific levels. Key: level, Value: XP.")]
public Dictionary LevelXPOverrides { get; set; } = new()
{
[0] = 0
};
- [Description("Whether or not to pause xp gain when the round ends.")]
+ [Description("Whether or not to pause XP gain when the round ends.")]
public bool XPAfterRoundEnd { get; set; } = true;
[Description("A global XP multiplier.")]
public float GlobalXPMultiplier { get; set; } = 1f;
- [Description("Whether or not the global XP multiplier should apply to xp given to people that aren't online (via commands, etc.).")]
+ [Description("Whether or not the global XP multiplier should apply to XP given to people that aren't online (via commands, etc.).")]
public bool GlobalXPMultiplierForNonOnline { get; set; } = true;
- [Description("Whether or not the global XP multiplier should apply to xp removed.")]
+ [Description("Whether or not the global XP multiplier should apply to XP removed.")]
public bool XPMultiplierForXPLoss { get; set; } = false;
[Description("Path to the event configs folder, relative to the ExtendedConfigPath.")]
@@ -58,22 +59,32 @@ public abstract class Config
public string DNTMessage { get; set; } =
"We can't track your stats while you have DNT enabled in your game options!";
- [Description("Whether or not to format a message according to a template when adding xp.")]
+ [Description("Whether or not to format a message according to a template when adding XP.")]
public bool UseAddedXPTemplate { get; set; } = true;
- [Description("When enabled, template used for messages that modify xp. Parameters: %message%, %currentxp%, %currentlevel%, %neededxp%, %nextlevel.")]
+ [Description("When enabled, template used for messages that modify XP. Parameters: %message%, %currentxp%, %currentlevel%, %neededxp%, %nextlevel%."
+ + "Also: %progressbarfilled%, %progressbarremaining%. Using them requires the same extra calculations as UseTotalXP = false.")]
public string AddedXPTemplate { get; set; } = "%message%, (%currentxp% / %neededxp%)";
- [Description("Whether or not to use the total xp instead of only the xp required for the next level. Requires extra calculations if false.")]
+ [Description("The characters to use for the progress bar, if present in the AddedXPTemplate.")]
+ public string AddedXPProgressBarChars { get; set; } = "██";
+
+ [Description("The total length (in chars) of the progress bar to be generated.")]
+ public int AddedXPProgressBarLength { get; set; } = 20;
+
+ [Description("Whether or not to use the total XP instead of only the XP required for the next level. Requires extra calculations if false and progress bar is not present in AddedXPTemplate.")]
public bool UseTotalXP { get; set; } = true;
[Description("Whether or not to show a message to a player if they advance a level.")]
public bool ShowAddedLVL { get; set; } = true;
+ [Description("Whether or not to show the XP gain message on level up. If false, only the level will be shown.")]
+ public bool ShowXPOnLevelUp { get; set; } = true;
+
[Description("When enabled, what message to show if player advances a level.")]
public string AddedLVLMessage { get; set; } = "NEW LEVEL: %level%";
- [Description("Decide how messages (ex. xp gain, level up) are displayed.")]
+ [Description("Decide how messages (ex. XP gain, level up) are displayed.")]
public DisplayMode DisplayMode { get; set; } = DisplayMode.Hint;
[Description("The duration of the message, if applicable.")]
@@ -85,7 +96,7 @@ public abstract class Config
[Description("Prepended to all messages.")]
public string TextSuffix { get; set; } = "";
- [Description("An alias for the client to view their own xp. Empty to disable.")]
+ [Description("An alias for the client to view their own XP. Empty to disable.")]
public string ClientGetCommandAlias { get; set; } = "";
[Description("An alias for the client to view the leaderboard. Empty to disable.")]
@@ -95,7 +106,7 @@ public abstract class Config
"Available, but I will not help you with: XPSystem.BuiltInProviders.MySql.MySqlProvider")]
public string StorageProvider { get; set; } = "XPSystem.BuiltInProviders.LiteDB.LiteDBProvider";
- [Description("The assembly qualified type names of xp display providers to load, in addition to the built-in rank and nick ones.")]
+ [Description("The assembly qualified type names of XP display providers to load, in addition to the built-in rank and nick ones.")]
public List AdditionalDisplayProviders { get; set; } = new()
{
};
diff --git a/XPSystem/Config/Events/Types/XPECDictFile.cs b/XPSystem/Config/Events/Types/XPECDictFile.cs
index 8e927f5..cc40d80 100644
--- a/XPSystem/Config/Events/Types/XPECDictFile.cs
+++ b/XPSystem/Config/Events/Types/XPECDictFile.cs
@@ -10,22 +10,21 @@
/// The type of the subkeys.
public class XPECDictFile : XPECFile
{
- public XPECItem Default { get; set; }
-
+ public XPECItem Default { get; set; } = null!;
public Dictionary Items { get; set; } = new();
///
- public override XPECItem Get(params object[] keys)
+ public override XPECItem Get(params object?[]? keys)
{
base.Get(keys);
if (keys == null || keys.Length == 0)
return Default;
- object keyObj = keys[0];
+ object? keyObj = keys[0];
if (keyObj is not T key)
- throw new InvalidCastException($"Key is not of the correct type (was: {keyObj.GetType().FormatType()}, expected: {typeof(T).FormatType()})");
+ throw new InvalidCastException($"Key is not of the correct type (was: {keyObj?.GetType().FormatType() ?? "null"}, expected: {typeof(T).FormatType()})");
- if (Items == null)
+ if (Items == null!)
{
XPAPI.LogDebug("Items null in XPECDictFile with keytype " + typeof(T).FormatType());
return Default;
diff --git a/XPSystem/Config/Events/Types/XPECFile.cs b/XPSystem/Config/Events/Types/XPECFile.cs
index c855052..ca0cb6c 100644
--- a/XPSystem/Config/Events/Types/XPECFile.cs
+++ b/XPSystem/Config/Events/Types/XPECFile.cs
@@ -1,7 +1,10 @@
-namespace XPSystem.Config.Events.Types
+#pragma warning disable CS8600 // Converting null literal or possible null value to non-nullable type.
+namespace XPSystem.Config.Events.Types
{
using System;
+ using System.Collections.Generic;
using System.IO;
+ using System.Linq;
using System.Reflection;
using YamlDotNet.Core;
using YamlDotNet.Core.Events;
@@ -16,7 +19,7 @@ public abstract class XPECFile
/// The key of the file.
/// Set by upon loading.
///
- internal string Key;
+ internal string Key = null!;
///
/// Gets an item with the specified keys.
@@ -24,11 +27,15 @@ public abstract class XPECFile
///
/// The keys of the item.
/// The item.
- public virtual XPECItem Get(params object[] keys)
+ public virtual XPECItem? Get(params object?[]? keys)
{
if (Config.Debug || Config.LogXPGainedMethods)
{
- string fullKey = $"{Key}/{string.Join("/", keys ?? Array.Empty
public class XPECItemFile : XPECFile
{
- public XPECItem Item { get; set; }
+ public XPECItem Item { get; set; } = null!;
///
- public override XPECItem Get(params object[] keys)
+ public override XPECItem Get(params object?[]? keys)
{
base.Get(keys);
return Item;
diff --git a/XPSystem/Config/Events/XPECLimitTracker.cs b/XPSystem/Config/Events/XPECLimitTracker.cs
index cb0c5ce..03bcefd 100644
--- a/XPSystem/Config/Events/XPECLimitTracker.cs
+++ b/XPSystem/Config/Events/XPECLimitTracker.cs
@@ -4,6 +4,7 @@
using System.Collections.Generic;
using PlayerRoles;
using XPSystem.API;
+ using XPSystem.API.Player;
using XPSystem.Config.Events.Types;
using XPSystem.Config.Events.Types.Custom;
using XPSystem.EventHandlers;
@@ -99,7 +100,7 @@ private static void OnPlayerChangedRole(XPPlayer player, RoleTypeId oldRole, Rol
private static Dictionary GetDict(XPPlayer player)
{
- if (!player.Variables.TryGet(DictKey, out Dictionary dict))
+ if (!player.Variables.TryGet(DictKey, out Dictionary? dict))
{
dict = new Dictionary();
player.Variables.Add(DictKey, dict);
@@ -110,7 +111,7 @@ private static Dictionary GetDict(XPPlayer player)
private class LimitData
{
- public IXPECLimitedFile File;
+ public IXPECLimitedFile File = null!;
public int LeftForLife;
public int LeftForRound;
diff --git a/XPSystem/Config/Events/XPECManager.cs b/XPSystem/Config/Events/XPECManager.cs
index e689c51..7e1f0e6 100644
--- a/XPSystem/Config/Events/XPECManager.cs
+++ b/XPSystem/Config/Events/XPECManager.cs
@@ -35,7 +35,11 @@ public static class XPECManager
},
["death"] = new XPECDictFile()
{
- Default = null
+ Default = new XPECItem()
+ {
+ Amount = 0,
+ Translation = null
+ }
},
["upgrade"] = new XPECDictFile()
{
@@ -190,7 +194,7 @@ public static class XPECManager
#endif
}.AsReadonly();
- public static XPECFileCollection Default;
+ public static XPECFileCollection Default = null!;
public static readonly Dictionary Overrides = new();
private static readonly RoleTypeId[] _skipRoles = new[]
@@ -200,7 +204,7 @@ public static class XPECManager
RoleTypeId.Overwatch
};
- public static Dictionary KeyUsage = new();
+ public static readonly Dictionary KeyUsage = new();
///
/// Gets the override for the specified role.
@@ -221,7 +225,7 @@ public static XPECFileCollection GetCollection(RoleTypeId role = RoleTypeId.None
/// The key of the file.
/// The role to check for overrides from.
/// The file, if found, otherwise null.
- public static XPECFile GetFile(string key, RoleTypeId role = RoleTypeId.None)
+ public static XPECFile? GetFile(string key, RoleTypeId role = RoleTypeId.None)
{
if (Overrides.TryGetValue(role, out XPECFileCollection collection))
{
@@ -244,9 +248,9 @@ public static XPECFile GetFile(string key, RoleTypeId role = RoleTypeId.None)
/// The type to cast the file to.
/// The file, if found, otherwise null.
/// Thrown if the file is not of the specified type.
- public static T GetFile(string key, RoleTypeId role = RoleTypeId.None) where T : XPECFile
+ public static T? GetFile(string key, RoleTypeId role = RoleTypeId.None) where T : XPECFile
{
- XPECFile file = GetFile(key, role);
+ XPECFile? file = GetFile(key, role);
return file switch
{
null => null,
@@ -263,12 +267,10 @@ public static T GetFile(string key, RoleTypeId role = RoleTypeId.None) where
/// The role to check for overrides for.
/// The (optional) subkeys of the item.
/// The item, if found, otherwise null.
- public static XPECItem GetItem(string key, RoleTypeId role = RoleTypeId.None, params object[] subkeys)
+ public static XPECItem? GetItem(string key, RoleTypeId role = RoleTypeId.None, params object?[] subkeys)
{
- XPECFile file = GetFile(key, role);
- XPECItem item = file?.Get(subkeys);
-
- return item;
+ XPECFile? file = GetFile(key, role);
+ return file?.Get(subkeys);
}
public static void Load(string dir)
diff --git a/XPSystem/Config/YamlConverters/CommentGatheringTypeInspector.cs b/XPSystem/Config/YamlConverters/CommentGatheringTypeInspector.cs
index d140320..bfe4c92 100644
--- a/XPSystem/Config/YamlConverters/CommentGatheringTypeInspector.cs
+++ b/XPSystem/Config/YamlConverters/CommentGatheringTypeInspector.cs
@@ -1,4 +1,5 @@
-namespace XPSystem.Config.YamlConverters
+#pragma warning disable CS8765 // Nullability of type of parameter doesn't match overridden member (possibly because of nullability attributes).
+namespace XPSystem.Config.YamlConverters
{
using System;
using System.Collections.Generic;
diff --git a/XPSystem/Config/YamlConverters/ValidatingNodeDeserializer.cs b/XPSystem/Config/YamlConverters/ValidatingNodeDeserializer.cs
index 9f7e020..bcd7d8c 100644
--- a/XPSystem/Config/YamlConverters/ValidatingNodeDeserializer.cs
+++ b/XPSystem/Config/YamlConverters/ValidatingNodeDeserializer.cs
@@ -1,4 +1,6 @@
-namespace XPSystem.Config.YamlConverters
+#pragma warning disable CS8601 // Possible null reference assignment.
+#pragma warning disable CS8614 // Nullability of reference types in type of parameter doesn't match implicitly implemented member.
+namespace XPSystem.Config.YamlConverters
{
using System;
using System.ComponentModel.DataAnnotations;
diff --git a/XPSystem/Config/YamlConverters/XPECFileYamlConverter.cs b/XPSystem/Config/YamlConverters/XPECFileYamlConverter.cs
index 370a375..1241b9a 100644
--- a/XPSystem/Config/YamlConverters/XPECFileYamlConverter.cs
+++ b/XPSystem/Config/YamlConverters/XPECFileYamlConverter.cs
@@ -1,4 +1,6 @@
-namespace XPSystem.Config.YamlConverters
+#pragma warning disable CS8600 // Converting null literal or possible null value to non-nullable type.
+#pragma warning disable CS8767 // Nullability of reference types in type of parameter doesn't match implicitly implemented member (possibly because of nullability attributes).
+namespace XPSystem.Config.YamlConverters
{
using System;
using System.IO;
@@ -13,8 +15,6 @@ public class XPECFileYamlConverter : IYamlTypeConverter
public object ReadYaml(IParser parser, Type type)
{
- object result;
-
if (!parser.TryConsume(out MappingStart _))
throw new InvalidDataException("Invalid YAML content: MappingStart not found.");
@@ -26,7 +26,7 @@ public object ReadYaml(IParser parser, Type type)
type = Type.GetType(typeValue.Value)
?? throw new InvalidDataException($"Invalid YAML content: type {typeValue.Value} not resolved.");
- result = Activator.CreateInstance(type);
+ object result = Activator.CreateInstance(type);
((XPECFile)result).Read(parser);
diff --git a/XPSystem/EventHandlers/LoaderSpecific/ExiledEventHandlers.cs b/XPSystem/EventHandlers/LoaderSpecific/ExiledEventHandlers.cs
index c356bc6..36a0f2e 100644
--- a/XPSystem/EventHandlers/LoaderSpecific/ExiledEventHandlers.cs
+++ b/XPSystem/EventHandlers/LoaderSpecific/ExiledEventHandlers.cs
@@ -26,7 +26,7 @@ public override void RegisterEvents(Main plugin)
Exiled.Events.Handlers.Player.DroppedItem += PlayerDroppedItem;
Exiled.Events.Handlers.Player.UsedItem += PlayerUsedItem;
Exiled.Events.Handlers.Player.Spawned += PlayerSpawned;
- Exiled.Events.Handlers.Player.Escaping += PlayerEscaping;
+ Exiled.Events.Handlers.Player.Escaped += PlayerEscaped;
Exiled.Events.Handlers.Scp049.FinishingRecall += Scp049FinishingRecall;
@@ -50,7 +50,7 @@ public override void UnregisterEvents(Main plugin)
Exiled.Events.Handlers.Player.DroppedItem -= PlayerDroppedItem;
Exiled.Events.Handlers.Player.UsedItem -= PlayerUsedItem;
Exiled.Events.Handlers.Player.Spawned -= PlayerSpawned;
- Exiled.Events.Handlers.Player.Escaping -= PlayerEscaping;
+ Exiled.Events.Handlers.Player.Escaped -= PlayerEscaped;
Exiled.Events.Handlers.Scp049.FinishingRecall -= Scp049FinishingRecall;
@@ -126,13 +126,7 @@ private void PlayerSpawned(SpawnedEventArgs ev)
OnPlayerSpawned(ev.Player);
}
- private void PlayerEscaping(EscapingEventArgs ev)
- {
- if (!ev.IsAllowed)
- return;
-
- OnPlayerEscaped(ev.Player);
- }
+ private void PlayerEscaped(EscapedEventArgs ev) => OnPlayerEscaped(ev.Player);
private void Scp049FinishingRecall(FinishingRecallEventArgs ev)
{
diff --git a/XPSystem/EventHandlers/UnifiedEventHandlers.cs b/XPSystem/EventHandlers/UnifiedEventHandlers.cs
index aea530d..1bce46b 100644
--- a/XPSystem/EventHandlers/UnifiedEventHandlers.cs
+++ b/XPSystem/EventHandlers/UnifiedEventHandlers.cs
@@ -7,7 +7,9 @@
using MEC;
using PlayerRoles;
using XPSystem.API;
+ using XPSystem.API.Player;
using XPSystem.API.StorageProviders;
+ using XPSystem.API.StorageProviders.Models;
using XPSystem.Config.Events;
using XPSystem.Config.Events.Types;
using static XPSystem.API.XPAPI;
@@ -48,37 +50,49 @@ protected bool IsNull(T obj)
}
// Event needs to exist to ensure players are added to list
- protected void OnPlayerJoined(XPPlayer player)
+ protected void OnPlayerJoined(BaseXPPlayer player)
{
- if (XPAPI.StorageProvider != null && !player.IsNPC)
+ if (XPAPI.StorageProvider != null)
{
- if (player.DNT)
+ if (player is XPPlayer xpPlayer)
{
- player.DisplayMessage(Config.DNTMessage);
- XPAPI.StorageProvider.DeletePlayerInfo(player.PlayerId);
- return;
- }
-
- Timing.CallDelayed(.5f + Config.ExtraDelay, () =>
- {
- PlayerInfoWrapper playerInfo = player.GetPlayerInfo();
- XPPlayerJoined.Invoke(player, playerInfo);
+ Timing.CallDelayed(.5f + Config.ExtraDelay, () =>
+ {
+ PlayerInfoWrapper playerInfo = xpPlayer.GetPlayerInfo();
+ XPPlayerJoined.Invoke(xpPlayer, playerInfo);
#if STORENICKS
- UpdateNickname(player);
+ UpdateNickname(xpPlayer);
#endif
- DisplayProviders.RefreshTo(player);
- DisplayProviders.RefreshOf(player, playerInfo);
- });
+ DisplayProviders.RefreshTo(xpPlayer);
+ DisplayProviders.RefreshOf(xpPlayer, playerInfo);
+ });
+ }
+ else if (player.DNT)
+ {
+ player.DisplayMessage(Config.DNTMessage);
+
+ if (!player.UserId.TryParseUserId(out IPlayerId? playerId))
+ {
+ LogError($"Failed to parse DNT user ID for player {player.Nickname} ({player.UserId}) in order to attempt deletion");
+ return;
+ }
+
+ XPAPI.StorageProvider.DeletePlayerInfo(playerId);
+ }
}
}
- protected void OnPlayerLeft(XPPlayer player)
+ protected void OnPlayerLeft(XPPlayer? player)
{
+ if (player == null)
+ return;
PlayerLeft.Invoke(player);
}
- protected void OnPlayerChangedRole(XPPlayer player, RoleTypeId oldRole, RoleTypeId newRole)
+ protected void OnPlayerChangedRole(XPPlayer? player, RoleTypeId oldRole, RoleTypeId newRole)
{
+ if (player == null)
+ return;
PlayerChangedRole.Invoke(player, oldRole, newRole);
}
@@ -87,11 +101,11 @@ protected void OnRoundEnded(RoundSummary.LeadingTeam leadingTeam)
if (!Config.XPAfterRoundEnd)
XPGainPaused = true;
- XPECItem roundwin = XPECManager.GetItem("win");
- foreach (var kvp in XPPlayer.Players)
+ XPECItem? roundwin = XPECManager.GetItem("win");
+ foreach (XPPlayer player in XPPlayer.XPPlayers)
{
- if (kvp.Value.LeadingTeam == leadingTeam)
- kvp.Value.AddXPAndDisplayMessage(roundwin);
+ if (player.LeadingTeam == leadingTeam)
+ player.AddXPAndDisplayMessage(roundwin);
}
if (Config.LogXPGainedMethods)
@@ -113,23 +127,25 @@ protected void OnRoundRestarting()
XPPlayer.PlayersValue.Clear();
}
- protected void OnPlayedDied(XPPlayer attacker, XPPlayer target, RoleTypeId? targetRole = null)
+ protected void OnPlayedDied(XPPlayer? attacker, XPPlayer? target, RoleTypeId? targetRole = null)
{
- targetRole ??= target.Role;
+ if (target != null)
+ {
+ targetRole ??= target.Role;
+ target.TryAddXPAndDisplayMessage("death", targetRole);
+ }
- if (attacker != target)
+ if (attacker != null && attacker != target)
attacker.TryAddXPAndDisplayMessage("kill", targetRole);
-
- target.TryAddXPAndDisplayMessage("death", targetRole);
}
- protected void OnPlayerUpgradedItem(XPPlayer player, ItemCategory item) => player.TryAddXPAndDisplayMessage("upgrade", item);
- protected void OnPlayerPickedUpItem(XPPlayer player, ItemCategory item) => player.TryAddXPAndDisplayMessage("pickup", item);
- protected void OnPlayerDroppedItem(XPPlayer player, ItemCategory item) => player.TryAddXPAndDisplayMessage("drop", item);
- protected void OnPlayerUsedItem(XPPlayer player, ItemType item) => player.TryAddXPAndDisplayMessage("use", item);
+ protected void OnPlayerUpgradedItem(XPPlayer? player, ItemCategory item) => player?.TryAddXPAndDisplayMessage("upgrade", item);
+ protected void OnPlayerPickedUpItem(XPPlayer? player, ItemCategory item) => player?.TryAddXPAndDisplayMessage("pickup", item);
+ protected void OnPlayerDroppedItem(XPPlayer? player, ItemCategory item) => player?.TryAddXPAndDisplayMessage("drop", item);
+ protected void OnPlayerUsedItem(XPPlayer? player, ItemType item) => player?.TryAddXPAndDisplayMessage("use", item);
- protected void OnPlayerSpawned(XPPlayer player) => player.TryAddXPAndDisplayMessage("spawn");
- protected void OnPlayerEscaped(XPPlayer player) => player.TryAddXPAndDisplayMessage("escape");
- protected void OnPlayerResurrected(XPPlayer scp049) => scp049.TryAddXPAndDisplayMessage("resurrect");
+ protected void OnPlayerSpawned(XPPlayer? player) => player?.TryAddXPAndDisplayMessage("spawn");
+ protected void OnPlayerEscaped(XPPlayer? player) => player?.TryAddXPAndDisplayMessage("escape");
+ protected void OnPlayerResurrected(XPPlayer? scp049) => scp049?.TryAddXPAndDisplayMessage("resurrect");
}
}
\ No newline at end of file
diff --git a/XPSystem/Main.cs b/XPSystem/Main.cs
index 907824e..6681c39 100644
--- a/XPSystem/Main.cs
+++ b/XPSystem/Main.cs
@@ -2,9 +2,9 @@
{
using System;
using System.Collections.Generic;
+ using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
- using Exiled.Loader.Models;
using HarmonyLib;
using XPSystem.API;
using XPSystem.API.Legacy;
@@ -25,7 +25,7 @@ public class Main
: LabApi.Loader.Features.Plugins.Plugin
#endif
{
- public const string VersionString = "2.0.9";
+ public const string VersionString = "2.1.0";
///
/// This number is increased every time the plugin is reloaded.
@@ -54,8 +54,8 @@ public class Main
public override Version RequiredApiVersion { get; } = LabApi.Features.LabApiProperties.CurrentVersion;
#endif
- public static Main Instance { get; private set; }
- public Harmony Harmony { get; private set; }
+ public static Main? Instance { get; private set; }
+ public Harmony? Harmony { get; private set; }
private readonly UnifiedEventHandlers _eventHandlers = new
#if EXILED
@@ -71,6 +71,10 @@ public override void OnEnabled()
public override void Enable()
#endif
{
+#if !EXILED
+ Config = Config ?? Config!; // why nullable (labapi ragebait)
+#endif
+
Instance = this;
XPAPI.Config = Config;
Harmony = new Harmony($"XPSystem - {DateTime.Now.Ticks}");
@@ -78,7 +82,7 @@ public override void Enable()
DisplayProviders.Add(new NickPatchXPDisplayProvider());
DisplayProviders.Add(new RankXPDisplayProvider());
- MessagingProvider = MessagingProviders.Get(Config.DisplayMode); // why nullable
+ MessagingProvider = MessagingProviders.Get(Config.DisplayMode);
XPECLimitTracker.Initialize();
LoadExtraConfigs();
@@ -111,13 +115,13 @@ public override void Disable()
XPECLimitTracker.Disable();
ClientAliasManager.UnregisterAliases();
- SetStorageProvider((IStorageProvider)null);
+ SetStorageProvider((IStorageProvider?)null);
MessagingProvider = null;
XPECManager.Default.Files.Clear();
XPECManager.Overrides.Clear();
- Harmony.UnpatchAll(Harmony.Id);
+ Harmony?.UnpatchAll(Harmony.Id);
Harmony = null;
Instance = null;
#if EXILED
@@ -138,7 +142,7 @@ public void SetDisplayProviders(IEnumerable typeNames)
{
foreach (string typeName in typeNames)
{
- if (!TryCreate(typeName, out Exception exception, out IXPDisplayProvider provider))
+ if (!TryCreate(typeName, out Exception? exception, out IXPDisplayProvider? provider))
{
LogError($"Could not create display provider {typeName}: {exception}");
continue;
@@ -175,7 +179,7 @@ public void LoadExtraConfigs()
}
}
- public static bool TryCreate(string typeName, out Exception exception, out T obj)
+ public static bool TryCreate(string typeName, [NotNullWhen(false)] out Exception? exception, [NotNullWhen(true)] out T? obj)
{
obj = default;
exception = null;
diff --git a/XPSystem/MessagingProviders.cs b/XPSystem/MessagingProviders.cs
index 470bac6..8934112 100644
--- a/XPSystem/MessagingProviders.cs
+++ b/XPSystem/MessagingProviders.cs
@@ -2,10 +2,11 @@
{
using XPSystem.API;
using XPSystem.API.Enums;
+ using XPSystem.API.Player;
public class MessagingProviders
{
- public static IMessagingProvider Get(DisplayMode displayMode) =>
+ public static IMessagingProvider? Get(DisplayMode displayMode) =>
displayMode switch
{
DisplayMode.Hint => new HintMessagingProvider(),
@@ -16,7 +17,7 @@ public static IMessagingProvider Get(DisplayMode displayMode) =>
public class HintMessagingProvider : IMessagingProvider
{
- public void DisplayMessage(XPPlayer player, string message, float duration)
+ public void DisplayMessage(BaseXPPlayer player, string message, float duration)
{
player.ShowHint(message, duration);
}
@@ -24,7 +25,7 @@ public void DisplayMessage(XPPlayer player, string message, float duration)
public class BroadcastMessagingProvider : IMessagingProvider
{
- public void DisplayMessage(XPPlayer player, string message, float duration)
+ public void DisplayMessage(BaseXPPlayer player, string message, float duration)
{
player.ShowBroadcast(message, (ushort)duration);
}
@@ -32,7 +33,7 @@ public void DisplayMessage(XPPlayer player, string message, float duration)
public class ConsoleMessagingProvider : IMessagingProvider
{
- public void DisplayMessage(XPPlayer player, string message, float duration)
+ public void DisplayMessage(BaseXPPlayer player, string message, float duration)
{
player.SendConsoleMessage(message, "green");
}
diff --git a/XPSystem/NotNullWhenAttribute.cs b/XPSystem/NotNullWhenAttribute.cs
new file mode 100644
index 0000000..0a7c2fe
--- /dev/null
+++ b/XPSystem/NotNullWhenAttribute.cs
@@ -0,0 +1,18 @@
+namespace System.Diagnostics.CodeAnalysis // i love
+{
+ using System;
+
+ /// Specifies that when a method returns , the parameter will not be null even if the corresponding type allows it.
+ [AttributeUsage(AttributeTargets.Parameter)]
+ internal sealed class NotNullWhenAttribute : Attribute
+ {
+ /// Initializes the attribute with the specified return value condition.
+ ///
+ /// The return value condition. If the method returns this value, the associated parameter will not be null.
+ ///
+ public NotNullWhenAttribute(bool returnValue) => ReturnValue = returnValue;
+
+ /// Gets the return value condition.
+ public bool ReturnValue { get; }
+ }
+}
\ No newline at end of file
diff --git a/XPSystem/XPSystem.csproj b/XPSystem/XPSystem.csproj
index 13b0402..c175762 100644
--- a/XPSystem/XPSystem.csproj
+++ b/XPSystem/XPSystem.csproj
@@ -13,7 +13,7 @@
v4.85129
- disable
+ enableAnyCPU
@@ -86,41 +86,41 @@
..\packages\Lib.Harmony.2.2.2\lib\net48\0Harmony.dll
- ..\packages\ExMod.Exiled.9.6.0\lib\net48\Assembly-CSharp-Publicized.dll
+ $(EXILED_References)\Assembly-CSharp-Publicized.dll
- ..\packages\ExMod.Exiled.9.6.0\lib\net48\CommandSystem.Core.dll
+ ..\packages\ExMod.Exiled.9.6.3\lib\net48\CommandSystem.Core.dll..\packages\Costura.Fody.5.8.0-alpha0098\lib\netstandard1.0\Costura.dll
-
- ..\packages\ExMod.Exiled.9.6.0\lib\net48\Exiled.API.dll
+
+ ..\packages\ExMod.Exiled.9.6.3\lib\net48\Exiled.API.dll
-
- ..\packages\ExMod.Exiled.9.6.0\lib\net48\Exiled.CreditTags.dll
+
+ ..\packages\ExMod.Exiled.9.6.3\lib\net48\Exiled.CreditTags.dll
-
- ..\packages\ExMod.Exiled.9.6.0\lib\net48\Exiled.CustomItems.dll
+
+ ..\packages\ExMod.Exiled.9.6.3\lib\net48\Exiled.CustomItems.dll
-
- ..\packages\ExMod.Exiled.9.6.0\lib\net48\Exiled.CustomRoles.dll
+
+ ..\packages\ExMod.Exiled.9.6.3\lib\net48\Exiled.CustomRoles.dll
-
- ..\packages\ExMod.Exiled.9.6.0\lib\net48\Exiled.Events.dll
+
+ ..\packages\ExMod.Exiled.9.6.3\lib\net48\Exiled.Events.dll
-
- ..\packages\ExMod.Exiled.9.6.0\lib\net48\Exiled.Loader.dll
+
+ ..\packages\ExMod.Exiled.9.6.3\lib\net48\Exiled.Loader.dll
-
- ..\packages\ExMod.Exiled.9.6.0\lib\net48\Exiled.Permissions.dll
+
+ ..\packages\ExMod.Exiled.9.6.3\lib\net48\Exiled.Permissions.dll..\packages\Flee.1.2.2\lib\net45\Flee.Net45.dll
-
- ..\packages\ExMod.Exiled.9.6.0\lib\net48\LabApi.dll
+
+ $(EXILED_References)\LabApi.dll..\packages\LiteDB.5.0.16\lib\net45\LiteDB.dll
@@ -135,7 +135,7 @@
..\packages\MySqlConnector.2.3.7\lib\net48\MySqlConnector.dll
- ..\packages\ExMod.Exiled.9.6.0\lib\net48\NorthwoodLib.dll
+ ..\packages\ExMod.Exiled.9.6.3\lib\net48\NorthwoodLib.dll
@@ -173,7 +173,7 @@
- ..\packages\ExMod.Exiled.9.6.0\lib\net48\YamlDotNet.dll
+ ..\packages\ExMod.Exiled.9.6.3\lib\net48\YamlDotNet.dll
@@ -185,7 +185,6 @@
-
@@ -204,7 +203,8 @@
-
+
+
@@ -261,6 +261,7 @@
+
diff --git a/XPSystem/packages.config b/XPSystem/packages.config
index 1ddcb21..8a208ac 100644
--- a/XPSystem/packages.config
+++ b/XPSystem/packages.config
@@ -1,7 +1,7 @@
-
+