/// <summary> /// Handles a <see cref="AcquireServerResponse"/>. /// </summary> private void HandleOperationResponseAcquireServerResponse(IRpcProtocol protocol, OperationResponse operationResponse) { var response = new AcquireServerResponse(protocol, operationResponse); if (!response.IsValid || operationResponse.ReturnCode != (short)ResultCode.Ok) { #if MMO_DEBUG _logger.DebugFormat("Re-acquiring chat server connection info. ResponseValid?={0}. ReturnCode={1}.", response.IsValid, operationResponse.ReturnCode); #endif this.AcquireChatServerConnection(ServerSettings.SERVER_RECONNECT_INTERVAL); return; } Interlocked.CompareExchange(ref listenerState, (int)ListenerState.Connecting, (int)ListenerState.Disconnected); var newListenerState = ListenerState; if (newListenerState != ListenerState.Connecting) { _logger.ErrorFormat("[HandleOperationResponseAcquireServerResponse]: Invalid listener state (State={0})", newListenerState); return; } var ipAddress = IPAddress.Parse(response.Address); var port = response.TcpPort; WorldApplication.Instance.ConnectToExternalServer(new IPEndPoint(ipAddress, port), "Chat", this); }
protected override void OnDisconnect(DisconnectReason reasonCode, string reasonDetail) { this.application.MasterLobby.OnServerDisconnected(this); #if MMO_DEBUG Logger.DebugFormat("Server (Id={0}:{1}) Disconnected.", this.ServerId, this.ServerType); #endif }
protected override void Setup() { // this will let us send raw bytes Protocol.AllowRawCustomValues = true; // init the settings this.Settings = ServerConfig.Initialize(this.BinaryPath); this.MasterLobby = new Lobby(); // register custom types TypeSerializer.RegisterType(CustomTypeCode.Guid); // setup logging this.SetupLogging(); // log any unhandled exception AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException; if (Logger.IsDebugEnabled) { Logger.DebugFormat("(:> ********** <:) MasterServer Started > {0} (:> ********** <:)", DateTime.Now); } }
/// <summary> /// Publishes a <see cref = "ItemPositionMessage" /> in the <see cref = "PositionUpdateChannel" /> /// and in the current <see cref = "Region" /> if it changes /// and then updates the <see cref = "CurrentWorldRegion" />. /// </summary> public void UpdateInterestManagement() { Region newRegion = this.World.GetRegion(this.Position); // inform attached and auto subscribed (delayed) interest areas ItemPositionMessage message = this.GetPositionUpdateMessage(this.Position, newRegion); this.positionUpdateChannel.Publish(message); if (this.SetCurrentWorldRegion(newRegion)) { // inform unsubscribed interest areas in new region ItemSnapshot snapshot = this.GetItemSnapshot(); newRegion.Publish(snapshot); #if MissingSubscribeDebug if (log.IsDebugEnabled) { log.DebugFormat("{0} sent snap shot to region {1}", this.id, newRegion.Coordinate); } #endif } }
/// <summary> /// Increments <see cref = "MessageCounters.CounterReceive" /> and subscribes the <see cref = "InterestArea" /> to the <see cref = "Source" /> item if it not already subscribed or attached. /// Called by the <see cref = "InterestArea" /> when received. /// </summary> /// <param name = "interestArea"> /// The calling interest area. /// </param> public override void OnInterestAreaReceive(InterestArea interestArea) { MessageCounters.CounterReceive.Increment(); interestArea.ReceiveItemSnapshot(this); #if MissingSubscribeDebug if (log.IsDebugEnabled) { log.DebugFormat("{1} received snap shot from item {0} - region {2}", this.source.Id, interestArea.GetHashCode(), this.WorldRegion.Coordinate); } #endif }
/// <summary> /// Called by the <see cref = "Item" /> when received. /// Increments <see cref = "MessageCounters.CounterReceive" /> and publishes an <see cref = "ItemPositionMessage" /> in the <paramref name = "item" />'s <see cref = "Item.CurrentWorldRegion" />. /// </summary> /// <param name = "item"> /// The calling item. /// </param> public override void OnItemReceive(Item item) { MessageCounters.CounterReceive.Increment(); ItemSnapshot itemSnapshot = item.GetItemSnapshot(); this.source.ReceiveItemSnapshot(itemSnapshot); #if MissingSubscribeDebug if (log.IsDebugEnabled) { log.DebugFormat( "{0} sent snap shot to interest area {1} - region {2}", item.Id, this.source.GetHashCode(), itemSnapshot.WorldRegion.Coordinate); } #endif }
public MasterClientPeer(InitRequest initRequest, MasterApplication application) : base(initRequest.Protocol, initRequest.PhotonPeer) { this.application = application; this.clientId = Utils.NewGuidInt32(); this.LoginData = null; this.WorldServer = null; this.CurrentState = ClientPeerState.Connect; this.IsSafelyDisconnected = false; this.Application.MasterLobby.OnClientConnected(this); #if MMO_DEBUG if (_logger.IsDebugEnabled) { _logger.DebugFormat("Client (Id={0}) Connected", clientId); } #endif }
private GameOperationResponse HandleOperationSendChat(GameOperationRequest operationRequest) { var operation = new SendChat(server.Protocol, operationRequest); if (!operation.IsValid) { return new GameErrorResponse(operationRequest.OperationCode) { ReturnCode = (short)ResultCode.InvalidOperationParameter, DebugMessage = operation.GetErrorMessage() } } ; switch ((MessageType)operation.MessageType) { case MessageType.Group: { lock (joinedChannels) { var channel = this.joinedChannels.Find(chnl => chnl.Type == ChannelType.Group); if (channel == null) { return new SendChatResponse(operation.OperationCode) { ReturnCode = (short)ResultCode.ChannelNotAvailable, MessageType = operation.MessageType } } ; // TODO: Normalize content and prevent spam var message = operation.Message; if (string.IsNullOrEmpty(message)) { return(operation.GetErrorResponse((short)ResultCode.MessageIsEmpty)); } channel.Publish(message, this); } } break; case MessageType.Guild: { lock (joinedChannels) { var channel = this.joinedChannels.Find(chnl => chnl.Type == ChannelType.Guild); if (channel == null) { return new SendChatResponse(operation.OperationCode) { ReturnCode = (short)ResultCode.ChannelNotAvailable, MessageType = operation.MessageType } } ; // TODO: Normalize content and prevent spam var message = operation.Message; if (string.IsNullOrEmpty(message)) { return(operation.GetErrorResponse((short)ResultCode.MessageIsEmpty)); } channel.Publish(message, this); } } break; case MessageType.Local: { lock (joinedChannels) { var channel = this.joinedChannels.Find(chnl => chnl.Type == ChannelType.Local); if (channel == null) { return new SendChatResponse(operation.OperationCode) { ReturnCode = (short)ResultCode.ChannelNotAvailable, MessageType = operation.MessageType } } ; // TODO: Normalize content and prevent spam var message = operation.Message; if (string.IsNullOrEmpty(message)) { return(operation.GetErrorResponse((short)ResultCode.MessageIsEmpty)); } channel.Publish(message, this); } } break; case MessageType.Trade: { lock (joinedChannels) { var channel = this.joinedChannels.Find(chnl => chnl.Type == ChannelType.Trade); if (channel == null) { return new SendChatResponse(operation.OperationCode) { ReturnCode = (short)ResultCode.ChannelNotAvailable, MessageType = operation.MessageType } } ; // TODO: Normalize content and prevent spam var message = operation.Message; if (string.IsNullOrEmpty(message)) { return(operation.GetErrorResponse((short)ResultCode.MessageIsEmpty)); } channel.Publish(message, this); } } break; case MessageType.Tell: { var receiverName = operation.Receiver; if (string.IsNullOrEmpty(receiverName)) { return(operation.GetErrorResponse((short)ResultCode.PlayerNotFound)); } ChatSession receiver; if (!chat.SessionCache.TryGetSessionBySessionName(receiverName, out receiver)) { return(operation.GetErrorResponse((short)ResultCode.PlayerNotFound)); } // TODO: Normalize content and prevent spam var message = operation.Message; if (string.IsNullOrEmpty(message)) { return(operation.GetErrorResponse((short)ResultCode.MessageIsEmpty)); } receiver.ReceiveTell(this, message); } break; default: { #if MMO_DEBUG _logger.DebugFormat("[HandleOperationSendChat]: Session (Name={0}) sent an unhandled Message (Type={1})", name, (MessageType)operation.MessageType); #endif } break; } return(null); } /// <summary> /// Call this to handle client operation requests /// </summary> void OnOperationRequest(GameOperationRequest operationRequest, MessageParameters messageParameters) { GameOperationResponse response; switch ((GameOperationCode)operationRequest.OperationCode) { case GameOperationCode.SendChat: response = this.HandleOperationSendChat(operationRequest); break; default: response = new GameErrorResponse(operationRequest.OperationCode) { ReturnCode = (short)ResultCode.OperationNotAvailable }; break; } if (response != null) { this.SendOperationResponse(response, messageParameters); } } #endregion #region Helper Methods void DoAddSession() { // adding session to the chat while (!chat.AddSession(this)) { ChatSession exisitingSession; if (chat.SessionCache.TryGetSessionBySessionId(sessionId, out exisitingSession)) { // this shouldn't happen because the master won't let the same player login twice it will disconnect the exisitng player // we are handling it to satisfy Murphy's Law #if MMO_DEBUG _logger.DebugFormat("[DoAddSession]: ChatSession (Name={0}) cannot be added because an existing ChatSession (Name={1}) is found", this.Name, exisitingSession.Name); #endif exisitingSession.Disconnect(); this.Disconnect(); this.Destroy(DestroySessionReason.KickedByExistingSession); return; } } } #endregion }