mirror of
https://github.com/JogmansonReal/Radicade.git
synced 2026-10-26 07:29:00 -07:00
167 lines
6.5 KiB
C#
167 lines
6.5 KiB
C#
using RadicadeServer.DB;
|
|
using RadicadeServer.Extensions;
|
|
using RadicadeServer.RecNet.Avatar;
|
|
using RadicadeServer.RecNet.Enums.Store;
|
|
|
|
namespace RadicadeServer.Utils
|
|
{
|
|
public static class LevelUpRewardPool
|
|
{
|
|
public const string ConfigFileName = "levelup-rewards.json";
|
|
|
|
public sealed class Pool
|
|
{
|
|
public List<string> AvatarItems { get; set; } = new();
|
|
|
|
public List<string> Consumables { get; set; } = new();
|
|
}
|
|
|
|
private static readonly string[] DeniedPatterns =
|
|
[
|
|
"exclusive", "early access", "alpha", "art festival",
|
|
"rec con", "reccon", "rrcc", "raw data", "sfvrcc",
|
|
"contest", "trophy", "competition",
|
|
"moderator", "volunteer",
|
|
"video partner", "creator program", "partnered creator", "partner",
|
|
"bug bounty", "security", "ethical hackers", "gold notes",
|
|
"seller swag", "sponsored league",
|
|
"rro-", "rro specific",
|
|
"promo", "promotional", "sponsor", "collab", "licensed", "prom",
|
|
"mrbeast", "mr beast", "miraculous", "nba",
|
|
|
|
"class of", "graduation", "class)", "creator conference",
|
|
|
|
"for earning", "available until", "unlocked by visiting",
|
|
"unlocked during", "xbox", "launch reward", "launch exclusive",
|
|
"reward for", "given to", "space marine", "space visor",
|
|
|
|
"(gold)",
|
|
|
|
"limited", "never return", "founder", "founders",
|
|
"halloween", "holiday", "thanksgiving", "invasion", "elseware",
|
|
"new year", "carnivale", "reclympics", "rec rocks", "anniversary", "2020 glasses",
|
|
"developer", "dev only", "staff only", "admin only", "test item", "debug",
|
|
];
|
|
|
|
private static readonly string[] DeniedTags =
|
|
[
|
|
"halloween", "holidays", "thanksgiving", "invasion", "elseware", "reccon", "reccon2021",
|
|
];
|
|
|
|
private static Pool? _cached;
|
|
private static string? _cachedFrom;
|
|
|
|
public static void ResetCache()
|
|
{
|
|
_cached = null;
|
|
_cachedFrom = null;
|
|
}
|
|
|
|
public static Pool Load(string? json = null)
|
|
{
|
|
if (json != null) return Parse(json);
|
|
if (_cached != null) return _cached;
|
|
|
|
foreach (var directory in DBConfig.AvatarCatalogDirectories())
|
|
{
|
|
var path = Path.Join(directory, ConfigFileName);
|
|
if (!File.Exists(path)) continue;
|
|
|
|
try
|
|
{
|
|
_cached = Parse(File.ReadAllText(path));
|
|
_cachedFrom = path;
|
|
return _cached;
|
|
}
|
|
catch (Exception)
|
|
{
|
|
}
|
|
}
|
|
_cached = new Pool();
|
|
return _cached;
|
|
}
|
|
|
|
public static string? LoadedFrom => _cachedFrom;
|
|
|
|
private static Pool Parse(string json)
|
|
{
|
|
var pool = json.FromJson<Pool>() ?? new Pool();
|
|
pool.AvatarItems = Clean(pool.AvatarItems);
|
|
pool.Consumables = Clean(pool.Consumables);
|
|
return pool;
|
|
}
|
|
|
|
private static List<string> Clean(IEnumerable<string>? values) =>
|
|
(values ?? Enumerable.Empty<string>())
|
|
.Where(value => !string.IsNullOrWhiteSpace(value))
|
|
.Select(value => value.Trim())
|
|
.Distinct(StringComparer.OrdinalIgnoreCase)
|
|
.ToList();
|
|
|
|
public static bool IsAlwaysDenied(string? name, string? tooltip, string? tag = null)
|
|
{
|
|
return Matches(name) || Matches(tooltip) || MatchesTag(tag);
|
|
|
|
static bool Matches(string? text)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(text)) return false;
|
|
return DeniedPatterns.Any(pattern =>
|
|
text.Contains(pattern, StringComparison.OrdinalIgnoreCase));
|
|
}
|
|
|
|
static bool MatchesTag(string? text)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(text)) return false;
|
|
var tags = text.Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
|
|
return tags.Any(tag => DeniedTags.Contains(tag, StringComparer.OrdinalIgnoreCase));
|
|
}
|
|
}
|
|
|
|
public static bool IsAlwaysDenied(AvatarItem item) =>
|
|
item != null && IsAlwaysDenied(item.FriendlyName, item.Tooltip, item.TagList);
|
|
|
|
public static bool IsAlwaysDenied(ConsumableItem item) =>
|
|
item != null && IsAlwaysDenied(item.FriendlyName, item.Tooltip);
|
|
|
|
public static string OwnershipKey(string? description) =>
|
|
AvatarItemDescription.Normalize(description).Trim().ToLowerInvariant();
|
|
|
|
public static AvatarItem? PickAvatarItem(
|
|
IEnumerable<AvatarItem> catalogue, Rarity rarity, ISet<string> owned, Random random, Pool? pool = null)
|
|
{
|
|
var allowed = (pool ?? Load()).AvatarItems.ToHashSet(StringComparer.OrdinalIgnoreCase);
|
|
if (allowed.Count == 0) return null;
|
|
|
|
var candidates = catalogue
|
|
.Where(item => item != null
|
|
&& !string.IsNullOrWhiteSpace(item.AvatarItemDesc)
|
|
&& !item.IsBaseAvatarItem
|
|
&& item.Rarity == (int)rarity
|
|
&& allowed.Contains(item.AvatarItemDesc)
|
|
&& !IsAlwaysDenied(item)
|
|
&& !owned.Contains(OwnershipKey(item.AvatarItemDesc)))
|
|
.OrderBy(item => item.AvatarItemDesc, StringComparer.Ordinal)
|
|
.ToList();
|
|
|
|
return candidates.Count == 0 ? null : candidates[random.Next(candidates.Count)];
|
|
}
|
|
|
|
public static ConsumableItem? PickConsumable(
|
|
IEnumerable<ConsumableItem> catalogue, ISet<string> owned, Random random, Pool? pool = null)
|
|
{
|
|
var configured = (pool ?? Load()).Consumables.ToHashSet(StringComparer.OrdinalIgnoreCase);
|
|
|
|
var candidates = catalogue
|
|
.Where(item => item != null
|
|
&& !string.IsNullOrWhiteSpace(item.ConsumableItemDesc)
|
|
&& (configured.Count == 0 || configured.Contains(item.ConsumableItemDesc))
|
|
&& !IsAlwaysDenied(item)
|
|
&& !owned.Contains(OwnershipKey(ConsumableCatalog.ToClientDesc(item.ConsumableItemDesc))))
|
|
.OrderBy(item => item.ConsumableItemDesc, StringComparer.Ordinal)
|
|
.ToList();
|
|
|
|
return candidates.Count == 0 ? null : candidates[random.Next(candidates.Count)];
|
|
}
|
|
}
|
|
}
|