internal IPromise <Nothing> ExpelPlayer(PlayerHandle player, UserRoom userRoom, TimeSpan duration) { lock (this.server) { this.expelRecordsFor(player.User.Id).Add(new ExpelRecord { UserId = player.User.Id, UserRoom = userRoom, UntilDate = DateTime.Now + duration, }); } lock (this.server) { if (player.CurrentLobby != null && player.CurrentLobby.Identifier == userRoom.Identifier) { var lobby = player.CurrentLobby; player.CurrentLobby = null; lobby.RemovePlayer(player); return(this.lobbyService.NotifyLobbyAboutLeavingPlayer(player, lobby) .Then((a) => player.Stream.Write(Responses.UserRoomClosed(userRoom)))); } else { Log.Debug("Player {name} is not currently in the target lobby ({identifier}), only timer added", player.Digest, userRoom.Identifier); } } return(Nothing.Resolved()); }
internal IPromise <Nothing> ErrorAlert(ErrorException exception) { var loginServer = DI.Get <LoginServerListener>(); if (this.Token != null && loginServer.HasClient(this.Token)) { try { var message = String.Format(Strings.DISCONNECTING_ON_TIMEOUT_LONG, exception.PlayerMessage, exception.Message); return(loginServer.Emit(this.Token, "alert", message)); } catch (LoginServerListener.NotFoundException) { } } if (this.Stream != null) { var message = String.Format(Strings.DISCONNECTING_ON_TIMEOUT_SHORT, exception.PlayerMessage); return(this.Stream.Write(Responses.MakeshiftAlert(message))); } Log.Error("Failed to alert player {player} ({hash}/{endpoint}) about exception error {exception}", this.Name, this.Stream != null ? this.Stream.ConnectionHash : 0, this.Stream != null ? this.Stream.ConnectionEndpoint : null, exception); return(Nothing.Resolved()); }
internal IPromise <Nothing> Listen() { return(new CIO.CIOListener("CoreServer") .Bind(this.config.ChatServerAddress, this.config.ChatServerPort) .Incoming() .Map(connection => this.coreServer.ConnectPlayer(connection)) .Map(player => player.Stream.Stream() .Map(ev => this.coreServer.ProcessMessage(player, ev)) .Then(_ => { Log.Information("Input stream of {player} finished", player.Digest); }) .Catch(ex => { if (player.Stream.IsConnectionAlive) { Log.Warning("Input stream of {player} rejected and is being terminated due to unhandled exception: {exception}", player.Digest, ex); } else { Log.Debug("Input stream of {player} ended on rejected state ({ex}), already terminated.", player.Digest, ex.Message); } }) .Then(() => { if (player.Stream.IsConnectionAlive) { Log.Debug("Terminating connection of {player}", player.Digest); this.coreServer.PlayerLoggedOff(player); player.Stream.Terminate(); } }) ).Then(a => Nothing.Resolved())); }
internal IPromise <Nothing> Dispatch(PlayerHandle client, Message eventMsg) { ARequest request = ARequest.Parse(client, this.server, eventMsg); if (request == null) { Log.Warning("Failed to parse request from {name}/{hash}/{address}: {msg_name} \"{msg_data}\"", client.Name, client.Stream.ConnectionHash, client.Stream.ConnectionEndpoint, eventMsg.name, eventMsg.DebugDescription()); return(Nothing.Resolved()); } if (!request.Validate(client, this.server)) { Log.Warning("Failed to validate request from {name}/{hash}/{address}: {msg_name} \"{msg_data}\"", client.Name, client.Stream.ConnectionHash, client.Stream.ConnectionEndpoint, eventMsg.name, eventMsg.DebugDescription()); return(Nothing.Resolved()); } Log.Verbose("<= {player}@{lobby} {event_description}", client.Digest, client.CurrentLobbyIdentifier, request.DebugDescription()); return(request.Process(client, this.server)); }
internal IPromise <Nothing> QueueMessage(PlayerHandle sender, string recipientName, string messageText) { try { Log.Debug("Offline message queue: from {sender} to {recipientName}", sender.Digest, recipientName); var recipient = this.characterService.Find(recipientName); var dateString = DateTime.Now.ToShortDateString(); var timeString = DateTime.Now.ToShortTimeString(); var message = new OfflineMessage { SenderId = sender.Id, RecepientId = recipient.Id, Message = String.Format("{0} {1}: {2}", dateString, timeString, messageText), }; this.db.Write((c) => c.OfflineMessageInsert(message)); return(sender.Stream.Write(Responses.ServerPrivateChatMessage( recipient.Name, recipient.Id, Strings.PLAYER_IS_OFFLINE_MESSAGES_WILL_BE_DELIVERED ))); } catch (Database.NotFoundException) { Log.Warning("Failed to queue offline message from {sender} - {recipientName} not found!", sender.Digest, recipientName); return(Nothing.Resolved()); } }
internal override IPromise <Nothing> Dispatch(PlayerHandle sender, CommandDomain domain, string tag, IEnumerable <string> arguments) { if (domain.IsWorld && (!this.manager.CheckWorldMessagePermission(sender) || !this.lobbyService.CheckSlowmodeTimerInWorld(sender))) { return(Nothing.Resolved()); } if (domain.IsLocal && sender.CurrentLobby != null && !this.lobbyService.CheckSlowmodeTimer(sender.CurrentLobby, sender)) { return(Nothing.Resolved()); } var contents = tag + " " + String.Join(" ", arguments); var messageToSend = ""; var components = contents.Split(new char[] { '\\', '/', ';' }).Select(s => s.Trim()).Where(s => s.Any()); var selfSufficient = contents.StartsWith("/me") && components.Count() == 1; foreach (var substring in components) { if (substring.StartsWith("me")) { messageToSend += substring.Substring(2); } else if (substring.StartsWith("я")) { messageToSend += substring.Substring(1); } else { messageToSend += String.Format(" \"{0}\"", substring); } } messageToSend = messageToSend.Trim(); var text = String.Format("{0}/me {1}", domain.Identifier, messageToSend); var commands = domain.Recipients.Select(r => r.Stream.Write(Responses.Message(sender, text))).ToList(); if (!selfSufficient) { if (domain.IsPrivate) { if (domain.Recipients.Count() > 0) { var recipient = domain.Recipients.First(); var selfText = String.Format("{0}/me {1} {2} {3}", domain.Identifier, this.manager.Monogram, sender.Name, messageToSend); commands.Add(sender.Stream.Write(Responses.Message(recipient, selfText))); } } else { var selfText = String.Format("{0}/me {1} {2}", domain.Identifier, sender.Name, messageToSend); commands.Add(sender.Stream.Write(Responses.ServerMessage(this.manager, selfText))); } } return(new CombinedPromise <Nothing>(commands)); }
internal IPromise <Nothing> OpenRoom(UserRoom room) { lock (this.server) { this.server.World.AddUserRoom(room); } return(Nothing.Resolved()); }
internal IPromise <Nothing> Dispatch(PlayerHandle sender, IEnumerable <PlayerHandle> recipients, ChatManager manager, string text) { if (recipients.Count() < 1) { Log.Debug("Failed to dispatch message from {sender} - no recipients", sender.Digest); return(Nothing.Resolved()); } return(sender.Stream.Write(Responses.CharacterAppearance(recipients.First()))); }
internal IPromise <Nothing> Dispatch(PlayerHandle sender, ChatManager manager, IEnumerable <PlayerHandle> recipients, string text) { var prefix = "~action2/"; var query = text.Substring(prefix.Length).Split('|'); Lobby lobby = sender.CurrentLobby; if (lobby == null) { Log.Debug("Player {player} requested radio get/set command when he wasn't in the lobby!", sender.Digest); return(Nothing.Resolved()); } var lobbyOwnerName = lobby.IsUserRoom ? lobby.UserRoom.OwnerName : lobby.Identifier.Substring(0, lobby.Identifier.Length - "_lobby".Length + 1); if (query.First() == "getRadioID") { var value = lobby.RadioURL ?? "no"; Log.Debug("Player {sender} requested radio stream of lobby {identifier}, returning {value}", sender.Digest, lobby.Identifier, value); return(sender.Stream.Write(Responses.RunRadio(manager, lobbyOwnerName, value))); } else if (query.First() == "runRadio") { var url = query.ElementAt(1).Trim(); if (lobbyOwnerName == sender.Name || sender.AdminOptions.HasFlag(AdminFlags.RoomManagement)) { Log.Debug("Player {sender} setting radio URL for lobby {identifier} to {url}", sender.Digest, lobby.Identifier, url); lobby.RadioURL = url; if (lobby.IsUserRoom) { lobby.UserRoom.RadioURL = url; } if (recipients.Count() > 0) { return(new CombinedPromise <Nothing>(recipients.Select(p => p.Stream.Write(Responses.RunRadio(manager, lobbyOwnerName, url))))); } else { return(Nothing.Resolved()); } } else { Log.Warning("Player {sender} attempted to run radio stream in lobby {identifier}, which is not his room!", sender.Digest, lobby.Identifier); return(Nothing.Resolved()); } } else { Debug.Assert(false, "invalid request"); return(Nothing.Resolved()); } }
internal IPromise <Nothing> Terminate() { try { Log.Debug("Terminating connection {hash}/{endpoint}", this.ConnectionHash, this.ConnectionEndpoint); this.socket.Shutdown(); } catch (Exception) {} return(Nothing.Resolved()); }
internal override IPromise <Nothing> Process(PlayerHandle sender, ChatManager server) { if (this.WillServicesDispatch()) { return(base.Process(sender, server)); } if (this.contents.StartsWith("~chat") && !this.lobbyService.CheckSlowmodeTimer(sender.CurrentLobby, sender)) { return(Nothing.Resolved()); } return(base.Process(sender, server)); }
internal override IPromise <Nothing> Process(PlayerHandle sender, ChatManager server) { { if (sender.CurrentLobby != null) { return(this.lobbyService.Leave(sender, sender.CurrentLobby)); } else { Log.Debug("Player {name} requested to leave the lobby with null lobby!", sender.Digest); return(Nothing.Resolved()); } } }
internal override IPromise <Nothing> Process(PlayerHandle sender, ChatManager server) { if (this.recipient != null || this.recipientName.Equals(server.Monogram) || this.WillServicesDispatch()) { return(base.Process(sender, server)); } else if (this.contents.StartsWith("~private/")) { return(this.offlineMessageService.QueueMessage(sender, this.recipientName, Send.StripCommand(this.contents))); } else { return(Nothing.Resolved()); } }
internal override IPromise <Nothing> Dispatch(PlayerHandle sender, CommandDomain domain, string tag, IEnumerable <string> arguments) { int cap = 6; if (arguments.Count() > 0) { try { cap = Convert.ToInt32(arguments.First()); } catch (FormatException) { } } if (domain.IsWorld && !this.manager.CheckWorldMessagePermission(sender)) { return(Nothing.Resolved()); } var value = this.random.Next(cap + 1); var messages = new List <Message> { Responses.ServerMessage(this.manager, domain.Identifier + String.Format(Strings.PLAYER_ROLLED_OUT_OF, sender.Name, value, cap)) }; var promises = new List <IPromise <Nothing> >(); foreach (var msg in messages) { if (domain.IsPrivate) { if (domain.Recipients.Count() > 0) { var recipient = domain.Recipients.First(); promises.Add(sender.Stream.Write(Responses.PrivateChatMessage(recipient, String.Format(Strings.PLAYER_ROLLED_OUT_OF, sender.Name, value, cap)))); promises.Add(recipient.Stream.Write(Responses.PrivateChatMessage(sender, String.Format(Strings.PLAYER_ROLLED_OUT_OF_VERIFY, sender.Name, value, cap)))); } } else { promises.Add(sender.Stream.Write(msg)); } promises.AddRange(domain.Recipients.Select(r => r.Stream.Write(msg))); } return(new CombinedPromise <Nothing>(promises)); }
internal override IPromise<Nothing> Process(PlayerHandle sender, ChatManager server) { try { this.giftService.ChangeCurrency(sender.User, -300); this.userRoom.IsPrioritized = true; Log.Information("User {username} prioritized room {identifier}", sender.User.Username, this.userRoom.Identifier); return sender.Stream.Write(Responses.OrderOk()); } catch (GiftsService.NotEnoughCurrencyException) { Log.Warning("Failed to prioritize {identifier} room - not enough currency on {user}", this.userRoom.Identifier, sender.User.Username); } return Nothing.Resolved(); }
internal IPromise <Nothing> NotifyLobbyAboutLeavingPlayer(PlayerHandle player, Lobby lobby) { PlayerHandle[] lobbyPlayers = new PlayerHandle[] { }; lock (this.manager) { lobbyPlayers = lobby.Players.ToArray(); } if (lobbyPlayers.Count() > 0) { return(new CombinedPromise <Nothing>(lobbyPlayers.Select(b => b.Stream.Write(Responses.PlayerLeave(player))))); } else { return(Nothing.Resolved()); } }
internal override IPromise <Nothing> Dispatch(PlayerHandle sender, CommandDomain domain, string tag, IEnumerable <string> arguments) { if (arguments.Count() < 1) { return(this.dispatcher.InvalidUsage(domain)); } var name = arguments.ElementAt(0); var reason = CommandUtils.GetText(arguments.Skip(1)) ?? Strings.REASON_NONE; if (name.Equals("\\all")) { List <PlayerHandle> players; lock (this.manager) { players = new List <PlayerHandle>(this.manager.World.Players); } foreach (var handle in players) { try { this.manager.Sink(this.manager.KickPlayer(handle, reason)); } catch (Exception e) { Log.Warning("Failed to kick player during kick-all: {exception}", e); } } return(Nothing.Resolved()); } else { PlayerHandle player = CommandUtils.GetPlayer(arguments.FirstOrDefault() ?? ".", domain, this.manager); if (player == null) { return(this.dispatcher.Error(domain, Strings.PLAYER_NOT_FOUND, arguments.First())); } return(this.manager.KickPlayer(player, reason) .Then(a => this.dispatcher.Output(domain, Strings.PLAYER_HAS_BEEN_KICKED, arguments.First()))); } }
internal override IPromise <Nothing> Process(PlayerHandle sender, ChatManager server) { if (this.WillServicesDispatch()) { return(base.Process(sender, server)); } if (!this.lobbyService.CheckSlowmodeTimerInWorld(sender)) { return(Nothing.Resolved()); } if (!server.CheckWorldMessagePermission(sender)) { return(Nothing.Resolved()); } return(base.Process(sender, server)); }
internal override IPromise <Nothing> Process(PlayerHandle sender, ChatManager server) { sender.Name = this.name; sender.Id = this.id; sender.Sex = this.sex; sender.IsLoggedIn = true; sender.Character = this.character; sender.User = this.user; sender.AdminOptions = new PlayerHandle.AdminOptionsConfiguration(this.user.AdminFlags); sender.Token = this.token; this.loginServer.AssociateCharacter(this.token, this.character); lock (server) { server.PlayerLoggedIn(sender); } return(Nothing.Resolved()); }
internal IPromise <Nothing> CloseRoom(UserRoom room) { PlayerHandle[] lobbyPlayers = new PlayerHandle[] { }; lock (this.server) { var lobby = this.server.World.FindLobby(room.Identifier); if (lobby != null) { lobbyPlayers = lobby.Players.ToArray(); } this.server.World.RemoveUserRoom(room.Identifier); } if (lobbyPlayers.Count() > 0) { return(new CombinedPromise <Nothing>(lobbyPlayers.Select(a => a.Stream.Write(Responses.UserRoomClosed(room))))); } else { return(Nothing.Resolved()); } }
internal override IPromise <Nothing> Process(PlayerHandle sender, ChatManager server) { var recipients = this.Recipients(sender, server); var text = Send.StripCommand(this.contents); var domain = new CommandDomain(Send.TextCommand(this.contents), sender, recipients); if (this.shellDispatcher.ShouldDispatch(text)) { return(this.shellDispatcher.Dispatch(sender, domain, text)); } else if (this.appearanceRequestService.ShouldDispatch(text)) { return(this.appearanceRequestService.Dispatch(sender, recipients, server, text)); } else if (this.roomRadioService.ShouldDispatch(text)) { return(this.roomRadioService.Dispatch(sender, server, recipients, text)); } else { var authenticationResult = this.actionsAuthenticator.Authenticate(sender, recipients.Count() == 1 ? recipients.First() : null, this.contents); switch (authenticationResult) { case ChatActionsAuthenticator.AuthenticationResult.Ok: return(new CombinedPromise <Nothing>(recipients.Select((r) => r.Stream.Write(Responses.Message(sender, this.contents))))); case ChatActionsAuthenticator.AuthenticationResult.SexDisabledInRoom: return(sender.Stream.Write(Responses.ServerPrivateChatMessage(server.Monogram, 0, Strings.SEX_IS_FORBIDDEN_IN_ROOM))); case ChatActionsAuthenticator.AuthenticationResult.NotAuthenticated: case ChatActionsAuthenticator.AuthenticationResult.Ignored: default: return(Nothing.Resolved()); } } }
internal override IPromise <Nothing> Process(PlayerHandle sender, CoreServer server) { server.World.CreateLobby(this.lobbyIdentifier); return(Nothing.Resolved()); }