v.1.1.7
This commit is contained in:
parent
a36fdbf92d
commit
04a4fdce0d
143 changed files with 3565 additions and 2344 deletions
|
|
@ -1,9 +1,5 @@
|
|||
using CounterStrikeSharp.API.Modules.Utils;
|
||||
using jRandomSkills.src.player;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using System.Reflection;
|
||||
using static jRandomSkills.jRandomSkills;
|
||||
|
||||
namespace jRandomSkills
|
||||
|
|
@ -12,111 +8,67 @@ namespace jRandomSkills
|
|||
{
|
||||
private static readonly string configsFolder = Path.Combine(Instance.ModuleDirectory, "configs");
|
||||
private static readonly string configPath = Path.Combine(configsFolder, "config.json");
|
||||
private static ConfigModel config = LoadConfig();
|
||||
private static readonly object fileLock = new();
|
||||
|
||||
public static ConfigModel LoadedConfig => config;
|
||||
private static SettingsModel config = LoadConfig();
|
||||
public static SettingsModel LoadedConfig => config;
|
||||
|
||||
public static ConfigModel LoadConfig()
|
||||
public static SettingsModel LoadConfig()
|
||||
{
|
||||
if (!File.Exists(configPath))
|
||||
lock (fileLock)
|
||||
{
|
||||
Instance.Logger.LogInformation("Config file does not exist. Create a new config file...");
|
||||
var defaultConfig = new ConfigModel();
|
||||
SaveConfig(defaultConfig);
|
||||
return defaultConfig;
|
||||
}
|
||||
var newConfig = new SettingsModel();
|
||||
|
||||
string json = File.ReadAllText(configPath);
|
||||
var config = new ConfigModel();
|
||||
if (!File.Exists(configPath))
|
||||
{
|
||||
Instance.Logger.LogInformation("Config file does not exist. Create a new config file...");
|
||||
SaveConfig(newConfig);
|
||||
return config = newConfig;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var root = JsonConvert.DeserializeObject<JObject>(json);
|
||||
if (root == null) return config;
|
||||
try
|
||||
{
|
||||
string json;
|
||||
using (var fs = new FileStream(configPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||
using (var sr = new StreamReader(fs))
|
||||
json = sr.ReadToEnd();
|
||||
newConfig = JsonConvert.DeserializeObject<SettingsModel>(json) ?? new SettingsModel();
|
||||
}
|
||||
catch
|
||||
{
|
||||
Instance.Logger.LogError("Error when loading the config file.");
|
||||
}
|
||||
|
||||
var settings = root["Settings"];
|
||||
if (settings != null) JsonConvert.PopulateObject(settings.ToString(), config.Settings);
|
||||
|
||||
var skillsArray = (JArray?)root["SkillsInfo"];
|
||||
if (skillsArray != null)
|
||||
foreach (var skillObj in skillsArray)
|
||||
{
|
||||
var name = skillObj["Name"];
|
||||
if (name == null) continue;
|
||||
var instance = config.SkillsInfo.FirstOrDefault(x => x.Name == name.ToString());
|
||||
if (instance != null) JsonConvert.PopulateObject(skillObj.ToString(), instance);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
Instance.Logger.LogError("Error when loading the config file.");
|
||||
}
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
public static void SaveConfig(ConfigModel config)
|
||||
{
|
||||
try
|
||||
{
|
||||
Directory.CreateDirectory(configsFolder);
|
||||
string json = JsonConvert.SerializeObject(config, Formatting.Indented);
|
||||
File.WriteAllText(configPath, json);
|
||||
}
|
||||
catch
|
||||
{
|
||||
Instance.Logger.LogError("Error when saving the config file.");
|
||||
if (newConfig.DisplayAlwaysDescription)
|
||||
newConfig.SkillDescriptionDuration = 9999;
|
||||
return config = newConfig;
|
||||
}
|
||||
}
|
||||
|
||||
public static T GetValue<T>(object skill, string key)
|
||||
public static void SaveConfig(SettingsModel config)
|
||||
{
|
||||
var skillConfig = config.SkillsInfo.FirstOrDefault(s => s.Name == skill.ToString());
|
||||
if (skillConfig == null) return default!;
|
||||
|
||||
var prop = skillConfig.GetType().GetProperty(key, BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase);
|
||||
if (prop != null)
|
||||
lock (fileLock)
|
||||
{
|
||||
var value = prop.GetValue(skillConfig);
|
||||
if (value == null) return default!;
|
||||
else return (T)Convert.ChangeType(value, typeof(T));
|
||||
}
|
||||
try
|
||||
{
|
||||
Directory.CreateDirectory(configsFolder);
|
||||
string json = JsonConvert.SerializeObject(config, Formatting.Indented);
|
||||
|
||||
var field = skillConfig.GetType().GetField(key, BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase);
|
||||
if (field != null)
|
||||
{
|
||||
var value = field.GetValue(skillConfig);
|
||||
if (value == null) return default!;
|
||||
else return (T)Convert.ChangeType(value, typeof(T));
|
||||
}
|
||||
string tempPath = $"{configPath}.temp";
|
||||
File.WriteAllText(tempPath, json);
|
||||
|
||||
return default!;
|
||||
}
|
||||
|
||||
public class ConfigModel
|
||||
{
|
||||
public Settings Settings { get; set; } = new Settings();
|
||||
public DefaultSkillInfo[] SkillsInfo { get; set; }
|
||||
|
||||
public ConfigModel()
|
||||
{
|
||||
SkillsInfo = Assembly.GetExecutingAssembly().GetTypes()
|
||||
.Where(t => typeof(DefaultSkillInfo).IsAssignableFrom(t) && t.Name == "SkillConfig")
|
||||
.Select(t =>
|
||||
{
|
||||
var ctor = t.GetConstructors().FirstOrDefault(c => c.GetParameters().All(p => p.IsOptional));
|
||||
if (ctor == null) return null;
|
||||
var args = ctor.GetParameters().Select(p => Type.Missing).ToArray();
|
||||
return ctor.Invoke(args) as DefaultSkillInfo;
|
||||
})
|
||||
.Where(instance => instance != null)
|
||||
.ToArray()!;
|
||||
File.Copy(tempPath, configPath, overwrite: true);
|
||||
File.Delete(tempPath);
|
||||
}
|
||||
catch
|
||||
{
|
||||
Instance.Logger.LogError("Error when saving the config file.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class Settings
|
||||
public class SettingsModel
|
||||
{
|
||||
public string LangCode { get; set; }
|
||||
public int GameMode { get; set; }
|
||||
public bool KillerSkillInfo { get; set; }
|
||||
public bool TeamMateSkillInfo { get; set; }
|
||||
|
|
@ -125,28 +77,17 @@ namespace jRandomSkills
|
|||
public string? AlternativeSkillButton { get; set; }
|
||||
public float SkillTimeBeforeStart { get; set; }
|
||||
public float SkillDescriptionDuration { get; set; }
|
||||
public bool DisplayAlwaysDescription { get; set; }
|
||||
public bool DisableSpectateHUD { get; set; }
|
||||
public bool FlashingHtmlHudFix { get; set; }
|
||||
public bool CS2TraceRayDebug { get; set; }
|
||||
public LanguageSystem LanguageSystem { get; set; }
|
||||
public HtmlHudCustomisation HtmlHudCustomisation { get; set; }
|
||||
public NormalCommands NormalCommands { get; set; }
|
||||
public VotingCommands VotingCommands { get; set; }
|
||||
|
||||
public NormalCommand SetSkillCommands { get; set; }
|
||||
public NormalCommand SkillsListCommands { get; set; }
|
||||
public NormalCommand UseSkillCommands { get; set; }
|
||||
public NormalCommand HealCommands { get; set; }
|
||||
public NormalCommand ConsoleCommands { get; set; }
|
||||
public NormalCommand SetStaticSkillCommands { get; set; }
|
||||
public NormalCommand ChangeLanguageCommands { get; set; }
|
||||
public NormalCommand ReloadCommands { get; set; }
|
||||
public VotingCommand StartGameCommands { get; set; }
|
||||
public VotingCommand ChangeMapCommands { get; set; }
|
||||
public VotingCommand SwapCommands { get; set; }
|
||||
public VotingCommand ShuffleCommands { get; set; }
|
||||
public VotingCommand PauseCommands { get; set; }
|
||||
public VotingCommand SetScoreCommands { get; set; }
|
||||
|
||||
public Settings()
|
||||
public SettingsModel()
|
||||
{
|
||||
LangCode = "en";
|
||||
GameMode = (int)GameModes.NoRepeat;
|
||||
KillerSkillInfo = true;
|
||||
TeamMateSkillInfo = true;
|
||||
|
|
@ -155,27 +96,100 @@ namespace jRandomSkills
|
|||
AlternativeSkillButton = null;
|
||||
SkillTimeBeforeStart = 7;
|
||||
SkillDescriptionDuration = 7;
|
||||
DisplayAlwaysDescription = false;
|
||||
FlashingHtmlHudFix = true;
|
||||
CS2TraceRayDebug = false;
|
||||
DisableSpectateHUD = false;
|
||||
|
||||
SetSkillCommands = new NormalCommand("ustawskill, ustaw_skill, setskill, set_skill, definirhabilidade, configurarhabilidade, 设置技能, 配置技能", "@jRandmosSkills/admin");
|
||||
SkillsListCommands = new NormalCommand("supermoc, skille, listamocy, supermoce, skills, listaHabilidades, habilidades, 技能列表, 超能力列表", "@jRandmosSkills/admin");
|
||||
UseSkillCommands = new NormalCommand("t, useSkill, usarHabilidade, 技能使用, 使用技能", "@jRandmosSkills/admin");
|
||||
HealCommands = new NormalCommand("heal, ulecz, curar, tratar, 治疗, 治愈", "@jRandmosSkills/admin");
|
||||
ConsoleCommands = new NormalCommand("console, sv, 控制台, 服务器", "@jRandmosSkills/root");
|
||||
SetStaticSkillCommands = new NormalCommand("ustawstatycznyskill, ustaw_statyczny_skill, setstaticskill, set_static_skill", "@jRandmosSkills/admin");
|
||||
ChangeLanguageCommands = new NormalCommand("lang, language, changelang, change_lang, jezyk, język", "");
|
||||
ReloadCommands = new NormalCommand("reload, refresh", "@jRandmosSkills/admin");
|
||||
LanguageSystem = new LanguageSystem
|
||||
{
|
||||
DefaultLangCode = "en",
|
||||
DisableGeoLite = false,
|
||||
LanguageInfos =
|
||||
[
|
||||
new LanguageInfo("CN, TW, HK, MO, SG", "pt-br"),
|
||||
new LanguageInfo("PT, BR, AO, CV, GW, MZ, ST, TL", "zh"),
|
||||
new LanguageInfo("FR, MC, HT", "fr"),
|
||||
new LanguageInfo("PL", "pl"),
|
||||
new LanguageInfo("GB, US", "en")
|
||||
]
|
||||
};
|
||||
|
||||
StartGameCommands = new VotingCommand(true, "start, go, começar, iniciar, 开始, 启动", "@jRandmosSkills/admin", 15, 60, 15, 500, 2);
|
||||
ChangeMapCommands = new VotingCommand( true, "map, mapa, changemap, zmienmape, zmienmape, mudarMapa, trocarMapa, 更换地图, 更改地图", "@jRandmosSkills/admin", 25, 90, 15, 500, 2);
|
||||
SwapCommands = new VotingCommand(true, "swap, zmiana, trocar, 交换, 切换", "@jRandmosSkills/admin", 15, 90, 15, 20, 2);
|
||||
ShuffleCommands = new VotingCommand(true, "shuffle, embaralhar, 随机排序, 洗牌", "@jRandmosSkills/admin", 15, 90, 15, 20, 2);
|
||||
PauseCommands = new VotingCommand(true, "pause, unpause, pausar, despausar, 暂停, 恢复", "@jRandmosSkills/admin", 15, 60, 15, 2, 2);
|
||||
SetScoreCommands = new VotingCommand(true, "setscore, wynik, definirPontuacao, configurarPontos, 设置分数, 调整分数", "@jRandmosSkills/root", 15, 90, 15, 90, 2);
|
||||
HtmlHudCustomisation = new HtmlHudCustomisation
|
||||
{
|
||||
HeaderLineColor = "#FFFFFF",
|
||||
HeaderLineSize = "ml",
|
||||
SkillLineSize = "l",
|
||||
InfoLineColor = "#FFFFFF",
|
||||
InfoLineSize = "sm",
|
||||
SkillDescriptionLineColor = "#999999",
|
||||
SkillDescriptionLineSize = "sm",
|
||||
WSADMenuSelectInfoLineColor = "#999999",
|
||||
WSADMenuSelectInfoLineSize = "sm",
|
||||
WSADMenuItemLineColor = "white",
|
||||
WSADMenuItemHoverLineColor = "orange",
|
||||
WSADMenuItemLineSize = "sm",
|
||||
WSADMenuControllsLineSize = "sm",
|
||||
WSADMenuControllsLineColor1 = "cyan",
|
||||
WSADMenuControllsLineColor2 = "white",
|
||||
WSADMenuControllsLineColor3 = "green",
|
||||
};
|
||||
|
||||
NormalCommands = new NormalCommands
|
||||
{
|
||||
SetSkillCommand = new NormalCommand("ustawskill, ustaw_skill, setskill, set_skill, definirhabilidade, configurarhabilidade, 设置技能, 配置技能", "@jRandmosSkills/admin"),
|
||||
SkillsListCommand = new NormalCommand("supermoc, skille, listamocy, supermoce, skills, listaHabilidades, habilidades, 技能列表, 超能力列表", "@jRandmosSkills/admin"),
|
||||
UseSkillCommand = new NormalCommand("t, useSkill, usarHabilidade, 技能使用, 使用技能", "@jRandmosSkills/admin"),
|
||||
HealCommand = new NormalCommand("heal, ulecz, curar, tratar, 治疗, 治愈", "@jRandmosSkills/admin"),
|
||||
ConsoleCommand = new NormalCommand("console, sv, 控制台, 服务器", "@jRandmosSkills/root"),
|
||||
SetStaticSkillCommand = new NormalCommand("ustawstatycznyskill, ustaw_statyczny_skill, setstaticskill, set_static_skill", "@jRandmosSkills/admin"),
|
||||
ChangeLanguageCommand = new NormalCommand("lang, language, changelang, change_lang, jezyk, język", ""),
|
||||
ReloadCommand = new NormalCommand("reload, refresh", "@jRandmosSkills/admin"),
|
||||
};
|
||||
|
||||
VotingCommands = new VotingCommands
|
||||
{
|
||||
StartGameCommand = new StartGameCommand(true, "start, go, começar, iniciar, 开始, 启动", "@jRandmosSkills/admin", "mp_freezetime 15; mp_forcecamera 0; mp_overtime_enable 1; sv_cheats 0", "mp_freezetime 0; mp_forcecamera 0; mp_overtime_enable 1; sv_cheats 1", 15, 60, 15, 500, 2),
|
||||
ChangeMapCommand = new VotingCommand(true, "map, mapa, changemap, zmienmape, zmienmape, mudarMapa, trocarMapa, 更换地图, 更改地图", "@jRandmosSkills/admin", 25, 90, 15, 500, 2),
|
||||
SwapCommand = new VotingCommand(true, "swap, zmiana, trocar, 交换, 切换", "@jRandmosSkills/admin", 15, 90, 15, 20, 2),
|
||||
ShuffleCommand = new VotingCommand(true, "shuffle, embaralhar, 随机排序, 洗牌", "@jRandmosSkills/admin", 15, 90, 15, 20, 2),
|
||||
PauseCommand = new VotingCommand(true, "pause, unpause, pausar, despausar, 暂停, 恢复", "@jRandmosSkills/admin", 15, 60, 15, 2, 2),
|
||||
SetScoreCommand = new VotingCommand(true, "setscore, wynik, definirPontuacao, configurarPontos, 设置分数, 调整分数", "@jRandmosSkills/root", 15, 90, 15, 90, 2),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public class HtmlHudCustomisation
|
||||
{
|
||||
public required string HeaderLineColor { get; set; }
|
||||
public required string HeaderLineSize { get; set; }
|
||||
public required string SkillLineSize { get; set; }
|
||||
public required string InfoLineColor { get; set; }
|
||||
public required string InfoLineSize { get; set; }
|
||||
public required string SkillDescriptionLineColor { get; set; }
|
||||
public required string SkillDescriptionLineSize { get; set; }
|
||||
public required string WSADMenuSelectInfoLineColor { get; set; }
|
||||
public required string WSADMenuSelectInfoLineSize { get; set; }
|
||||
public required string WSADMenuItemLineColor { get; set; }
|
||||
public required string WSADMenuItemHoverLineColor { get; set; }
|
||||
public required string WSADMenuItemLineSize { get; set; }
|
||||
public required string WSADMenuControllsLineSize { get; set; }
|
||||
public required string WSADMenuControllsLineColor1 { get; set; }
|
||||
public required string WSADMenuControllsLineColor2 { get; set; }
|
||||
public required string WSADMenuControllsLineColor3 { get; set; }
|
||||
}
|
||||
|
||||
public class LanguageSystem
|
||||
{
|
||||
public required string DefaultLangCode { get; set; }
|
||||
public required bool DisableGeoLite { get; set; }
|
||||
public required LanguageInfo[] LanguageInfos { get; set; }
|
||||
}
|
||||
|
||||
public class LanguageInfo(string isoCodes, string fileName)
|
||||
{
|
||||
public string IsoCodes { get; set; } = isoCodes;
|
||||
public string FileName { get; set; } = fileName;
|
||||
}
|
||||
|
||||
public class NormalCommand(string alias, string permissions)
|
||||
|
|
@ -184,6 +198,18 @@ namespace jRandomSkills
|
|||
public string Permissions { get; set; } = permissions;
|
||||
}
|
||||
|
||||
public class NormalCommands
|
||||
{
|
||||
public required NormalCommand SetSkillCommand { get; set; }
|
||||
public required NormalCommand SkillsListCommand { get; set; }
|
||||
public required NormalCommand UseSkillCommand { get; set; }
|
||||
public required NormalCommand HealCommand { get; set; }
|
||||
public required NormalCommand ConsoleCommand { get; set; }
|
||||
public required NormalCommand SetStaticSkillCommand { get; set; }
|
||||
public required NormalCommand ChangeLanguageCommand { get; set; }
|
||||
public required NormalCommand ReloadCommand { get; set; }
|
||||
}
|
||||
|
||||
public class VotingCommand(bool enableVoting, string alias, string permissions, float timeToVote, float percentagesToSuccess, float timeToNextVoting, float timeToNextSameVoting, int minimumPlayersToStartVoting) : NormalCommand(alias, permissions)
|
||||
{
|
||||
public bool EnableVoting { get; set; } = enableVoting;
|
||||
|
|
@ -194,13 +220,28 @@ namespace jRandomSkills
|
|||
public int MinimumPlayersToStartVoting { get; set; } = minimumPlayersToStartVoting;
|
||||
}
|
||||
|
||||
public class DefaultSkillInfo(Skills skill, bool active = true, string color = "#ffffff", CsTeam onlyTeam = CsTeam.None, bool needsTeammates = false)
|
||||
public class StartGameCommand(bool enableVoting, string alias, string permissions, string startParams, string svStartParams, float timeToVote, float percentagesToSuccess, float timeToNextVoting, float timeToNextSameVoting, int minimumPlayersToStartVoting)
|
||||
{
|
||||
public bool NeedsTeammates { get; set; } = needsTeammates;
|
||||
public int OnlyTeam { get; set; } = (int)onlyTeam;
|
||||
public string Color { get; set; } = color;
|
||||
public bool Active { get; set; } = active;
|
||||
public string Name { get; set; } = skill.ToString();
|
||||
public bool EnableVoting { get; set; } = enableVoting;
|
||||
public string Alias { get; set; } = alias;
|
||||
public string Permissions { get; set; } = permissions;
|
||||
public string StartParams { get; set; } = startParams;
|
||||
public string SVStartParams { get; set; } = svStartParams;
|
||||
public float TimeToVote { get; set; } = timeToVote;
|
||||
public float PercentagesToSuccess { get; set; } = percentagesToSuccess;
|
||||
public float TimeToNextVoting { get; set; } = timeToNextVoting;
|
||||
public float TimeToNextSameVoting { get; set; } = timeToNextSameVoting;
|
||||
public int MinimumPlayersToStartVoting { get; set; } = minimumPlayersToStartVoting;
|
||||
}
|
||||
|
||||
public class VotingCommands
|
||||
{
|
||||
public required StartGameCommand StartGameCommand { get; set; }
|
||||
public required VotingCommand ChangeMapCommand { get; set; }
|
||||
public required VotingCommand SwapCommand { get; set; }
|
||||
public required VotingCommand ShuffleCommand { get; set; }
|
||||
public required VotingCommand PauseCommand { get; set; }
|
||||
public required VotingCommand SetScoreCommand { get; set; }
|
||||
}
|
||||
|
||||
public enum GameModes
|
||||
|
|
|
|||
|
|
@ -5,21 +5,20 @@ using jRandomSkills.src.player;
|
|||
using MaxMind.Db;
|
||||
using Newtonsoft.Json;
|
||||
using System.Net;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace jRandomSkills.src.utils
|
||||
{
|
||||
public static class Localization
|
||||
{
|
||||
private static readonly string languagesFolderPath = Path.Combine(jRandomSkills.Instance.ModuleDirectory, "languages");
|
||||
private static readonly Dictionary<string, Dictionary<string, string>> _translations = [];
|
||||
private static readonly ConcurrentDictionary<string, ConcurrentDictionary<string, string>> _translations = [];
|
||||
|
||||
private static readonly string playersLanguageFileName = "playersLanguage.json";
|
||||
private static readonly string configsFolderPath = Path.Combine(jRandomSkills.Instance.ModuleDirectory, "configs");
|
||||
private static Dictionary<ulong, string> _playersLanguage = [];
|
||||
private static ConcurrentDictionary<ulong, string> _playersLanguage = [];
|
||||
private static readonly string geoliteFilePath = Path.Combine(jRandomSkills.Instance.ModuleDirectory, "packages", "GeoLite2-Country.mmdb");
|
||||
public static readonly string[] chinaIsoCodes = ["CN", "TW", "HK", "MO", "SG"];
|
||||
public static readonly string[] portugalIsoCodes = ["PT", "BR", "AO", "CV", "GW", "MZ", "ST", "TL"];
|
||||
public static readonly string[] frenchIsoCodes = ["FR", "MC", "HT"];
|
||||
|
||||
private static string defaultLangCode = "en";
|
||||
|
||||
|
|
@ -34,7 +33,7 @@ namespace jRandomSkills.src.utils
|
|||
|
||||
private static void SetLangCode()
|
||||
{
|
||||
defaultLangCode = Config.LoadedConfig.Settings.LangCode;
|
||||
defaultLangCode = Config.LoadedConfig.LanguageSystem.DefaultLangCode;
|
||||
}
|
||||
|
||||
private static void LoadAllLanguages()
|
||||
|
|
@ -51,29 +50,67 @@ namespace jRandomSkills.src.utils
|
|||
if (!File.Exists(langPath))
|
||||
return;
|
||||
|
||||
var code = Path.GetFileNameWithoutExtension(langPath);
|
||||
var code = Path.GetFileNameWithoutExtension(langPath).ToLower();
|
||||
var jsonText = File.ReadAllText(langPath);
|
||||
var translations = JsonConvert.DeserializeObject<Dictionary<string, string>>(jsonText);
|
||||
var translations = JsonConvert.DeserializeObject<ConcurrentDictionary<string, string>>(jsonText);
|
||||
|
||||
if (translations != null)
|
||||
_translations[code] = translations;
|
||||
_translations.AddOrUpdate(code, translations, (k, v) => translations);
|
||||
}
|
||||
|
||||
public static bool HasTranslation(string code)
|
||||
{
|
||||
return _translations.ContainsKey(code);
|
||||
return _translations.ContainsKey(code.ToLower());
|
||||
}
|
||||
|
||||
public static string GetSkillName(this CCSPlayerController player, Skills skill)
|
||||
public static string GetSkillName(this CCSPlayerController player, Skills skill, float? chance = null)
|
||||
{
|
||||
string langCode = GetLangCode(player);
|
||||
return GetTranslation(skill.ToString().ToLower(), langCode);
|
||||
if (chance == null)
|
||||
{
|
||||
var translation = GetTranslation(skill.ToString().ToLower(), langCode);
|
||||
if (!translation.Contains("{0}"))
|
||||
return translation;
|
||||
|
||||
if (!translation.Contains(' '))
|
||||
return translation.Replace("{0}", "").Trim();
|
||||
|
||||
var parts = translation.Split(' ', StringSplitOptions.RemoveEmptyEntries);
|
||||
var filtered = parts.Where(p => !p.Contains("{0}"));
|
||||
return string.Join(' ', filtered);
|
||||
}
|
||||
|
||||
var value = Math.Round((double)(chance ?? 1), 2);
|
||||
var skillNameText = GetTranslation(skill.ToString().ToLower(), langCode, value);
|
||||
if (skillNameText.Contains('%')) skillNameText = skillNameText.Replace(value.ToString(), Math.Round(value * 100, 0).ToString());
|
||||
return skillNameText;
|
||||
}
|
||||
|
||||
public static string GetSkillDescription(this CCSPlayerController player, Skills skill)
|
||||
public static string GetSkillDescription(this CCSPlayerController player, Skills skill, float? chance = null)
|
||||
{
|
||||
string langCode = GetLangCode(player);
|
||||
return GetTranslation($"{skill.ToString().ToLower()}_desc", langCode);
|
||||
if (chance == null)
|
||||
{
|
||||
var translation = GetTranslation($"{skill.ToString().ToLower()}_desc", langCode);
|
||||
if (!translation.Contains("{0}"))
|
||||
return translation;
|
||||
|
||||
if (!translation.Contains(' '))
|
||||
return translation.Replace("{0}", "").Trim();
|
||||
|
||||
var parts = translation.Split(' ', StringSplitOptions.RemoveEmptyEntries);
|
||||
var filtered = parts.Where(p => !p.Contains("{0}"));
|
||||
return string.Join(' ', filtered);
|
||||
}
|
||||
|
||||
var skillName = $"{skill.ToString().ToLower()}_desc2";
|
||||
var value = Math.Round((double)(chance ?? 1), 2);
|
||||
var desc2 = GetTranslation(skillName, langCode, value);
|
||||
|
||||
var skilLDescription = desc2 == skillName
|
||||
? player.GetTranslation($"{skill.ToString().ToLower()}_desc")
|
||||
: (desc2.Contains('%') ? desc2.Replace(value.ToString(), Math.Round(value * 100, 0).ToString()) : desc2);
|
||||
return skilLDescription;
|
||||
}
|
||||
|
||||
public static void PrintTranslationToChatAll(string message, string[]? key, params object[][]? args)
|
||||
|
|
@ -112,9 +149,10 @@ namespace jRandomSkills.src.utils
|
|||
return translation;
|
||||
else
|
||||
{
|
||||
string output = string.Format(translation, args).Replace("CHATCOLORS.RED", ChatColors.Red.ToString());
|
||||
if (Config.LoadedConfig.Settings.AlternativeSkillButton != null)
|
||||
output = output.Replace("css_useSkill", $"css_useSkill/{Config.LoadedConfig.Settings.AlternativeSkillButton}");
|
||||
string output = args.Length == 0 ? translation : string.Format(translation, args);
|
||||
output = output.Replace("CHATCOLORS.RED", ChatColors.Red.ToString());
|
||||
if (Config.LoadedConfig.AlternativeSkillButton != null)
|
||||
output = output.Replace("css_useSkill", $"css_useSkill/{Config.LoadedConfig.AlternativeSkillButton}");
|
||||
return output;
|
||||
}
|
||||
|
||||
|
|
@ -129,6 +167,9 @@ namespace jRandomSkills.src.utils
|
|||
if (!string.IsNullOrEmpty(fileLangCode))
|
||||
return fileLangCode;
|
||||
|
||||
if (Config.LoadedConfig.LanguageSystem.DisableGeoLite == true)
|
||||
return defaultLangCode;
|
||||
|
||||
string? geoliteLandCode = GetLangCodeFromDatabase(GetPlayerIP(player)) ?? defaultLangCode;
|
||||
ChangePlayerLanguage(player, geoliteLandCode);
|
||||
return geoliteLandCode;
|
||||
|
|
@ -149,21 +190,18 @@ namespace jRandomSkills.src.utils
|
|||
if (!File.Exists(geoliteFilePath)) return null;
|
||||
using var reader = new Reader(geoliteFilePath);
|
||||
var ip = IPAddress.Parse(playerIP);
|
||||
var data = reader.Find<Dictionary<string, object>>(ip);
|
||||
if (data == null || data.Count == 0) return null;
|
||||
var data = reader.Find<ConcurrentDictionary<string, object>>(ip);
|
||||
if (data == null || data.IsEmpty) return null;
|
||||
|
||||
if (data.TryGetValue("country", out var _country) && _country is Dictionary<string, object> country)
|
||||
if (data.TryGetValue("country", out var _country) && _country is ConcurrentDictionary<string, object> country)
|
||||
if (country.TryGetValue("iso_code", out var _isoCode) && _isoCode is string isoCode)
|
||||
{
|
||||
if (portugalIsoCodes.Contains(isoCode))
|
||||
isoCode = "pt-br";
|
||||
if (chinaIsoCodes.Contains(isoCode))
|
||||
isoCode = "zh";
|
||||
if (frenchIsoCodes.Contains(isoCode))
|
||||
isoCode = "fr";
|
||||
isoCode = isoCode.ToLower();
|
||||
if (_translations.ContainsKey(isoCode))
|
||||
return isoCode;
|
||||
string fileName = Config.LoadedConfig.LanguageSystem.DefaultLangCode;
|
||||
foreach (var langInfo in Config.LoadedConfig.LanguageSystem.LanguageInfos)
|
||||
if (langInfo.IsoCodes.Contains(isoCode))
|
||||
fileName = langInfo.FileName;
|
||||
if (_translations.ContainsKey(fileName))
|
||||
return fileName;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
|
@ -175,7 +213,7 @@ namespace jRandomSkills.src.utils
|
|||
return;
|
||||
|
||||
var jsonText = File.ReadAllText(filePath);
|
||||
_playersLanguage = JsonConvert.DeserializeObject<Dictionary<ulong, string>>(jsonText) ?? [];
|
||||
_playersLanguage = JsonConvert.DeserializeObject<ConcurrentDictionary<ulong, string>>(jsonText) ?? [];
|
||||
}
|
||||
|
||||
private static void SavePlayersLanguage()
|
||||
|
|
@ -198,7 +236,7 @@ namespace jRandomSkills.src.utils
|
|||
public static void ChangePlayerLanguage(CCSPlayerController? player, string language)
|
||||
{
|
||||
if (player == null || !player.IsValid) return;
|
||||
_playersLanguage[player.SteamID] = language;
|
||||
_playersLanguage.AddOrUpdate(player.SteamID, language, (k,v) => language);
|
||||
SavePlayersLanguage();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,17 +11,27 @@ using System.Runtime.InteropServices;
|
|||
using WASDMenuAPI.Classes;
|
||||
using WASDSharedAPI;
|
||||
using static CounterStrikeSharp.API.Core.Listeners;
|
||||
using System.Collections.Concurrent;
|
||||
using System;
|
||||
using static System.Net.Mime.MediaTypeNames;
|
||||
using System.Drawing;
|
||||
|
||||
namespace jRandomSkills
|
||||
{
|
||||
public static class SkillUtils
|
||||
{
|
||||
private static readonly MemoryFunctionWithReturn<IntPtr, IntPtr, IntPtr, IntPtr, IntPtr, IntPtr, IntPtr, int> HEGrenadeProjectile_CreateFunc = new(GameData.GetSignature("HEGrenadeProjectile_CreateFunc"));
|
||||
private static readonly MemoryFunctionVoid<nint, float, RoundEndReason, nint, nint> TerminateRoundFunc = new(GameData.GetSignature("CCSGameRules_TerminateRound"));
|
||||
|
||||
public static void PrintToChat(CCSPlayerController player, string msg, bool isError)
|
||||
{
|
||||
string checkIcon = isError ? $"{ChatColors.DarkRed}✖{ChatColors.LightRed}" : $"{ChatColors.Green}✔{ChatColors.Lime}";
|
||||
player.PrintToChat($" {ChatColors.DarkRed}► {ChatColors.Green}[{ChatColors.DarkRed} jRadnomSkills {ChatColors.Green}] {checkIcon} {msg}");
|
||||
player.PrintToChat($" {ChatColors.DarkRed}► {ChatColors.Green}[{ChatColors.DarkRed} {jRandomSkills.Tag} {ChatColors.Green}] {checkIcon} {msg}");
|
||||
}
|
||||
|
||||
public static bool IsFreezeTime()
|
||||
{
|
||||
return jRandomSkills.Instance?.GameRules?.FreezePeriod == true;
|
||||
}
|
||||
|
||||
public static void RegisterSkill(Skills skill, string color, bool display = true)
|
||||
|
|
@ -76,10 +86,14 @@ namespace jRandomSkills
|
|||
var playerPawn = player.PlayerPawn.Value;
|
||||
if (playerPawn == null || !playerPawn.IsValid || playerPawn.CBodyComponent == null || playerPawn.CBodyComponent.SceneNode == null) return;
|
||||
|
||||
playerPawn.CBodyComponent.SceneNode.Scale = scale;
|
||||
playerPawn.CBodyComponent.SceneNode.GetSkeletonInstance().Scale = scale;
|
||||
playerPawn.AcceptInput("SetScale", null, null, scale.ToString());
|
||||
Server.NextFrame(() => Utilities.SetStateChanged(playerPawn, "CBaseEntity", "m_CBodyComponent"));
|
||||
Utilities.SetStateChanged(playerPawn, "CBaseEntity", "m_CBodyComponent");
|
||||
Server.NextFrame(() => playerPawn.AcceptInput("SetScale", playerPawn, playerPawn, scale.ToString()));
|
||||
}
|
||||
|
||||
public static void CreateHEGrenadeProjectile(Vector pos, QAngle angle, Vector vel, int teamNum)
|
||||
{
|
||||
HEGrenadeProjectile_CreateFunc.Invoke(pos.Handle, angle.Handle, vel.Handle, vel.Handle, IntPtr.Zero, 44, teamNum);
|
||||
}
|
||||
|
||||
public static void TakeHealth(CCSPlayerPawn? pawn, int damage)
|
||||
|
|
@ -98,6 +112,13 @@ namespace jRandomSkills
|
|||
});
|
||||
}
|
||||
|
||||
public static void ResetPrintHTML(CCSPlayerController? player)
|
||||
{
|
||||
var playerInfo = jRandomSkills.Instance.SkillPlayer.FirstOrDefault(s => s.SteamID == player?.SteamID);
|
||||
if (playerInfo == null) return;
|
||||
playerInfo.PrintHTML = null;
|
||||
}
|
||||
|
||||
public static void AddHealth(CCSPlayerPawn? pawn, int extraHealth, int maxHealth = 100)
|
||||
{
|
||||
if (pawn == null || !pawn.IsValid || pawn.LifeState != (byte)LifeState_t.LIFE_ALIVE)
|
||||
|
|
@ -159,7 +180,7 @@ namespace jRandomSkills
|
|||
return manager.HasMenu(player);
|
||||
}
|
||||
|
||||
public static void UpdateMenu(CCSPlayerController? player, HashSet<(string, string)> items)
|
||||
public static void UpdateMenu(CCSPlayerController? player, ConcurrentBag<(string, string)> items)
|
||||
{
|
||||
if (player == null) return;
|
||||
|
||||
|
|
@ -171,7 +192,7 @@ namespace jRandomSkills
|
|||
|
||||
Dictionary<string, Action<CCSPlayerController, IWasdMenuOption>> list = [];
|
||||
foreach (var item in items)
|
||||
list.Add(item.Item1, (p, option) =>
|
||||
list.TryAdd(item.Item1, (p, option) =>
|
||||
{
|
||||
jRandomSkills.Instance.SkillAction(playerInfo.Skill.ToString(), "TypeSkill", [p, new[] { item.Item2 }]);
|
||||
manager.CloseMenu(p);
|
||||
|
|
@ -180,7 +201,7 @@ namespace jRandomSkills
|
|||
manager.UpdateActiveMenu(player, list);
|
||||
}
|
||||
|
||||
public static void CreateMenu(CCSPlayerController? player, HashSet<(string, string)> enemies)
|
||||
public static void CreateMenu(CCSPlayerController? player, ConcurrentBag<(string, string)> enemies, (string, string)? lastElement = null)
|
||||
{
|
||||
if (player == null || !player.IsValid) return;
|
||||
|
||||
|
|
@ -190,20 +211,47 @@ namespace jRandomSkills
|
|||
var skillData = SkillData.Skills.FirstOrDefault(s => s.Skill == playerInfo.Skill);
|
||||
if (skillData == null) return;
|
||||
|
||||
string infoLine = $"<font class='fontSize-l' class='fontWeight-Bold' color='#FFFFFF'>{player.GetTranslation("your_skill")}:</font> <br>";
|
||||
string skillLine = $"<font class='fontSize-l' class='fontWeight-Bold' color='{skillData.Color}'>{player.GetSkillName(skillData.Skill)}</font> <br>"
|
||||
+ $"<font color='green'>{player.GetTranslation($"{playerInfo.Skill.ToString().ToLower()}_select_info")}</font>";
|
||||
|
||||
var manager = GetMenuManager();
|
||||
if (manager == null) return;
|
||||
|
||||
IWasdMenu menu = manager.CreateMenu(infoLine + skillLine, "<font class='fontSize-m' color='cyan'>W/S - Scroll</font> <font class='fontSize-m' color='white'> | </font> <font class='fontSize-m' color='green'>E - Select</font> <br>");
|
||||
var config = Config.LoadedConfig.HtmlHudCustomisation;
|
||||
var your_skill = player.GetTranslation("your_skill");
|
||||
var emptySymbol = $"<font class='fontSize-{(string.IsNullOrEmpty(your_skill) ? "l" : "ml")}'> </font>";
|
||||
|
||||
string infoLine = string.IsNullOrEmpty(your_skill)
|
||||
? ""
|
||||
: $"<font class='fontWeight-Bold fontSize-{config.HeaderLineSize}' color='{config.HeaderLineColor}'>{your_skill}:</font><br>";
|
||||
|
||||
string skillLine = $"<font class='fontWeight-Bold fontSize-{config.SkillLineSize}' color='{skillData.Color}'>{player.GetSkillName(skillData.Skill)}</font><br>";
|
||||
|
||||
var skill_select_info = player.GetTranslation($"{playerInfo.Skill.ToString().ToLower()}_select_info");
|
||||
string remainingLine = string.IsNullOrWhiteSpace(skill_select_info)
|
||||
? ""
|
||||
: $"<font class='fontSize-{config.WSADMenuSelectInfoLineSize}' color='{config.WSADMenuSelectInfoLineColor}'>{skill_select_info}</font><br>";
|
||||
|
||||
var hudContent = infoLine + skillLine + remainingLine;
|
||||
|
||||
string controllsLine =
|
||||
$"{emptySymbol}<font class='fontSize-{config.WSADMenuControllsLineSize}' color='{config.WSADMenuControllsLineColor1}'>{player.GetTranslation($"menu_controlls_scroll")}</font>"
|
||||
+ $"<font class='fontSize-{config.WSADMenuControllsLineSize}' color='{config.WSADMenuControllsLineColor2}'>{player.GetTranslation($"menu_controlls_padding")}</font>"
|
||||
+ $"<font class='fontSize-{config.WSADMenuControllsLineSize}' color='{config.WSADMenuControllsLineColor3}'>{player.GetTranslation($"menu_controlls_select")}</font>{emptySymbol}";
|
||||
|
||||
string itemText = $"<font class='fontSize-{config.WSADMenuItemLineSize}' color='{config.WSADMenuItemLineColor}'>{{0}}</font><br>";
|
||||
string itemHoverText = $"<font class='fontSize-{config.WSADMenuItemLineSize}'><font color='purple'>[ </font><font color='{config.WSADMenuItemHoverLineColor}'>{{0}}</font><font color='purple'> ]</font></font><br>";
|
||||
|
||||
IWasdMenu menu = manager.CreateMenu(hudContent, itemText, itemHoverText, controllsLine);
|
||||
foreach (var enemy in enemies)
|
||||
menu.Add(enemy.Item1, (p, option) =>
|
||||
{
|
||||
jRandomSkills.Instance.SkillAction(playerInfo.Skill.ToString(), "TypeSkill", [p, new[] { enemy.Item2 }]);
|
||||
manager.CloseMenu(p);
|
||||
});
|
||||
if (lastElement != null)
|
||||
menu.Add(lastElement.Value.Item1, (p, option) =>
|
||||
{
|
||||
jRandomSkills.Instance.SkillAction(playerInfo.Skill.ToString(), "TypeSkill", [p, new[] { lastElement.Value.Item2 }]);
|
||||
manager.CloseMenu(p);
|
||||
});
|
||||
manager.OpenMainMenu(player, menu);
|
||||
}
|
||||
|
||||
|
|
|
|||
139
jRandomSkills - SRC Files/src/utils/SkillsInfo.cs
Normal file
139
jRandomSkills - SRC Files/src/utils/SkillsInfo.cs
Normal file
|
|
@ -0,0 +1,139 @@
|
|||
using CounterStrikeSharp.API;
|
||||
using CounterStrikeSharp.API.Modules.Utils;
|
||||
using jRandomSkills.src.player;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using System.Reflection;
|
||||
using static jRandomSkills.jRandomSkills;
|
||||
|
||||
namespace jRandomSkills
|
||||
{
|
||||
public static class SkillsInfo
|
||||
{
|
||||
private static readonly string configsFolder = Path.Combine(Instance.ModuleDirectory, "configs");
|
||||
private static readonly string configPath = Path.Combine(configsFolder, "skillsInfo.json");
|
||||
private static readonly object fileLock = new();
|
||||
|
||||
private static SkillsInfoModel config = LoadSkillsInfo();
|
||||
public static SkillsInfoModel LoadedConfig => config;
|
||||
|
||||
public static SkillsInfoModel LoadSkillsInfo()
|
||||
{
|
||||
lock (fileLock)
|
||||
{
|
||||
var newConfig = new SkillsInfoModel();
|
||||
|
||||
if (!File.Exists(configPath))
|
||||
{
|
||||
Instance.Logger.LogInformation("Config file does not exist. Create a new skills info file...");
|
||||
SaveConfig(newConfig);
|
||||
return config = newConfig;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
string json;
|
||||
using (var fs = new FileStream(configPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||
using (var sr = new StreamReader(fs))
|
||||
json = sr.ReadToEnd();
|
||||
|
||||
var root = JsonConvert.DeserializeObject<JArray>(json);
|
||||
if (root != null)
|
||||
foreach (var skillObj in root)
|
||||
{
|
||||
var name = skillObj["Name"]?.ToString();
|
||||
if (string.IsNullOrEmpty(name)) continue;
|
||||
|
||||
var instance = newConfig.FirstOrDefault(x => x.Name == name.ToString());
|
||||
if (instance != null) JsonConvert.PopulateObject(skillObj.ToString(), instance);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
Instance.Logger.LogError("Error when loading the skills info file.");
|
||||
}
|
||||
|
||||
return config = newConfig;
|
||||
}
|
||||
}
|
||||
|
||||
public static void SaveConfig(SkillsInfoModel config)
|
||||
{
|
||||
lock (fileLock)
|
||||
{
|
||||
try
|
||||
{
|
||||
Directory.CreateDirectory(configsFolder);
|
||||
string json = JsonConvert.SerializeObject(config, Formatting.Indented);
|
||||
|
||||
string tempPath = $"{configPath}.temp";
|
||||
File.WriteAllText(tempPath, json);
|
||||
|
||||
File.Copy(tempPath, configPath, overwrite: true);
|
||||
File.Delete(tempPath);
|
||||
}
|
||||
catch
|
||||
{
|
||||
Instance.Logger.LogError("Error when saving the skills info file.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static T GetValue<T>(object skill, string key)
|
||||
{
|
||||
if (config == null) return default!;
|
||||
|
||||
var skillConfig = LoadedConfig.FirstOrDefault(s => s.Name == skill.ToString());
|
||||
if (skillConfig == null) return default!;
|
||||
|
||||
var prop = skillConfig.GetType().GetProperty(key, BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase);
|
||||
if (prop != null)
|
||||
{
|
||||
var value = prop.GetValue(skillConfig);
|
||||
if (value == null) return default!;
|
||||
else return (T)Convert.ChangeType(value, typeof(T));
|
||||
}
|
||||
|
||||
var field = skillConfig.GetType().GetField(key, BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase);
|
||||
if (field != null)
|
||||
{
|
||||
var value = field.GetValue(skillConfig);
|
||||
if (value == null) return default!;
|
||||
else return (T)Convert.ChangeType(value, typeof(T));
|
||||
}
|
||||
|
||||
return default!;
|
||||
}
|
||||
|
||||
public class SkillsInfoModel : List<DefaultSkillInfo>
|
||||
{
|
||||
public SkillsInfoModel()
|
||||
{
|
||||
AddRange(
|
||||
Assembly.GetExecutingAssembly().GetTypes()
|
||||
.Where(t => typeof(DefaultSkillInfo).IsAssignableFrom(t) && t.Name == "SkillConfig")
|
||||
.Select(t =>
|
||||
{
|
||||
var ctor = t.GetConstructors().FirstOrDefault(c => c.GetParameters().All(p => p.IsOptional));
|
||||
if (ctor == null) return null;
|
||||
var args = ctor.GetParameters().Select(p => Type.Missing).ToArray();
|
||||
return ctor.Invoke(args) as DefaultSkillInfo;
|
||||
})
|
||||
.Where(instance => instance != null)
|
||||
.Cast<DefaultSkillInfo>()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public class DefaultSkillInfo(Skills skill, bool active = true, string color = "#ffffff", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false)
|
||||
{
|
||||
public bool NeedsTeammates { get; set; } = needsTeammates;
|
||||
public bool DisableOnFreezeTime { get; set; } = disableOnFreezeTime;
|
||||
public int OnlyTeam { get; set; } = (int)onlyTeam;
|
||||
public string Color { get; set; } = color;
|
||||
public bool Active { get; set; } = active;
|
||||
public string Name { get; set; } = skill.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue