public Game(string userName, UsersContext db)
        {
            this.user = db.UserProfiles.Include(up => up.player)
                        .Include(up => up.player.characters)
                        .Include(up => up.player.characters.Select(c => c.characterClasses))
                        .Include(up => up.player.characters.Select(c => c.stats))
                        .Include(up => up.player.objectives)
                        .Include(up => up.player.parties)
                        .Include(up => up.player.parties.Select(c => c.characters))
                        .Include(up => up.player.parties.Select(c => c.location))
                        .Include(up => up.player.parties.Select(c => c.location).Select(t => t.eventCollection))
                        .Include(up => up.player.parties.Select(c => c.location).Select(t => t.eventCollection).Select(e => e.events))
                        .Include(up => up.player.parties.Select(c => c.location).Select(t => t.eventCollection).Select(e => e.events.Select(k => k.eventData)))
                        .Include(up => up.player.parties.Select(c => c.location).Select(t => t.eventCollection).Select(e => e.events.Select(k => k.eventData.encounter)))
                        .Include(up => up.player.parties.Select(c => c.location).Select(t => t.eventCollection).Select(e => e.events.Select(k => k.eventData.encounter.enemies)))
                        .Include(up => up.player.currentCombat)
                        .Include(up => up.player.currentCombat.pcs)
                        .Include(up => up.player.currentCombat.npcs)
                        .Include(up => up.player.currentCombat.pcs.Select(c => c.stats))
                        .Include(up => up.player.currentCombat.pcs.Select(c => c.mods))
                        .Include(up => up.player.currentCombat.pcs.Select(c => c.mods.Select(d => d.conditions)))
                        .Include(up => up.player.currentCombat.npcs.Select(c => c.stats))
                        .Include(up => up.player.currentCombat.npcs.Select(c => c.mods))
                        .Include(up => up.player.currentCombat.npcs.Select(c => c.mods.Select(d => d.conditions)))
                        .Include(up => up.player.currentCombat.combatData)
                        .Include(up => up.player.currentCombat.combatData.cooldowns)
                        .FirstOrDefault(u => u.UserName.ToLower() == userName);
            this.player       = user.player;
            this.userName     = userName;
            this.db           = db;
            this.messageQueue = new List <ClientMessage>();

            this.rng = new GameRNG();

            //Initialize player stuff if they have no value
            if (player.objectives == null)
            {
                player.objectives = new List <PlayerObjectiveModel>();
            }

            MapDataClasses.MapDataManager.setFunctions(() =>
            {
                List <string> characters = new List <string>();
                foreach (CharacterModel cm in this.player.characters)
                {
                    characters.Add(cm.name);
                }
                return(characters);
            }, () =>
            {
                List <string> classes = PlayerDataManager.getClasses(player);
                return(classes);
            }, (int start, int end) =>
            {
                return(this.rng.getNumber(start, end));
            }, (string name) =>
            {
                return(DungeonUnlockedDirector.isDungeonUnlocked(name, player));
            }
                                                       );

            currentMap = player.getActiveParty().location;
            if (currentMap == null)
            {
                currentMap = MapDataClasses.MapDataManager.createMap(this.player.rootMap);
                this.player.getActiveParty().location = currentMap;
                ObjectiveDirector.markCompletedObjectives(this.player);
            }
            else
            {
                MapDataClasses.MapDataManager.setupMapModel(currentMap);
                this.player.getActiveParty().location = currentMap;
                ObjectiveDirector.markCompletedObjectives(this.player);
            }

            foreach (CharacterModel cm in this.player.characters)
            {
                PlayerModels.StatCalculations.StatCalculator.updateCharacterStats(cm);
            }

            this.combatCountdown = rng.getNumber(MapDataClasses.MapDataManager.getMinCombatCount(player.rootMap), MapDataClasses.MapDataManager.getMaxCombatCount(player.rootMap));

            combatDirector = new CombatDataClasses.CombatDirector(this.player,
                                                                  currentMap.name,
                                                                  () =>
            {
                return(rng.getNumber(1, MapDataClasses.MapDataManager.getRandomEncounterCount(currentMap.name)));
            },
                                                                  () =>
            {
                return(rng.calculateIntiative());
            },
                                                                  () =>
            {
                setMap(MapDataClasses.MapDataManager.getHubMap(player.rootMap), true);
                this.player.getActiveParty().location = currentMap;
                this.combatCountdown = rng.getNumber(MapDataClasses.MapDataManager.getMinCombatCount(player.rootMap), MapDataClasses.MapDataManager.getMaxCombatCount(player.rootMap));
                currentMap           = MapDataClasses.MapDataManager.createMap(player.rootMap);
                ObjectiveDirector.markCompletedObjectives(this.player);
                player.rootX = currentMap.startX;
                player.rootY = currentMap.startY;
            },
                                                                  () =>
            {
                db.SaveChanges();
            },
                                                                  (CombatEndType combatEndType) =>
            {
                if (player.currentCombat != null)
                {
                    foreach (PartyModel pm in player.parties)
                    {
                        if (pm.uniq == player.activeParty)
                        {
                            foreach (PartyCharacterModel pcm in pm.characters)
                            {
                                foreach (PlayerModels.CombatDataModels.CombatCharacterModel ccm in player.currentCombat.pcs)
                                {
                                    if (pcm.characterUniq == ccm.characterUniq)
                                    {
                                        pcm.hp = ccm.stats.hp;
                                        pcm.mp = ccm.stats.mp;
                                    }
                                }
                            }
                        }
                    }
                }

                player.currentCombat = null;

                if (player.getActiveParty() != null)
                {
                    MapDataClasses.MapEventModel currentEvent = player.getActiveParty().location.activeEvent;
                    if (currentEvent != null && currentEvent.eventData.type == MapDataClasses.EventClasses.EventDataType.Combat && combatEndType == CombatEndType.Victory)
                    {
                        if (currentEvent.eventData.nextEvent == null)
                        {
                            PlayerDataManager.processEvent(currentEvent, this.player, ref messageQueue);
                        }
                        else
                        {
                            messageQueue.Add(new ClientMessage()
                            {
                                type = ClientMessage.ClientMessageType.ExecuteEvent
                            });
                            currentEvent.eventData = currentEvent.eventData.nextEvent;
                            player.getActiveParty().location.activeEvent = currentEvent;
                        }
                    }
                }

                db.SaveChanges();
            }
                                                                  );
        }
        public Game(string userName, UsersContext db)
        {
            this.user = db.UserProfiles.Include(up => up.player)
                    .Include(up => up.player.characters)
                    .Include(up => up.player.characters.Select(c => c.characterClasses))
                    .Include(up => up.player.characters.Select(c => c.stats))
                    .Include(up => up.player.objectives)
                    .Include(up => up.player.parties)
                    .Include(up => up.player.parties.Select(c => c.characters))
                    .Include(up => up.player.parties.Select(c => c.location))
                    .Include(up => up.player.parties.Select(c => c.location).Select(t => t.eventCollection))
                    .Include(up => up.player.parties.Select(c => c.location).Select(t => t.eventCollection).Select(e => e.events))
                    .Include(up => up.player.parties.Select(c => c.location).Select(t => t.eventCollection).Select(e => e.events.Select(k => k.eventData)))
                    .Include(up => up.player.parties.Select(c => c.location).Select(t => t.eventCollection).Select(e => e.events.Select(k => k.eventData.encounter)))
                    .Include(up => up.player.parties.Select(c => c.location).Select(t => t.eventCollection).Select(e => e.events.Select(k => k.eventData.encounter.enemies)))
                    .Include(up => up.player.currentCombat)
                    .Include(up => up.player.currentCombat.pcs)
                    .Include(up => up.player.currentCombat.npcs)
                    .Include(up => up.player.currentCombat.pcs.Select(c => c.stats))
                    .Include(up => up.player.currentCombat.pcs.Select(c => c.mods))
                    .Include(up => up.player.currentCombat.pcs.Select(c => c.mods.Select(d => d.conditions)))
                    .Include(up => up.player.currentCombat.npcs.Select(c => c.stats))
                    .Include(up => up.player.currentCombat.npcs.Select(c => c.mods))
                    .Include(up => up.player.currentCombat.npcs.Select(c => c.mods.Select(d => d.conditions)))
                    .Include(up => up.player.currentCombat.combatData)
                    .Include(up => up.player.currentCombat.combatData.cooldowns)
                    .FirstOrDefault(u => u.UserName.ToLower() == userName);
            this.player = user.player;
            this.userName = userName;
            this.db = db;
            this.messageQueue = new List<ClientMessage>();

            this.rng = new GameRNG();

            //Initialize player stuff if they have no value
            if (player.objectives == null)
            {
                player.objectives = new List<PlayerObjectiveModel>();
            }

            MapDataClasses.MapDataManager.setFunctions(() =>
            {
                List<string> characters = new List<string>();
                foreach (CharacterModel cm in this.player.characters)
                {
                    characters.Add(cm.name);
                }
                return characters;
            }, () =>
            {
                List<string> classes = PlayerDataManager.getClasses(player);
                return classes;
            }, (int start, int end) =>
            {
                return this.rng.getNumber(start, end);
            }, (string name) =>
                {
                    return DungeonUnlockedDirector.isDungeonUnlocked(name, player);
                }
            );

            currentMap = player.getActiveParty().location;
            if (currentMap == null)
            {
                currentMap = MapDataClasses.MapDataManager.createMap(this.player.rootMap);
                this.player.getActiveParty().location = currentMap;
                ObjectiveDirector.markCompletedObjectives(this.player);
            }
            else
            {
                MapDataClasses.MapDataManager.setupMapModel(currentMap);
                this.player.getActiveParty().location = currentMap;
                ObjectiveDirector.markCompletedObjectives(this.player);
            }

            foreach (CharacterModel cm in this.player.characters)
            {
                PlayerModels.StatCalculations.StatCalculator.updateCharacterStats(cm);
            }

            this.combatCountdown = rng.getNumber(MapDataClasses.MapDataManager.getMinCombatCount(player.rootMap), MapDataClasses.MapDataManager.getMaxCombatCount(player.rootMap));

            combatDirector = new CombatDataClasses.CombatDirector(this.player,
                currentMap.name,
                () =>
                {
                    return rng.getNumber(1, MapDataClasses.MapDataManager.getRandomEncounterCount(currentMap.name));
                },
                () =>
                {
                    return rng.calculateIntiative();
                },
                () =>
                {
                    setMap(MapDataClasses.MapDataManager.getHubMap(player.rootMap), true);
                    this.player.getActiveParty().location = currentMap;
                    this.combatCountdown = rng.getNumber(MapDataClasses.MapDataManager.getMinCombatCount(player.rootMap), MapDataClasses.MapDataManager.getMaxCombatCount(player.rootMap));
                    currentMap = MapDataClasses.MapDataManager.createMap(player.rootMap);
                    ObjectiveDirector.markCompletedObjectives(this.player);
                    player.rootX = currentMap.startX;
                    player.rootY = currentMap.startY;
                },
                () =>
                {
                    db.SaveChanges();
                },
                (CombatEndType combatEndType) =>
                {
                    if (player.currentCombat != null)
                    {
                        foreach (PartyModel pm in player.parties)
                        {
                            if (pm.uniq == player.activeParty)
                            {
                                foreach (PartyCharacterModel pcm in pm.characters)
                                {
                                    foreach (PlayerModels.CombatDataModels.CombatCharacterModel ccm in player.currentCombat.pcs)
                                    {
                                        if (pcm.characterUniq == ccm.characterUniq)
                                        {
                                            pcm.hp = ccm.stats.hp;
                                            pcm.mp = ccm.stats.mp;
                                        }
                                    }
                                }
                            }
                        }
                    }

                    player.currentCombat = null;

                    if (player.getActiveParty() != null)
                    {
                        MapDataClasses.MapEventModel currentEvent = player.getActiveParty().location.activeEvent;
                        if (currentEvent != null && currentEvent.eventData.type == MapDataClasses.EventClasses.EventDataType.Combat && combatEndType == CombatEndType.Victory)
                        {
                            if (currentEvent.eventData.nextEvent == null)
                            {
                                PlayerDataManager.processEvent(currentEvent, this.player, ref messageQueue);
                            }
                            else
                            {
                                messageQueue.Add(new ClientMessage() { type = ClientMessage.ClientMessageType.ExecuteEvent });
                                currentEvent.eventData = currentEvent.eventData.nextEvent;
                                player.getActiveParty().location.activeEvent = currentEvent;
                            }

                        }
                    }

                    db.SaveChanges();
                }
                );
        }