Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(2190): take into account GridX/Y and camera holds for map cache #2502

Merged
merged 1 commit into from
Jan 25, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 9 additions & 3 deletions Intersect (Core)/Network/Packets/Server/MapPacket.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
using MessagePack;
using System.Buffers.Binary;
using System.Numerics;
using MessagePack;
using System.Security.Cryptography;
using Intersect.GameObjects.Maps;
using Intersect.Models;
using Newtonsoft.Json.Converters;

namespace Intersect.Network.Packets.Server;

Expand Down Expand Up @@ -94,15 +97,18 @@ public string? CacheVersion
return _version;
}

_version = ComputeCacheVersion(MapId, Revision);
_version = ComputeCacheVersion(MapId, Revision, GridX, GridY, CameraHolds);
return _version;
}
}

public static string ComputeCacheVersion(Guid id, int revision)
public static string ComputeCacheVersion(Guid id, int revision, int gridX, int gridY, bool[] cameraHolds)
{
var hashInputData = id.ToByteArray()
.Concat(BitConverter.GetBytes(revision))
.Concat(BitConverter.GetBytes(gridX))
.Concat(BitConverter.GetBytes(gridY))
.Concat(cameraHolds.SelectMany(BitConverter.GetBytes))
.ToArray();
var versionData = SHA256.HashData(hashInputData);
var version = Convert.ToBase64String(versionData);
Expand Down
2 changes: 1 addition & 1 deletion Intersect.Client.Core/Core/Sounds/MapSound.cs
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ private void UpdateSoundVolume()
}
else
{
if (mDistance > 0 && Globals.GridMaps.Contains(mMapId))
if (mDistance > 0 && Globals.GridMaps.ContainsKey(mMapId))
{
var volume = 100 - 100 / (mDistance + 1) * CalculateSoundDistance();
if (volume < 0)
Expand Down
10 changes: 8 additions & 2 deletions Intersect.Client.Core/Entities/Entity.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
using Intersect.Client.General;
using Intersect.Client.Items;
using Intersect.Client.Localization;
using Intersect.Client.Maps;
using Intersect.Client.Spells;
using Intersect.Core;
using Intersect.Enums;
Expand Down Expand Up @@ -1054,8 +1055,8 @@ public virtual void Draw()
}

WorldPos.Reset();
var map = Maps.MapInstance.Get(MapId);
if (map == null || !Globals.GridMaps.Contains(MapId))

if (!Globals.GridMaps.ContainsKey(MapId) || !Maps.MapInstance.TryGet(MapId, out var map))
{
return;
}
Expand Down Expand Up @@ -1391,6 +1392,11 @@ public virtual void DrawEquipment(string filename, Color renderColor)

protected virtual void CalculateOrigin()
{
if (LatestMap?.IsDisposed ?? false)
{
LatestMap = Maps.MapInstance.TryGet(MapId, out MapInstance updatedInstance) ? updatedInstance : null;
}

if (LatestMap == default)
{
mOrigin = default;
Expand Down
2 changes: 1 addition & 1 deletion Intersect.Client.Core/Entities/Events/Event.cs
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ protected bool TryEnsureTexture(out GameTexture? texture)
public override void Draw()
{
WorldPos.Reset();
if (MapInstance == default || !Globals.GridMaps.Contains(MapId) || !TryEnsureTexture(out var texture))
if (MapInstance == default || !Globals.GridMaps.ContainsKey(MapId) || !TryEnsureTexture(out var texture))
{
return;
}
Expand Down
4 changes: 2 additions & 2 deletions Intersect.Client.Core/Entities/Projectiles/Projectile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -328,7 +328,7 @@ public override bool Update()
for (var s = 0; s < _spawnedAmount; s++)
{
var spawn = _spawns[s];

if (spawn != null && Maps.MapInstance.Get(spawn.SpawnMapId) != null)
{
if (_targetId != Guid.Empty && _targetId != _owner &&
Expand Down Expand Up @@ -774,7 +774,7 @@ private bool Collided(int i)
/// </summary>
public override void Draw()
{
if (Maps.MapInstance.Get(MapId) == null || !Globals.GridMaps.Contains(MapId))
if (Maps.MapInstance.Get(MapId) == null || !Globals.GridMaps.ContainsKey(MapId))
{
return;
}
Expand Down
2 changes: 1 addition & 1 deletion Intersect.Client.Core/General/Globals.cs
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ public static GameStates GameState
}
}

public static List<Guid> GridMaps = new List<Guid>();
public static Dictionary<Guid, Point> GridMaps = [];

public static bool HasGameData = false;

Expand Down
38 changes: 31 additions & 7 deletions Intersect.Client.Core/Maps/MapInstance.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,19 @@ public partial class MapInstance : MapBase, IGameObject<Guid, MapInstance>, IMap
//Map State Variables
public static Dictionary<Guid, long> MapRequests { get; set; } = new Dictionary<Guid, long>();

public static MapLoadedDelegate OnMapLoaded { get; set; }
public static event MapLoadedDelegate? MapLoaded;

public void MarkLoadFinished()
{
ApplicationContext.CurrentContext.Logger.LogDebug(
"Done loading map {Id} ({Name}) @ ({GridX}, {GridY})",
Id,
Name,
GridX,
GridY
);
MapLoaded?.Invoke(this);
}

private static MapControllers sLookup;

Expand Down Expand Up @@ -120,6 +132,8 @@ public MapInstance(Guid id) : base(id)
{
}

public bool IsDisposed { get; private set; }

public bool IsLoaded { get; private set; }

//Camera Locking Variables
Expand Down Expand Up @@ -177,8 +191,8 @@ public void Load(string json)

IsLoaded = true;
Autotiles = new MapAutotiles(this);
OnMapLoaded -= HandleMapLoaded;
OnMapLoaded += HandleMapLoaded;
MapLoaded -= HandleMapLoaded;
MapLoaded += HandleMapLoaded;
MapRequests.Remove(Id);
}

Expand Down Expand Up @@ -328,7 +342,7 @@ private void HandleMapLoaded(MapInstance map)
{
//See if this new map is on the same grid as us
var updatedBuffers = new HashSet<GameTileBuffer>();
if (map != this && Globals.GridMaps.Contains(map.Id) && Globals.GridMaps.Contains(Id) && IsLoaded)
if (map != this && Globals.GridMaps.ContainsKey(map.Id) && Globals.GridMaps.ContainsKey(Id) && IsLoaded)
{
var surroundingMaps = GenerateAutotileGrid();
if (map.GridX == GridX - 1)
Expand Down Expand Up @@ -546,7 +560,7 @@ private GameTileBuffer[] CheckAutotile(int x, int y, MapBase[,] surroundingMaps)
public MapBase[,] GenerateAutotileGrid()
{
var mapBase = new MapBase[3, 3];
if (Globals.MapGrid != null && Globals.GridMaps.Contains(Id))
if (Globals.MapGrid != null && Globals.GridMaps.ContainsKey(Id))
{
for (var x = -1; x <= 1; x++)
{
Expand Down Expand Up @@ -770,7 +784,7 @@ public void BuildVBOs()

var endVbo = DateTime.UtcNow;
var elapsedVbo = endVbo - startVbo;
ApplicationContext.Context.Value?.Logger.LogInformation($"Built VBO for map instance {Id} in {elapsedVbo.TotalMilliseconds}ms");
ApplicationContext.Context.Value?.Logger.LogInformation($"Built VBO for map {Id} '{Name}' in {elapsedVbo.TotalMilliseconds}ms");

// lock (mTileBuffers)
// {
Expand Down Expand Up @@ -1571,8 +1585,18 @@ public override void Delete()
//Dispose
public void Dispose(bool prep = true, bool killentities = true)
{
IsDisposed = true;

ApplicationContext.CurrentContext.Logger.LogDebug(
"Disposing map {Id} ({Name}) @ ({GridX}, {GridY})",
Id,
Name,
GridX,
GridY
);

IsLoaded = false;
OnMapLoaded -= HandleMapLoaded;
MapLoaded -= HandleMapLoaded;

foreach (var evt in mEvents)
{
Expand Down
95 changes: 68 additions & 27 deletions Intersect.Client.Core/Networking/PacketHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,16 @@ private void HandleMap(IPacketSender packetSender, MapPacket packet, bool skipSa

if (!skipSave)
{
ApplicationContext.CurrentContext.Logger.LogDebug(
"Saving map {Id} @ ({GridX}, {GridY}) revision {Revision} version {Version} holds {CameraHolds}",
packet.MapId,
packet.GridX,
packet.GridY,
packet.Revision,
packet.CacheVersion,
$"[{string.Join(", ", packet.CameraHolds)}]"
);

ObjectCacheData<MapBase> cacheData = new()
{
Id = new Id<MapBase>(mapId),
Expand All @@ -246,15 +256,15 @@ private void HandleMap(IPacketSender packetSender, MapPacket packet, bool skipSa

if (!ObjectDataDiskCache<MapBase>.TrySave(cacheData))
{
ApplicationContext.Context.Value?.Logger.LogWarning($"Failed to save cache for {cacheKey}");
ApplicationContext.CurrentContext.Logger.LogWarning("Failed to save cache for {CacheKey}", cacheKey);
}
}

MapInstance.UpdateMapRequestTime(packet.MapId);

if (MapInstance.TryGet(mapId, out var mapInstance))
{
if (packet.Revision == mapInstance.Revision)
if (skipSave && packet.Revision == mapInstance.Revision)
{
return;
}
Expand All @@ -270,28 +280,56 @@ private void HandleMap(IPacketSender packetSender, MapPacket packet, bool skipSa
mapInstance.LoadTileData(packet.TileData);
mapInstance.AttributeData = packet.AttributeData;
mapInstance.CreateMapSounds();
if (mapId == Globals.Me.MapId)

if (mapId == Globals.Me?.MapId)
{
Audio.PlayMusic(mapInstance.Music, ClientConfiguration.Instance.MusicFadeTimer, ClientConfiguration.Instance.MusicFadeTimer, true);
Audio.PlayMusic(
mapInstance.Music,
ClientConfiguration.Instance.MusicFadeTimer,
ClientConfiguration.Instance.MusicFadeTimer,
true
);
}

mapInstance.GridX = packet.GridX;
mapInstance.GridY = packet.GridY;
if (!Globals.GridMaps.TryGetValue(packet.MapId, out var gridPosition))
{
ApplicationContext.CurrentContext.Logger.LogDebug(
"Falling back to packet position for map '{MapName}' ({MapId})",
mapInstance.Name,
mapInstance.Id
);
gridPosition = new Point(packet.GridX, packet.GridY);
}

mapInstance.GridX = gridPosition.X;
mapInstance.GridY = gridPosition.Y;
mapInstance.CameraHolds = packet.CameraHolds;

ApplicationContext.CurrentContext.Logger.LogDebug(
"Loading map {Id} ({Name}) @ ({GridX}, {GridY}) revision {Revision} version {Version} holds {CameraHolds}",
mapInstance.Id,
mapInstance.Name,
gridPosition.X,
gridPosition.Y,
mapInstance.Revision,
packet.CacheVersion,
$"[{string.Join(", ", mapInstance.CameraHolds)}]"
);

mapInstance.Autotiles.InitAutotiles(mapInstance.GenerateAutotileGrid());

if (Globals.PendingEvents.ContainsKey(mapId))
if (Globals.PendingEvents.TryGetValue(mapId, out var pendingEventsForMap))
{
foreach (var evt in Globals.PendingEvents[mapId])
foreach (var (eventId, eventEntityPacket) in pendingEventsForMap)
{
mapInstance.AddEvent(evt.Key, evt.Value);
mapInstance.AddEvent(eventId, eventEntityPacket);
}

Globals.PendingEvents[mapId].Clear();
pendingEventsForMap.Clear();
}
}

MapInstance.OnMapLoaded?.Invoke(mapInstance);
mapInstance.MarkLoadFinished();
}

//MapPacket
Expand Down Expand Up @@ -403,32 +441,35 @@ public void HandlePacket(IPacketSender packetSender, EventEntityPacket packet)
}

//MapEntitiesPacket
public void HandlePacket(IPacketSender packetSender, MapEntitiesPacket packet)
public void HandlePacket(IPacketSender packetSender, MapEntitiesPacket entitiesPacket)
{
var mapEntities = new Dictionary<Guid, List<Guid>>();
foreach (var pkt in packet.MapEntities)
Dictionary<Guid, HashSet<Guid>> entitiesByMapId = [];
foreach (var entityPacket in entitiesPacket.MapEntities)
{
HandlePacket(pkt);
HandlePacket(entityPacket);

if (!mapEntities.ContainsKey(pkt.MapId))
if (!entitiesByMapId.TryGetValue(entityPacket.MapId, out var value))
{
mapEntities.Add(pkt.MapId, new List<Guid>());
value = [];
entitiesByMapId.Add(entityPacket.MapId, value);
}

mapEntities[pkt.MapId].Add(pkt.EntityId);
value.Add(entityPacket.EntityId);
}

//Remove any entities on the map that shouldn't be there anymore!
foreach (var entities in mapEntities)
// Remove any entities on the map that shouldn't be there anymore!
foreach (var (mapId, entitiesOnMap) in entitiesByMapId)
{
foreach (var entity in Globals.Entities)
foreach (var (entityId, entity) in Globals.Entities)
{
if (entity.Value.MapId == entities.Key && !entities.Value.Contains(entity.Key))
if (entity.MapId != mapId || entitiesOnMap.Contains(entityId))
{
if (!Globals.EntitiesToDispose.Contains(entity.Key) && entity.Value != Globals.Me && !(entity.Value is Projectile))
{
Globals.EntitiesToDispose.Add(entity.Key);
}
continue;
}

if (!Globals.EntitiesToDispose.Contains(entityId) && entity != Globals.Me && entity is not Projectile)
{
Globals.EntitiesToDispose.Add(entityId);
}
}
}
Expand Down Expand Up @@ -1755,7 +1796,7 @@ public void HandlePacket(IPacketSender packetSender, MapGridPacket packet)
Globals.MapGrid[x, y] = packet.Grid[x, y];
if (Globals.MapGrid[x, y] != Guid.Empty)
{
Globals.GridMaps.Add(Globals.MapGrid[x, y]);
Globals.GridMaps[Globals.MapGrid[x, y]] = new Point(x, y);
// MapInstance.UpdateMapRequestTime(Globals.MapGrid[x, y]);
}
}
Expand Down
1 change: 1 addition & 0 deletions Intersect.Client.Framework/Maps/IMapInstance.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ public interface IMapInstance
int Y { get; }
int GridX { get; set; }
int GridY { get; set; }
bool IsDisposed { get; }
bool IsLoaded { get; }

void AddTileAnimation(Guid animId, int tileX, int tileY, Direction dir = Direction.None, IEntity? owner = null);
Expand Down
Loading
Loading