private void ProcessCommandMessage(CliClient client, string domain, ConcurrentDictionary <ulong, MessageEntry> messages, ObjectCommandEnvelope commandEnvelope) { BaseCommand responseCommand = null; switch ((CommandType)commandEnvelope.Command.Type) { case CommandType.ObjectCreate: responseCommand = new ObjectCreateCommand(commandEnvelope.Command); break; case CommandType.ObjectUpdatePosition: responseCommand = new ObjectUpdatePositionCommand(commandEnvelope.Command); break; case CommandType.ObjectDestroy: responseCommand = new ObjectDestroyCommand(commandEnvelope.Command); break; } if (!messages.ContainsKey(commandEnvelope.ToObjectId)) { Log.WriteLine($"[{client.ClientId} ERROR: {domain} mMessage {commandEnvelope.ToObjectId} is missing"); return; } messages[commandEnvelope.ToObjectId].ResponseTimeStamp = DateTime.Now; messages[commandEnvelope.ToObjectId].ResponseCount++; byte[] responseData = commandEnvelope.Serialize(); byte[] requestData = messages[commandEnvelope.ToObjectId].CommandEnvelope.Serialize(); if (!ComparyBinary(responseData, requestData)) { Log.WriteLine($"{client.ClientId} ERROR: {domain} message {commandEnvelope.ToObjectId} invalid response"); } }
private IActorRef CreateDefaultObjectActor(TestProbe areaRegionProbe, AVector3 pos) { //setup var localShardRegionResolver = new Mock <IShardRegionResolver>(); localShardRegionResolver.Setup(m => m.GetShardRegion(ShardRegions.AREAREGION)).Returns(areaRegionProbe); var testeeRef = Sys.ActorOf(Props.Create(() => new ObjectActor(localShardRegionResolver.Object)), DEFAULTOBJECTID.ToString(CultureInfo.InvariantCulture)); Watch(testeeRef); var cmdCreate = new ObjectCreateCommand( frameTick: 0, objectId: DEFAULTOBJECTID, parentObjectId: 0, ownerId: 0, typeId: 0, targetPosition: pos, targetOrientation: new AQuaternion { X = 40.0f, Y = 50.0f, Z = 60.0f, W = 70.0f }); var cmdEnvCreate = new ObjectCommandEnvelope(0, cmdCreate, DEFAULTOBJECTID); //execute testeeRef.Tell(cmdEnvCreate); //verify areaRegionProbe.ExpectMsg <ObjectEnterAreaCommand>(); areaRegionProbe.ExpectMsg <AreaCommandEnvelope>(); return(testeeRef); }
private void NotifyNewSubscriber(IActorRef subscriber) { var createCommand = new ObjectCreateCommand(0, this.state.ObjectId, this.state.ParentObjectId, this.state.OwnerId, this.state.TypeId, this.state.WorldPosition, this.state.WorldOrientation); subscriber.Tell(this.CreateEnvelope(createCommand)); if (this.state.LockOwnerId != LOCKNOOWNER) { var lockCommand = new ObjectLockCommand(this.state.ObjectId, this.state.LockOwnerId, this.state.LockTimeout); subscriber.Tell(this.CreateEnvelope(lockCommand)); subscriber.Tell(this.CreateEnvelope(this.CreateObjectUpdatePositionCommand())); } foreach (var stateValue in this.state.ObjectStateValues) { var stateValueUpdate = new ObjectValueUpdateCommand(this.state.ObjectId, stateValue.Key, stateValue.Value.Data); subscriber.Tell(this.CreateEnvelope(stateValueUpdate)); } }
public void ActorMustNotifyAreaRegionOnCreationAndDestruction() { //setup var areRegionProbe = CreateTestProbe(); var localShardRegionResolver = new Mock <IShardRegionResolver>(); localShardRegionResolver.Setup(m => m.GetShardRegion(ShardRegions.AREAREGION)).Returns(areRegionProbe); var testeeRef = Sys.ActorOf(Props.Create(() => new ObjectActor(localShardRegionResolver.Object)), DEFAULTOBJECTID.ToString(CultureInfo.InvariantCulture)); Watch(testeeRef); var cmdCreate = new ObjectCreateCommand( frameTick: 0, objectId: DEFAULTOBJECTID, parentObjectId: 0, ownerId: 0, typeId: 0, targetPosition: new AVector3 { X = 10.0f, Y = 20.0f, Z = 30.0f, }, targetOrientation: new AQuaternion { X = 40.0f, Y = 50.0f, Z = 60.0f, W = 70.0f, }); var cmdEnvCreate = new ObjectCommandEnvelope(0, cmdCreate, DEFAULTOBJECTID); var cmdDestroy = new ObjectDestroyCommand( frameTick: 0, objectId: DEFAULTOBJECTID, targetPosition: new AVector3 { X = 10.0f, Y = 20.0f, Z = 30.0f }); var cmdEnvDestroy = new ObjectCommandEnvelope(0, cmdDestroy, DEFAULTOBJECTID); //execute testeeRef.Tell(cmdEnvCreate); //verify - object enters area areRegionProbe.ExpectMsg <ObjectEnterAreaCommand>(m => { Assert.Equal(DEFAULTOBJECTID, m.ObjectId); Assert.Equal(Locator.GetAreaIdFromWorldPosition(cmdCreate.TargetPosition), m.AreaId); }); //create reaches area subscribers areRegionProbe.ExpectMsg <AreaCommandEnvelope>(m => { Assert.Equal(Locator.GetAreaIdFromWorldPosition(cmdCreate.TargetPosition), m.ToAreaId); Assert.Equal(CommandType.ObjectCreate, m.ObjectCommandEnvelope.Command.Type); }); //execute testeeRef.Tell(cmdEnvDestroy); //verify - object leaves area areRegionProbe.ExpectMsg <ObjectLeaveAreaCommand>(m => { Assert.Equal(DEFAULTOBJECTID, m.ObjectId); Assert.Equal(Locator.GetAreaIdFromWorldPosition(cmdDestroy.TargetPosition), m.AreaId); }); //verify - destroy reaches area subscribers areRegionProbe.ExpectMsg <AreaCommandEnvelope>(m => { Assert.Equal(Locator.GetAreaIdFromWorldPosition(cmdCreate.TargetPosition), m.ToAreaId); Assert.Equal(CommandType.ObjectDestroy, m.ObjectCommandEnvelope.Command.Type); }); ExpectTerminated(testeeRef); }
/// <summary> /// Command handler. Typically validates commands against current state - possibly by communicating with other actors. /// On successful validation, one or more events are derived from command and persisted. /// </summary> /// <param name="message">Message to process.</param> /// <returns>Message is processed.</returns> protected override bool ReceiveCommand(object message) { if (message is SaveSnapshotSuccess) { this.Log.Debug("SaveSnapshotSuccess"); } if (message is SaveSnapshotFailure) { this.Log.Error("SaveSnapshotFailure"); } if (message is RequestStateCommand) { this.RespondState(((RequestStateCommand)message).ReplyTo); return(true); } if (message is ReceiveTimeout) { this.ValidateResetLock(); } if (message is QuorumRequestEnvelope) { var quorumEnvelope = message as QuorumRequestEnvelope; this.ProcessQuorumRequest(quorumEnvelope); } if (message is Terminated) { this.RemoveQuorumActor((Terminated)message); } if (message is ObjectCommandEnvelope) { var objCmd = (ObjectCommandEnvelope)message; uint senderId = objCmd.SenderId; if (this.state.LockOwnerId != 0 && this.state.LockOwnerId != senderId && IsLockProtectedCommand(objCmd.Command.Type)) { this.log.Warning($"[Object:{this.state.ObjectId}] type: {objCmd.Command.Type} invalid lock owner"); return(false); } this.ValidateResetLock(); this.state.TimeStampLastCommand = DateTime.UtcNow; switch (objCmd.Command.Type) { case CommandType.ObjectUpdatePosition: this.UpdateStatePersistent(new ObjectUpdatePositionCommand(objCmd.Command), (cmd) => this.ForwardToArea(objCmd)); break; case CommandType.ObjectValueUpdate: this.UpdateStatePersistent(new ObjectValueUpdateCommand(objCmd.Command), (cmd) => this.ForwardToArea(objCmd)); break; case CommandType.ObjectValueRemove: this.UpdateStatePersistent(new ObjectValueRemoveCommand(objCmd.Command), (cmd) => this.ForwardToArea(objCmd)); break; case CommandType.ObjectCreate: ObjectCreateCommand createCmd = new ObjectCreateCommand(objCmd.Command); this.NotifyEnterArea(senderId, Locator.GetAreaIdFromWorldPosition(this.state.WorldPosition)); this.UpdateStatePersistent(createCmd, (cmd) => this.ForwardToArea(objCmd)); break; case CommandType.ObjectDestroy: this.NotifyLeaveArea(Locator.GetAreaIdFromWorldPosition(this.state.WorldPosition)); this.ForwardToArea(objCmd); this.Self.Tell(PoisonPill.Instance); this.DeleteMessages(this.LastSequenceNr); this.DeleteSnapshots(SnapshotSelectionCriteria.Latest); break; case CommandType.ObjectLock: ObjectLockCommand lockCmd = new ObjectLockCommand(objCmd.Command); this.Lock(lockCmd); break; case CommandType.ObjectUnlock: ObjectUnlockCommand unlockCmd = new ObjectUnlockCommand(objCmd.Command); this.Unlock(unlockCmd); break; default: throw new InvalidOperationException(objCmd.Command.Type.ToString()); } return(true); } if (message is NotifySubscribeObjectExistenceCommand) { NotifySubscribeObjectExistenceCommand cmd = (NotifySubscribeObjectExistenceCommand)message; this.NotifyNewSubscriber(cmd.Subscriber); } this.SetReceiveTimeout(this.state.LockTimeout); return(true); }