private void Unlock(ObjectUnlockCommand unlockCommand)
        {
            if (this.state.LockOwnerId != LOCKNOOWNER && unlockCommand.LockOwnerId != LOCKNOOWNER && unlockCommand.LockOwnerId != this.state.LockOwnerId)
            {
                this.Log.Warning("Unlock requested from invalid owner. LockOwner {0} UnlockRequester {1}", this.state.LockOwnerId, unlockCommand.LockOwnerId);
                return;
            }

            this.UpdateStatePersistent(unlockCommand, (cmd) =>
            {
                this.ForwardToArea(new ObjectCommandEnvelope(this.state.LockOwnerId, new ObjectUnlockCommand(this.state.ObjectId, this.state.LockOwnerId), this.state.ObjectId));
            });
        }
        /// <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);
        }