Persistence fixes

master v3.2
Liza 2024-06-17 00:34:15 +02:00
parent 668287a7e2
commit 90adbdab89
Signed by: liza
GPG Key ID: 7199F8D727D55F67
3 changed files with 44 additions and 14 deletions

View File

@ -95,7 +95,7 @@ internal sealed unsafe class GameHooks : IDisposable
if (!string.IsNullOrEmpty(mapping.PlayerName))
{
_logger.LogTrace("Content id {ContentId} belongs to '{Name}'", mapping.ContentId,
_logger.LogDebug("Content id {ContentId} belongs to '{Name}'", mapping.ContentId,
mapping.PlayerName);
mappings.Add(mapping);
}
@ -136,7 +136,7 @@ internal sealed unsafe class GameHooks : IDisposable
///
/// Both 1 and 2 are sent to you on login, unprompted.
/// </summary>
[StructLayout(LayoutKind.Explicit, Size = 0x380)]
[StructLayout(LayoutKind.Explicit, Size = 0x420)]
internal struct SocialListResultPage
{
[FieldOffset(0x10)] private fixed byte Players[10 * 0x58];
@ -144,7 +144,7 @@ internal sealed unsafe class GameHooks : IDisposable
public Span<SocialListPlayer> PlayerSpan => new(Unsafe.AsPointer(ref Players[0]), 10);
}
[StructLayout(LayoutKind.Explicit, Size = 0x58)]
[StructLayout(LayoutKind.Explicit, Size = 0x68, Pack = 1)]
internal struct SocialListPlayer
{
/// <summary>
@ -156,6 +156,6 @@ internal sealed unsafe class GameHooks : IDisposable
/// <summary>
/// This *can* be empty, e.g. if you're querying your friend list, the names are ONLY set for characters on the same world.
/// </summary>
[FieldOffset(0x31)] public fixed byte CharacterName[32];
[FieldOffset(0x3C)] public fixed byte CharacterName[32];
}
}

View File

@ -89,29 +89,43 @@ internal sealed class PersistenceContext
WorldId = worldId,
OwnerLocalContentId = l.RetainerOwnerId,
})
.Where(mapping =>
{
if (mapping.Name == null)
return true;
var currentWorldCache = _worldRetainerCache.GetOrAdd(mapping.WorldId, _ => new());
if (currentWorldCache.TryGetValue(mapping.Name, out ulong playerContentId))
return mapping.OwnerLocalContentId != playerContentId;
return true;
})
.DistinctBy(x => x.LocalContentId)
.ToList();
using var scope = _serviceProvider.CreateScope();
using var dbContext = scope.ServiceProvider.GetRequiredService<RetainerTrackContext>();
var ids = updates.Select(x => x.LocalContentId).ToList();
var dbRetainers = dbContext.Retainers.Where(x => ids.Contains(x.LocalContentId))
.ToDictionary(x => x.LocalContentId, x => x);
foreach (var retainer in updates)
{
if (dbRetainers.TryGetValue(retainer.LocalContentId, out var dbRetainer))
Retainer? dbRetainer = dbContext.Retainers.Find(retainer.LocalContentId);
if (dbRetainer != null)
{
_logger.LogDebug("Updating retainer {RetainerName} with {LocalContentId}", retainer.Name, retainer.LocalContentId);
dbRetainer.Name = retainer.Name;
dbRetainer.WorldId = retainer.WorldId;
dbRetainer.OwnerLocalContentId = retainer.OwnerLocalContentId;
dbContext.Retainers.Update(dbRetainer);
}
else
{
_logger.LogDebug("Adding retainer {RetainerName} with {LocalContentId}", retainer.Name, retainer.LocalContentId);
dbContext.Retainers.Add(retainer);
}
if (!_playerNameCache.TryGetValue(retainer.OwnerLocalContentId, out string? ownerName))
ownerName = retainer.OwnerLocalContentId.ToString(CultureInfo.InvariantCulture);
_logger.LogTrace("Retainer {RetainerName} belongs to {OwnerId}", retainer.Name,
_logger.LogDebug(" Retainer {RetainerName} belongs to {OwnerName}", retainer.Name,
ownerName);
if (retainer.Name != null)
@ -121,7 +135,9 @@ internal sealed class PersistenceContext
}
}
dbContext.SaveChanges();
int changeCount = dbContext.SaveChanges();
if (changeCount > 0)
_logger.LogDebug("Saved {Count} retainer mappings", changeCount);
}
catch (Exception e)
{
@ -153,17 +169,31 @@ internal sealed class PersistenceContext
})
.ToList();
if (updates.Count == 0)
return;
using (var scope = _serviceProvider.CreateScope())
{
using var dbContext = scope.ServiceProvider.GetRequiredService<RetainerTrackContext>();
foreach (var update in updates)
{
if (!dbContext.Players.Any(x => x.LocalContentId == update.LocalContentId))
dbContext.Players.AddRange(updates);
var dbPlayer = dbContext.Players.Find(update.LocalContentId);
if (dbPlayer == null)
dbContext.Players.Add(update);
else
{
dbPlayer.Name = update.Name;
dbContext.Players.Update(dbPlayer);
}
}
dbContext.SaveChanges();
int changeCount = dbContext.SaveChanges();
if (changeCount > 0)
{
_logger.LogDebug("Saved {Count} player mappings", changeCount);
foreach (var update in updates)
_logger.LogTrace(" {ContentId} = {Name}", update.LocalContentId, update.Name);
}
}
foreach (var player in updates)

View File

@ -2,7 +2,7 @@
<PropertyGroup>
<TargetFramework>net8.0-windows</TargetFramework>
<Version>3.1</Version>
<Version>3.2</Version>
<LangVersion>12.0</LangVersion>
<Nullable>enable</Nullable>
<RuntimeIdentifier>win-x64</RuntimeIdentifier>