초기커밋
This commit is contained in:
271
GameServer/Contents/Chat/Action/ChatAction.cs
Normal file
271
GameServer/Contents/Chat/Action/ChatAction.cs
Normal file
@@ -0,0 +1,271 @@
|
||||
|
||||
using ServerCore;
|
||||
using ServerBase;
|
||||
using ServerCommon;
|
||||
|
||||
|
||||
namespace GameServer;
|
||||
|
||||
public class ChatAction : EntityActionBase
|
||||
{
|
||||
public ChatAction(EntityBase owner)
|
||||
: base(owner)
|
||||
{
|
||||
}
|
||||
|
||||
public override Task<Result> onInit()
|
||||
{
|
||||
var result = new Result();
|
||||
|
||||
return Task.FromResult(result);
|
||||
}
|
||||
|
||||
public override void onClear()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// 일반 주변 채팅
|
||||
public Result NormalChat(string message)
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var player = getOwner() as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
|
||||
|
||||
var server_logic = GameServerApp.getServerLogic();
|
||||
var game_zone_action = player.getEntityAction<GameZoneAction>();
|
||||
|
||||
ChatNotifyHelper.send_S2C_NTF_CHAT_BROADCAST(player, ChatType.Normal, player.getUserNickname(), string.Empty, PlayerStateType.None, message);
|
||||
|
||||
var invokers = new List<ILogInvoker>();
|
||||
var log_action = new LogActionEx(LogActionType.ChatNormal);
|
||||
|
||||
var cellPos = game_zone_action.GetPlayerCellPos(player);
|
||||
|
||||
var task_log_data = ChatBusinessLogHelper.toLogInfo(message, cellPos);
|
||||
invokers.Add(new ChatBusinessLog(task_log_data));
|
||||
|
||||
BusinessLogger.collectLogs(log_action, player, invokers);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// 채널 서버 내 채팅
|
||||
public Result ChannelChat(string message)
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var player = getOwner() as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(player, () => $"server_logic is null !!!");
|
||||
|
||||
var server_logic = GameServerApp.getServerLogic();
|
||||
|
||||
var receivers = server_logic.getPlayerManager().getUsers();
|
||||
foreach(var receiver in receivers)
|
||||
{
|
||||
ChatNotifyHelper.send_S2C_NTF_CHAT(receiver.Value, ChatType.Channel, player.getUserNickname(), string.Empty, PlayerStateType.None, message);
|
||||
}
|
||||
|
||||
var invokers = new List<ILogInvoker>();
|
||||
var log_action = new LogActionEx(LogActionType.ChatChannel);
|
||||
|
||||
var task_log_data = ChatBusinessLogHelper.toLogInfo(message, string.Empty);
|
||||
invokers.Add(new ChatBusinessLog(task_log_data));
|
||||
|
||||
BusinessLogger.collectLogs(log_action, player, invokers);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// 전서버 채팅
|
||||
public Result NoticeChat(string message)
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var player = getOwner() as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(player, () => $"server_logic is null !!!");
|
||||
|
||||
var server_logic = GameServerApp.getServerLogic();
|
||||
|
||||
// GM인지 확인
|
||||
//if (AccountAuthorityManager.Instance.IsWhiteListUser(player.getAccountId()) == false)
|
||||
//{
|
||||
// err_msg = $"Not Enough Authority to NoticeChat : player - {player.toBasicString()}";
|
||||
// result.setFail(ServerErrorCode.NotEnoughAuthority, err_msg);
|
||||
// Log.getLogger().error(err_msg);
|
||||
// ChatPacketHandler.send_S2C_ACK_CHAT(player, result, ChatType.Notice, player.getUserNickname(), string.Empty, string.Empty, PlayerStateType.None, message);
|
||||
// return result;
|
||||
//}
|
||||
|
||||
var rabbitMQ4Game = server_logic.getRabbitMqConnector() as RabbitMQ4Game;
|
||||
NullReferenceCheckHelper.throwIfNull(rabbitMQ4Game, () => $"rabbitMQ4Game is null !!!");
|
||||
|
||||
|
||||
rabbitMQ4Game.sendChat(message, player.getUserNickname(), ChatType.Notice);
|
||||
|
||||
var invokers = new List<ILogInvoker>();
|
||||
var log_action = new LogActionEx(LogActionType.ChatNotice);
|
||||
|
||||
var task_log_data = ChatBusinessLogHelper.toLogInfo(message, string.Empty);
|
||||
invokers.Add(new ChatBusinessLog(task_log_data));
|
||||
|
||||
BusinessLogger.collectLogs(log_action, player, invokers);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// 귓속말 채팅
|
||||
public async Task<Result> WhisperChat(string receiver_nickname, string message)
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var player = getOwner() as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
|
||||
|
||||
var server_logic = GameServerApp.getServerLogic();
|
||||
var rabbitMQ4Game = server_logic.getRabbitMqConnector() as RabbitMQ4Game;
|
||||
NullReferenceCheckHelper.throwIfNull(rabbitMQ4Game, () => $"rabbitMQ4Game is null !!!");
|
||||
|
||||
var dynamo_db_client = server_logic.getDynamoDbClient();
|
||||
|
||||
if (receiver_nickname == player.getUserNickname())
|
||||
{
|
||||
err_msg = $"Can't Send Chat to Self. nickname : {receiver_nickname}";
|
||||
result.setFail(ServerErrorCode.ChatSendSelfFailed, err_msg);
|
||||
Log.getLogger().error(err_msg);
|
||||
PacketHandler.ChatPacketHandler.send_S2C_ACK_CHAT(player, result, receiver_nickname, ChatType.Whisper, player.getUserNickname(), string.Empty, (int)PlayerStateType.None, message);
|
||||
return result;
|
||||
}
|
||||
|
||||
(result, var nickname_attrib) = await NicknameHelper.findNickname(receiver_nickname);
|
||||
if (result.isFail())
|
||||
{
|
||||
err_msg = $"Not Found Target. nickname : {receiver_nickname}";
|
||||
result.setFail(ServerErrorCode.TargetUserNotFound, err_msg);
|
||||
Log.getLogger().error(err_msg);
|
||||
PacketHandler.ChatPacketHandler.send_S2C_ACK_CHAT(player, result, receiver_nickname, ChatType.Whisper, player.getUserNickname(), string.Empty, (int)PlayerStateType.None, message);
|
||||
return result;
|
||||
}
|
||||
NullReferenceCheckHelper.throwIfNull(nickname_attrib, () => $"nickname_attrib is null !!!");
|
||||
var receiver_user_guid = nickname_attrib.UserGuid;
|
||||
|
||||
var login_cache_request = new LoginCacheOtherUserRequest(player, server_logic.getRedisConnector(), nickname_attrib.UserGuid);
|
||||
result = await login_cache_request.fetchLogin();
|
||||
var login_cache = login_cache_request.getLoginCache();
|
||||
if (result.isFail() || login_cache == null)
|
||||
{
|
||||
err_msg = $"Logoff user : target_usenicknamer - {receiver_nickname}";
|
||||
result.setFail(ServerErrorCode.TargetUserNotLogIn, err_msg);
|
||||
Log.getLogger().error(err_msg);
|
||||
PacketHandler.ChatPacketHandler.send_S2C_ACK_CHAT(player, result, receiver_nickname, ChatType.Whisper, player.getUserNickname(), string.Empty, (int)PlayerStateType.None, message);
|
||||
return result;
|
||||
}
|
||||
|
||||
var user_block_action = player.getEntityAction<BlockUserAgentAction>();
|
||||
if (user_block_action == null)
|
||||
{
|
||||
err_msg = $"Failed to get user block action : {nameof(BlockUserAgentAction)}";
|
||||
result.setFail(ServerErrorCode.EntityActionNotFound, err_msg);
|
||||
Log.getLogger().error(err_msg);
|
||||
PacketHandler.ChatPacketHandler.send_S2C_ACK_CHAT(player, result, receiver_nickname, ChatType.Whisper, player.getUserNickname(), string.Empty, (int)PlayerStateType.None, message);
|
||||
return result;
|
||||
}
|
||||
|
||||
//내가 차단한경우
|
||||
if (user_block_action.isBlockUser(receiver_user_guid))
|
||||
{
|
||||
err_msg = $"Failed chat with blocked user.";
|
||||
result.setFail(ServerErrorCode.ChatBlockUserCannotWhisper, err_msg);
|
||||
PacketHandler.ChatPacketHandler.send_S2C_ACK_CHAT(player, result, receiver_nickname, ChatType.Whisper, player.getUserNickname(), string.Empty, (int)PlayerStateType.None, message);
|
||||
return result;
|
||||
}
|
||||
|
||||
//상대방이 차단한경우 상대방에겐 보내지 않고 정상 처리 되도록
|
||||
(result, bool isblocked) = await user_block_action.amIBockedFromOthers(receiver_user_guid);
|
||||
if (result.isFail())
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
if (isblocked == true)
|
||||
{
|
||||
PacketHandler.ChatPacketHandler.send_S2C_ACK_CHAT(player, result, receiver_nickname, ChatType.Whisper, player.getUserNickname(), receiver_user_guid, login_cache.State, message);
|
||||
return result;
|
||||
}
|
||||
|
||||
if (login_cache.CurrentServer != server_logic.getServerName())
|
||||
{
|
||||
ServerMessage chatMessage = new();
|
||||
chatMessage.Chat = new();
|
||||
chatMessage.Chat.Type = ChatType.Whisper;
|
||||
chatMessage.Chat.SenderNickName = player.getUserNickname();
|
||||
chatMessage.Chat.ReceiverGuid = receiver_user_guid;
|
||||
chatMessage.Chat.Receiverstate = login_cache.State;
|
||||
chatMessage.Chat.Message = message;
|
||||
|
||||
rabbitMQ4Game.SendMessage(login_cache.CurrentServer, chatMessage);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(server_logic.getPlayerManager().tryGetUserByPrimaryKey(receiver_user_guid, out var receiver) == false)
|
||||
{
|
||||
err_msg = $"Failed to get player from player manager : receiver_user_guid - {receiver_user_guid}";
|
||||
result.setFail(ServerErrorCode.TargetUserNotLogIn, err_msg);
|
||||
Log.getLogger().error(err_msg);
|
||||
PacketHandler.ChatPacketHandler.send_S2C_ACK_CHAT(player, result, receiver_nickname, ChatType.Whisper, player.getUserNickname(), string.Empty, (int)PlayerStateType.None, message);
|
||||
return result;
|
||||
}
|
||||
|
||||
if(receiver == null)
|
||||
{
|
||||
err_msg = $"Failed to get player from player manager : receiver_user_guid - {receiver_user_guid}";
|
||||
result.setFail(ServerErrorCode.TargetUserNotLogIn, err_msg);
|
||||
Log.getLogger().error(err_msg);
|
||||
PacketHandler.ChatPacketHandler.send_S2C_ACK_CHAT(player, result, receiver_nickname, ChatType.Whisper, player.getUserNickname(), string.Empty, (int)PlayerStateType.None, message);
|
||||
return result;
|
||||
}
|
||||
|
||||
ChatNotifyHelper.send_S2C_NTF_CHAT(receiver, ChatType.Whisper, player.getUserNickname(), receiver_nickname, login_cache.State, message);
|
||||
}
|
||||
|
||||
ChatNotifyHelper.send_S2C_NTF_CHAT(player, ChatType.Whisper, player.getUserNickname(), receiver_nickname, login_cache.State, message);
|
||||
|
||||
var invokers = new List<ILogInvoker>();
|
||||
var log_action = new LogActionEx(LogActionType.ChatWhisper);
|
||||
|
||||
var task_log_data = ChatBusinessLogHelper.toLogInfo(message, receiver_nickname);
|
||||
invokers.Add(new ChatBusinessLog(task_log_data));
|
||||
|
||||
BusinessLogger.collectLogs(log_action, player, invokers);
|
||||
return result;
|
||||
}
|
||||
|
||||
// 파티 채팅
|
||||
public async Task<Result> PartyChat(string message)
|
||||
{
|
||||
var player = getOwner() as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
|
||||
|
||||
var personal_party_action = player.getEntityAction<PersonalPartyAction>();
|
||||
NullReferenceCheckHelper.throwIfNull(personal_party_action, () => $"personal_party_action is null !!!");
|
||||
|
||||
var result = await personal_party_action.sendPartyChat(message);
|
||||
|
||||
var invokers = new List<ILogInvoker>();
|
||||
var log_action = new LogActionEx(LogActionType.ChatParty);
|
||||
|
||||
//personal_party_action.getPersonalParty().
|
||||
|
||||
var task_log_data = ChatBusinessLogHelper.toLogInfo(message, string.Empty);
|
||||
invokers.Add(new ChatBusinessLog(task_log_data));
|
||||
|
||||
BusinessLogger.collectLogs(log_action, player, invokers);
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
278
GameServer/Contents/Chat/ChatCommand.cs
Normal file
278
GameServer/Contents/Chat/ChatCommand.cs
Normal file
@@ -0,0 +1,278 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
using ServerCore; using ServerBase;
|
||||
using ServerCommon;
|
||||
|
||||
|
||||
using GameServer.PacketHandler;
|
||||
|
||||
|
||||
namespace GameServer.ChatCommandHandler;
|
||||
|
||||
[ChatCommandAttribute("warp", typeof(WarpCommandHandler), AuthAdminLevelType.Developer, AuthAdminLevelType.GmNormal, AuthAdminLevelType.GmSuper)]
|
||||
internal class WarpCommandHandler : ChatCommandBase
|
||||
{
|
||||
public override async Task invoke(Player player, string token, string[] args)
|
||||
{
|
||||
if (args.Length < 1) return;
|
||||
if (!int.TryParse(args[0], out var warp_id)) return;
|
||||
|
||||
var result = await player.runTransactionRunnerSafely(TransactionIdType.PrivateContents, "CheetWarp", warpDelegate);
|
||||
if (result.isFail())
|
||||
{
|
||||
var err_msg = $"Failed to runTransactionRunnerSafely : {result.toBasicString()} - {player.toBasicString()}";
|
||||
Log.getLogger().error(err_msg);
|
||||
}
|
||||
|
||||
async Task<Result> warpDelegate() => await warpAsync(player, warp_id);
|
||||
}
|
||||
|
||||
private async Task<Result> warpAsync(Player player, int warpId)
|
||||
{
|
||||
var result = new Result();
|
||||
string err_msg;
|
||||
|
||||
var server_logic = GameServerApp.getServerLogic();
|
||||
var res = new ClientToGameRes.Types.WarpRes();
|
||||
|
||||
var game_zone_move_action = player.getEntityAction<GameZoneMoveAction>();
|
||||
NullReferenceCheckHelper.throwIfNull(game_zone_move_action, () => $"game_zone_move_action is null !!! - {player.toBasicString()}");
|
||||
|
||||
(result, res, var business_logs) = await game_zone_move_action.tryWarp(warpId);
|
||||
if (result.isFail())
|
||||
{
|
||||
err_msg = $"Failed to tryWarp() !!! : {result.toBasicString()} - {player.toBasicString()}";
|
||||
Log.getLogger().error(err_msg);
|
||||
|
||||
WarpPacketHandler.send_S2C_ACK_WARP(player, result, res);
|
||||
return result;
|
||||
}
|
||||
NullReferenceCheckHelper.throwIfNull(business_logs, () => $"business_logs is null !!! - warpId:{warpId}, {player.toBasicString()}");
|
||||
|
||||
var batch = new QueryBatchEx<QueryRunnerWithDocument>(player, LogActionType.Warp, server_logic.getDynamoDbClient());
|
||||
{
|
||||
batch.addQuery(new DBQWriteToAttributeAllWithTransactionRunner());
|
||||
batch.addQuery(new QueryFinal());
|
||||
}
|
||||
|
||||
batch.appendBusinessLogs(business_logs);
|
||||
|
||||
result = await QueryHelper.sendQueryAndBusinessLog(batch);
|
||||
if (result.isFail())
|
||||
{
|
||||
WarpPacketHandler.send_S2C_ACK_WARP(player, result, res);
|
||||
return result;
|
||||
}
|
||||
|
||||
WarpPacketHandler.send_S2C_ACK_WARP(player, result, res);
|
||||
if (res.PlaceCase == ClientToGameRes.Types.WarpRes.PlaceOneofCase.Pos)
|
||||
{
|
||||
player.send_S2C_NTF_SET_LOCATION();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
32
GameServer/Contents/Chat/Log/ChatBusinessLog.cs
Normal file
32
GameServer/Contents/Chat/Log/ChatBusinessLog.cs
Normal file
@@ -0,0 +1,32 @@
|
||||
using Google.Protobuf;
|
||||
using Google.Protobuf.WellKnownTypes;
|
||||
|
||||
|
||||
using ServerCore;
|
||||
using ServerBase;
|
||||
using ServerCommon;
|
||||
using ServerCommon.BusinessLogDomain;
|
||||
using MetaAssets;
|
||||
|
||||
|
||||
namespace GameServer;
|
||||
|
||||
public class ChatBusinessLog : ILogInvokerEx
|
||||
{
|
||||
private ChatLogData m_data_to_log;
|
||||
public ChatBusinessLog(ChatLogData log_data_param)
|
||||
: base(LogDomainType.Chat)
|
||||
{
|
||||
m_data_to_log = log_data_param;
|
||||
}
|
||||
|
||||
public override bool hasLog()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override void fillup(ref BusinessLog.LogBody body)
|
||||
{
|
||||
body.append(new ChatLogData(this, m_data_to_log));
|
||||
}
|
||||
}
|
||||
39
GameServer/Contents/Chat/Log/ChatBusinessLogHelper.cs
Normal file
39
GameServer/Contents/Chat/Log/ChatBusinessLogHelper.cs
Normal file
@@ -0,0 +1,39 @@
|
||||
|
||||
using ServerCore;
|
||||
using ServerBase;
|
||||
using ServerCommon;
|
||||
using ServerCommon.BusinessLogDomain;
|
||||
using MetaAssets;
|
||||
|
||||
|
||||
namespace GameServer;
|
||||
|
||||
public static class ChatBusinessLogHelper
|
||||
{
|
||||
static public ChatLogData toLogInfo(string chatMessage, CellPos cellpos)
|
||||
{
|
||||
var logData = new ChatLogData();
|
||||
logData.setInfo(chatMessage, cellpos);
|
||||
return logData;
|
||||
}
|
||||
|
||||
static public ChatLogData toLogInfo(string chatMessage, string targetUser = "")
|
||||
{
|
||||
var logData = new ChatLogData();
|
||||
logData.setInfo(chatMessage, targetUser);
|
||||
return logData;
|
||||
}
|
||||
|
||||
static public void setInfo(this ChatLogData logData, string chatMessage, string targetUser)
|
||||
{
|
||||
logData.TargetUser = targetUser;
|
||||
logData.ChatMessage = chatMessage;
|
||||
}
|
||||
|
||||
static public void setInfo(this ChatLogData logData, string chatMessage, CellPos cellpos)
|
||||
{
|
||||
logData.ChatMessage = chatMessage;
|
||||
logData.cellPosX = cellpos.CellX;
|
||||
logData.cellPosX = cellpos.CellY;
|
||||
}
|
||||
}
|
||||
81
GameServer/Contents/Chat/PacketHandler/ChatNotifyHelper.cs
Normal file
81
GameServer/Contents/Chat/PacketHandler/ChatNotifyHelper.cs
Normal file
@@ -0,0 +1,81 @@
|
||||
using ServerCore; using ServerBase;
|
||||
using static ServerMessage.Types;
|
||||
|
||||
namespace GameServer
|
||||
{
|
||||
public class ChatNotifyHelper
|
||||
{
|
||||
|
||||
public static ClientToGame makeChatMessage(ChatType chat_type, string sender_nickname, string receiver_nickname, PlayerStateType receiver_state, string message)
|
||||
{
|
||||
var noti_packet = new ClientToGame();
|
||||
noti_packet.Message = new();
|
||||
noti_packet.Message.Chat = new();
|
||||
|
||||
noti_packet.Message.Chat.Type = chat_type;
|
||||
noti_packet.Message.Chat.Sender = sender_nickname;
|
||||
noti_packet.Message.Chat.Receiver = receiver_nickname;
|
||||
noti_packet.Message.Chat.Receiverstate = receiver_state;
|
||||
noti_packet.Message.Chat.Message = message;
|
||||
|
||||
return noti_packet;
|
||||
}
|
||||
|
||||
public static bool send_S2C_NTF_CHAT(Player player, ChatType chat_type, string sender_nickname, string receiver_nickname, PlayerStateType receiver_state, string message)
|
||||
{
|
||||
var noti_packet = makeChatMessage(chat_type, sender_nickname, receiver_nickname, receiver_state, message);
|
||||
|
||||
if (false == GameServerApp.getServerLogic().onSendPacket(player, noti_packet))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool send_S2C_NTF_CHAT_BROADCAST(Player player, ChatType chat_type, string sender_nickname, string receiver_nickname, PlayerStateType receiver_state, string message)
|
||||
{
|
||||
var noti_packet = makeChatMessage(chat_type, sender_nickname, receiver_nickname, receiver_state, message);
|
||||
|
||||
var game_zone_action = player.getEntityAction<GameZoneAction>();
|
||||
NullReferenceCheckHelper.throwIfNull(game_zone_action, () => $"game_zone_action is null !!!");
|
||||
game_zone_action.broadcast(player, noti_packet);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void send_S2C_NTF_MQ_CHAT(Chat chat)
|
||||
{
|
||||
var server_logic = GameServerApp.getServerLogic();
|
||||
var player_manager = server_logic.getPlayerManager();
|
||||
|
||||
switch (chat.Type)
|
||||
{
|
||||
case ChatType.Notice:
|
||||
{
|
||||
var players = player_manager.getUsers();
|
||||
foreach (var player in players)
|
||||
{
|
||||
ChatNotifyHelper.send_S2C_NTF_CHAT(player.Value, chat.Type, chat.SenderNickName, "", PlayerStateType.None, chat.Message);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ChatType.Whisper:
|
||||
{
|
||||
if (player_manager.tryGetUserByPrimaryKey(chat.ReceiverGuid, out var found_user) == false) return;
|
||||
if (found_user == null) return;
|
||||
|
||||
ChatNotifyHelper.send_S2C_NTF_CHAT(found_user, chat.Type, chat.SenderNickName, found_user.getUserNickname(), PlayerStateType.None, chat.Message);
|
||||
break;
|
||||
}
|
||||
case ChatType.Party:
|
||||
{
|
||||
//await PartyManager.Instance.ChatBroadcast(chat.Receiver, clientToGame);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
180
GameServer/Contents/Chat/PacketHandler/ChatPacketHandler.cs
Normal file
180
GameServer/Contents/Chat/PacketHandler/ChatPacketHandler.cs
Normal file
@@ -0,0 +1,180 @@
|
||||
using Google.Protobuf;
|
||||
|
||||
|
||||
using ServerCore;
|
||||
using ServerBase;
|
||||
using ServerCommon;
|
||||
|
||||
using static ClientToGameReq.Types;
|
||||
using static ClientToGameRes.Types;
|
||||
|
||||
|
||||
|
||||
namespace GameServer.PacketHandler;
|
||||
|
||||
[PacketHandler(typeof(ClientToGameReq), typeof(ClientToGameReq.Types.ChatReq), typeof(ChatPacketHandler), typeof(GameLoginListener))]
|
||||
public class ChatPacketHandler : PacketRecvHandler
|
||||
{
|
||||
public static bool send_S2C_ACK_CHAT(Player player, Result result, string receiver_nickname, ChatType chat_type = ChatType.None, string sender_nickname = "", string receiver_guid = "", PlayerStateType receiver_state = PlayerStateType.None, string message = "")
|
||||
{
|
||||
var ack_packet = new ClientToGame();
|
||||
ack_packet.Response = new ClientToGameRes();
|
||||
|
||||
ack_packet.Response.ErrorCode = result.ErrorCode;
|
||||
ack_packet.Response.ChatRes = new ChatRes();
|
||||
|
||||
ack_packet.Response.ChatRes.Type = chat_type;
|
||||
ack_packet.Response.ChatRes.Sender = sender_nickname;
|
||||
ack_packet.Response.ChatRes.Receiver = receiver_nickname;
|
||||
ack_packet.Response.ChatRes.Receiverid = receiver_guid;
|
||||
ack_packet.Response.ChatRes.Receiverstate = receiver_state;
|
||||
ack_packet.Response.ChatRes.Message = message;
|
||||
|
||||
if (false == GameServerApp.getServerLogic().onSendPacket(player, ack_packet))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override async Task<Result> onProcessPacket(ISession entityWithSession, IMessage recvMessage)
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var entity_player = entityWithSession as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(entity_player, () => $"entity_player is null !!!");
|
||||
|
||||
var server_logic = GameServerApp.getServerLogic();
|
||||
|
||||
var chat_action = entity_player.getEntityAction<ChatAction>();
|
||||
NullReferenceCheckHelper.throwIfNull(chat_action, () => $"chat_action is null !!!");
|
||||
|
||||
// 1. 메시지 체크
|
||||
var game_msg = recvMessage as ClientToGame;
|
||||
if (game_msg == null)
|
||||
{
|
||||
err_msg = $"Failed to cast ClientToGame !!! : {nameof(ClientToGame.Request.ChatReq)}";
|
||||
result.setFail(ServerErrorCode.ClassTypeCastIsNull, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
|
||||
send_S2C_ACK_CHAT(entity_player, result, "");
|
||||
return result;
|
||||
}
|
||||
|
||||
var request = game_msg.Request.ChatReq;
|
||||
|
||||
// 2. 유저 block 체크
|
||||
var account_attribute = entity_player.getEntityAttribute<AccountAttribute>();
|
||||
NullReferenceCheckHelper.throwIfNull(account_attribute, () => $"account_attribute is null !!! - {entity_player.toBasicString()}");
|
||||
var account_base_doc = account_attribute.getOriginDocBase<AccountAttribute>() as AccountBaseDoc;
|
||||
NullReferenceCheckHelper.throwIfNull(account_base_doc, () => $"account_base_doc is null !!!");
|
||||
|
||||
var doc_account_base_attrib = account_base_doc.getAttrib<AccountBaseAttrib>();
|
||||
NullReferenceCheckHelper.throwIfNull(doc_account_base_attrib, () => $"doc_account_base_attrib is null !!!");
|
||||
|
||||
var block_policy = UserBlockHelper.convertBlockPolicyToJavaPolicy(doc_account_base_attrib.BlockPolicy);
|
||||
if (block_policy.Contains(UserBlockPolicyType.ChattingRestrictions.ToString()))
|
||||
{
|
||||
//여기서 강제로 리턴
|
||||
send_S2C_ACK_CHAT(entity_player, result, request.ToNickName);
|
||||
return result;
|
||||
}
|
||||
|
||||
// 3. cheat 체크
|
||||
if (server_logic.ChatCommand.isCheatCommand(request.Message) == true)
|
||||
{
|
||||
await server_logic.ChatCommand.HandleCommand(entity_player, request.Message);
|
||||
send_S2C_ACK_CHAT(entity_player, result, request.ToNickName);
|
||||
return result;
|
||||
}
|
||||
|
||||
// 4. chat 기본 조건 체크
|
||||
result = checkChatConditions(request.Message);
|
||||
if (result.isFail())
|
||||
{
|
||||
send_S2C_ACK_CHAT(entity_player, result, request.ToNickName);
|
||||
return result;
|
||||
}
|
||||
|
||||
var chat_type = request.Type;
|
||||
|
||||
// 5. 채팅 처리
|
||||
switch (chat_type)
|
||||
{
|
||||
case ChatType.Normal:
|
||||
result = chat_action.NormalChat(request.Message);
|
||||
break;
|
||||
case ChatType.Channel:
|
||||
result = chat_action.ChannelChat(request.Message);
|
||||
break;
|
||||
case ChatType.Notice:
|
||||
result = chat_action.NoticeChat(request.Message);
|
||||
break;
|
||||
case ChatType.Whisper:
|
||||
result = await chat_action.WhisperChat(request.ToNickName, request.Message);
|
||||
break;
|
||||
case ChatType.Party:
|
||||
result = await chat_action.PartyChat(request.Message);
|
||||
break;
|
||||
default:
|
||||
err_msg = $"Invalid EChatType !!! EChatType : {request.Type} - {entity_player.toBasicString()}";
|
||||
result.setFail(ServerErrorCode.ChatInvalidChatType, err_msg);
|
||||
Log.getLogger().error(err_msg);
|
||||
break;
|
||||
}
|
||||
|
||||
if (result.isFail())
|
||||
{
|
||||
err_msg = $"Failed to trySendMail() !!! : {result.toBasicString()} - {entity_player.toBasicString()}";
|
||||
Log.getLogger().error(err_msg);
|
||||
return result;
|
||||
}
|
||||
|
||||
await QuestManager.It.QuestCheck(entity_player, new QuestChat(EQuestEventTargetType.CHAT, EQuestEventNameType.USED, chat_type.ToString(), request.Message));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private Result checkChatConditions(string message)
|
||||
{
|
||||
var result = new Result();
|
||||
string err_msg;
|
||||
|
||||
// 1. 총 길이 체크
|
||||
if (message.Length > MetaHelper.GameConfigMeta.ChatStringInputMax)
|
||||
{
|
||||
err_msg = $"fail to send chat !!! : invalid chat message length - {message.Length}";
|
||||
result.setFail(ServerErrorCode.ChatInvalidMessageLength, err_msg);
|
||||
Log.getLogger().error(err_msg);
|
||||
return result;
|
||||
}
|
||||
|
||||
// 2. 금칙어 체크 ( Client 에서 처리함 )
|
||||
/*if (ServerUtil.isBanWorld(message, false))
|
||||
{
|
||||
err_msg = $"fail to send chat !!! : include ban word - {message}";
|
||||
result.setFail(ServerErrorCode.ChatIncludeBanWord, err_msg);
|
||||
Log.getLogger().error(err_msg);
|
||||
return result;
|
||||
}*/
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public override async Task onProcessPacketException(ISession entityWithSession, IMessage recvMessage
|
||||
, Result errorResult)
|
||||
{
|
||||
await Task.CompletedTask;
|
||||
|
||||
var player = entityWithSession as Player;
|
||||
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!! - {entityWithSession.toBasicString()}");
|
||||
var recv_msg = recvMessage as ClientToGame;
|
||||
NullReferenceCheckHelper.throwIfNull(recv_msg, () => $"recv_msg is null !!! - {player.toBasicString()}");
|
||||
var request = recv_msg.Request.ChatReq;
|
||||
NullReferenceCheckHelper.throwIfNull(request, () => $"request is null !!! - {player.toBasicString()}");
|
||||
|
||||
send_S2C_ACK_CHAT(player, errorResult, request.ToNickName);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
using Newtonsoft.Json;
|
||||
using Google.Protobuf;
|
||||
using Google.Protobuf.WellKnownTypes;
|
||||
|
||||
|
||||
using ServerCore;
|
||||
using ServerBase;
|
||||
using ServerCommon;
|
||||
using ServerCommon.BusinessLogDomain;
|
||||
using MetaAssets;
|
||||
|
||||
|
||||
|
||||
namespace GameServer;
|
||||
|
||||
|
||||
public class RabbitNoticeChatHandler
|
||||
{
|
||||
public void MOS2GS_noticeChatSend(ServerMessage.Types.MOS2GS_NTF_NOTICE_CHAT chatMsg)
|
||||
{
|
||||
//OperationSystemNoticeChatType
|
||||
|
||||
Log.getLogger().debug("MOS2GS_noticeChatSend call start");
|
||||
// 1. 메시지 체크
|
||||
if (chatMsg == null)
|
||||
{
|
||||
var err_msg = $"chatMsg is null !!! : {nameof(ServerMessage.Types.MOS2GS_NTF_NOTICE_CHAT)}";
|
||||
Log.getLogger().error(err_msg);
|
||||
return;
|
||||
}
|
||||
//await server_logic.getNoticeChatManager().LoadDB();
|
||||
var notice_type = chatMsg.NoticeType.ToString();
|
||||
var chat_msgs = chatMsg.ChatMessage;
|
||||
var senders = chatMsg.Sender;
|
||||
|
||||
Dictionary<int, string> dic_msg_by_lang = new();
|
||||
Dictionary<int, string> dic_sender_by_lang = new();
|
||||
foreach(var chat_msg in chat_msgs)
|
||||
{
|
||||
var txt = StringRuleHelper.convertStringFromBase64(chat_msg.Text);
|
||||
dic_msg_by_lang.Add((int)chat_msg.LanguageType, txt);
|
||||
}
|
||||
|
||||
foreach(var sender in senders)
|
||||
{
|
||||
var sender_txt = StringRuleHelper.convertStringFromBase64(sender.Text);
|
||||
dic_sender_by_lang.Add((int)sender.LanguageType, sender_txt);
|
||||
}
|
||||
|
||||
|
||||
var server_logic = GameServerApp.getServerLogic();
|
||||
var player_manager = server_logic.getPlayerManager();
|
||||
// if (notice_type.Equals(OperationSystemNoticeChatType.CHATTING.ToString()))
|
||||
// {
|
||||
|
||||
//일단 채팅이든 토스트든 전부 notice로 전달한다.
|
||||
var users = player_manager.getUsers();
|
||||
foreach (var user in users)
|
||||
{
|
||||
var player = user.Value;
|
||||
var account_attribute = player.getEntityAttribute<AccountAttribute>();
|
||||
if(account_attribute == null) continue;
|
||||
|
||||
if(dic_msg_by_lang.TryGetValue((int)account_attribute.LanguageType, out var chat_msg) == false)
|
||||
{
|
||||
var err_msg = $"dic_msg_by_lang error accountid : {account_attribute.AccountId}, langtype : {account_attribute.LanguageType}, {JsonConvert.SerializeObject(dic_msg_by_lang)}";
|
||||
Log.getLogger().error(err_msg);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (dic_sender_by_lang.TryGetValue((int)account_attribute.LanguageType, out var sender) == false)
|
||||
{
|
||||
var err_msg = $"dic_sender_by_lang error accountid : {account_attribute.AccountId}, langtype : {account_attribute.LanguageType}, {JsonConvert.SerializeObject(dic_sender_by_lang)}";
|
||||
Log.getLogger().error(err_msg);
|
||||
continue;
|
||||
}
|
||||
ChatNotifyHelper.send_S2C_NTF_CHAT(player, ChatType.Notice, sender, player.getUserNickname(), PlayerStateType.None, chat_msg);
|
||||
}
|
||||
|
||||
Log.getLogger().debug($"MOS2GS_noticeChatSend call end userCount = {users.Count}, lang_msg : {JsonConvert.SerializeObject(dic_msg_by_lang)}, sender_msg : {JsonConvert.SerializeObject(dic_sender_by_lang)}");
|
||||
|
||||
// }
|
||||
// else if (notice_type.Equals(OperationSystemNoticeChatType.CHATTING_TOAST.ToString()))
|
||||
// {
|
||||
// var err_msg = $"CHATTING_TOAST not implement !!!";
|
||||
// return;
|
||||
// }
|
||||
|
||||
//메시지에 대한 필터링을 어떻게 해야하지?
|
||||
// 4. 채팅 처리
|
||||
// switch (chat_type)
|
||||
// {
|
||||
// case ChatType.Normal:
|
||||
// result = chat_action.NormalChat(request.Message);
|
||||
// break;
|
||||
// case ChatType.Channel:
|
||||
// result = chat_action.ChannelChat(request.Message);
|
||||
// break;
|
||||
// case ChatType.Notice:
|
||||
//result = chat_action.NoticeChat(request.Message);
|
||||
// break;
|
||||
// case ChatType.Whisper:
|
||||
// result = await chat_action.WhisperChat(request.ToNickName, request.Message);
|
||||
// break;
|
||||
// case ChatType.Party:
|
||||
// result = await chat_action.PartyChat(request.Message);
|
||||
// break;
|
||||
// if (result.isFail())
|
||||
// {
|
||||
// err_msg = $"Failed to trySendMail() !!! : {result.toBasicString()} - {entity_player.toBasicString()}";
|
||||
// Log.getLogger().error(err_msg);
|
||||
// return result;
|
||||
// }
|
||||
// return result;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user