Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 15 additions & 1 deletion XPSystem/API/DisplayProviders/XPDisplayProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -139,10 +139,24 @@ internal override void LoadConfig(string folder)
try
{
Config = Deserializer.Deserialize<T>(File.ReadAllText(file));
if (Config == null)
throw new InvalidDataException("Config file deserialized to null.");
}
catch (Exception e)
{
LogError($"Error loading display provider config for {name}: {e}");
Config = new T();

try
{
string defaultFile = Path.Combine(folder, name + ".default.yml");
File.WriteAllText(defaultFile, Serializer.Serialize(Config));
LogWarn($"Using default config for {name}. A fresh default was written to {defaultFile}");
}
catch (Exception writeException)
{
LogError($"Could not write default display provider config for {name}: {writeException}");
}
}
}
else
Expand All @@ -164,4 +178,4 @@ public abstract class ConfigXPDisplayProvider : IXPDisplayProvider
internal abstract IXPDisplayProviderConfig ConfigPropertyInternal { get; }
internal abstract void LoadConfig(string folder);
}
}
}
115 changes: 89 additions & 26 deletions XPSystem/API/XPAPI.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ namespace XPSystem.API
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Text;
using MEC;
using NorthwoodLib.Pools;
using PlayerRoles;
using XPSystem.API.DisplayProviders;
Expand Down Expand Up @@ -58,6 +59,7 @@ public static class XPAPI
/// </summary>
private static SerializerBuilder SerializerBuilder => new SerializerBuilder()
.WithLoaderTypeConverters()
.WithTypeConverter(new StringYamlConverter())
.WithTypeConverter(new XPECFileYamlConverter())
.WithTypeInspector(inner => new CommentGatheringTypeInspector(inner))
.WithEmissionPhaseObjectGraphVisitor(args => new CommentsObjectGraphVisitor(args.InnerVisitor))
Expand Down Expand Up @@ -265,19 +267,11 @@ internal static bool AddXP(PlayerInfoWrapper playerInfo, int amount, XPPlayer? p
XPPlayer.TryGetXP(playerInfo.Player, out player);

int prevLevel = playerInfo.Level;
float floatAmount = amount;
bool connected = player != null;

if (amount > 0 || Config.XPMultiplierForXPLoss)
{
if (player?.XPMultiplier != null)
floatAmount *= player.XPMultiplier;

if (connected || Config.GlobalXPMultiplierForNonOnline)
floatAmount *= Config.GlobalXPMultiplier;
}

amount = (int)floatAmount;
amount = CalculateModifiedXPAmount(amount, player, connected);
if (amount == 0)
return false;

playerInfo.PlayerInfo.XP += amount;
StorageProvider!.SetPlayerInfo(playerInfo);
Expand All @@ -290,6 +284,22 @@ internal static bool AddXP(PlayerInfoWrapper playerInfo, int amount, XPPlayer? p

return true;
}

private static int CalculateModifiedXPAmount(int amount, XPPlayer? player, bool connected)
{
float floatAmount = amount;

if (amount > 0 || Config.XPMultiplierForXPLoss)
{
if (player?.XPMultiplier != null)
floatAmount *= player.XPMultiplier;

if (connected || Config.GlobalXPMultiplierForNonOnline)
floatAmount *= Config.GlobalXPMultiplier;
}

return (int)floatAmount;
}
#endregion
#region Translations
/// <summary>
Expand Down Expand Up @@ -360,22 +370,47 @@ public static bool AddXPAndDisplayMessage(XPPlayer player, XPECItem? xpecItem)
/// <returns>Whether or not XP was added.</returns>
public static bool AddXPAndDisplayMessage(XPPlayer player, int amount, string? message, bool force = false)
{
if (amount == 0 && !force || XPGainPaused)
if (amount == 0 && !force || XPGainPaused && !force)
return false;

PlayerInfoWrapper playerInfo = GetPlayerInfo(player.PlayerId);
bool levelup = AddXP(player, amount, force: true, playerInfo: playerInfo);
int modifiedAmount = CalculateModifiedXPAmount(amount, player, true);
bool levelup = AddXPWithoutLevelMessage(player, amount, playerInfo);

if (levelup && !Config.ShowXPOnLevelUp)
return true;
List<string> messages = new();

if (!string.IsNullOrWhiteSpace(message))
if ((!levelup || Config.ShowXPOnLevelUp) && !string.IsNullOrWhiteSpace(message))
{
if (Config.UseAddedXPTemplate)
message = FormatMessage(message!, playerInfo);
DisplayMessage(player, message);
message = FormatMessage(message!, playerInfo, modifiedAmount);

if (!string.IsNullOrWhiteSpace(message))
messages.Add(message!);
}

if (levelup && Config.ShowAddedLVL)
messages.Add(Config.AddedLVLMessage.Replace("%level%", playerInfo.Level.ToString()));

if (messages.Count > 0)
DisplayMessage(player, string.Join(Config.AddedXPLevelSeparator, messages));

return levelup || modifiedAmount != 0 || force;
}

private static bool AddXPWithoutLevelMessage(XPPlayer player, int amount, PlayerInfoWrapper playerInfo)
{
int prevLevel = playerInfo.Level;
amount = CalculateModifiedXPAmount(amount, player, true);
if (amount == 0)
return false;

playerInfo.PlayerInfo.XP += amount;
StorageProvider!.SetPlayerInfo(playerInfo);

if (playerInfo.Level == prevLevel)
return false;

HandleLevelUp(player, playerInfo, prevLevel, false);
return true;
}

Expand All @@ -385,10 +420,17 @@ public static bool AddXPAndDisplayMessage(XPPlayer player, int amount, string? m
/// <param name="message">The message to format.</param>
/// <param name="playerInfo">The <see cref="PlayerInfoWrapper"/> of the player to format the message for.</param>
/// <returns>The formatted message.</returns>
public static string FormatMessage(string message, PlayerInfoWrapper playerInfo)
public static string FormatMessage(string message, PlayerInfoWrapper playerInfo, int amount = 0)
{
message = Config.AddedXPTemplate
string template = Config.AddedXPTemplate;
string xpChange = FormatXPChange(amount);
if (!template.Contains("%xpchange%") && !template.Contains("%xpamount%"))
message = $"{message} <color=yellow>{xpChange} XP</color>";

message = template
.Replace("%message%", message)
.Replace("%xpamount%", Math.Abs(amount).ToString())
.Replace("%xpchange%", xpChange)
.Replace("%currentlevel%", playerInfo.Level.ToString())
.Replace("%nextlevel%", (playerInfo.Level + 1).ToString());

Expand Down Expand Up @@ -418,8 +460,9 @@ public static string FormatMessage(string message, PlayerInfoWrapper playerInfo)
{
char filledChar = Config.AddedXPProgressBarChars[0];
char remainingChar = Config.AddedXPProgressBarChars[1];
double fillPercentage = (double)(playerInfo.XP - playerInfo.NeededXPCurrent) /
(playerInfo.NeededXPNext - playerInfo.NeededXPCurrent);
int neededDelta = Math.Max(1, playerInfo.NeededXPNext - playerInfo.NeededXPCurrent);
double fillPercentage = Math.Max(0d, Math.Min(1d,
(double)(playerInfo.XP - playerInfo.NeededXPCurrent) / neededDelta));
int fill = (int)(Config.AddedXPProgressBarLength * fillPercentage);

message = message
Expand All @@ -432,6 +475,8 @@ public static string FormatMessage(string message, PlayerInfoWrapper playerInfo)

return message;
}

private static string FormatXPChange(int amount) => amount > 0 ? "+" + amount : amount.ToString();
#endregion
#region Misc
/// <summary>
Expand All @@ -440,11 +485,11 @@ public static string FormatMessage(string message, PlayerInfoWrapper playerInfo)
/// <param name="player">The player that leveled up.</param>
/// <param name="wrapper">The <see cref="PlayerInfoWrapper"/> belonging to the player.</param>
/// <param name="prevLevel">The previous level the player had.</param>
public static void HandleLevelUp(XPPlayer player, PlayerInfoWrapper wrapper, int prevLevel)
public static void HandleLevelUp(XPPlayer player, PlayerInfoWrapper wrapper, int prevLevel, bool showMessage = true)
{
DisplayProviders.RefreshOf(player);
RefreshDisplaysAfterXPChange(player, wrapper);

if (Config.ShowAddedLVL)
if (showMessage && Config.ShowAddedLVL)
{
player.DisplayMessage(Config.AddedLVLMessage.Replace("%level%",
wrapper.Level.ToString()));
Expand All @@ -453,6 +498,24 @@ public static void HandleLevelUp(XPPlayer player, PlayerInfoWrapper wrapper, int
PlayerLevelUp.Invoke(player, wrapper.Level, prevLevel);
}

public static void RefreshDisplaysAfterXPChange(XPPlayer player, PlayerInfoWrapper? playerInfo = null)
{
playerInfo ??= GetPlayerInfo(player);
DisplayProviders.RefreshOf(player, playerInfo);

int retries = Math.Max(0, Config.DisplayRefreshRetryCount);
float delay = Math.Max(0f, Config.DisplayRefreshRetryDelay);
for (int i = 1; i <= retries; i++)
{
float refreshDelay = delay * i + Config.ExtraDelay;
Timing.CallDelayed(refreshDelay, () =>
{
if (player.IsConnected)
DisplayProviders.RefreshOf(player, playerInfo);
});
}
}

/// <summary>
/// Attempts to create a <see cref="IPlayerId"/> from an id and an <see cref="AuthType"/>.
/// </summary>
Expand Down Expand Up @@ -579,4 +642,4 @@ public static string FormatType(Type type)
}
#endregion
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,15 @@

public class RankSetXPDisplayProvider : XPDisplayProvider<RankSetXPDisplayProvider.RankConfig>
{
public override void RefreshAll() {}
public override void RefreshAll()
{
if (!Config.Enabled)
return;

foreach (BaseXPPlayer player in XPPlayer.PlayersRealConnected)
Refresh(player, player is XPPlayer xpPlayer ? xpPlayer.GetPlayerInfo() : null);
}

public override void RefreshTo(BaseXPPlayer player) {}

private Badge? GetBadge(BaseXPPlayer player, PlayerInfoWrapper? playerInfo)
Expand All @@ -37,7 +45,9 @@ public override void RefreshTo(BaseXPPlayer player) {}

Badge? badge = null;
string format = !player.HasBadge || player.HasHiddenBadge
? Config.BadgeStructureNoBadge
? string.IsNullOrWhiteSpace(Config.BadgeStructureNoBadge)
? Config.BadgeStructure
: Config.BadgeStructureNoBadge
: Config.BadgeStructure;
string? color = null;

Expand All @@ -61,7 +71,7 @@ public override void RefreshTo(BaseXPPlayer player) {}
Text = format
.Replace("%lvl%", playerInfo.Level.ToString())
.Replace("%badge%", badge.Text)
.Replace("%oldbadge%", player.BadgeText),
.Replace("%oldbadge%", player.BadgeText ?? string.Empty),
Color = color ?? "default"
};
}
Expand All @@ -76,6 +86,14 @@ private void Refresh(BaseXPPlayer player, PlayerInfoWrapper? playerInfo = null)
player.Hub.serverRoles.Network_myColor = badge.Color;
}

public override void RefreshOf(BaseXPPlayer player, PlayerInfoWrapper? playerInfo = null)
{
if (!Config.Enabled)
return;

Refresh(player, playerInfo);
}

public override void Enable()
{
base.Enable();
Expand Down Expand Up @@ -202,4 +220,4 @@ public class RankConfig : IXPDisplayProviderConfig
};
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,9 @@ public class RankXPDisplayProvider : SyncVarXPDisplayProvider<RankXPDisplayProvi

Badge? badge = null;
string format = !player.HasBadge || player.HasHiddenBadge
? Config.BadgeStructureNoBadge
? string.IsNullOrWhiteSpace(Config.BadgeStructureNoBadge)
? Config.BadgeStructure
: Config.BadgeStructureNoBadge
: Config.BadgeStructure;
string? color = null;

Expand All @@ -62,7 +64,7 @@ public class RankXPDisplayProvider : SyncVarXPDisplayProvider<RankXPDisplayProvi
Text = format
.Replace("%lvl%", playerInfo.Level.ToString())
.Replace("%badge%", badge.Text)
.Replace("%oldbadge%", player.BadgeText),
.Replace("%oldbadge%", player.BadgeText ?? string.Empty),
Color = color ?? "default"
};
}
Expand Down Expand Up @@ -195,4 +197,4 @@ public class RankConfig : IXPDisplayProviderConfig
};
}
}
}
}
8 changes: 7 additions & 1 deletion XPSystem/Commands/Admin/DatabasePlayerCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -72,5 +72,11 @@ protected bool DoThingWithArgs(ref ArraySegment<string> arguments, byte targetPl
return false;

}

protected void RefreshTargetDisplayIfOnline(IPlayerId playerId, PlayerInfoWrapper playerInfo)
{
if (XPPlayer.TryGetXP(playerId, out XPPlayer? player))
XPAPI.RefreshDisplaysAfterXPChange(player, playerInfo);
}
}
}
}
3 changes: 2 additions & 1 deletion XPSystem/Commands/Admin/Subcommands/GiveCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ public override bool Execute(ArraySegment<string> arguments, ICommandSender send
return false;

playerInfo.XP += amount;
RefreshTargetDisplayIfOnline(playerId, playerInfo);

response = $"Gave {amount} XP to {playerId.ToString()} ({playerInfo.Nickname}).";
return true;
Expand All @@ -45,4 +46,4 @@ public override bool Execute(ArraySegment<string> arguments, ICommandSender send
public override string Command { get; } = "give";
public override string Description { get; } = "Give a player XP.";
}
}
}
3 changes: 2 additions & 1 deletion XPSystem/Commands/Admin/Subcommands/SetCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ public override bool Execute(ArraySegment<string> arguments, ICommandSender send
return false;

playerInfo.XP = amount;
RefreshTargetDisplayIfOnline(playerId, playerInfo);

response = $"Set {playerId.ToString()} ({playerInfo.Nickname})'s XP to {amount}.";
return true;
Expand All @@ -47,4 +48,4 @@ public override bool Execute(ArraySegment<string> arguments, ICommandSender send
public override string Command { get; } = "set";
public override string Description { get; } = "Set a player's XP.";
}
}
}
3 changes: 2 additions & 1 deletion XPSystem/Commands/Admin/Subcommands/SetLevelCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ public override bool Execute(ArraySegment<string> arguments, ICommandSender send
return false;

playerInfo.Level = level;
RefreshTargetDisplayIfOnline(playerId, playerInfo);

response = $"Set {playerId.ToString()} ({playerInfo.Nickname})'s level to {level}.";
return true;
Expand All @@ -47,4 +48,4 @@ public override bool Execute(ArraySegment<string> arguments, ICommandSender send
public override string Command { get; } = "setlevel";
public override string Description { get; } = "Set a player's level.";
}
}
}
Loading