public void ResolveMovement()
        {
            Dictionary <int, BoardSquarePathInfo> paths = new Dictionary <int, BoardSquarePathInfo>();

            foreach (ActorData actor in GameFlowData.Get().GetActors())
            {
                paths.Add(actor.ActorIndex, ResolveMovement(actor));
            }

            Dictionary <int, BoardSquarePathInfo> nodes = new Dictionary <int, BoardSquarePathInfo>(paths);
            bool finished = false;

            for (float time = 0; !finished; time += RESOLUTION_STEP)
            {
                if (!ResolveSubstep(nodes, time, out finished))
                {
                    // TODO optimize
                    time  = -RESOLUTION_STEP;
                    nodes = new Dictionary <int, BoardSquarePathInfo>(paths);
                    Log.Info("Restarting movement resolution loop");
                }
            }

            var movementActions = ArtemisServerBarrierManager.Get().OnMovement(paths);

            ArtemisServerResolutionManager.Get().SendMovementActions(movementActions);

            // TODO ClientMovementManager.MsgServerMovementStarting

            foreach (ActorData actor in GameFlowData.Get().GetActors())
            {
                BoardSquarePathInfo start = paths[actor.ActorIndex];
                BoardSquarePathInfo end   = start;
                while (end.next != null)
                {
                    end = end.next;
                }

                ActorTeamSensitiveData atsd = actor.TeamSensitiveData_authority;

                // TODO GetPathEndpoint everywhere

                // TODO movement camera bounds
                actor.MoveFromBoardSquare    = end.square;
                actor.InitialMoveStartSquare = end.square;

                atsd.CallRpcMovement(
                    GameEventManager.EventType.Invalid,
                    GridPosProp.FromGridPos(start.square.GetGridPosition()),
                    GridPosProp.FromGridPos(end.square.GetGridPosition()),
                    MovementUtils.SerializePath(start),
                    ActorData.MovementType.Normal,
                    false,
                    false);

                atsd.MovementLine?.m_positions.Clear();
            }
            Log.Info("Movement resolved");
        }