private async Task SavePassengersDestination(int aPlayerId, int aVesselId)
        {
            var G = await Request_GlobalStructure_List();

            var P = await Request_Player_Info(aPlayerId.ToId());

            var PilotVessel = G.globalStructures
                              .Select(GPL => GPL.Value?
                                      .FirstOrDefault(S => (S.pilotId == P.entityId && aVesselId == 0) ||
                                                      ((S.factionId == P.factionId || P.permission >= (int)PermissionType.Moderator) && S.id == aVesselId)))
                              .Where(S => S.Value.id != 0)
                              .Select(S => S.Value)
                              .FirstOrDefault();

            if (PilotVessel.id == 0)
            {
                Log($"{P.playerName}({P.entityId}): Not pilot of a vessel!");
                AlertPlayer(P.entityId, $"Not pilot of a vessel! Wait a minute or use '/pass [VesselID]'");
            }
            else
            {
                PassengersDB.AddPassenderDestination(G, PilotVessel.id, P);
                PassengersDB.Configuration.Save();
                Log($"{P.playerName}({P.entityId}): Passenger set to '{PilotVessel.name}' ({PilotVessel.id})");
                await ShowDialog(aPlayerId, P, "Passengers", $"\nPassenger set to '{PilotVessel.name}' ({PilotVessel.id})");
            }
        }
        private async Task ListTeleporterRoutes(int aPlayerId, int aStructureId)
        {
            var G = await Request_GlobalStructure_List();

            var P = await Request_Player_Info(aPlayerId.ToId());

            await ShowDialog(aPlayerId, P, "Passengers", PassengersDB.List(aStructureId, P).OrderBy(T => T.PassengerName).Aggregate("\n", (S, T) => S + T.ToString(G) + "\n"));
        }
        private async Task DeletePassengers(int aPlayerId, int aSourceId)
        {
            var P = await Request_Player_Info(aPlayerId.ToId());

            var deletedCount = PassengersDB.Delete(aSourceId);

            PassengersDB.Configuration.Save();

            AlertPlayer(P.entityId, $"Delete {deletedCount} passenger from {aSourceId}");
        }
        private async Task CleanUpTeleporterRoutes(int aPlayerId)
        {
            var G = await Request_GlobalStructure_List();

            var GlobalFlatIdList     = G.globalStructures.Aggregate(new List <int>(), (L, P) => { L.AddRange(P.Value.Select(S => S.id)); return(L); });
            var TeleporterFlatIdList = PassengersDB.Configuration.Current.PassengersDestinations.Aggregate(new List <int>(), (L, P) => { L.Add(P.Destination.Id); return(L); });

            var DeleteList = TeleporterFlatIdList.Where(I => !GlobalFlatIdList.Contains(I)).Distinct();
            var DelCount   = DeleteList.Aggregate(0, (C, I) => C + PassengersDB.Delete(I));

            Log($"CleanUpPassengers: {DelCount} Structures: {DeleteList.Aggregate("", (S, I) => S + "," + I)}", LogLevel.Message);
            InformPlayer(aPlayerId, $"CleanUp: {DelCount} Passengers");

            if (DelCount > 0)
            {
                PassengersDB.Configuration.Save();
            }
        }
        private async Task <bool> ExecTeleportPlayer(GlobalStructureList aGlobalStructureList, PlayerInfo aPlayer, int aPlayerId)
        {
            var FoundDestination = PassengersDB.SearchRoute(aGlobalStructureList, aPlayer);

            if (FoundDestination == null)
            {
                Log($"EmpyrionPassenger: Exec: {aPlayer.playerName}/{aPlayer.entityId}/{aPlayer.clientId} -> no logout vessel found for", LogLevel.Message);
                return(false);
            }

            if (Math.Abs(Vector3.Distance(FoundDestination.Position, GetVector3(aPlayer.pos))) <= PassengersDB.Configuration.Current.NoTeleportNearVesselDistance)
            {
                Log($"EmpyrionPassenger: Exec: {aPlayer.playerName}/{aPlayer.entityId}/{aPlayer.clientId} -> near logout vessel pos={GetVector3(aPlayer.pos).String()} on '{aPlayer.playfield}'", LogLevel.Message);
                PassengersDB.DeletePassenger(aPlayer.entityId);
                PassengersDB.Configuration.Save();
                return(false);
            }

            Log($"EmpyrionPassenger: Exec: {aPlayer.playerName}/{aPlayer.entityId}-> {FoundDestination.Id} on '{FoundDestination.Playfield}' pos={FoundDestination.Position.String()} rot={FoundDestination.Rotation.String()}", LogLevel.Message);

            if (!PlayerLastGoodPosition.ContainsKey(aPlayer.entityId))
            {
                PlayerLastGoodPosition.Add(aPlayer.entityId, null);
            }
            PlayerLastGoodPosition[aPlayer.entityId] = new IdPlayfieldPositionRotation(aPlayer.entityId, aPlayer.playfield, aPlayer.pos, aPlayer.rot);

            Action <PlayerInfo> ActionTeleportPlayer = async(P) =>
            {
                if (FoundDestination.Playfield == P.playfield)
                {
                    try
                    {
                        await Request_Entity_Teleport(new IdPositionRotation(aPlayer.entityId, GetVector3(FoundDestination.Position), GetVector3(FoundDestination.Rotation)));
                    }
                    catch (Exception error)
                    {
                        InformPlayer(aPlayerId, $"Entity_Teleport: {error.Message}");
                    }
                }
                else
                {
                    try
                    {
                        await Request_Player_ChangePlayerfield(new IdPlayfieldPositionRotation(aPlayer.entityId, FoundDestination.Playfield, GetVector3(FoundDestination.Position), GetVector3(FoundDestination.Rotation)));
                    }
                    catch (Exception error)
                    {
                        InformPlayer(aPlayerId, $"Player_ChangePlayerfield: {error.Message}");
                    }
                }
            };

            try
            {
                await Request_Player_SetPlayerInfo(new PlayerInfoSet()
                {
                    entityId = aPlayer.entityId, health = (int)aPlayer.healthMax
                });
            }
            catch (Exception error)
            {
                InformPlayer(aPlayerId, $"Player_SetHealth: {error.Message}");
            }

            new Thread(new ThreadStart(() =>
            {
                var TryTimer = new Stopwatch();
                TryTimer.Start();
                while (TryTimer.ElapsedMilliseconds < (PassengersDB.Configuration.Current.PreparePlayerForTeleport * 1000))
                {
                    var WaitTime = PassengersDB.Configuration.Current.PreparePlayerForTeleport - (int)(TryTimer.ElapsedMilliseconds / 1000);
                    InformPlayer(aPlayerId, WaitTime > 1 ? $"Prepare for teleport in {WaitTime} sec." : $"Prepare for teleport now.");
                    if (WaitTime > 0)
                    {
                        Thread.Sleep(2000);
                    }
                }

                ActionTeleportPlayer(aPlayer);
                CheckPlayerStableTargetPos(aPlayerId, aPlayer, ActionTeleportPlayer, FoundDestination.Position);
                PassengersDB.DeletePassenger(aPlayer.entityId);
                PassengersDB.Configuration.Save();
            })).Start();

            return(true);
        }