public async Task CompleteMissionAsync(int missionId)
        {
            //
            // Get the mission the player is responding to.
            //

            var mission = MissionInstances.FirstOrDefault(m => m.MissionId == missionId);

            //
            // Check if the player is accepting a mission or responding to one.
            //

            if (mission == default)
            {
                var instance = new MissionInstance(GameObject as Player, missionId);

                MissionInstances.Add(instance);

                await instance.LoadAsync();

                await instance.CompleteAsync();

                return;
            }

            await mission.CompleteAsync();
        }
        public async Task LoadAsync()
        {
            await using var ctx = new UchuContext();

            var missions = await ctx.Missions.Where(
                m => m.CharacterId == GameObject.Id
                ).ToArrayAsync();

            MissionInstances = new List <MissionInstance>();

            Player player = GameObject as Player;

            foreach (var mission in missions)
            {
                var instance = new MissionInstance(player, mission.MissionId);

                MissionInstances.Add(instance);

                await instance.LoadAsync();
            }

            Listen(player.OnRespondToMission, async(MissionID, Reciever, RewardLOT) =>
            {
                await RespondToMissionAsync(MissionID, Reciever, RewardLOT);
            });
        }
        /// <summary>
        /// Loads all player missions, combining the cd client and uchu database into mission instances
        /// </summary>
        private async Task LoadAsync()
        {
            if (GameObject is Player player)
            {
                await using var uchuContext = new UchuContext();

                // On load, load all the missions from database and store them in memory
                var missions = await uchuContext.Missions.Where(
                    m => m.CharacterId == GameObject.Id
                    ).ToArrayAsync();

                foreach (var mission in missions)
                {
                    var instance = new MissionInstance(mission.MissionId, player);
                    await instance.LoadAsync(uchuContext);

                    lock (Missions)
                    {
                        Missions.Add(instance);
                    }
                }
                this._loaded = true;

                Listen(player.OnRespondToMission, async(missionId, receiver, rewardLot) =>
                {
                    await RespondToMissionAsync(missionId, receiver, rewardLot);
                });
            }
        }
        /// <summary>
        /// Creates and loads a new mission securely into the mission inventory
        /// </summary>
        /// <param name="missionId">The missionId to create a mission for</param>
        /// <param name="gameObject">The game object to assign the mission to</param>
        /// <returns>The newly created mission instance</returns>
        public async Task <MissionInstance> AddMissionAsync(int missionId, GameObject gameObject)
        {
            var mission = new MissionInstance(missionId, (Player)GameObject);
            await mission.LoadAsync();

            lock (Missions) {
                Missions.Add(mission);
            }

            return(mission);
        }
        public async Task LoadAsync()
        {
            await using var ctx = new UchuContext();

            var missions = await ctx.Missions.Where(
                m => m.CharacterId == GameObject.ObjectId
                ).ToArrayAsync();

            MissionInstances = new List <MissionInstance>();

            foreach (var mission in missions)
            {
                var instance = new MissionInstance(GameObject as Player, mission.MissionId);

                MissionInstances.Add(instance);

                await instance.LoadAsync();
            }
        }
        public async Task RespondToMissionAsync(int missionId, GameObject missionGiver, Lot rewardItem)
        {
            //
            // The player has clicked on the accept or complete button.
            //

            await using var ctx      = new UchuContext();
            await using var cdClient = new CdClientContext();

            //
            // Get the mission the player is responding to.
            //

            var mission = MissionInstances.FirstOrDefault(m => m.MissionId == missionId);

            //
            // Check if the player is accepting a mission or responding to one.
            //

            if (mission == default)
            {
                var instance = new MissionInstance(GameObject as Player, missionId);

                MissionInstances.Add(instance);

                await instance.LoadAsync();

                await instance.StartAsync();

                return;
            }

            //
            // Player is responding to an active mission.
            //

            var isComplete = await mission.IsCompleteAsync();

            if (!isComplete)
            {
                //
                // Mission is not complete.
                //

                var currentState = await mission.GetMissionStateAsync();

                await mission.UpdateMissionStateAsync(currentState);

                MessageOfferMission(missionId, missionGiver);

                return;
            }

            //
            // Complete mission.
            //

            await mission.CompleteAsync(rewardItem);

            missionGiver?.GetComponent <MissionGiverComponent>().OfferMission(GameObject as Player);
        }
        // TODO: Improve
        private async Task SearchForNewAchievementsAsync <T>(MissionTaskType type, Lot lot, Func <T, Task> progress = null) where T : MissionTaskBase
        {
            await using var cdClient = new CdClientContext();

            //
            // Collect tasks which fits the requirements of this action.
            //

            var otherTasks = new List <MissionTasks>();

            // ReSharper disable once LoopCanBeConvertedToQuery
            foreach (var missionTask in cdClient.MissionTasksTable)
            {
                if (MissionParser.GetTargets(missionTask).Contains(lot))
                {
                    otherTasks.Add(missionTask);
                }
            }

            foreach (var task in otherTasks)
            {
                var mission = await cdClient.MissionsTable.FirstOrDefaultAsync(m => m.Id == task.Id);

                if (mission == default)
                {
                    continue;
                }

                //
                // Check if mission is an achievement and has a task of the correct type.
                //

                if (mission.OfferobjectID != -1 ||
                    mission.TargetobjectID != -1 ||
                    (mission.IsMission ?? true) ||
                    task.TaskType != (int)type)
                {
                    continue;
                }

                //
                // Get the mission on the character. If present.
                //

                var characterMission = MissionInstances.FirstOrDefault(m => m.MissionId == mission.Id);

                //
                // Check if the player could passably start this achievement.
                //

                if (characterMission != default)
                {
                    continue;
                }

                //
                // Check if player has the Prerequisites to start this achievement.
                //

                var hasPrerequisites = MissionParser.CheckPrerequiredMissions(
                    mission.PrereqMissionID,
                    GetCompletedMissions()
                    );

                if (!hasPrerequisites)
                {
                    continue;
                }

                //
                // Player can start achievement.
                //

                // Get Mission Id of new achievement.
                if (mission.Id == default)
                {
                    continue;
                }

                var missionId = mission.Id.Value;

                //
                // Setup new achievement.
                //

                var instance = new MissionInstance(GameObject as Player, missionId);

                MissionInstances.Add(instance);

                await instance.LoadAsync();

                // TODO: Silent?
                await instance.StartAsync();

                var activeTask = instance.Tasks.First(t => t.TaskId == task.Uid);

                if (progress != null)
                {
                    Detach(async() =>
                    {
                        await progress(activeTask as T);
                    });
                }
            }
        }