Core/Transports: Localized transport objects within each map

Port From (https://github.com/TrinityCore/TrinityCore/commit/cace41449771bbe692e1a45c4d38b15a12f6496e)
This commit is contained in:
hondacrx
2022-06-16 14:08:22 -04:00
parent 30525b4567
commit 37d62e3a32
9 changed files with 208 additions and 208 deletions
+1 -1
View File
@@ -3663,7 +3663,7 @@ namespace Game.Entities
ITransport m_transport; ITransport m_transport;
Map _currMap; Map _currMap;
uint instanceId; public uint instanceId;
PhaseShift _phaseShift = new(); PhaseShift _phaseShift = new();
PhaseShift _suppressedPhaseShift = new(); // contains phases for current area but not applied due to conditions PhaseShift _suppressedPhaseShift = new(); // contains phases for current area but not applied due to conditions
int _dbPhase; int _dbPhase;
+25 -18
View File
@@ -612,22 +612,14 @@ namespace Game.Entities
{ {
var createPosition = m_createMode == PlayerCreateMode.NPE && info.createPositionNPE.HasValue ? info.createPositionNPE.Value : info.createPosition; var createPosition = m_createMode == PlayerCreateMode.NPE && info.createPositionNPE.HasValue ? info.createPositionNPE.Value : info.createPosition;
homebind.WorldRelocate(createPosition.Loc); if (!createPosition.TransportGuid.HasValue)
if (createPosition.TransportGuid.HasValue)
{ {
Transport transport = Global.ObjAccessor.FindTransport(ObjectGuid.Create(HighGuid.Transport, createPosition.TransportGuid.Value)); homebind.WorldRelocate(createPosition.Loc);
if (transport != null) homebindAreaId = Global.MapMgr.GetAreaId(PhasingHandler.EmptyPhaseShift, homebind);
{
float orientation = homebind.GetOrientation(); saveHomebindToDb();
transport.CalculatePassengerPosition(ref homebind.posX, ref homebind.posY, ref homebind.posZ, ref orientation); ok = true;
homebind.SetOrientation(orientation);
}
} }
homebindAreaId = Global.MapMgr.GetAreaId(PhasingHandler.EmptyPhaseShift, homebind);
saveHomebindToDb();
ok = true;
} }
if (!ok) if (!ok)
@@ -2864,10 +2856,25 @@ namespace Game.Entities
ObjectGuid transGUID = ObjectGuid.Create(HighGuid.Transport, transguid); ObjectGuid transGUID = ObjectGuid.Create(HighGuid.Transport, transguid);
Transport transport = null; Transport transport = null;
Transport go = Global.ObjAccessor.FindTransport(transGUID); Map transportMap = Global.MapMgr.CreateMap(mapId, this, instanceId);
if (go) if (transportMap != null)
transport = go; {
Transport transportOnMap = transportMap.GetTransport(transGUID);
if (transportOnMap != null)
{
if (transportOnMap.GetExpectedMapId() != mapId)
{
mapId = transportOnMap.GetExpectedMapId();
instanceId = 0;
transportMap = Global.MapMgr.CreateMap(mapId, this, instanceId);
if (transportMap)
transport = transportMap.GetTransport(transGUID);
}
else
transport = transportOnMap;
}
}
if (transport) if (transport)
{ {
float x = trans_x; float x = trans_x;
+1 -1
View File
@@ -203,7 +203,7 @@ namespace Game.Entities
if (position.TransportGuid.HasValue) if (position.TransportGuid.HasValue)
{ {
Transport transport = Global.ObjAccessor.FindTransport(ObjectGuid.Create(HighGuid.Transport, position.TransportGuid.Value)); Transport transport = ObjectAccessor.GetTransport(this, ObjectGuid.Create(HighGuid.Transport, position.TransportGuid.Value));
if (transport != null) if (transport != null)
{ {
transport.AddPassenger(this); transport.AddPassenger(this);
+61 -34
View File
@@ -18,6 +18,7 @@
using Framework.Constants; using Framework.Constants;
using Game.DataStorage; using Game.DataStorage;
using Game.Maps; using Game.Maps;
using Game.Networking.Packets;
using System; using System;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
@@ -142,14 +143,13 @@ namespace Game.Entities
base.Dispose(); base.Dispose();
} }
public bool Create(ulong guidlow, uint entry, uint mapid, float x, float y, float z, float ang, uint animprogress) public bool Create(ulong guidlow, uint entry, float x, float y, float z, float ang)
{ {
Relocate(x, y, z, ang); Relocate(x, y, z, ang);
if (!IsPositionValid()) if (!IsPositionValid())
{ {
Log.outError(LogFilter.Transport, "Transport (GUID: {0}) not created. Suggested coordinates isn't valid (X: {1} Y: {2})", Log.outError(LogFilter.Transport, $"Transport (GUID: {guidlow}) not created. Suggested coordinates isn't valid (X: {x} Y: {y})");
guidlow, x, y);
return false; return false;
} }
@@ -159,7 +159,7 @@ namespace Game.Entities
if (goinfo == null) if (goinfo == null)
{ {
Log.outError(LogFilter.Sql, "Transport not created: entry in `gameobject_template` not found, guidlow: {0} map: {1} (X: {2} Y: {3} Z: {4}) ang: {5}", guidlow, mapid, x, y, z, ang); Log.outError(LogFilter.Sql, $"Transport not created: entry in `gameobject_template` not found, entry: {entry}");
return false; return false;
} }
@@ -191,12 +191,20 @@ namespace Game.Entities
SetDisplayId(goinfo.displayId); SetDisplayId(goinfo.displayId);
SetGoState(goinfo.MoTransport.allowstopping == 0 ? GameObjectState.Ready : GameObjectState.Active); SetGoState(goinfo.MoTransport.allowstopping == 0 ? GameObjectState.Ready : GameObjectState.Active);
SetGoType(GameObjectTypes.MapObjTransport); SetGoType(GameObjectTypes.MapObjTransport);
SetGoAnimProgress(animprogress); SetGoAnimProgress(255);
SetUpdateFieldValue(m_values.ModifyValue(m_gameObjectData).ModifyValue(m_gameObjectData.SpawnTrackingStateAnimID), Global.DB2Mgr.GetEmptyAnimStateID()); SetUpdateFieldValue(m_values.ModifyValue(m_gameObjectData).ModifyValue(m_gameObjectData.SpawnTrackingStateAnimID), Global.DB2Mgr.GetEmptyAnimStateID());
SetName(goinfo.name); SetName(goinfo.name);
SetLocalRotation(0.0f, 0.0f, 0.0f, 1.0f); SetLocalRotation(0.0f, 0.0f, 0.0f, 1.0f);
SetParentRotation(Quaternion.Identity); SetParentRotation(Quaternion.Identity);
int legIndex;
var position = _transportInfo.ComputePosition(_pathProgress, out _, out legIndex);
if (position != null)
{
Relocate(position.GetPositionX(), position.GetPositionY(), position.GetPositionZ(), position.GetOrientation());
_currentPathLeg = legIndex;
}
CreateModel(); CreateModel();
return true; return true;
} }
@@ -258,7 +266,11 @@ namespace Game.Entities
{ {
while (eventToTriggerIndex < _transportInfo.Events.Count && _transportInfo.Events[eventToTriggerIndex].Timestamp < timer) while (eventToTriggerIndex < _transportInfo.Events.Count && _transportInfo.Events[eventToTriggerIndex].Timestamp < timer)
{ {
GameEvents.Trigger(_transportInfo.Events[eventToTriggerIndex].EventId, this, this); TransportPathLeg leg = _transportInfo.GetLegForTime(_transportInfo.Events[eventToTriggerIndex].Timestamp);
if (leg != null)
if (leg.MapId == GetMapId())
GameEvents.Trigger(_transportInfo.Events[eventToTriggerIndex].EventId, this, this);
_eventsToTrigger.Set(eventToTriggerIndex, false); _eventsToTrigger.Set(eventToTriggerIndex, false);
++eventToTriggerIndex; ++eventToTriggerIndex;
} }
@@ -283,13 +295,14 @@ namespace Game.Entities
if (legIndex != _currentPathLeg) if (legIndex != _currentPathLeg)
{ {
uint oldMapId = _transportInfo.PathLegs[_currentPathLeg].MapId;
_currentPathLeg = legIndex; _currentPathLeg = legIndex;
TeleportTransport(_transportInfo.PathLegs[legIndex].MapId, newPosition.GetPositionX(), newPosition.GetPositionY(), newPosition.GetPositionZ(), newPosition.GetOrientation()); TeleportTransport(oldMapId, _transportInfo.PathLegs[legIndex].MapId, newPosition.GetPositionX(), newPosition.GetPositionY(), newPosition.GetPositionZ(), newPosition.GetOrientation());
return; return;
} }
// set position // set position
if (_positionChangeTimer.Passed()) if (_positionChangeTimer.Passed() && GetExpectedMapId() == GetMapId())
{ {
_positionChangeTimer.Reset(positionUpdateDelay); _positionChangeTimer.Reset(positionUpdateDelay);
if (_movementState == TransportMovementState.Moving || justStopped) if (_movementState == TransportMovementState.Moving || justStopped)
@@ -323,11 +336,6 @@ namespace Game.Entities
} }
} }
public void DelayedUpdate(uint diff)
{
DelayedTeleportTransport();
}
public void AddPassenger(WorldObject passenger) public void AddPassenger(WorldObject passenger)
{ {
if (!IsInWorld) if (!IsInWorld)
@@ -646,14 +654,12 @@ namespace Game.Entities
public void SetDelayedAddModelToMap() { _delayedAddModel = true; } public void SetDelayedAddModelToMap() { _delayedAddModel = true; }
bool TeleportTransport(uint newMapid, float x, float y, float z, float o) bool TeleportTransport(uint oldMapId, uint newMapId, float x, float y, float z, float o)
{ {
Map oldMap = GetMap(); if (oldMapId != newMapId)
if (oldMap.GetId() != newMapid)
{ {
_delayedTeleport = new(newMapid, x, y, z, o);
UnloadStaticPassengers(); UnloadStaticPassengers();
TeleportPassengersAndHideTransport(newMapId, x, y, z, o);
return true; return true;
} }
else else
@@ -683,21 +689,41 @@ namespace Game.Entities
} }
} }
void DelayedTeleportTransport() void TeleportPassengersAndHideTransport(uint newMapid, float x, float y, float z, float o)
{ {
if (_delayedTeleport == null) if (newMapid == GetMapId())
return; {
AddToWorld();
Map newMap = Global.MapMgr.CreateBaseMap(_delayedTeleport.GetMapId()); foreach (var player in GetMap().GetPlayers())
GetMap().RemoveFromMap(this, false); {
SetMap(newMap); if (player.GetTransport() != this && player.IsInPhase(this))
{
UpdateData data = new(GetMap().GetId());
BuildCreateUpdateBlockForPlayer(data, player);
player.m_visibleTransports.Add(GetGUID());
data.BuildPacket(out UpdateObject packet);
player.SendPacket(packet);
}
}
}
else
{
UpdateData data = new(GetMap().GetId());
BuildOutOfRangeUpdateBlock(data);
float x = _delayedTeleport.GetPositionX(), data.BuildPacket(out UpdateObject packet);
y = _delayedTeleport.GetPositionY(), foreach (var player in GetMap().GetPlayers())
z = _delayedTeleport.GetPositionZ(), {
o = _delayedTeleport.GetOrientation(); if (player.GetTransport() != this && player.m_visibleTransports.Contains(GetGUID()))
{
player.SendPacket(packet);
player.m_visibleTransports.Remove(GetGUID());
}
}
_delayedTeleport = null; RemoveFromWorld();
}
List<WorldObject> passengersToTeleport = new(_passengers); List<WorldObject> passengersToTeleport = new(_passengers);
foreach (WorldObject obj in passengersToTeleport) foreach (WorldObject obj in passengersToTeleport)
@@ -709,7 +735,7 @@ namespace Game.Entities
switch (obj.GetTypeId()) switch (obj.GetTypeId())
{ {
case TypeId.Player: case TypeId.Player:
if (!obj.ToPlayer().TeleportTo(newMap.GetId(), destX, destY, destZ, destO, TeleportToOptions.NotLeaveTransport, newMap.GetInstanceId())) if (!obj.ToPlayer().TeleportTo(newMapid, destX, destY, destZ, destO, TeleportToOptions.NotLeaveTransport))
RemovePassenger(obj); RemovePassenger(obj);
break; break;
case TypeId.DynamicObject: case TypeId.DynamicObject:
@@ -721,9 +747,6 @@ namespace Game.Entities
break; break;
} }
} }
Relocate(x, y, z, o);
GetMap().AddToMap(this);
} }
void UpdatePassengerPositions(HashSet<WorldObject> passengers) void UpdatePassengerPositions(HashSet<WorldObject> passengers)
@@ -750,6 +773,11 @@ namespace Game.Entities
ClearUpdateMask(true); ClearUpdateMask(true);
} }
public uint GetExpectedMapId()
{
return _transportInfo.PathLegs[_currentPathLeg].MapId;
}
public HashSet<WorldObject> GetPassengers() { return _passengers; } public HashSet<WorldObject> GetPassengers() { return _passengers; }
public ObjectGuid GetTransportGUID() { return GetGUID(); } public ObjectGuid GetTransportGUID() { return GetGUID(); }
@@ -772,6 +800,5 @@ namespace Game.Entities
HashSet<WorldObject> _staticPassengers = new(); HashSet<WorldObject> _staticPassengers = new();
bool _delayedAddModel; bool _delayedAddModel;
WorldLocation _delayedTeleport;
} }
} }
+1 -23
View File
@@ -27,7 +27,6 @@ public class ObjectAccessor : Singleton<ObjectAccessor>
object _lockObject = new(); object _lockObject = new();
Dictionary<ObjectGuid, Player> _players = new(); Dictionary<ObjectGuid, Player> _players = new();
Dictionary<ObjectGuid, Transport> _transports = new();
ObjectAccessor() { } ObjectAccessor() { }
@@ -119,16 +118,11 @@ public class ObjectAccessor : Singleton<ObjectAccessor>
return u.GetMap().GetGameObject(guid); return u.GetMap().GetGameObject(guid);
} }
static Transport GetTransportOnMap(WorldObject u, ObjectGuid guid) public static Transport GetTransport(WorldObject u, ObjectGuid guid)
{ {
return u.GetMap().GetTransport(guid); return u.GetMap().GetTransport(guid);
} }
Transport GetTransport(ObjectGuid guid)
{
return _transports.LookupByKey(guid);
}
static DynamicObject GetDynamicObject(WorldObject u, ObjectGuid guid) static DynamicObject GetDynamicObject(WorldObject u, ObjectGuid guid)
{ {
return u.GetMap().GetDynamicObject(guid); return u.GetMap().GetDynamicObject(guid);
@@ -227,12 +221,6 @@ public class ObjectAccessor : Singleton<ObjectAccessor>
return PlayerNameMapHolder.Find(name); return PlayerNameMapHolder.Find(name);
} }
public Transport FindTransport(ObjectGuid guid)
{
lock (_lockObject)
return _transports.LookupByKey(guid);
}
public void SaveAllPlayers() public void SaveAllPlayers()
{ {
lock (_lockObject) lock (_lockObject)
@@ -256,11 +244,6 @@ public class ObjectAccessor : Singleton<ObjectAccessor>
_players[obj.GetGUID()] = obj; _players[obj.GetGUID()] = obj;
} }
} }
public void AddObject(Transport obj)
{
lock (_lockObject)
_transports[obj.GetGUID()] = obj;
}
public void RemoveObject(Player obj) public void RemoveObject(Player obj)
{ {
@@ -270,11 +253,6 @@ public class ObjectAccessor : Singleton<ObjectAccessor>
_players.Remove(obj.GetGUID()); _players.Remove(obj.GetGUID());
} }
} }
public void RemoveObject(Transport obj)
{
lock (_lockObject)
_transports.Remove(obj.GetGUID());
}
} }
class PlayerNameMapHolder class PlayerNameMapHolder
+13
View File
@@ -255,6 +255,11 @@ namespace Game
Map oldMap = player.GetMap(); Map oldMap = player.GetMap();
Map newMap = GetPlayer().GetTeleportDestInstanceId().HasValue ? Global.MapMgr.FindMap(loc.GetMapId(), GetPlayer().GetTeleportDestInstanceId().Value) : Global.MapMgr.CreateMap(loc.GetMapId(), GetPlayer()); Map newMap = GetPlayer().GetTeleportDestInstanceId().HasValue ? Global.MapMgr.FindMap(loc.GetMapId(), GetPlayer().GetTeleportDestInstanceId().Value) : Global.MapMgr.CreateMap(loc.GetMapId(), GetPlayer());
MovementInfo.TransportInfo transportInfo = player.m_movementInfo.transport;
ITransport transport = player.GetTransport();
if (transport != null)
transport.RemovePassenger(player);
if (player.IsInWorld) if (player.IsInWorld)
{ {
Log.outError(LogFilter.Network, $"Player (Name {player.GetName()}) is still in world when teleported from map {oldMap.GetId()} to new map {loc.GetMapId()}"); Log.outError(LogFilter.Network, $"Player (Name {player.GetName()}) is still in world when teleported from map {oldMap.GetId()} to new map {loc.GetMapId()}");
@@ -286,6 +291,14 @@ namespace Game
if (!seamlessTeleport) if (!seamlessTeleport)
player.SendInitialPacketsBeforeAddToMap(); player.SendInitialPacketsBeforeAddToMap();
// move player between transport copies on each map
Transport newTransport = newMap.GetTransport(transportInfo.guid);
if (newTransport != null)
{
player.m_movementInfo.transport = transportInfo;
newTransport.AddPassenger(player);
}
if (!player.GetMap().AddPlayerToMap(player, !seamlessTeleport)) if (!player.GetMap().AddPlayerToMap(player, !seamlessTeleport))
{ {
Log.outError(LogFilter.Network, $"WORLD: failed to teleport player {player.GetName()} ({player.GetGUID()}) to map {loc.GetMapId()} ({(newMap ? newMap.GetMapName() : "Unknown")}) because of unknown reason!"); Log.outError(LogFilter.Network, $"WORLD: failed to teleport player {player.GetName()} ({player.GetGUID()}) to map {loc.GetMapId()} ({(newMap ? newMap.GetMapName() : "Unknown")}) because of unknown reason!");
+33 -36
View File
@@ -83,6 +83,8 @@ namespace Game.Maps
_poolData = Global.PoolMgr.InitPoolsForMap(this); _poolData = Global.PoolMgr.InitPoolsForMap(this);
Global.TransportMgr.CreateTransportsForMap(this);
Global.MMapMgr.LoadMapInstance(Global.WorldMgr.GetDataPath(), GetId(), i_InstanceId); Global.MMapMgr.LoadMapInstance(Global.WorldMgr.GetDataPath(), GetId(), i_InstanceId);
Global.ScriptMgr.OnCreateMap(this); Global.ScriptMgr.OnCreateMap(this);
@@ -408,12 +410,6 @@ namespace Game.Maps
player.Dispose(); player.Dispose();
} }
void DeleteFromWorld(Transport transport)
{
Global.ObjAccessor.RemoveObject(transport);
transport.Dispose();
}
void DeleteFromWorld(WorldObject obj) void DeleteFromWorld(WorldObject obj)
{ {
obj.Dispose(); obj.Dispose();
@@ -642,20 +638,24 @@ namespace Game.Maps
return false; //Should delete object return false; //Should delete object
} }
obj.AddToWorld();
_transports.Add(obj); _transports.Add(obj);
// Broadcast creation to players if (obj.GetExpectedMapId() == GetId())
foreach (Player player in GetPlayers())
{ {
if (player.GetTransport() != obj) obj.AddToWorld();
// Broadcast creation to players
foreach (var player in GetPlayers())
{ {
var data = new UpdateData(GetId()); if (player.GetTransport() != obj && player.IsInPhase(obj))
obj.BuildCreateUpdateBlockForPlayer(data, player); {
player.m_visibleTransports.Add(obj.GetGUID()); var data = new UpdateData(GetId());
UpdateObject packet; obj.BuildCreateUpdateBlockForPlayer(data, player);
data.BuildPacket(out packet); player.m_visibleTransports.Add(obj.GetGUID());
player.SendPacket(packet); UpdateObject packet;
data.BuildPacket(out packet);
player.SendPacket(packet);
}
} }
} }
@@ -830,7 +830,7 @@ namespace Game.Maps
for (var i = 0; i < _transports.Count; ++i) for (var i = 0; i < _transports.Count; ++i)
{ {
Transport transport = _transports[i]; Transport transport = _transports[i];
if (!transport || !transport.IsInWorld) if (!transport)
continue; continue;
transport.Update(diff); transport.Update(diff);
@@ -1011,19 +1011,22 @@ namespace Game.Maps
public void RemoveFromMap(Transport obj, bool remove) public void RemoveFromMap(Transport obj, bool remove)
{ {
obj.RemoveFromWorld(); if (obj.IsInWorld)
var players = GetPlayers();
if (!players.Empty())
{ {
obj.RemoveFromWorld();
UpdateData data = new(GetId()); UpdateData data = new(GetId());
obj.BuildOutOfRangeUpdateBlock(data); if (obj.IsDestroyedObject())
obj.BuildDestroyUpdateBlock(data);
else
obj.BuildOutOfRangeUpdateBlock(data);
UpdateObject packet; UpdateObject packet;
data.BuildPacket(out packet); data.BuildPacket(out packet);
foreach (var player in players) foreach (var player in GetPlayers())
{ {
if (player.GetTransport() != obj) if (player.GetTransport() != obj && player.m_visibleTransports.Contains(obj.GetGUID()))
{ {
player.SendPacket(packet); player.SendPacket(packet);
player.m_visibleTransports.Remove(obj.GetGUID()); player.m_visibleTransports.Remove(obj.GetGUID());
@@ -2270,11 +2273,11 @@ namespace Game.Maps
void SendInitTransports(Player player) void SendInitTransports(Player player)
{ {
var transData = new UpdateData(player.GetMapId()); var transData = new UpdateData(GetId());
foreach (Transport transport in _transports) foreach (Transport transport in _transports)
{ {
if (transport != player.GetTransport() && player.IsInPhase(transport)) if (transport.IsInWorld && transport != player.GetTransport() && player.IsInPhase(transport))
{ {
transport.BuildCreateUpdateBlockForPlayer(transData, player); transport.BuildCreateUpdateBlockForPlayer(transData, player);
player.m_visibleTransports.Add(transport.GetGUID()); player.m_visibleTransports.Add(transport.GetGUID());
@@ -2291,7 +2294,7 @@ namespace Game.Maps
var transData = new UpdateData(player.GetMapId()); var transData = new UpdateData(player.GetMapId());
foreach (Transport transport in _transports) foreach (Transport transport in _transports)
{ {
if (transport != player.GetTransport()) if (player.m_visibleTransports.Contains(transport.GetGUID()) && transport != player.GetTransport())
{ {
transport.BuildOutOfRangeUpdateBlock(transData); transport.BuildOutOfRangeUpdateBlock(transData);
player.m_visibleTransports.Remove(transport.GetGUID()); player.m_visibleTransports.Remove(transport.GetGUID());
@@ -2309,6 +2312,9 @@ namespace Game.Maps
UpdateData transData = new(player.GetMapId()); UpdateData transData = new(player.GetMapId());
foreach (var transport in _transports) foreach (var transport in _transports)
{ {
if (!transport.IsInWorld)
continue;
var hasTransport = player.m_visibleTransports.Contains(transport.GetGUID()); var hasTransport = player.m_visibleTransports.Contains(transport.GetGUID());
if (player.IsInPhase(transport)) if (player.IsInPhase(transport))
{ {
@@ -2914,15 +2920,6 @@ namespace Game.Maps
while (_farSpellCallbacks.TryDequeue(out FarSpellCallback callback)) while (_farSpellCallbacks.TryDequeue(out FarSpellCallback callback))
callback(this); callback(this);
for (var i = 0; i < _transports.Count; ++i)
{
Transport transport = _transports[i];
if (!transport.IsInWorld)
continue;
transport.DelayedUpdate(diff);
}
RemoveAllObjectsInRemoveList(); RemoveAllObjectsInRemoveList();
// Don't unload grids if it's Battleground, since we may have manually added GOs, creatures, those doesn't load from DB at grid re-load ! // Don't unload grids if it's Battleground, since we may have manually added GOs, creatures, those doesn't load from DB at grid re-load !
+73 -92
View File
@@ -72,15 +72,7 @@ namespace Game.Maps
// paths are generated per template, saves us from generating it again in case of instanced transports // paths are generated per template, saves us from generating it again in case of instanced transports
TransportTemplate transport = new(); TransportTemplate transport = new();
List<uint> mapsUsed = new(); GeneratePath(goInfo, transport);
GeneratePath(goInfo, transport, mapsUsed);
_transportTemplates[entry] = transport;
// transports in instance are only on one map
if (transport.InInstance)
_instanceTransports.Add(mapsUsed.First(), entry);
++count; ++count;
} while (result.NextRow()); } while (result.NextRow());
@@ -118,7 +110,8 @@ namespace Game.Maps
uint phaseId = result.Read<uint>(3); uint phaseId = result.Read<uint>(3);
uint phaseGroupId = result.Read<uint>(4); uint phaseGroupId = result.Read<uint>(4);
if (GetTransportTemplate(entry) == null) TransportTemplate transportTemplate = GetTransportTemplate(entry);
if (transportTemplate == null)
{ {
Log.outError(LogFilter.Sql, $"Table `transports` have transport (GUID: {guid} Entry: {entry}) with unknown gameobject `entry` set, skipped."); Log.outError(LogFilter.Sql, $"Table `transports` have transport (GUID: {guid} Entry: {entry}) with unknown gameobject `entry` set, skipped.");
continue; continue;
@@ -167,6 +160,9 @@ namespace Game.Maps
spawn.PhaseId = phaseId; spawn.PhaseId = phaseId;
spawn.PhaseGroup = phaseGroupId; spawn.PhaseGroup = phaseGroupId;
foreach (uint mapId in transportTemplate.MapIds)
_transportsByMap[mapId].Add(spawn);
_transportSpawns[guid] = spawn; _transportSpawns[guid] = spawn;
} while (result.NextRow()); } while (result.NextRow());
@@ -321,7 +317,7 @@ namespace Game.Maps
} }
} }
void GeneratePath(GameObjectTemplate goInfo, TransportTemplate transport, List<uint> mapsUsed) void GeneratePath(GameObjectTemplate goInfo, TransportTemplate transport)
{ {
uint pathId = goInfo.MoTransport.taxiPathID; uint pathId = goInfo.MoTransport.taxiPathID;
TaxiPathNodeRecord[] path = CliDB.TaxiPathNodesByPath[pathId]; TaxiPathNodeRecord[] path = CliDB.TaxiPathNodesByPath[pathId];
@@ -360,21 +356,21 @@ namespace Game.Maps
if (node.ArrivalEventID != 0 || node.DepartureEventID != 0) if (node.ArrivalEventID != 0 || node.DepartureEventID != 0)
events.Add(node); events.Add(node);
mapsUsed.Add(node.ContinentID); transport.MapIds.Add(node.ContinentID);
} }
if (leg.Spline == null) if (leg.Spline == null)
InitializeLeg(leg, transport.Events, pathPoints, pauses, events, goInfo, ref totalTime); InitializeLeg(leg, transport.Events, pathPoints, pauses, events, goInfo, ref totalTime);
if (mapsUsed.Count > 1) if (transport.MapIds.Count > 1)
{ {
foreach (uint mapId in mapsUsed) foreach (uint mapId in transport.MapIds)
Cypher.Assert(!CliDB.MapStorage.LookupByKey(mapId).Instanceable()); Cypher.Assert(!CliDB.MapStorage.LookupByKey(mapId).Instanceable());
transport.InInstance = false; transport.InInstance = false;
} }
else else
transport.InInstance = CliDB.MapStorage.LookupByKey(mapsUsed.First()).Instanceable(); transport.InInstance = CliDB.MapStorage.LookupByKey(transport.MapIds.First()).Instanceable();
transport.TotalPathTime = totalTime; transport.TotalPathTime = totalTime;
transport.PathLegs.Add(leg); transport.PathLegs.Add(leg);
@@ -403,23 +399,20 @@ namespace Game.Maps
animNode.TotalTime = timeSeg; animNode.TotalTime = timeSeg;
} }
public Transport CreateTransport(uint entry, ulong guid = 0, Map map = null, PhaseUseFlagsValues phaseUseFlags = 0, uint phaseId = 0, uint phaseGroupId = 0) public Transport CreateTransport(uint entry, Map map, ulong guid = 0, PhaseUseFlagsValues phaseUseFlags = 0, uint phaseId = 0, uint phaseGroupId = 0)
{ {
// instance case, execute GetGameObjectEntry hook // SetZoneScript() is called after adding to map, so fetch the script using map
if (map != null) InstanceMap instanceMap = map.ToInstanceMap();
if (instanceMap != null)
{ {
// SetZoneScript() is called after adding to map, so fetch the script using map InstanceScript instance = instanceMap.GetInstanceScript();
if (map.IsDungeon()) if (instance != null)
{ entry = instance.GetGameObjectEntry(0, entry);
InstanceScript instance = ((InstanceMap)map).GetInstanceScript();
if (instance != null)
entry = instance.GetGameObjectEntry(0, entry);
}
if (entry == 0)
return null;
} }
if (entry == 0)
return null;
TransportTemplate tInfo = GetTransportTemplate(entry); TransportTemplate tInfo = GetTransportTemplate(entry);
if (tInfo == null) if (tInfo == null)
{ {
@@ -446,7 +439,7 @@ namespace Game.Maps
// initialize the gameobject base // initialize the gameobject base
ulong guidLow = guid != 0 ? guid : map.GenerateLowGuid(HighGuid.Transport); ulong guidLow = guid != 0 ? guid : map.GenerateLowGuid(HighGuid.Transport);
if (!trans.Create(guidLow, entry, mapId, x, y, z, o, 255)) if (!trans.Create(guidLow, entry, x, y, z, o))
return null; return null;
PhasingHandler.InitDbPhaseShift(trans.GetPhaseShift(), phaseUseFlags, phaseId, phaseGroupId); PhasingHandler.InitDbPhaseShift(trans.GetPhaseShift(), phaseUseFlags, phaseId, phaseGroupId);
@@ -462,42 +455,27 @@ namespace Game.Maps
} }
// use preset map for instances (need to know which instance) // use preset map for instances (need to know which instance)
trans.SetMap(map != null ? map : Global.MapMgr.CreateMap(mapId, null)); trans.SetMap(map);
if (map != null && map.IsDungeon()) if (instanceMap != null)
trans.m_zoneScript = map.ToInstanceMap().GetInstanceScript(); trans.m_zoneScript = instanceMap.GetInstanceScript();
// Passengers will be loaded once a player is near // Passengers will be loaded once a player is near
Global.ObjAccessor.AddObject(trans); map.AddToMap(trans);
trans.GetMap().AddToMap(trans);
return trans; return trans;
} }
public void SpawnContinentTransports() public void CreateTransportsForMap(Map map)
{ {
uint oldMSTime = Time.GetMSTime(); var mapTransports = _transportsByMap.LookupByKey(map.GetId());
uint count = 0;
foreach (var pair in _transportSpawns)
if (!GetTransportTemplate(pair.Value.TransportGameObjectId).InInstance)
if (CreateTransport(pair.Value.TransportGameObjectId, pair.Value.SpawnId, null, pair.Value.PhaseUseFlags, pair.Value.PhaseId, pair.Value.PhaseGroup))
++count;
Log.outInfo(LogFilter.ServerLoading, "Spawned {0} continent transports in {1} ms", count, Time.GetMSTimeDiffToNow(oldMSTime));
}
public void CreateInstanceTransports(Map map)
{
var mapTransports = _instanceTransports.LookupByKey(map.GetId());
// no transports here // no transports here
if (mapTransports.Empty()) if (mapTransports.Empty())
return; return;
// create transports // create transports
foreach (var transportGameObjectId in mapTransports) foreach (var transport in mapTransports)
CreateTransport(transportGameObjectId, 0, map); CreateTransport(transport.TransportGameObjectId, map, transport.SpawnId, transport.PhaseUseFlags, transport.PhaseId, transport.PhaseGroup);
} }
public TransportTemplate GetTransportTemplate(uint entry) public TransportTemplate GetTransportTemplate(uint entry)
@@ -516,7 +494,7 @@ namespace Game.Maps
} }
Dictionary<uint, TransportTemplate> _transportTemplates = new(); Dictionary<uint, TransportTemplate> _transportTemplates = new();
MultiMap<uint, uint> _instanceTransports = new(); MultiMap<uint, TransportSpawn> _transportsByMap = new();
Dictionary<uint, TransportAnimation> _transportAnimations = new(); Dictionary<uint, TransportAnimation> _transportAnimations = new();
Dictionary<ulong, TransportSpawn> _transportSpawns = new(); Dictionary<ulong, TransportSpawn> _transportSpawns = new();
} }
@@ -553,34 +531,29 @@ namespace Game.Maps
public List<TransportPathLeg> PathLegs = new(); public List<TransportPathLeg> PathLegs = new();
public List<TransportPathEvent> Events = new(); public List<TransportPathEvent> Events = new();
public List<uint> MapIds = new();
public bool InInstance; public bool InInstance;
public Position ComputePosition(uint time, out TransportMovementState moveState, out int legIndex) public Position ComputePosition(uint time, out TransportMovementState moveState, out int legIndex)
{ {
moveState = TransportMovementState.Moving; moveState = TransportMovementState.Moving;
legIndex = 0;
time %= TotalPathTime; time %= TotalPathTime;
// find leg // find leg
legIndex = 0; TransportPathLeg leg = GetLegForTime(time);
while (PathLegs[legIndex].StartTimestamp + PathLegs[legIndex].Duration <= time) if (leg == null)
{ return null;
++legIndex;
if (PathLegs.Count >= legIndex)
return null;
}
var legItr = PathLegs[legIndex];
// find segment // find segment
uint prevSegmentTime = legItr.StartTimestamp; uint prevSegmentTime = leg.StartTimestamp;
var segmentIndex = 0; var segmentIndex = 0;
double distanceMoved = 0.0; double distanceMoved = 0.0;
bool isOnPause = false; bool isOnPause = false;
for (segmentIndex = 0; segmentIndex < legItr.Segments.Count; ++segmentIndex) for (segmentIndex = 0; segmentIndex < leg.Segments.Count; ++segmentIndex)
{ {
var segment = legItr.Segments[segmentIndex]; var segment = leg.Segments[segmentIndex];
if (time < segment.SegmentEndArrivalTimestamp) if (time < segment.SegmentEndArrivalTimestamp)
break; break;
@@ -594,28 +567,57 @@ namespace Game.Maps
prevSegmentTime = segment.SegmentEndArrivalTimestamp + segment.Delay; prevSegmentTime = segment.SegmentEndArrivalTimestamp + segment.Delay;
} }
var pathSegment = legItr.Segments[segmentIndex]; var pathSegment = leg.Segments[segmentIndex];
if (!isOnPause) if (!isOnPause)
distanceMoved += CalculateDistanceMoved( distanceMoved += CalculateDistanceMoved(
(double)(time - prevSegmentTime) * 0.001, (double)(time - prevSegmentTime) * 0.001,
(double)(pathSegment.SegmentEndArrivalTimestamp - prevSegmentTime) * 0.001, (double)(pathSegment.SegmentEndArrivalTimestamp - prevSegmentTime) * 0.001,
segmentIndex == 0, segmentIndex == 0,
segmentIndex == legItr.Segments.Count); segmentIndex == leg.Segments.Count);
int splineIndex = 0; int splineIndex = 0;
float splinePointProgress = 0; float splinePointProgress = 0;
legItr.Spline.ComputeIndex((float)Math.Min(distanceMoved / legItr.Spline.Length(), 1.0), ref splineIndex, ref splinePointProgress); leg.Spline.ComputeIndex((float)Math.Min(distanceMoved / leg.Spline.Length(), 1.0), ref splineIndex, ref splinePointProgress);
Vector3 pos, dir; Vector3 pos, dir;
legItr.Spline.Evaluate_Percent(splineIndex, splinePointProgress, out pos); leg.Spline.Evaluate_Percent(splineIndex, splinePointProgress, out pos);
legItr.Spline.Evaluate_Derivative(splineIndex, splinePointProgress, out dir); leg.Spline.Evaluate_Derivative(splineIndex, splinePointProgress, out dir);
moveState = isOnPause ? TransportMovementState.WaitingOnPauseWaypoint : TransportMovementState.Moving; moveState = isOnPause ? TransportMovementState.WaitingOnPauseWaypoint : TransportMovementState.Moving;
legIndex = PathLegs.IndexOf(leg);
return new Position(pos.X, pos.Y, pos.Z, MathF.Atan2(dir.Y, dir.X) + MathF.PI); return new Position(pos.X, pos.Y, pos.Z, MathF.Atan2(dir.Y, dir.X) + MathF.PI);
} }
public TransportPathLeg GetLegForTime(uint time)
{
int legIndex = 0;
while (PathLegs[legIndex].StartTimestamp + PathLegs[legIndex].Duration <= time)
{
++legIndex;
if (PathLegs.Count >= legIndex)
return null;
}
return PathLegs[legIndex];
}
public uint GetNextPauseWaypointTimestamp(uint time)
{
TransportPathLeg leg = GetLegForTime(time);
if (leg == null)
return time;
int segmentIndex = 0;
for (; segmentIndex != leg.Segments.Count - 1; ++segmentIndex)
if (time < leg.Segments[segmentIndex].SegmentEndArrivalTimestamp + leg.Segments[segmentIndex].Delay)
break;
return leg.Segments[segmentIndex].SegmentEndArrivalTimestamp + leg.Segments[segmentIndex].Delay;
}
double CalculateDistanceMoved(double timePassedInSegment, double segmentDuration, bool isFirstSegment, bool isLastSegment) double CalculateDistanceMoved(double timePassedInSegment, double segmentDuration, bool isFirstSegment, bool isLastSegment)
{ {
if (isFirstSegment) if (isFirstSegment)
@@ -669,27 +671,6 @@ namespace Game.Maps
+ (2.0 * AccelerationRate * accelerationTime1 - segmentTimeSpentAccelerating * AccelerationRate) * 0.5 * segmentTimeSpentAccelerating; + (2.0 * AccelerationRate * accelerationTime1 - segmentTimeSpentAccelerating * AccelerationRate) * 0.5 * segmentTimeSpentAccelerating;
} }
} }
public uint GetNextPauseWaypointTimestamp(uint time)
{
var legIndex = 0;
while (PathLegs[legIndex].StartTimestamp + PathLegs[legIndex].Duration <= time)
{
++legIndex;
if (legIndex >= PathLegs.Count)
return time;
}
var leg = PathLegs[legIndex];
var segmentIndex = 0;
for (; segmentIndex != leg.Segments.Count - 1; ++segmentIndex)
if (time < leg.Segments[segmentIndex].SegmentEndArrivalTimestamp + leg.Segments[segmentIndex].Delay)
break;
return leg.Segments[segmentIndex].SegmentEndArrivalTimestamp + leg.Segments[segmentIndex].Delay;
}
} }
public class SplineRawInitializer public class SplineRawInitializer
-3
View File
@@ -1053,9 +1053,6 @@ namespace Game
Log.outInfo(LogFilter.ServerLoading, "Starting Battlefield System"); Log.outInfo(LogFilter.ServerLoading, "Starting Battlefield System");
Global.BattleFieldMgr.InitBattlefield(); Global.BattleFieldMgr.InitBattlefield();
Log.outInfo(LogFilter.ServerLoading, "Loading Transports...");
Global.TransportMgr.SpawnContinentTransports();
// Initialize Warden // Initialize Warden
Log.outInfo(LogFilter.ServerLoading, "Loading Warden Checks..."); Log.outInfo(LogFilter.ServerLoading, "Loading Warden Checks...");
Global.WardenCheckMgr.LoadWardenChecks(); Global.WardenCheckMgr.LoadWardenChecks();