/// <summary> /// Expects operation EnterWorld and creates a new MmoActor with a new Item as avatar and a new MmoClientInterestArea. /// </summary> /// <remarks> /// The MmoActor becomes the new Peer.CurrentOperationHandler. /// If another MmoActor with the same name exists he is disconnected. /// An OperationResponse with error code ReturnCode.Ok is published on success. /// </remarks> public OperationResponse OperationEnterWorld(PeerBase peer, OperationRequest request, SendParameters sendParameters) { var operation = new EnterWorld(peer.Protocol, request); if (!operation.IsValid) { return new OperationResponse(request.OperationCode) { ReturnCode = (int)ReturnCode.InvalidOperationParameter, DebugMessage = operation.GetErrorMessage() }; } World world; if (WorldCache.Instance.TryGet(operation.WorldName, out world) == false) { return operation.GetOperationResponse((int)ReturnCode.WorldNotFound, "WorldNotFound"); } var interestArea = new ClientInterestArea(peer, operation.InterestAreaId, world) { ViewDistanceEnter = operation.ViewDistanceEnter, ViewDistanceExit = operation.ViewDistanceExit }; var actor = new MmoActorOperationHandler(peer, world, interestArea); var avatar = new Item(operation.Position, operation.Rotation, operation.Properties, actor, operation.Username, (byte)ItemType.Avatar, world); while (world.ItemCache.AddItem(avatar) == false) { Item otherAvatarItem; if (world.ItemCache.TryGetItem(avatar.Id, out otherAvatarItem)) { avatar.Dispose(); actor.Dispose(); interestArea.Dispose(); (((Item)otherAvatarItem).Owner).DisconnectByOtherPeer(this.peer, request, sendParameters); // request continued later, no response here return null; } } // init avatar actor.AddItem(avatar); actor.Avatar = avatar; ((Peer)peer).SetCurrentOperationHandler(actor); // set return values var responseObject = new EnterWorldResponse { BoundingBox = world.Area, TileDimensions = world.TileDimensions, WorldName = world.Name }; // send response; use item channel to ensure that this event arrives before any move or subscribe events var response = new OperationResponse(request.OperationCode, responseObject); sendParameters.ChannelId = Settings.ItemEventChannel; peer.SendOperationResponse(response, sendParameters); lock (interestArea.SyncRoot) { interestArea.AttachToItem(avatar); interestArea.UpdateInterestManagement(); } avatar.Spawn(operation.Position); world.Radar.AddItem(avatar, operation.Position); // response already sent return null; }
/// <summary> /// Expects operation EnterWorld and creates a new MmoActor with a new Item as avatar and a new MmoClientInterestArea. /// </summary> /// <remarks> /// The MmoActor becomes the new Peer.CurrentOperationHandler. /// If another MmoActor with the same name exists he is disconnected. /// An OperationResponse with error code ReturnCode.Ok is published on success. /// </remarks> public OperationResponse OperationEnterWorld(PeerBase peer, OperationRequest request, SendParameters sendParameters) { var operation = new EnterWorld(peer.Protocol, request); if (!operation.IsValid) { return(new OperationResponse(request.OperationCode) { ReturnCode = (int)ReturnCode.InvalidOperationParameter, DebugMessage = operation.GetErrorMessage() }); } World world; if (WorldCache.Instance.TryGet(operation.WorldName, out world) == false) { return(operation.GetOperationResponse((int)ReturnCode.WorldNotFound, "WorldNotFound")); } var interestArea = new ClientInterestArea(peer, operation.InterestAreaId, world) { ViewDistanceEnter = operation.ViewDistanceEnter, ViewDistanceExit = operation.ViewDistanceExit }; var actor = new MmoActorOperationHandler(peer, world, interestArea); var avatar = new Item(operation.Position, operation.Rotation, operation.Properties, actor, operation.Username, (byte)ItemType.Avatar, world); while (world.ItemCache.AddItem(avatar) == false) { Item otherAvatarItem; if (world.ItemCache.TryGetItem(avatar.Id, out otherAvatarItem)) { avatar.Dispose(); actor.Dispose(); interestArea.Dispose(); (((Item)otherAvatarItem).Owner).DisconnectByOtherPeer(this.peer, request, sendParameters); // request continued later, no response here return(null); } } // init avatar actor.AddItem(avatar); actor.Avatar = avatar; ((Peer)peer).SetCurrentOperationHandler(actor); // set return values var responseObject = new EnterWorldResponse { BoundingBox = world.Area, TileDimensions = world.TileDimensions, WorldName = world.Name }; // send response; use item channel to ensure that this event arrives before any move or subscribe events var response = new OperationResponse(request.OperationCode, responseObject); sendParameters.ChannelId = Settings.ItemEventChannel; peer.SendOperationResponse(response, sendParameters); lock (interestArea.SyncRoot) { interestArea.AttachToItem(avatar); interestArea.UpdateInterestManagement(); } avatar.Spawn(operation.Position); world.Radar.AddItem(avatar, operation.Position); // response already sent return(null); }