void _ResetSave(KeyValuePair <uint, InstanceSave> pair) { // unbind all players bound to the instance // do not allow UnbindInstance to automatically unload the InstanceSaves lock_instLists = true; bool shouldDelete = true; var pList = pair.Value.m_playerList; List <Player> temp = new List <Player>(); // list of expired binds that should be unbound foreach (var player in pList) { InstanceBind bind = player.GetBoundInstance(pair.Value.GetMapId(), pair.Value.GetDifficultyID()); if (bind != null) { Cypher.Assert(bind.save == pair.Value); if (bind.perm && bind.extendState != 0) // permanent and not already expired { // actual promotion in DB already happened in caller bind.extendState = bind.extendState == BindExtensionState.Extended ? BindExtensionState.Normal : BindExtensionState.Expired; shouldDelete = false; continue; } } temp.Add(player); } var gList = pair.Value.m_groupList; while (!gList.Empty()) { Group group = gList.First(); group.UnbindInstance(pair.Value.GetMapId(), pair.Value.GetDifficultyID(), true); } if (shouldDelete) { m_instanceSaveById.Remove(pair.Key); } lock_instLists = false; }
public Map CreateInstanceForPlayer(uint mapId, Player player, uint loginInstanceId = 0) { if (GetId() != mapId || player == null) { return(null); } Map map = null; uint newInstanceId = 0; // instanceId of the resulting map if (IsBattlegroundOrArena()) { // instantiate or find existing bg map for player // the instance id is set in Battlegroundid newInstanceId = player.GetBattlegroundId(); if (newInstanceId == 0) { return(null); } map = Global.MapMgr.FindMap(mapId, newInstanceId); if (map == null) { Battleground bg = player.GetBattleground(); if (bg) { map = CreateBattleground(newInstanceId, bg); } else { player.TeleportToBGEntryPoint(); return(null); } } } else if (!IsGarrison()) { InstanceBind pBind = player.GetBoundInstance(GetId(), player.GetDifficultyID(GetEntry())); InstanceSave pSave = pBind != null ? pBind.save : null; // priority: // 1. player's permanent bind // 2. player's current instance id if this is at login // 3. group's current bind // 4. player's current bind if (pBind == null || !pBind.perm) { if (loginInstanceId != 0) // if the player has a saved instance id on login, we either use this instance or relocate him out (return null) { map = FindInstanceMap(loginInstanceId); return((map && map.GetId() == GetId()) ? map : null); // is this check necessary? or does MapInstanced only find instances of itself? } InstanceBind groupBind = null; Group group = player.GetGroup(); // use the player's difficulty setting (it may not be the same as the group's) if (group) { groupBind = group.GetBoundInstance(this); if (groupBind != null) { // solo saves should be reset when entering a group's instance player.UnbindInstance(GetId(), player.GetDifficultyID(GetEntry())); pSave = groupBind.save; } } } if (pSave != null) { // solo/perm/group newInstanceId = pSave.GetInstanceId(); map = FindInstanceMap(newInstanceId); // it is possible that the save exists but the map doesn't if (map == null) { map = CreateInstance(newInstanceId, pSave, pSave.GetDifficultyID(), player.GetTeamId()); } } else { // if no instanceId via group members or instance saves is found // the instance will be created for the first time newInstanceId = Global.MapMgr.GenerateInstanceId(); Difficulty diff = player.GetGroup() != null?player.GetGroup().GetDifficultyID(GetEntry()) : player.GetDifficultyID(GetEntry()); //Seems it is now possible, but I do not know if it should be allowed map = FindInstanceMap(newInstanceId); if (map == null) { map = CreateInstance(newInstanceId, null, diff, player.GetTeamId()); } } } else { newInstanceId = (uint)player.GetGUID().GetCounter(); map = FindInstanceMap(newInstanceId); if (!map) { map = CreateGarrison(newInstanceId, player); } } return(map); }