Persistence fixes
This commit is contained in:
parent
668287a7e2
commit
a3f8145806
@ -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];
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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>
|
||||
|
Loading…
Reference in New Issue
Block a user