Init enter game

This commit is contained in:
Naruse
2025-06-14 11:15:32 +08:00
commit 6a03b39f07
568 changed files with 92872 additions and 0 deletions

View File

@@ -0,0 +1,79 @@
using KianaBH.Database.Account;
using KianaBH.GameServer.Server;
using KianaBH.Internationalization;
namespace KianaBH.GameServer.Command;
public class CommandArg
{
public string RawArg { get; } = "";
public List<string> Args { get; } = [];
public List<string> Attributes { get; } = [];
public ICommandSender Sender { get; }
public int TargetUid { get; set; } = 0;
public Connection? Target { get; set; }
public CommandArg(string rawArg, ICommandSender sender)
{
Sender = sender;
RawArg = rawArg;
foreach (var arg in rawArg.Split(' '))
{
if (string.IsNullOrEmpty(arg)) continue;
Args.Add(arg);
}
}
public async ValueTask SendMsg(string msg)
{
await Sender.SendMsg(msg);
}
public int GetInt(int index)
{
if (Args.Count <= index) return 0;
if (int.TryParse(Args[index], out var res))
return res;
return 0;
}
public async ValueTask<int?> GetOption(char pre, string def = "1")
{
var opStr = Args.FirstOrDefault(x => x[0] == pre)?[1..] ?? def;
if (!int.TryParse(opStr, out var op))
{
await SendMsg(I18NManager.Translate("Game.Command.Notice.InvalidArguments"));
return null;
}
return op;
}
public async ValueTask<bool> CheckArgCnt(int start, int? end = null)
{
end ??= start;
if (Args.Count >= start && Args.Count <= end) return true;
await SendMsg(I18NManager.Translate("Game.Command.Notice.InvalidArguments"));
return false;
}
public async ValueTask<bool> CheckTarget()
{
if (AccountData.GetAccountByUid(TargetUid) == null)
{
await SendMsg(I18NManager.Translate("Game.Command.Notice.PlayerNotFound"));
return false;
}
return true;
}
public async ValueTask<bool> CheckOnlineTarget(bool sendMsg = true)
{
if (Target == null)
{
if (sendMsg)
await SendMsg(I18NManager.Translate("Game.Command.Notice.PlayerNotFound"));
return false;
}
return true;
}
}

View File

@@ -0,0 +1,25 @@
using KianaBH.Enums.Player;
namespace KianaBH.GameServer.Command;
[AttributeUsage(AttributeTargets.Class)]
public class CommandInfoAttribute(
string name, string desc, string usage, string[] alias, PermEnum[] perm) : Attribute
{
public string Name { get; } = name;
public string Description { get; } = desc;
public string Usage { get; } = usage;
public PermEnum[] Perm { get; } = perm;
public string[] Alias { get; } = alias;
}
[AttributeUsage(AttributeTargets.Method)]
public class CommandDefaultAttribute : Attribute
{
}
[AttributeUsage(AttributeTargets.Method)]
public class CommandMethodAttribute(string method) : Attribute
{
public string MethodName { get; } = method;
}

View File

@@ -0,0 +1,19 @@

namespace KianaBH.GameServer.Command;
public static class CommandExecutor
{
public delegate void RunCommand(ICommandSender sender, string cmd);
public static event RunCommand? OnRunCommand;
public static void ExecuteCommand(ICommandSender sender, string cmd)
{
OnRunCommand?.Invoke(sender, cmd);
}
public static void ConsoleExcuteCommand(string input)
{
CommandManager.HandleCommand(input, new ConsoleCommandSender(CommandManager.Logger));
}
}

View File

@@ -0,0 +1,3 @@
namespace KianaBH.GameServer.Command;
public interface ICommands;

View File

@@ -0,0 +1,126 @@
using KianaBH.Database.Account;
using KianaBH.Enums.Player;
using KianaBH.GameServer.Server;
using KianaBH.Internationalization;
using KianaBH.KcpSharp;
using KianaBH.Util;
using System.Reflection;
namespace KianaBH.GameServer.Command;
public class CommandManager
{
public static Logger Logger { get; } = new("CommandManager");
public static Dictionary<string, ICommands> Commands { get; } = [];
public static Dictionary<string, CommandInfoAttribute> CommandInfo { get; } = [];
public static Dictionary<string, string> CommandAlias { get; } = []; // <aliaName, fullName>
public static void RegisterCommands()
{
foreach (var type in Assembly.GetExecutingAssembly().GetTypes())
if (typeof(ICommands).IsAssignableFrom(type) && !type.IsAbstract)
RegisterCommand(type);
Logger.Info(I18NManager.Translate("Server.ServerInfo.RegisterItem", Commands.Count.ToString(),
I18NManager.Translate("Word.Command")));
}
public static void RegisterCommand(Type type)
{
var attr = type.GetCustomAttribute<CommandInfoAttribute>();
if (attr == null) return;
var instance = Activator.CreateInstance(type);
if (instance is not ICommands command) return;
Commands.Add(attr.Name, command);
CommandInfo.Add(attr.Name, attr);
// register alias
foreach (var alias in attr.Alias) // add alias
CommandAlias.Add(alias, attr.Name);
}
public static async void HandleCommand(string input, ICommandSender sender)
{
try
{
var argInfo = new CommandArg(input, sender);
var target = sender.GetSender();
foreach (var arg in argInfo.Args.ToList()) // Copy
{
switch (arg[0])
{
case '-':
argInfo.Attributes.Add(arg[1..]);
break;
case '@':
_ = int.TryParse(arg[1..], out target);
argInfo.Args.Remove(arg);
break;
}
}
argInfo.TargetUid = target;
if (KcpListener.Connections.Values.ToList().Find(item =>
(item as Connection)?.Player?.Uid == target) is Connection con)
argInfo.Target = con;
// find register cmd
var cmdName = argInfo.Args[0];
if (CommandAlias.TryGetValue(cmdName, out var fullName)) cmdName = fullName;
if (!Commands.TryGetValue(cmdName, out var command))
{
await sender.SendMsg(I18NManager.Translate("Game.Command.Notice.CommandNotFound"));
return;
}
argInfo.Args.RemoveAt(0);
var cmdInfo = CommandInfo[cmdName];
// Check cmd perms
if (!AccountData.HasPerm(cmdInfo.Perm, sender.GetSender()))
{
await sender.SendMsg(I18NManager.Translate("Game.Command.Notice.NoPermission"));
return;
}
if (argInfo.Target?.Player?.Uid != sender.GetSender() && !AccountData.HasPerm([PermEnum.Other], sender.GetSender()))
{
await sender.SendMsg(I18NManager.Translate("Game.Command.Notice.NoPermission"));
return;
}
// find CommandMethodAttribute
var isFound = false;
foreach (var methodInfo in command.GetType().GetMethods())
{
var attr = methodInfo.GetCustomAttribute<CommandMethodAttribute>();
if (attr == null) continue;
if (argInfo.Args.Count > 0 && attr.MethodName == argInfo.Args[0])
{
argInfo.Args.RemoveAt(0);
isFound = true;
methodInfo.Invoke(command, [argInfo]);
break;
}
}
if (isFound) return;
// find CommandDefaultAttribute
foreach (var methodInfo in command.GetType().GetMethods())
{
var attr = methodInfo.GetCustomAttribute<CommandDefaultAttribute>();
if (attr == null) continue;
isFound = true;
methodInfo.Invoke(command, [argInfo]);
break;
}
if (isFound) return;
// failed to find method
await sender.SendMsg(I18NManager.Translate(cmdInfo.Usage));
}
catch (Exception ex)
{
Logger.Error(I18NManager.Translate("Game.Command.Notice.InternalError", ex.ToString()));
}
}
}

View File

@@ -0,0 +1,41 @@
using KianaBH.Enums.Player;
using KianaBH.GameServer.Game.Player;
using KianaBH.Util;
namespace KianaBH.GameServer.Command;
public interface ICommandSender
{
public ValueTask SendMsg(string msg);
public int GetSender();
}
public class ConsoleCommandSender(Logger logger) : ICommandSender
{
public async ValueTask SendMsg(string msg)
{
logger.Info(msg);
await Task.CompletedTask;
}
public int GetSender()
{
return (int)ServerEnum.Console;
}
}
public class PlayerCommandSender(PlayerInstance player) : ICommandSender
{
public PlayerInstance Player = player;
public async ValueTask SendMsg(string msg)
{
// TODO SEND MSG
}
public int GetSender()
{
return Player.Uid;
}
}