/// <summary> /// Modifying messages instead of cache objects as cache objects are not meant to /// be modified locally but only as response to messages from cloud. /// </summary> /// <param name="modifyRequest"></param> public void ModifyObject(ModifyRequestMessage modifyRequest) { CloudObject cloudObject = cloudCache.GetObject(modifyRequest.ObjectFragment.ObjectId); modifyRequest.ObjectFragment.ObjectIndex = cloudObject.RemoteObjectIndex; client.Send(modifyRequest); }
public void RemoveObject(Guid objectId) { if (objects.ContainsKey(objectId)) { CloudObject cloudObject = objects[objectId]; objects.Remove(objectId); objectList.Remove(objectId); bubbleObjects[cloudObject.BubbleId].Remove(objectId); bubbleObjectGuidIndexDictionary[cloudObject.BubbleId].Remove(objectId); bubbleObjectIndexGuidDictionary[cloudObject.BubbleId].Remove(cloudObject.RemoteObjectIndex); if (bubbleObjects[cloudObject.BubbleId].Count == 0) { bubbleObjects.Remove(cloudObject.BubbleId); bubbleObjectGuidIndexDictionary.Remove(cloudObject.BubbleId); bubbleObjectIndexGuidDictionary.Remove(cloudObject.BubbleId); } objectBubbleDictionary.Remove(cloudObject.ObjectId); objectKDTree.Remove(objectId); participantObjects[objectParticipantDictionary[objectId]].Remove(objectId); if (participantObjects[objectParticipantDictionary[objectId]].Count == 0) { participantObjects.Remove(objectParticipantDictionary[objectId]); } objectParticipantDictionary.Remove(objectId); CacheObjectRemoved(cloudObject); } }
private void RequestIdentify(BubbleLink bubbleLink, CloudObject cloudObject) { Session session = bubble.GetBubbleLinkSession(bubbleLink); Guid participantId = cloudObject.OwnerId; ParticipantLink participantLink = bubble.GetParticipant(cloudObject.OwnerId); // Delegate to access participant identity string participantIdentity = CloudParticipantIdentify(participantId); IdentifyRequestMessage identifyRequest = (IdentifyRequestMessage)MessageFactory.Current.ReserveMessage(typeof(IdentifyRequestMessage)); identifyRequest.ParticipantId = participantId; identifyRequest.ParticipantIdentityType = IdentifyRequestMessage.OPEN_ID_IDENTITY; identifyRequest.ParticipantIdentity = participantIdentity; Handover handover = new Handover(); handover.Started = DateTime.Now; handover.RemoteBubbleId = bubbleLink.RemoteBubbleId; handover.ParticipantId = cloudObject.OwnerId; handover.ObjectId = cloudObject.ObjectId; handover.IdentityRequestMessageId = identifyRequest.MessageId; handovers.Add(handover); LogUtil.Info("Sent identify request from " + bubble.BubbleName + " to " + bubbleLink.RemoteBubbleName + " for " + identifyRequest.ParticipantIdentity + " (" + identifyRequest.ParticipantIdentityType + ") to be able to handover object " + cloudObject.ObjectId + "."); session.Send(identifyRequest); }
private void HandleHandoverRequest(Session session, HandoverRequestMessage handoverRequest) { BubbleLink bubbleLink = bubble.GetBubbleLink(session); LogUtil.Info("Received handover request from " + bubbleLink.RemoteBubbleName + " to " + bubble.BubbleName + " for object " + handoverRequest.ObjectFragment.ObjectId + ")."); HandoverResponseMessage handoverResponse = (HandoverResponseMessage)MessageFactory.Current.ReserveMessage(typeof(HandoverResponseMessage)); handoverResponse.RequestMessageId = handoverRequest.MessageId; // Calling delegate to allow application to reject the handover. handoverResponse.FailureCode = CloudObjectHandover(bubble, handoverRequest); if (handoverResponse.FailureCode == MxpResponseCodes.SUCCESS) { CloudObject cloudObject = bubble.CloudCache.GetObject(handoverRequest.ObjectFragment.ObjectId); if (cloudObject == null) { // Remote object does not exist in cache so creating new one. cloudObject = new CloudObject(); } else { // Object should be located in bubble requesting handover if (cloudObject.BubbleId != handoverRequest.SourceBubbleId) { handoverResponse.FailureCode = MxpResponseCodes.UNAUTHORIZED_OPERATION; session.Send(handoverResponse); return; } // Object should be owned by same participant if not then this is id collision. if (cloudObject.OwnerId != handoverRequest.ObjectFragment.OwnerId) { handoverResponse.FailureCode = MxpResponseCodes.RESERVED_ID; session.Send(handoverResponse); return; } } cloudObject.FromObjectFragment(bubble.BubbleId, handoverRequest.ObjectFragment); // Setting remove object index to 0 as it is local object now and cache will then set it equal to local index cloudObject.RemoteObjectIndex = 0; bubble.CloudCache.PutObject(cloudObject, true); } session.Send(handoverResponse); // send event }
private void OnCloudParticipantDisconnected(CloudBubble bubble, Guid participantId) { HashSet <Guid> participantObjectIds = bubble.CloudCache.GetParticipantObjectIds(participantId); List <Guid> participantObjectsToRemove = participantObjectIds.ToList <Guid>(); foreach (Guid objectId in participantObjectsToRemove) { MXP.Cloud.CloudObject cloudObject = bubble.CloudCache.GetObject(objectId); // Remove if local bubble is primary bubble. if (bubble.BubbleId == cloudObject.BubbleId) { bubble.CloudCache.RemoveObject(objectId); } } }
public void EvaluateHandoverNeed(CloudObject cloudObject) { if (cloudObject.BubbleId != bubble.BubbleId) { throw new Exception("Remote objects can not need to be handed over."); } MsdVector3f origo = new MsdVector3f(); // Evaluating if object center is inside bubble range float distanceFromCenter = MathUtil.Distance(cloudObject.Location, origo); if (distanceFromCenter < bubble.BubbleRange) { return; } foreach (Handover handover in handovers) { if (handover.ObjectId == cloudObject.ObjectId) { // Object is already in handover process. return; } } // Object is not inside bubble radius // Evaluate if there is another linked bubble where object center would be inside bubble range float shortestDistance = float.MaxValue; BubbleLink closestBubbleLink = null; foreach (BubbleLink bubbleLink in bubble.GetBubbleLinks().Values) { float distanceFromRemoteCenter = MathUtil.Distance(cloudObject.Location, bubbleLink.RemoteBubbleCenter); if (distanceFromRemoteCenter < bubble.BubbleRange && distanceFromCenter < shortestDistance) { shortestDistance = distanceFromRemoteCenter; closestBubbleLink = bubbleLink; } } if (closestBubbleLink != null) { RequestIdentify(closestBubbleLink, cloudObject); } }
private void HandleIdentifyResponse(Session session, IdentifyResponseMessage identifyResponse) { foreach (Handover handover in handovers) { if (identifyResponse.RequestMessageId == handover.IdentityRequestMessageId) { CloudObject cloudObject = bubble.CloudCache.GetObject(handover.ObjectId); if (cloudObject == null) { return; } if (cloudObject.BubbleId != bubble.BubbleId) { throw new Exception("Remote objects can not need to be handed over."); } ParticipantLink participantLink = bubble.GetParticipant(cloudObject.OwnerId); BubbleLink bubbleLink = bubble.GetBubbleLink(handover.RemoteBubbleId); LogUtil.Info("Received identify response (" + identifyResponse.FailureCode + ") from " + bubble.BubbleName + " to " + bubbleLink.RemoteBubbleName + " to be able to handover object " + handover.ObjectId + "."); if (identifyResponse.FailureCode != MxpResponseCodes.SUCCESS) { return; } HandoverRequestMessage handoverRequest = (HandoverRequestMessage)MessageFactory.Current.ReserveMessage(typeof(HandoverRequestMessage)); handoverRequest.SourceBubbleId = bubble.BubbleId; handoverRequest.TargetBubbleId = handover.RemoteBubbleId; cloudObject.ToObjectFragment(handoverRequest.ObjectFragment); handoverRequest.ObjectFragment.Location.X = cloudObject.Location.X - bubbleLink.RemoteBubbleCenter.X; handoverRequest.ObjectFragment.Location.Y = cloudObject.Location.Y - bubbleLink.RemoteBubbleCenter.Y; handoverRequest.ObjectFragment.Location.Z = cloudObject.Location.Z - bubbleLink.RemoteBubbleCenter.Z; handover.HandoverRequestMessageId = handoverRequest.MessageId; session.Send(handoverRequest); // Storing cloud object in case of rollback handover.CloudObject = cloudObject; // Removing cloud object from bubble. bubble.CloudCache.RemoveObject(cloudObject.ObjectId); return; } } }
public void Process() { // Crawling cache to remove timed out remote objects. for (int i = 0; i < cacheObjectsToCrawlPerCycle && objectList.Count > 0; i++) { lastCrawledObjectListIndex++; if (lastCrawledObjectListIndex >= objectList.Count) { lastCrawledObjectListIndex = 0; } CloudObject cloudObject = objects[objectList[lastCrawledObjectListIndex]]; if (cloudObject.LastUpdated.Add(cacheObjectLifeSpan) < DateTime.Now && cloudObject.BubbleId != localBubbleId && localBubbleId != Guid.Empty) { LogUtil.Debug("Carbage collecting object: " + cloudObject.ObjectId + " frm bubble " + localBubbleId); RemoveObject(cloudObject.ObjectId); } } }
public void OnServerMessageReceived(Message message) { if (message.GetType() == typeof(PerceptionEventMessage)) { PerceptionEventMessage perception = (PerceptionEventMessage)message; CloudObject cloudObject = cloudCache.GetObject(perception.ObjectFragment.ObjectId); if (cloudObject == null) { cloudObject = new CloudObject(); } cloudObject.FromObjectFragment(client.BubbleId, perception.ObjectFragment); cloudCache.PutObject(cloudObject, true); } if (message.GetType() == typeof(MovementEventMessage)) { MovementEventMessage movement = (MovementEventMessage)message; CloudObject cloudObject = cloudCache.GetObject(client.BubbleId, movement.ObjectIndex); if (cloudObject != null) { cloudObject.Location.X = movement.Location.X; cloudObject.Location.Y = movement.Location.Y; cloudObject.Location.Z = movement.Location.Z; cloudObject.Orientation.X = movement.Orientation.X; cloudObject.Orientation.Y = movement.Orientation.Y; cloudObject.Orientation.Z = movement.Orientation.Z; cloudObject.Orientation.W = movement.Orientation.W; cloudCache.PutObject(cloudObject, true); } } if (message.GetType() == typeof(DisappearanceEventMessage)) { DisappearanceEventMessage disappearance = (DisappearanceEventMessage)message; CloudObject cloudObject = cloudCache.GetObject(client.BubbleId, disappearance.ObjectIndex); if (cloudObject != null) { cloudCache.RemoveObject(cloudObject.ObjectId); } } if (message.GetType() == typeof(ActionEventMessage)) { ServerAction((ActionEventMessage)message); } if (message.GetType() == typeof(SynchronizationBeginEventMessage)) { ServerSynchronizationBegin((SynchronizationBeginEventMessage)message); } if (message.GetType() == typeof(SynchronizationEndEventMessage)) { ServerSynchronizationEnd((SynchronizationEndEventMessage)message); } if (message.GetType() == typeof(ListBubblesResponse)) { LinkedBubbleListReceived((ListBubblesResponse)message); } if (message.GetType() == typeof(HandoverEventMessage)) { ServerObjectHandover((HandoverEventMessage)message); } if (message.GetType() == typeof(InteractRequestMessage)) { ServerInteractRequest((InteractRequestMessage)message); } if (message.GetType() == typeof(InteractResponseMessage)) { ServerInteractResponse((InteractResponseMessage)message); } }
public void PutObject(CloudObject cloudObject, bool publicUpdate) { if (!objects.ContainsKey(cloudObject.ObjectId)) { // Assigning local cache index to the object. This will be used when object is sent to clients. cloudObject.LastUpdated = DateTime.Now; localObjectIndexCounter++; cloudObject.LocalObjectIndex = localObjectIndexCounter; if (cloudObject.RemoteObjectIndex == 0) { // For participant lets set remote object index. cloudObject.RemoteObjectIndex = localObjectIndexCounter; } objects.Add(cloudObject.ObjectId, cloudObject); objectList.Add(cloudObject.ObjectId); if (!bubbleObjects.ContainsKey(cloudObject.BubbleId)) { bubbleObjects.Add(cloudObject.BubbleId, new Dictionary <Guid, Guid>()); bubbleObjectGuidIndexDictionary.Add(cloudObject.BubbleId, new Dictionary <Guid, uint>()); bubbleObjectIndexGuidDictionary.Add(cloudObject.BubbleId, new Dictionary <uint, Guid>()); } bubbleObjects[cloudObject.BubbleId].Add(cloudObject.ObjectId, cloudObject.ObjectId); bubbleObjectGuidIndexDictionary[cloudObject.BubbleId].Add(cloudObject.ObjectId, cloudObject.RemoteObjectIndex); bubbleObjectIndexGuidDictionary[cloudObject.BubbleId].Add(cloudObject.RemoteObjectIndex, cloudObject.ObjectId); objectBubbleDictionary.Add(cloudObject.ObjectId, cloudObject.BubbleId); objectKDTree.Put(cloudObject.Location.X - cloudObject.BoundingSphereRadius, cloudObject.Location.Y - cloudObject.BoundingSphereRadius, cloudObject.Location.Z - cloudObject.BoundingSphereRadius, cloudObject.Location.X + cloudObject.BoundingSphereRadius, cloudObject.Location.Y + cloudObject.BoundingSphereRadius, cloudObject.Location.Z + cloudObject.BoundingSphereRadius, cloudObject.ObjectId ); if (!participantObjects.ContainsKey(cloudObject.OwnerId)) { participantObjects.Add(cloudObject.OwnerId, new HashSet <Guid>()); } participantObjects[cloudObject.OwnerId].Add(cloudObject.ObjectId); objectParticipantDictionary.Add(cloudObject.ObjectId, cloudObject.OwnerId); } else { if (cloudObject.RemoteObjectIndex == 0) { // For participant lets set remote object index. cloudObject.RemoteObjectIndex = cloudObject.LocalObjectIndex; } if (publicUpdate) { cloudObject.LastUpdated = DateTime.Now; } if (objects[cloudObject.ObjectId] != cloudObject) { throw new Exception("Cache must be updated with same cache object."); } // Updating changed bubble id. if (objectBubbleDictionary[cloudObject.ObjectId] != cloudObject.BubbleId) { Guid oldBubbleId = objectBubbleDictionary[cloudObject.ObjectId]; bubbleObjects[oldBubbleId].Remove(cloudObject.ObjectId); uint oldIndex = bubbleObjectGuidIndexDictionary[oldBubbleId][cloudObject.ObjectId]; bubbleObjectGuidIndexDictionary[oldBubbleId].Remove(cloudObject.ObjectId); bubbleObjectIndexGuidDictionary[oldBubbleId].Remove(oldIndex); if (bubbleObjects[objectBubbleDictionary[cloudObject.ObjectId]].Count == 0) { bubbleObjects.Remove(oldBubbleId); bubbleObjectGuidIndexDictionary.Remove(oldBubbleId); bubbleObjectIndexGuidDictionary.Remove(oldBubbleId); } if (!bubbleObjects.ContainsKey(cloudObject.BubbleId)) { bubbleObjects.Add(cloudObject.BubbleId, new Dictionary <Guid, Guid>()); bubbleObjectGuidIndexDictionary.Add(cloudObject.BubbleId, new Dictionary <Guid, uint>()); bubbleObjectIndexGuidDictionary.Add(cloudObject.BubbleId, new Dictionary <uint, Guid>()); } bubbleObjects[cloudObject.BubbleId].Add(cloudObject.ObjectId, cloudObject.ObjectId); bubbleObjectGuidIndexDictionary[cloudObject.BubbleId].Add(cloudObject.ObjectId, cloudObject.RemoteObjectIndex); bubbleObjectIndexGuidDictionary[cloudObject.BubbleId].Add(cloudObject.RemoteObjectIndex, cloudObject.ObjectId); objectBubbleDictionary[cloudObject.ObjectId] = cloudObject.BubbleId; } // Updating changed object index. if (bubbleObjectGuidIndexDictionary[cloudObject.BubbleId][cloudObject.ObjectId] != cloudObject.RemoteObjectIndex) { uint oldRemoteIndex = bubbleObjectGuidIndexDictionary[cloudObject.BubbleId][cloudObject.ObjectId]; bubbleObjectIndexGuidDictionary[cloudObject.BubbleId].Remove(oldRemoteIndex); bubbleObjectGuidIndexDictionary[cloudObject.BubbleId][cloudObject.ObjectId] = cloudObject.RemoteObjectIndex; bubbleObjectIndexGuidDictionary[cloudObject.BubbleId].Add(cloudObject.RemoteObjectIndex, cloudObject.ObjectId); } objectKDTree.Put(cloudObject.Location.X - cloudObject.BoundingSphereRadius, cloudObject.Location.Y - cloudObject.BoundingSphereRadius, cloudObject.Location.Z - cloudObject.BoundingSphereRadius, cloudObject.Location.X + cloudObject.BoundingSphereRadius, cloudObject.Location.Y + cloudObject.BoundingSphereRadius, cloudObject.Location.Z + cloudObject.BoundingSphereRadius, cloudObject.ObjectId ); // Updating changed object participantId if (cloudObject.OwnerId != objectParticipantDictionary[cloudObject.ObjectId]) { participantObjects[objectParticipantDictionary[cloudObject.ObjectId]].Remove(cloudObject.ObjectId); if (participantObjects[objectParticipantDictionary[cloudObject.ObjectId]].Count == 0) { participantObjects.Remove(objectParticipantDictionary[cloudObject.ObjectId]); } if (!participantObjects.ContainsKey(cloudObject.OwnerId)) { participantObjects.Add(cloudObject.OwnerId, new HashSet <Guid>()); } participantObjects[cloudObject.OwnerId].Add(cloudObject.ObjectId); objectParticipantDictionary[cloudObject.ObjectId] = cloudObject.OwnerId; } } if (publicUpdate) { CacheObjectPut(cloudObject); } }