Core/Maps: Check group that owns instance (first group to enter a given instance id owns it)
Port From (https://github.com/TrinityCore/TrinityCore/commit/a131542855d23022714a97640be1c8d68a741c31)
This commit is contained in:
@@ -584,44 +584,27 @@ namespace Game.Entities
|
||||
|
||||
// non-instances are always valid
|
||||
Map map = GetMap();
|
||||
if (!map || !map.IsDungeon())
|
||||
InstanceMap instance = map?.ToInstanceMap();
|
||||
if (instance == null)
|
||||
return true;
|
||||
|
||||
Group group = GetGroup();
|
||||
// raid instances require the player to be in a raid group to be valid
|
||||
if (map.IsRaid() && !WorldConfig.GetBoolValue(WorldCfg.InstanceIgnoreRaid) && (map.GetEntry().Expansion() >= (Expansion)WorldConfig.GetIntValue(WorldCfg.Expansion)))
|
||||
if (!GetGroup() || !GetGroup().IsRaidGroup())
|
||||
if (group == null || group.IsRaidGroup())
|
||||
return false;
|
||||
|
||||
Group group = GetGroup();
|
||||
if (group)
|
||||
{
|
||||
// check if player's group is bound to this instance
|
||||
InstanceBind bind = group.GetBoundInstance(map.GetDifficultyID(), map.GetId());
|
||||
if (bind == null || bind.save == null || bind.save.GetInstanceId() != map.GetInstanceId())
|
||||
if (group != instance.GetOwningGroup())
|
||||
return false;
|
||||
|
||||
var players = map.GetPlayers();
|
||||
if (!players.Empty())
|
||||
foreach (var otherPlayer in players)
|
||||
{
|
||||
if (otherPlayer.IsGameMaster())
|
||||
continue;
|
||||
if (!otherPlayer.m_InstanceValid) // ignore players that currently have a homebind timer active
|
||||
continue;
|
||||
if (group != otherPlayer.GetGroup())
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// instance is invalid if we are not grouped and there are other players
|
||||
if (map.GetPlayersCountExceptGMs() > 1)
|
||||
return false;
|
||||
|
||||
// check if the player is bound to this instance
|
||||
InstanceBind bind = GetBoundInstance(map.GetId(), map.GetDifficultyID());
|
||||
if (bind == null || bind.save == null || bind.save.GetInstanceId() != map.GetInstanceId())
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
@@ -166,7 +166,9 @@ namespace Game.Groups
|
||||
|
||||
DB.Characters.Execute(stmt);
|
||||
|
||||
ConvertLeaderInstancesToGroup(leader, this, false);
|
||||
InstanceMap leaderInstance = leader.GetMap().ToInstanceMap();
|
||||
if (leaderInstance != null)
|
||||
leaderInstance.TrySetOwningGroup(this);
|
||||
|
||||
Cypher.Assert(AddMember(leader)); // If the leader can't be added to a new group because it appears full, something is clearly wrong.
|
||||
}
|
||||
@@ -691,9 +693,6 @@ namespace Game.Groups
|
||||
}
|
||||
}
|
||||
|
||||
// Copy the permanent binds from the new leader to the group
|
||||
ConvertLeaderInstancesToGroup(newLeader, this, true);
|
||||
|
||||
// Update the group leader
|
||||
stmt = DB.Characters.GetPreparedStatement(CharStatements.UPD_GROUP_LEADER);
|
||||
|
||||
@@ -721,47 +720,6 @@ namespace Game.Groups
|
||||
BroadcastPacket(groupNewLeader, true);
|
||||
}
|
||||
|
||||
public static void ConvertLeaderInstancesToGroup(Player player, Group group, bool switchLeader)
|
||||
{
|
||||
// copy all binds to the group, when changing leader it's assumed the character
|
||||
// will not have any solo binds
|
||||
foreach (var difficultyDic in player.m_boundInstances.Values)
|
||||
{
|
||||
foreach (var pair in difficultyDic)
|
||||
{
|
||||
if (!switchLeader || group.GetBoundInstance(pair.Value.save.GetDifficultyID(), pair.Key) == null)
|
||||
if (pair.Value.extendState != 0) // not expired
|
||||
group.BindToInstance(pair.Value.save, pair.Value.perm, false);
|
||||
|
||||
// permanent binds are not removed
|
||||
if (switchLeader && !pair.Value.perm)
|
||||
{
|
||||
player.UnbindInstance(pair, difficultyDic, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if group leader is in a non-raid dungeon map and nobody is actually bound to this map then the group can "take over" the instance
|
||||
// (example: two-player group disbanded by disconnect where the player reconnects within 60 seconds and the group is reformed)
|
||||
Map playerMap = player.GetMap();
|
||||
if (playerMap)
|
||||
{
|
||||
if (!switchLeader && playerMap.IsNonRaidDungeon())
|
||||
{
|
||||
InstanceSave save = Global.InstanceSaveMgr.GetInstanceSave(playerMap.GetInstanceId());
|
||||
if (save != null)
|
||||
{
|
||||
if (save.GetGroupCount() == 0 && save.GetPlayerCount() == 0)
|
||||
{
|
||||
Log.outDebug(LogFilter.Maps, "Group.ConvertLeaderInstancesToGroup: Group for player {0} is taking over unbound instance map {1} with Id {2}", player.GetName(), playerMap.GetId(), playerMap.GetInstanceId());
|
||||
// if nobody is saved to this, then the save wasn't permanent
|
||||
group.BindToInstance(save, false, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Disband(bool hideDestroy = false)
|
||||
{
|
||||
Global.ScriptMgr.OnGroupDisband(this);
|
||||
@@ -1585,45 +1543,9 @@ namespace Game.Groups
|
||||
return null;
|
||||
}
|
||||
|
||||
public InstanceBind BindToInstance(InstanceSave save, bool permanent, bool load = false)
|
||||
public void LinkOwnedInstance(GroupInstanceReference refe)
|
||||
{
|
||||
if (save == null || IsBGGroup() || IsBFGroup())
|
||||
return null;
|
||||
|
||||
if (!m_boundInstances.ContainsKey(save.GetDifficultyID()))
|
||||
m_boundInstances[save.GetDifficultyID()] = new Dictionary<uint, InstanceBind>();
|
||||
|
||||
if (!m_boundInstances[save.GetDifficultyID()].ContainsKey(save.GetMapId()))
|
||||
m_boundInstances[save.GetDifficultyID()][save.GetMapId()] = new InstanceBind();
|
||||
|
||||
InstanceBind bind = m_boundInstances[save.GetDifficultyID()][save.GetMapId()];
|
||||
if (!load && (bind.save == null || permanent != bind.perm || save != bind.save))
|
||||
{
|
||||
PreparedStatement stmt = DB.Characters.GetPreparedStatement(CharStatements.REP_GROUP_INSTANCE);
|
||||
|
||||
stmt.AddValue(0, m_dbStoreId);
|
||||
stmt.AddValue(1, save.GetInstanceId());
|
||||
stmt.AddValue(2, permanent);
|
||||
|
||||
DB.Characters.Execute(stmt);
|
||||
}
|
||||
|
||||
if (bind.save != save)
|
||||
{
|
||||
if (bind.save != null)
|
||||
bind.save.RemoveGroup(this);
|
||||
save.AddGroup(this);
|
||||
}
|
||||
|
||||
bind.save = save;
|
||||
bind.perm = permanent;
|
||||
if (!load)
|
||||
Log.outDebug(LogFilter.Maps, "Group.BindToInstance: Group ({0}, storage id: {1}) is now bound to map {2}, instance {3}, difficulty {4}",
|
||||
GetGUID().ToString(), m_dbStoreId, save.GetMapId(), save.GetInstanceId(), save.GetDifficultyID());
|
||||
|
||||
m_boundInstances[save.GetDifficultyID()][save.GetMapId()] = bind;
|
||||
|
||||
return bind;
|
||||
m_ownedInstancesMgr.InsertLast(refe);
|
||||
}
|
||||
|
||||
public void UnbindInstance(uint mapid, Difficulty difficulty, bool unload = false)
|
||||
@@ -2199,6 +2121,7 @@ namespace Game.Groups
|
||||
ObjectGuid m_masterLooterGuid;
|
||||
Dictionary<Difficulty, Dictionary<uint, InstanceBind>> m_boundInstances = new();
|
||||
Dictionary<uint, Tuple<ObjectGuid, uint>> m_recentInstances = new();
|
||||
GroupInstanceRefManager m_ownedInstancesMgr = new();
|
||||
byte[] m_subGroupsCounts;
|
||||
ObjectGuid m_guid;
|
||||
uint m_dbStoreId;
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (C) 2012-2020 CypherCore <http://github.com/CypherCore>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using Framework.Dynamic;
|
||||
using Game.Maps;
|
||||
|
||||
namespace Game.Groups
|
||||
{
|
||||
public class GroupInstanceReference : Reference<Group, InstanceMap>
|
||||
{
|
||||
~GroupInstanceReference() { Unlink(); }
|
||||
|
||||
public new GroupInstanceReference Next() { return (GroupInstanceReference)base.Next(); }
|
||||
|
||||
public override void TargetObjectBuildLink()
|
||||
{
|
||||
GetTarget().LinkOwnedInstance(this);
|
||||
}
|
||||
}
|
||||
|
||||
class GroupInstanceRefManager : RefManager<Group, InstanceMap>
|
||||
{
|
||||
public new GroupInstanceReference GetFirst() { return (GroupInstanceReference)base.GetFirst(); }
|
||||
}
|
||||
}
|
||||
+10
-1
@@ -4914,7 +4914,7 @@ namespace Game.Maps
|
||||
if (i_instanceLock != null)
|
||||
{
|
||||
MapDb2Entries entries = new(GetEntry(), GetMapDifficulty());
|
||||
if (entries.IsInstanceIdBound() || IsRaid() || entries.MapDifficulty.IsRestoringDungeonState() || !i_owningGroupRef.isValid())
|
||||
if (entries.IsInstanceIdBound() || IsRaid() || entries.MapDifficulty.IsRestoringDungeonState() || !i_owningGroupRef.IsValid())
|
||||
{
|
||||
InstanceLockData lockData = i_instanceLock.GetInstanceInitializationData();
|
||||
i_data.SetCompletedEncountersMask(lockData.CompletedEncountersMask);
|
||||
@@ -4931,6 +4931,14 @@ namespace Game.Maps
|
||||
i_data.Create();
|
||||
}
|
||||
|
||||
public Group GetOwningGroup() { return i_owningGroupRef.GetTarget(); }
|
||||
|
||||
public void TrySetOwningGroup(Group group)
|
||||
{
|
||||
if (!i_owningGroupRef.IsValid())
|
||||
i_owningGroupRef.Link(group, this);
|
||||
}
|
||||
|
||||
public bool Reset(InstanceResetMethod method)
|
||||
{
|
||||
// note: since the map may not be loaded when the instance needs to be reset
|
||||
@@ -5149,6 +5157,7 @@ namespace Game.Maps
|
||||
uint i_script_id;
|
||||
InstanceScenario i_scenario;
|
||||
InstanceLock i_instanceLock;
|
||||
GroupInstanceReference i_owningGroupRef = new();
|
||||
bool m_resetAfterUnload;
|
||||
bool m_unloadWhenEmpty;
|
||||
}
|
||||
|
||||
@@ -91,6 +91,8 @@ namespace Game.Entities
|
||||
|
||||
map.LoadRespawnTimes();
|
||||
map.LoadCorpseData();
|
||||
if (group != null)
|
||||
map.TrySetOwningGroup(group);
|
||||
|
||||
map.CreateInstanceData();
|
||||
map.SetInstanceScenario(Global.ScenarioMgr.CreateInstanceScenario(map, team));
|
||||
|
||||
Reference in New Issue
Block a user