void IServer.HandleUserReconnect(IServerUser user) { foreach (var game in _runningGames.Where(game => game.Value.HasUser(user))) { game.Value.HandleReconnect(user); } }
void IServer.HandleUserLeaveQueue(IServerUser user, QueueAction action) { var matchmaking = GetMatchmaking(user, action); if (matchmaking == null) { return; } lock (matchmaking) { var regCount = matchmaking.GetRegisterCount(user); if (action.Count >= regCount) { matchmaking.LeaveQueueCompletely(user); } else { for (var i = 0; i < action.Count; i++) { matchmaking.LeaveQueue(user); } } user.Send(Packet.PacketTypeS2C.QueueState, Math.Max(0, regCount - action.Count)); } }
public GameEnd(long gameIdentifier, IServerUser[] participants, bool youWon, IServerUser winner) { GameIdentifier = gameIdentifier; Participants = participants; YouWon = youWon; Winner = winner; }
void IServer.HandleUserEnterQueue(IServerUser user, QueueAction action) { var matchmaking = GetMatchmaking(user, action); if (matchmaking == null) { return; } lock (matchmaking) { var regCount = matchmaking.GetRegisterCount(user); if (regCount >= _config.MaxQueueCount) { user.IllegalAction("Exceeded max queue action: " + _config.MaxQueueCount); return; } var queueLimitExclusive = Math.Min(_config.MaxQueueCount, regCount + action.Count); for (; regCount < queueLimitExclusive; regCount++) { matchmaking.EnterQueue(user); } user.Send(Packet.PacketTypeS2C.QueueState, regCount); } }
public bool RemoveUser(IServerUser user) { using (StoreKeeperServiceProxy proxy = new StoreKeeperServiceProxy(_clientConfiguration)) { return(proxy.RemoveUser(_sessionId, user.UserId)); } }
public void Should_Use_User_From_Server_If_Direct_Message() { _message.Channel.IsPrivateMessage.Returns(true); _parser.ParseCommand(_message).Returns(new ParsedCommand() { Success = true, Command = "test" }); ICommandHandler commandHandler = Substitute.For <ICommandHandler>(); commandHandler.CommandName.Returns("test"); commandHandler.UserFilter.Returns((Func <DiscloseUser, bool>)null); commandHandler.ChannelFilter.Returns((Func <DiscloseChannel, bool>)null); _discloseClient.Register(commandHandler); IServerUser serverUser = Substitute.For <IServerUser>(); serverUser.Id.Returns((ulong)123); serverUser.Name.Returns("foo"); _server.GetUsersAsync().Returns(Task.FromResult((new[] { serverUser }).AsEnumerable())); _discordClient.OnMessageReceived += Raise.EventWith(new object(), new MessageEventArgs(_message)); commandHandler.Received(1).Handle(Arg.Is <DiscloseMessage>(m => m.User.Name == "foo"), null); }
public bool WouldAuthCollide(Guid login, IServerUser connectingUser, out IServerUser existingUser) { lock (_connectedUsers) { existingUser = _connectedUsers.FirstOrDefault(item => item.Key.Login == login && item.Key != connectingUser).Key; return(existingUser != null); } }
internal DiscloseUser(IServerUser user, DiscloseServer server) { DiscordUser = user; IEnumerable <DiscloseRole> roles = server.GetRoles(); Roles = user.RoleIds.Select(ur => roles.FirstOrDefault(r => ur == r.Id)).Where(r => r != null).ToList().AsReadOnly(); }
void IServer.HandleUserEndTurn(IServerUser user, long gameIdentifier) { ServerGame game; if (!_runningGames.TryGetValue(gameIdentifier, out game)) { user.IllegalAction("You can't end your turn in a game you don't even play in: " + gameIdentifier); return; } game.UserRequestsEndTurn(user); }
void IServer.HandleUserAction(IServerUser @from, LiveGameAction action) { ServerGame game; if (!_runningGames.TryGetValue(action.GameIdentifier, out game)) { @from.IllegalAction("You cannot take action in a game you don't even play in!"); return; } game.AddGameAction(from, action); }
void IServer.HandleUserResync(IServerUser user, long gameIdentifier) { ServerGame game; if (!_runningGames.TryGetValue(gameIdentifier, out game)) { _logger.LogWarning($"User tried resyncing in an unknown game: {gameIdentifier}"); user.IllegalAction($"Cannot resync in game: {gameIdentifier}, because it does not exist!"); return; } game.HandleReconnect(user); }
/// <summary> /// Replaces the socket with the socket of the given user. This should be used to let a reconnecting user continue /// where he left /// </summary> /// <param name="user"></param> /// <param name="socket"></param> public void Inherit(IServerUser user, Socket socket) { var userImpl = user as User; if (userImpl == null) { throw new NotImplementedException(); // assuming there are no other implementations of IServerUser than User } _socket.Dispose(); // Dispose disconnected userImpl._socket.StopJobs(); // Discontinue wrapper because the events will call the methods of the new (duplicate) user SetupSocket(userImpl._socket.Socket); // Recreate wrapper _packetParser = userImpl._packetParser; Username = user.Username; FullGameState = user.FullGameState; Authorized = user.Authorized; }
void IServer.Kick(IServerUser user) { DateTime connectedTime; lock (_connectedUsers) { _connectedUsers.TryRemove(user, out connectedTime); } if (user.Connected) { user.Dispose(); } _logger.LogDebug($"Kicking user: {user}, who connected {connectedTime}"); // Todo: instead of letting running games wait for the timeout, kick the user and his entities out right away }
/// <summary> /// Constructs a game user /// </summary> /// <param name="serverUser">Server user</param> public AGameUser(IServerUser serverUser) { if (serverUser == null) { throw new ArgumentNullException(nameof(serverUser)); } if (!serverUser.IsValid) { throw new ArgumentException("Server user is not valid.", nameof(serverUser)); } ServerUser = serverUser; serverUser.OnUsernameUpdated += () => OnUsernameUpdated?.Invoke(); serverUser.OnUserLobbyColorUpdated += () => OnUserLobbyColorUpdated?.Invoke(); serverUser.OnGameLoadingFinished += () => OnGameLoadingFinished?.Invoke(); serverUser.OnClientTicked += (entityDeltas, hits) => OnClientTicked?.Invoke(entityDeltas, hits); serverUser.OnServerTicked += (time, entityDeltas, hits) => OnServerTicked?.Invoke(time, entityDeltas, hits); }
private IMatchmaking GetMatchmaking(IServerUser user, QueueAction action) { if (action.Count <= 0) { user.IllegalAction("Invalid queue count"); return(null); } IMatchmaking matchmaking; if (!_matchmaking.TryGetValue(action.GameMode, out matchmaking)) { user.IllegalAction("There is no such gamemode"); return(null); } return(matchmaking); }
/// <summary> /// "ban" console command executed event /// </summary> /// <param name="arguments">Arguments</param> private static void BanConsoleCommmandExecutedEvent(IReadOnlyList <string> arguments) { IServerUser banned_server_user = null; string user_guid = arguments[0]; foreach (ILobby lobby in server.Lobbies.Values) { if (lobby.Users.ContainsKey(user_guid)) { banned_server_user = lobby.Users[user_guid] as IServerUser; if (banned_server_user != null) { server.Bans.AddPeer(banned_server_user.Peer, "Banned by admin"); banned_server_user.Disconnect(EDisconnectionReason.Banned); server.Bans.WriteToFile(bansJSONFilePath); break; } } } if (banned_server_user == null) { WriteErrorLogLine($"User with GUID \"{ user_guid }\" does not exist or could not been banned."); } else { foreach (ILobby lobby in server.Lobbies.Values) { foreach (IUser user in lobby.Users.Values) { if (user is IServerUser server_user) { if ((banned_server_user != server_user) && (server.Bans.IsPeerBanned(server_user.Peer, out _))) { server_user.Disconnect(EDisconnectionReason.Banned); } } } } WriteOutputLogLine($"User \"{ banned_server_user.Name }\" with GUID \"{ banned_server_user.GUID }\" at \"{ banned_server_user.Peer.Secret }\" has been banned."); } }
public void Setup() { _parser = Substitute.For <ICommandParser>(); _discordClient = Substitute.For <IDiscordClient>(); _discloseClient = new DiscloseClient(_discordClient, _parser); _discloseClient.Init(new DiscloseOptions()); _message = Substitute.For <IMessage>(); _server = Substitute.For <IServer>(); IServerUser serverUser = Substitute.For <IServerUser>(); serverUser.Id.Returns((ulong)123); _message.User.Returns(serverUser); _server.Id.Returns((ulong)1); _discordClient.OnServerAvailable += Raise.EventWith(new object(), new ServerEventArgs(_server)); }
public void Setup() { _parser = Substitute.For <ICommandParser>(); _discordClient = Substitute.For <IDiscordClient>(); _discloseClient = new DiscloseClient(_discordClient, _parser); _discloseClient.Init(new DiscloseOptions()); _user = Substitute.For <IServerUser>(); _server = Substitute.For <IServer>(); _user.Id.Returns((ulong)1); _server.Id.Returns((ulong)2); _handler1 = Substitute.For <IUserJoinsServerHandler>(); _handler2 = Substitute.For <IUserJoinsServerHandler>(); _discloseClient.Register(_handler1); _discloseClient.Register(_handler2); _discordClient.OnServerAvailable += Raise.EventWith <ServerEventArgs>(new object(), new ServerEventArgs(_server)); }
public void EnterQueue(IServerUser user) { var time = _time.Elapsed.TotalSeconds; if (time - _lastQueuerTime > _maxTimeInQueue && _inQueue.All(item => item.IsBot) && _inQueue.Any() && !user.IsBot) { AddUser(user); var bestMatch = Supervisor.GetBestChoice(user.Login, _inQueue.Where(item => item != user).ToArray().Select(item => item.Login)); var bestBotBot = _inQueue.FirstOrDefault(bot => bot.Login == bestMatch); if (bestBotBot == null) { _logger.LogError($"{GetType().Name}: {Supervisor.GetType()} gave me an invalid GUID as best choice!"); } else { _logger.LogDebug($"Found a match (Queue very empty for a longer time, matching with bot: {bestBotBot})"); OnSuggested?.Invoke(this, new MatchCreatedArgs(this, _gameMode, user, bestBotBot)); return; } } if (!user.IsBot) { _lastQueuerTime = time; } AddUser(user); var autoBestMatch = _inQueue.FirstOrDefault(usr => usr != user && !usr.HasEverPlayedAgainst(user, Supervisor)); if (autoBestMatch != null) { _logger.LogDebug($"Found a match (never played against {autoBestMatch})"); OnSuggested?.Invoke(this, new MatchCreatedArgs(this, _gameMode, autoBestMatch, user)); } }
public void ForceLogout(IServerUser user) => this.Server.ForceLogout(user);
/// <summary> /// Creates a new game user /// </summary> /// <param name="serverUser">Server user</param> /// <returns>Game user</returns> public IGameUser CreateNewGameUser(IServerUser serverUser) => new ExampleGameUser(serverUser);
public static bool HasEverPlayedAgainst(this IServerUser me, IServerUser other, IServerSupervisor supervisor) { return(supervisor.GetWinStatistics(me.Login, other.Login).GetTotalGames() > 0); }
private void LoadInternalCommand() { /* * {"Call":"command","Args":{"command":"cmd arg1 arg2 ..."}} */ this.AddFunction(new Function() { Name = "command", Comment = null, Func = (args, caller) => { if (caller.Type.In(CallerType.Client)) { IServerUser user = (IServerUser)caller; string command = args.GetString("command"); if (!string.IsNullOrWhiteSpace(command)) { this.HandleCommand(command, caller); } } return(0); } }); this.AddFunction(new Function() { Name = "heartbeat", Func = (args, caller) => { return(0); } }); this.AddCommand(new Function() { Name = "plugin-unload", Comment = "Unload plugin", Func = (args, caller) => { string name = args.GetString("0"); if (name.IsNullOrWhiteSpace()) { caller.Logger.Info($"Missing parameter: [pluginName]"); return(-1); } var plugin = this.pluginList.FirstOrDefault(x => x.Key == name).Value; if (plugin == null) { caller.Logger.Info($"Plugin cannot be found: {name}"); return(-1); } string pluginName = plugin.Name; if (plugin.UnLoadable) { plugin.Config.Enabled = false; SavePluginConfig(plugin); if (UnLoadPlugin(plugin)) { caller.Logger.Info($"Plugin unload successfully: {pluginName}"); this.pluginList.Remove(pluginName); } else { caller.Logger.Error($"Plugin unload failed: {pluginName}!"); } } else { this.Logger.Error($"Plugin cannot be unloaded: {pluginName}"); } return(0); } }); this.AddCommand(new Function() { Name = "plugin-load", Comment = "Load plugin", Func = (args, caller) => { string name = args.GetString("0"); if (name.IsNullOrWhiteSpace()) { caller.Logger.Info($"Missing parameter: [pluginName]"); return(-1); } FileInfo file = new FileInfo(Path.Combine(GetFolderPath(FolderPath.Plugin), name)); if (file.Exists) { return(this.LoadPlugin(file.FullName, true) ? 0 : -1); } else { this.Logger.Error($"Plugin cannot be found: {name}"); return(-1); } } }); this.AddCommand(new Function() { Name = "plugin-list", Comment = "Show plugin list", Func = (args, caller) => { DirectoryInfo folderPlugin = new DirectoryInfo(GetFolderPath(FolderPath.Plugin)); var list = new List <string>(); foreach (DirectoryInfo folder in folderPlugin.GetDirectories()) { foreach (FileInfo file in folder.GetFiles(PATTERN_DLL)) { if (PluginLoader.TryGetPluginName(file.FullName, out string name)) { var plugin = this.pluginList.FirstOrDefault(x => x.Value.AssemblyPath == file.FullName).Value; list.Add($"{file.Directory.Name}{Path.DirectorySeparatorChar}{file.Name} (Name: {name}, Status: {(plugin != null ? "Enabled" : "Disabled")})"); } } } caller.Logger.Info("- Plugin List"); caller.Logger.Info(list); return(0); } });
public void LeaveQueueCompletely(IServerUser user) { _inQueue.RemoveAll(usr => usr == user); _logger.LogDebug($"{user} left matchmaking completely"); }
public UserEventArgs(IServerUser user, IServer server) { User = user; Server = server; }
private void AddUser(IServerUser user) { _inQueue.Add(user); _joinedQueueTime[user] = _time.Elapsed.TotalMilliseconds; _logger.LogDebug($"{user} entered matchmaking"); }
/// <summary> /// Constructs an example game user /// </summary> /// <param name="serverUser"></param> public ExampleGameUser(IServerUser serverUser) : base(serverUser) { // ... }
public int GetRegisterCount(IServerUser user) { return(_inQueue.Count(usr => usr == user)); }
private void HandleMessage(object sender, TcpClient.ReceiveEventArgs e) { this.Traffic_In += e.Data.Length; TcpClient tcpClient = sender as TcpClient; #if GZIP string text = GZip.Decompress(e.Data).GetString(); #else string text = e.Data.GetString(); #endif DataReceived?.Invoke(this, new DataReceivedEventArgs(tcpClient.RemoteAddress.Address, tcpClient.RemoteAddress.Port, text)); this.Logger.Debug($"DataReceived: {tcpClient.RemoteAddress}"); try { MessageBody message = this.JsonSerialzation.Deserialize <MessageBody>(text); if (message.Flag == MessageFlag.RequestPublicKey) { this.Logger.Debug("AKA", $"客户端 : 请求公钥 - {tcpClient.RemoteAddress}"); this.SendPublicKey(tcpClient); this.Logger.Debug("AKA", $"发送 : 服务端公钥- {tcpClient.RemoteAddress}"); } else if (message.Flag == MessageFlag.RequestValidate) { this.Logger.Debug("AKA", $"客户端 : 请求签名 - {tcpClient.RemoteAddress}"); byte[] rawData = RSAHelper.Decrypt(message.Content, this.RSAKey); if (rawData != null) { this.SendSignature(rawData, tcpClient); this.Logger.Debug("AKA", $"发送 : 服务端签名 - {tcpClient.RemoteAddress}"); } else { this.RefuseSignature(tcpClient); this.Logger.Debug("AKA", $"解析数据 : 失败 - {tcpClient.RemoteAddress}"); } } else if (message.Flag == MessageFlag.SendClientPublicKey) { this.Logger.Debug("AKA", $"接受 : 客户端公钥 - {tcpClient.RemoteAddress}"); this.Logger.Debug("AKA", $"生成 : AES密钥 - {tcpClient.RemoteAddress}"); this.GenerateAndSendAESKey(message.Content, tcpClient); this.Logger.Debug("AKA", $"发送 : AES密钥 - {tcpClient.RemoteAddress}"); } else if (message.Flag == MessageFlag.Message) { if (!string.IsNullOrWhiteSpace(message.Guid) && this.AESKeyList.ContainsKey(message.Guid)) { AESKey key = this.AESKeyList[message.Guid]; CallBody call = message.Content != null?this.JsonSerialzation.Deserialize <CallBody>(AESHelper.Decrypt(message.Content, key).GetString()) : null; if (this.UserList.ContainsKey(message.Guid)) { IServerUser user = this.UserList[message.Guid]; user.RefreshHeartBeat(); this.Logger.Debug($"RefreshHeartBeat: {user.Name} / {user.Guid}"); if (call != null) { ThreadPool.QueueUserWorkItem((x) => { var tuple = x as Tuple <Server <TConfig>, CallBody, ICaller>; tuple.Item1.CallFunction(tuple.Item2.Call, tuple.Item2.Args, tuple.Item3); }, new Tuple <Server <TConfig>, CallBody, ICaller>(this, call, user)); } } else { //新登录 if (call == null) { return; } if (call.Call == "login") { this.Logger.Debug($"尝试登入 - {tcpClient.RemoteAddress.Address}"); ServerUser user = new ServerUser() { Guid = message.Guid, Server = this, Name = null, NetAddress = tcpClient.RemoteAddress, AESKey = this.AESKeyList[message.Guid] }; if (ClientPreLogin != null) { ClientPreLoginEventArgs <ServerUser> eventArgs = new ClientPreLoginEventArgs <ServerUser>(ref user, call.Args); ClientPreLogin?.Invoke(this, eventArgs); user = eventArgs.User; } if (user != null) { user._TcpClient = tcpClient; if (user.Status == UserStatus.Online) { user.LoginTime = DateTime.Now; user.SocketError += (x, y) => { this.Logger.Error("SocketError", y.Exception.Message); ForceLogout(this.UserList[y.Guid]); }; user.RefreshHeartBeat(); this.UserList.Add(user.Guid, user); Arguments args = new Arguments(); args.Put("status", true); args.Put("guid", user.Guid); args.Put("name", user.Name); user.CallFunction("login", args); ClientLogin?.Invoke(this, new ClientEventArgs <IServerUser>(user, ClientLoginStatus.Success)); this.Logger.Debug($"登入成功 - {tcpClient.RemoteAddress.Address}"); } else if (user.Status == UserStatus.Offline) { Arguments args = new Arguments(); args.Put("status", false); ClientLogin?.Invoke(this, new ClientEventArgs <IServerUser>(user, ClientLoginStatus.Fail)); user.CallFunction("login", args); this.Logger.Error($"登入失败 - {tcpClient.RemoteAddress.Address}"); } } } } } } } catch (Exception ex) { this.Logger.Error(ex.Message); } }
/// <summary> /// Creates a new game user /// </summary> /// <param name="serverUser">Server user</param> /// <returns>Game user</returns> public IGameUser CreateNewGameUser(IServerUser serverUser) => new DeathmatchGameUser(serverUser);