Files
caliverse_server/GameServer/Contents/Chat/ChatCommand.cs
2025-05-01 07:20:41 +09:00

279 lines
8.6 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Security.Claims;
using Amazon.DynamoDBv2.Model;
using Amazon.DynamoDBv2;
using Microsoft.AspNetCore.Authentication.OAuth.Claims;
using Google.Protobuf;
using ServerCore;
using ServerBase;
using ServerCommon;
using GameServer.PacketHandler;
using MetaAssets;
using static ClientToGameReq.Types;
using static ClientToGameRes.Types;
using static ClientToGameMessage.Types;
using SESSION_ID = System.Int32;
using WORLD_META_ID = System.UInt32;
using META_ID = System.UInt32;
using ENTITY_GUID = System.String;
using ACCOUNT_ID = System.String;
using OWNER_GUID = System.String;
using USER_GUID = System.String;
using CHARACTER_GUID = System.String;
using ITEM_GUID = System.String;
namespace GameServer;
public class ChatCommand : Attribute
{
Dictionary<string, ChatCommandBase> command_base_map = new Dictionary<string, ChatCommandBase>();
public ChatCommand()
{
loadChatCommand();
}
private void loadChatCommand()
{
// ChatCommand 클래스의 모든 메서드를 가져옵니다.
var assemblies = AppDomain.CurrentDomain.GetAssemblies();
foreach (var assembly in assemblies)
{
foreach (Type type in assembly.GetTypes())
{
ChatCommandAttribute[] attributes = (ChatCommandAttribute[])type.GetCustomAttributes(typeof(ChatCommandAttribute), false);
foreach (var attrib in attributes)
{
var command_key = attrib.getCommand();
if (command_key == null)
{
Log.getLogger().error($"ChatCommand Key is null !!!, in ChatCommandAttributes : {attrib.getHandlerClass().FullName}");
continue;
}
var handler_class = Activator.CreateInstance(attrib.getHandlerClass()) as ChatCommandBase;
if (handler_class == null)
{
Log.getLogger().error($"Failed to create ChatCommand !!! : commandKey:{command_key}");
continue;
}
handler_class.setAuthAdminLevelType(attrib.getAdminLevel());
handler_class.setClassName(attrib.getHandlerClass().Name);
if (command_base_map.TryAdd(command_key, handler_class) == false)
{
Log.getLogger().error($"Failed to TryAdd() !!!, Already added CommandKey !!! : commandKey:{command_key}");
continue;
}
}
}
}
}
public bool isCheatCommand(string input)
{
return input.StartsWith("//");
}
public async Task<bool> HandleCommand(Player player, string input)
{
var tokenArr = input.Split(" ", 2);
try
{
var command = tokenArr[0].Remove(0, 2);
if (command_base_map.TryGetValue(command.ToLower(), out var handler_class) == false)
{
Log.getLogger().error($"Command Not Exist Command : {command.ToLower()}");
return false;
}
if (await hasAuthority(handler_class, player) == false)
{
return false;
}
if (tokenArr.Length > 1)
{
var args = tokenArr[1].Split(" ", StringSplitOptions.RemoveEmptyEntries);
await handler_class.invoke(player, tokenArr[1], args);
}
else
{
await handler_class.invoke(player, String.Empty, new string[] { });
}
}
catch (TaskCanceledException e)
{
Log.getLogger().error($"TaskCanceledException !!!, Failed to perform in HandleCommand() !!! : exception:{e}, inputString:{input} - {player.toBasicString()}");
}
catch (Exception e)
{
Log.getLogger().error($"Exception !!!, Failed to perform in HandleCommand() !!! : exception:{e}, inputString:{input} - {player.toBasicString()}");
return false;
}
return true;
}
private async Task<bool> hasAuthority(ChatCommandBase handlerClass, Player player)
{
await Task.CompletedTask;
var server_config = ServerConfigHelper.getServerConfig();
NullReferenceCheckHelper.throwIfNull(server_config, () => $"server_config is null !!!");
// ServiceType.Dev 타입일 경우 무조건 치트 사용이 가능 하다. !!!
if (server_config.ServiceType.Equals(ServiceType.Dev.ToString()))
{
return true;
}
// CheatCommandAlwaysAllow == true 일 경우 무조건 치트 사용이 가능 하다. !!!
if (true == server_config.CheatCommandAlwaysAllow)
{
return true;
}
var account_attribute = player.getEntityAttribute<AccountAttribute>();
NullReferenceCheckHelper.throwIfNull(account_attribute, () => $"account_attribute is null !!!");
var admin_level_type = account_attribute.AuthAdminLevelType;
//여기에 유저 레벨이랑, 클래스에 할당된 레벨이랑 비교 필요
var class_admin_level_type = handlerClass.getAuthAddminLevelType();
if (class_admin_level_type.Contains(admin_level_type) == false)
{
Log.getLogger().info($"Not Match Admin LevelType !!! : className = {handlerClass.getAuthAddminLevelType().ToString()}, className:{handlerClass.getClassName()} - {player.toBasicString()}");
return false;
}
return true;
}
}
[AttributeUsage(AttributeTargets.Class)]
internal class ChatCommandAttribute : Attribute
{
readonly string m_cheat_comment;
private readonly Type m_handler_class;
private readonly HashSet<AuthAdminLevelType> m_auth_admin_level_type;
public ChatCommandAttribute(string cheatCommend, Type handlerClass, params AuthAdminLevelType[] authAdminLevelType)
{
m_cheat_comment = cheatCommend;
m_handler_class = handlerClass;
m_auth_admin_level_type = new HashSet<AuthAdminLevelType>(authAdminLevelType);
}
public string getCommand()
{
return m_cheat_comment;
}
public HashSet<AuthAdminLevelType> getAdminLevel()
{
return m_auth_admin_level_type;
}
public Type getHandlerClass()
{
return m_handler_class;
}
}
public abstract class ChatCommandBase
{
private HashSet<AuthAdminLevelType> m_auth_admin_level_type = new();
private string m_class_name = string.Empty;
public void setAuthAdminLevelType(HashSet<AuthAdminLevelType> typeSet)
{
m_auth_admin_level_type = typeSet;
}
public HashSet<AuthAdminLevelType> getAuthAddminLevelType()
{
return m_auth_admin_level_type;
}
public void setClassName(string className)
{
m_class_name = className;
}
public string getClassName()
{
return m_class_name;
}
public virtual async Task invoke(Player player, string token, string[] args)
{
await Task.CompletedTask;
}
}
[ChatCommandAttribute("sessionkeepalivetime", typeof(ChatCommandSessionKeepAliveTime), AuthAdminLevelType.Developer, AuthAdminLevelType.GmNormal, AuthAdminLevelType.GmSuper)]
internal class ChatCommandSessionKeepAliveTime : ChatCommandBase
{
public override async Task invoke(Player player, string token, string[] args)
{
await Task.CompletedTask;
Log.getLogger().info($"Call sessionkeepalivetime !!! - {player.toBasicString()}");
var result = new Result();
var err_msg = string.Empty;
if (args.Length < 1)
{
err_msg = $"Not enough argument !!! : argCount:{args.Length} == 3 - {player.toBasicString()}";
Log.getLogger().error(err_msg);
return;
}
var keep_alive_minutes = int.Parse(args[0]);
var server_logic = GameServerApp.getServerLogic();
NullReferenceCheckHelper.throwIfNull(server_logic, () => $"server_logic is null !!! - {player.toBasicString()}");
var session = player as IEntityWithSession;
NullReferenceCheckHelper.throwIfNull(session, () => $"session is null !!! - {player.toBasicString()}");
var timeout_ms = keep_alive_minutes * ConstValue.default_1_min_to_sec * ConstValue.default_1_sec_to_milisec;
var net_server = server_logic.getProudNetListener().getNetServer();
NullReferenceCheckHelper.throwIfNull(net_server, () => $"net_server is null !!!");
net_server.SetTimeoutTimeMs(session.getHostId(), timeout_ms);
}
}