//user U can take cursor on shape S <=> (U doesn't have other cursors && S is free) public void HandleCursorRequest(LitePeer peer, OperationRequest operationRequest, SendParameters sendParameters) { var req = CursorRequest.Read(operationRequest.Parameters); var changes = false; if (req.doSet) { if (_doc.UserHasCursor(req.ownerId)) { return; //already holds another cursor } var sh = _doc.TryGetShape(req.shapeId); if (sh == null) { return; //no such shape } if (sh.GetCursor() != null) { return; // shape is busy } //ok, lock shape _doc.LockShape(sh, req.ownerId); changes = true; } else { //cursor remove operation is always ok var sh = _doc.TryGetShape(req.shapeId); if (sh == null) { return; //no such shape } _doc.UnlockShape(sh, req.ownerId); changes = true; } if (changes) { _room.Broadcast(peer, CursorEvent.Write(req.doSet, req.ownerId, req.shapeId, _topicId), sendParameters, (byte)DiscussionEventCode.CursorEvent, BroadcastTo.RoomAll); //include self } }
public void HandleInitialSceneLoad(LitePeer peer, OperationRequest operationRequest, SendParameters sendParameters) { //// var req = InitialSceneLoadRequest.Read(operationRequest); /// req.topicId _log.Debug("scene load request"); CleanupEmptyClusters(); //1st phase, send creation events for simple shapes (+cluster) in the scene var simpleShapes = _doc.GetShapes().Where(sh => sh.ShapeCode() != VdShapeType.ClusterLink).ToArray(); foreach (var sh in simpleShapes) { _room.PublishEventToSingle(peer, CreateShape.Write(sh.InitialOwner(), sh.Id(), sh.ShapeCode(), 400, 400, false, sh.Tag(), _topicId), sendParameters, (byte)DiscussionEventCode.CreateShapeEvent); } //2nd phase, send state update packets foreach (var sh in simpleShapes) { var st = sh.GetState(); if (st == null) { continue; } _room.PublishEventToSingle(peer, st.ToDict(), sendParameters, (byte)DiscussionEventCode.StateSyncEvent); } //3rd phase, sequence of cluster-add operations (enumerate contents of all existing clusters) var clusterShapes = _doc.GetShapes().Where(sh => sh.ShapeCode() == VdShapeType.Cluster); foreach (var clShape in clusterShapes) { var cluster = _topology.GetCluster(clShape.Id()); _log.Info("scene load, cluster updates, num badges =" + cluster.GetClusterables()); foreach (var badge in cluster.GetClusterables()) { var clustMsg = ClusterBadgeMessage.Write(badge.GetId(), _doc.TryGetShape(badge.GetId()).InitialOwner(), badge == cluster.GetClusterables().Last(), cluster.GetId(), _topicId, -1); _room.PublishEventToSingle(peer, clustMsg, sendParameters, (byte)DiscussionEventCode.ClusterBadgeEvent); } } //4rd phase, create links var linkShapes = _doc.GetShapes().Where(sh => sh.ShapeCode() == VdShapeType.ClusterLink); foreach (var lnk in linkShapes) { var edge = _topology.GetForwardEdge(lnk.Id()); var ev = LinkCreateMessage.Write(edge.curr.GetId(), edge.next.GetId(), lnk.InitialOwner(), lnk.Id(), _topicId, false, (LinkHeadType)lnk.Tag()); _room.PublishEventToSingle(peer, ev, sendParameters, (byte)DiscussionEventCode.LinkCreateEvent); //send link state update var st = lnk.GetState(); if (st != null) { _room.PublishEventToSingle(peer, st.ToDict(), sendParameters, (byte)DiscussionEventCode.StateSyncEvent); } } //5th phase, send cursor events foreach (var sh in _doc.GetShapes()) { if (sh.GetCursor() == null) { continue; //cursors are unset by default for all shapes } _room.PublishEventToSingle(peer, CursorEvent.Write(true, sh.GetCursor().OwnerId, sh.Id(), _topicId), sendParameters, (byte)DiscussionEventCode.CursorEvent); } //6th phase, send ink if (_doc.inkData != null) { _room.PublishEventToSingle(peer, InkMessage.Write(-1, _topicId, _doc.inkData), sendParameters, (byte)DiscussionEventCode.InkEvent); } //7th phase, send laser pointers foreach (var laserPointer in _doc.LaserPointers) { _room.PublishEventToSingle(peer, laserPointer.ToDict(), sendParameters, (byte)DiscussionEventCode.AttachLaserPointerEvent); } //notify client loading sequence complete _room.PublishEventToSingle(peer, null, sendParameters, (byte)DiscussionEventCode.SceneLoadingDone); }