mirror of
https://github.com/rafi1212122/BLHX.Server.git
synced 2025-12-12 14:34:39 +01:00
utils for JSON files and RNG/rolling, abstracted arg parsing for commands
This commit is contained in:
25
BLHX.Server.Common/Utils/Config.cs
Normal file
25
BLHX.Server.Common/Utils/Config.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
namespace BLHX.Server.Common.Utils;
|
||||
|
||||
public class Config : Singleton<Config>
|
||||
{
|
||||
public string Address { get; set; } = "192.168.1.4";
|
||||
public uint Port { get; set; } = 20000;
|
||||
|
||||
public static void Load()
|
||||
{
|
||||
Instance = JSON.Load<Config>(JSON.ConfigPath);
|
||||
|
||||
#if DEBUG
|
||||
Logger.c.Log($"Loaded Config:\n{JSON.Stringify(Instance)}");
|
||||
#endif
|
||||
}
|
||||
|
||||
public static void Save()
|
||||
{
|
||||
JSON.Save(JSON.ConfigPath, Instance);
|
||||
|
||||
#if DEBUG
|
||||
Logger.c.Log("Saved Config");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
35
BLHX.Server.Common/Utils/JSON.cs
Normal file
35
BLHX.Server.Common/Utils/JSON.cs
Normal file
@@ -0,0 +1,35 @@
|
||||
using System.Text.Json;
|
||||
|
||||
namespace BLHX.Server.Common.Utils;
|
||||
|
||||
public static class JSON
|
||||
{
|
||||
public static string ConfigPath => Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Config.json");
|
||||
|
||||
public static T Load<T>(string path) where T : new()
|
||||
{
|
||||
if (!File.Exists(path))
|
||||
{
|
||||
T obj = new T();
|
||||
Save(path, obj);
|
||||
}
|
||||
|
||||
return JsonSerializer.Deserialize<T>(File.ReadAllText(path));
|
||||
}
|
||||
|
||||
public static void Save<T>(string path, T obj)
|
||||
{
|
||||
File.WriteAllText(path, JsonSerializer.Serialize(obj, new JsonSerializerOptions()
|
||||
{
|
||||
WriteIndented = true
|
||||
}));
|
||||
}
|
||||
|
||||
public static string Stringify<T>(T obj)
|
||||
{
|
||||
return JsonSerializer.Serialize(obj, new JsonSerializerOptions()
|
||||
{
|
||||
WriteIndented = true
|
||||
});
|
||||
}
|
||||
}
|
||||
63
BLHX.Server.Common/Utils/RNG.cs
Normal file
63
BLHX.Server.Common/Utils/RNG.cs
Normal file
@@ -0,0 +1,63 @@
|
||||
namespace BLHX.Server.Common.Utils;
|
||||
|
||||
public static class RNG
|
||||
{
|
||||
public static readonly SortedDictionary<int, float> ShipRarityRates = new()
|
||||
{
|
||||
{6, 1.2f}, // UR
|
||||
{5, 7f}, // SSR
|
||||
{4, 12f}, // Elite
|
||||
{2, 28.8f}, // Normal
|
||||
{3, 51f}, // Rare
|
||||
};
|
||||
|
||||
static readonly Random random = new Random((int)DateTime.Now.Ticks);
|
||||
|
||||
public static int Next(int min, int max)
|
||||
=> random.Next(min, max);
|
||||
|
||||
public static int Next(int max)
|
||||
=> random.Next(max);
|
||||
|
||||
public static float NextFloat(float min, float max)
|
||||
{
|
||||
double range = (double)max - min;
|
||||
double sample = random.NextDouble();
|
||||
double scaled = (sample * range) + min;
|
||||
|
||||
return (float)scaled;
|
||||
}
|
||||
|
||||
public static float NextFloat(float max)
|
||||
=> NextFloat(0f, max);
|
||||
|
||||
public static bool NextBool()
|
||||
=> random.Next(2) == 0;
|
||||
|
||||
public static float NextRoll()
|
||||
=> NextFloat(100f);
|
||||
|
||||
public static T NextFromList<T>(IList<T> list)
|
||||
=> list[random.Next(list.Count)];
|
||||
|
||||
public static U NextFromDict<T, U>(IDictionary<T, U> dict)
|
||||
=> dict.ElementAt(random.Next(dict.Count)).Value;
|
||||
|
||||
public static int NextFromRarityDict(SortedDictionary<int, float> dict)
|
||||
{
|
||||
float roll = NextRoll();
|
||||
float sum = 0f;
|
||||
|
||||
foreach (var pair in dict)
|
||||
{
|
||||
sum += pair.Value;
|
||||
if (roll <= sum)
|
||||
return pair.Key;
|
||||
}
|
||||
|
||||
throw new Exception("NextFromRarityDict() roll failed");
|
||||
}
|
||||
|
||||
public static int NextShipRarity()
|
||||
=> NextFromRarityDict(ShipRarityRates);
|
||||
}
|
||||
17
BLHX.Server.Common/Utils/Singleton.cs
Normal file
17
BLHX.Server.Common/Utils/Singleton.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
namespace BLHX.Server.Common.Utils;
|
||||
|
||||
public abstract class Singleton<T> where T : new()
|
||||
{
|
||||
static T instance;
|
||||
public static T Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
if (instance == null)
|
||||
instance = new T();
|
||||
|
||||
return instance;
|
||||
}
|
||||
set => instance = value;
|
||||
}
|
||||
}
|
||||
@@ -16,6 +16,7 @@ public class commandHandler : Attribute
|
||||
Description = description;
|
||||
Example = example;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
[AttributeUsage(AttributeTargets.Property)]
|
||||
@@ -48,6 +49,22 @@ public abstract class Command
|
||||
prop.SetValue(this, arg.Value);
|
||||
}
|
||||
}
|
||||
|
||||
protected T Parse<T>(string? value, T fallback = default)
|
||||
{
|
||||
var tryParseMethod = typeof(T).GetMethod("TryParse", [typeof(string), typeof(T).MakeByRefType()]);
|
||||
|
||||
if (tryParseMethod != null)
|
||||
{
|
||||
var parameters = new object[] { value, null };
|
||||
bool success = (bool)tryParseMethod.Invoke(null, parameters);
|
||||
|
||||
if (success)
|
||||
return (T)parameters[1];
|
||||
}
|
||||
|
||||
return fallback;
|
||||
}
|
||||
}
|
||||
|
||||
public static class CommandHandler
|
||||
|
||||
62
BLHX.Server.Game/Commands/TestCommand.cs
Normal file
62
BLHX.Server.Game/Commands/TestCommand.cs
Normal file
@@ -0,0 +1,62 @@
|
||||
using BLHX.Server.Common.Utils;
|
||||
|
||||
namespace BLHX.Server.Game.Commands;
|
||||
|
||||
[commandHandler("test", "Test command", "test type=gacha")]
|
||||
public class TestCommand : Command
|
||||
{
|
||||
static readonly string[] RarityStrings = { "Unknown", "Unused", "Normal", "Rare", "Elite", "SSR", "UR" };
|
||||
|
||||
[Argument("type")]
|
||||
public string? Type { get; set; }
|
||||
|
||||
[Argument("count")]
|
||||
public string? Count { get; set; }
|
||||
|
||||
[Argument("verbose")]
|
||||
public string? Verbose { get; set; }
|
||||
|
||||
public override void Execute(Dictionary<string, string> args)
|
||||
{
|
||||
base.Execute(args);
|
||||
|
||||
switch (Type)
|
||||
{
|
||||
case "gacha":
|
||||
TestGacha(Parse(Count, 1000000), Parse(Verbose, false));
|
||||
break;
|
||||
default:
|
||||
Logger.c.Warn("Unknown test type");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void TestGacha(int count, bool verbose)
|
||||
{
|
||||
var stopwatch = System.Diagnostics.Stopwatch.StartNew();
|
||||
var counts = new int[7];
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
int rarity = RNG.NextShipRarity();
|
||||
|
||||
counts[rarity]++;
|
||||
|
||||
if (verbose)
|
||||
Logger.c.Log($"Roll {i + 1}: {rarity} - {RarityStrings[rarity]}");
|
||||
}
|
||||
|
||||
stopwatch.Stop();
|
||||
|
||||
Logger.c.Log("----------------------------------------");
|
||||
Logger.c.Log($"TOTAL ROLLS: {count}");
|
||||
Logger.c.Log($"PROCESSING TIME: {stopwatch.Elapsed}");
|
||||
|
||||
for (int i = 2; i < counts.Length; i++)
|
||||
{
|
||||
double percentage = (double)Math.Round(counts[i] / (double)count * 100, 2);
|
||||
|
||||
Logger.c.Log($"{RarityStrings[i]}: {counts[i]} ({percentage}%)");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16,7 +16,7 @@ namespace BLHX.Server.Game
|
||||
// Preload
|
||||
System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(typeof(PacketFactory).TypeHandle);
|
||||
|
||||
EndPoint = new(IPAddress.Any, 20000);
|
||||
EndPoint = new(IPAddress.Any, (int)Config.Instance.Port);
|
||||
listener = new TcpListener(EndPoint);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using BHXY.Server.Common.Proto.p10;
|
||||
using BLHX.Server.Common.Proto;
|
||||
using BLHX.Server.Common.Utils;
|
||||
|
||||
namespace BLHX.Server.Game.Handlers
|
||||
{
|
||||
@@ -11,11 +12,11 @@ namespace BLHX.Server.Game.Handlers
|
||||
var req = packet.Decode<Cs10800>();
|
||||
connection.Send(new Sc10801()
|
||||
{
|
||||
GatewayIp = "192.168.1.4",
|
||||
GatewayPort = 20000,
|
||||
Url = "http://192.168.1.4",
|
||||
ProxyIp = "192.168.1.4",
|
||||
ProxyPort = 20000,
|
||||
GatewayIp = Config.Instance.Address,
|
||||
GatewayPort = Config.Instance.Port,
|
||||
Url = "http://" + Config.Instance.Address,
|
||||
ProxyIp = Config.Instance.Address,
|
||||
ProxyPort = Config.Instance.Port,
|
||||
Versions = [
|
||||
"$azhash$7$1$459$470aa097fec844d6",
|
||||
"$cvhash$467$98edcdd4e7dac668",
|
||||
@@ -48,10 +49,10 @@ namespace BLHX.Server.Game.Handlers
|
||||
{
|
||||
Ids = [0],
|
||||
Name = "BLHX.Server",
|
||||
Ip = "192.168.1.4",
|
||||
Port = 20000,
|
||||
ProxyIp = "192.168.1.4",
|
||||
ProxyPort = 20000
|
||||
Ip = Config.Instance.Address,
|
||||
Port = Config.Instance.Port,
|
||||
ProxyIp = Config.Instance.Address,
|
||||
ProxyPort = Config.Instance.Port
|
||||
}
|
||||
],
|
||||
ServerTicket = req.Arg3
|
||||
|
||||
@@ -9,6 +9,8 @@ internal class Program
|
||||
{
|
||||
Logger.c.Log("Starting...");
|
||||
|
||||
Config.Load();
|
||||
|
||||
Task.Run(GameServer.Start);
|
||||
Task.Run(InputSystem.Start).Wait();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user