Skip to content

Commit

Permalink
Vehicle signs and requests are mostly working. Worked on some TODO st…
Browse files Browse the repository at this point in the history
…uff.
  • Loading branch information
DanielWillett committed Nov 13, 2024
1 parent 8589893 commit 400c936
Show file tree
Hide file tree
Showing 29 changed files with 801 additions and 2,112 deletions.
183 changes: 112 additions & 71 deletions UncreatedWarfare/Buildables/BuildableSaver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ public class BuildableSaver : ILayoutHostedService, IDisposable
public BuildableSaver(IServiceProvider serviceProvider)
{
_dbContext = serviceProvider.GetRequiredService<IBuildablesDbContext>();
_dbContext.ChangeTracker.AutoDetectChangesEnabled = false;

_signs = serviceProvider.GetService<SignInstancer>();
_logger = serviceProvider.GetRequiredService<ILogger<BuildableSaver>>();
Expand All @@ -53,7 +52,7 @@ async UniTask ILayoutHostedService.StartAsync(CancellationToken token)
byte region = _region;
int mapId = _mapScheduler.Current;

await _semaphore.WaitAsync(token);
await _semaphore.WaitAsync(token).ConfigureAwait(false);
try
{
List<BuildableSave> saves = await _dbContext.Saves
Expand All @@ -72,24 +71,17 @@ async UniTask ILayoutHostedService.StartAsync(CancellationToken token)

await UniTask.SwitchToMainThread(token);

// todo need to load this on level load
List<BuildableSave> newSaves = _saves;

for (int i = newSaves.Count - 1; i >= 0; i--)
{
BuildableSave save = newSaves[i];
uint oldInstanceId = save.InstanceId;
if (!RestoreSave(newSaves, i, save))
continue;

_dbContext.Update(save);
if (save.InstanceIds?.FirstOrDefault(instanceId => instanceId.RegionId == _region) is { } instId && instId.InstanceId != oldInstanceId)
{
_dbContext.Update(instId);
}
RestoreSave(newSaves, i, save);
}

await _dbContext.SaveChangesAsync(token);

_dbContext.ChangeTracker.Clear();
}
finally
{
Expand Down Expand Up @@ -127,25 +119,28 @@ public async UniTask<bool> SaveBarricadeAsync(BarricadeDrop barricade, Cancellat
BarricadeData data = barricade.GetServersideData();
await UniTask.SwitchToThreadPool();

BuildableSave newSave;
List<BuildableSave> saves;
bool removedAny;

await _semaphore.WaitAsync(token);
await _semaphore.WaitAsync(token).ConfigureAwait(false);
try
{
byte region = _region;
int mapId = _mapScheduler.Current;
uint instId = barricade.instanceID;

saves = await _dbContext.Saves
List<BuildableSave> saves = await _dbContext.Saves
.Include(save => save.InstanceIds)
.Where(save => !save.IsStructure && save.MapId.HasValue && save.MapId.Value == mapId && save.InstanceIds!.Any(instanceId => instanceId.RegionId == region && instanceId.InstanceId == instId))
.Where(save => !save.IsStructure
&& save.MapId.HasValue
&& save.MapId.Value == mapId
&& save.InstanceIds!.Any(instanceId => instanceId.RegionId == region && instanceId.InstanceId == instId)
)
.ToListAsync(token);

_dbContext.RemoveRange(saves);
_dbContext.Saves.RemoveRange(saves);

Vector3 rot = data.rotation.eulerAngles;
newSave = new BuildableSave
BuildableSave newSave = new BuildableSave
{
Buildable = new BuildableBarricade(barricade),
InstanceId = instId,
Expand Down Expand Up @@ -229,34 +224,26 @@ public async UniTask<bool> SaveBarricadeAsync(BarricadeDrop barricade, Cancellat
Save = newSave
};

newSave.InstanceIds.Add(instanceId);

_dbContext.Add(newSave);
_dbContext.Add(instanceId);

await _dbContext.SaveChangesAsync(token);
}
finally
{
_semaphore.Release();
}

bool removedAny = saves.Count == 0;

if (!data.barricade.isDead)
return removedAny;
removedAny = saves.Count == 0;

await UniTask.SwitchToMainThread(CancellationToken.None);

if (!RestoreSave(null, 0, newSave))
return removedAny;
if (data.barricade.isDead)
{
await UniTask.SwitchToMainThread(CancellationToken.None);

await _semaphore.WaitAsync(token);
try
{
_dbContext.Update(newSave);
if (newSave.InstanceIds.FirstOrDefault(x => x.RegionId == _region) is { } instanceId)
_dbContext.Update(instanceId);
if (RestoreSave(null, 0, newSave))
{
await _dbContext.SaveChangesAsync(token);
}
}

await _dbContext.SaveChangesAsync(token);
_dbContext.ChangeTracker.Clear();
}
finally
{
Expand All @@ -275,25 +262,28 @@ public async UniTask<bool> SaveStructureAsync(StructureDrop structure, Cancellat
StructureData data = structure.GetServersideData();
await UniTask.SwitchToThreadPool();

BuildableSave newSave;
List<BuildableSave> saves;
bool removedAny;

await _semaphore.WaitAsync(token);
await _semaphore.WaitAsync(token).ConfigureAwait(false);
try
{
byte region = _region;
int mapId = _mapScheduler.Current;
uint instId = structure.instanceID;

saves = await _dbContext.Saves
List<BuildableSave> saves = await _dbContext.Saves
.Include(save => save.InstanceIds)
.Where(save => save.IsStructure && save.MapId.HasValue && save.MapId.Value == mapId && save.InstanceIds!.Any(instanceId => instanceId.RegionId == region && instanceId.InstanceId == instId))
.Where(save => save.IsStructure
&& save.MapId.HasValue
&& save.MapId.Value == mapId
&& save.InstanceIds!.Any(instanceId => instanceId.RegionId == region && instanceId.InstanceId == instId)
)
.ToListAsync(token);

_dbContext.RemoveRange(saves);
_dbContext.Saves.RemoveRange(saves);

Vector3 rot = data.rotation.eulerAngles;
newSave = new BuildableSave
BuildableSave newSave = new BuildableSave
{
Buildable = new BuildableStructure(structure),
InstanceId = instId,
Expand Down Expand Up @@ -326,30 +316,20 @@ public async UniTask<bool> SaveStructureAsync(StructureDrop structure, Cancellat
_dbContext.Add(instanceId);

await _dbContext.SaveChangesAsync(token);
}
finally
{
_semaphore.Release();
}

bool removedAny = saves.Count == 0;
removedAny = saves.Count == 0;

if (!data.structure.isDead)
return removedAny;

await UniTask.SwitchToMainThread(CancellationToken.None);
if (data.structure.isDead)
{
await UniTask.SwitchToMainThread(CancellationToken.None);

if (!RestoreSave(null, 0, newSave))
return removedAny;

await _semaphore.WaitAsync(token);
try
{
_dbContext.Update(newSave);
if (newSave.InstanceIds.FirstOrDefault(x => x.RegionId == _region) is { } instanceId)
_dbContext.Update(instanceId);
if (RestoreSave(null, 0, newSave))
{
await _dbContext.SaveChangesAsync(token);
}
}

await _dbContext.SaveChangesAsync(token);
_dbContext.ChangeTracker.Clear();
}
finally
{
Expand All @@ -359,6 +339,14 @@ public async UniTask<bool> SaveStructureAsync(StructureDrop structure, Cancellat
return removedAny;
}

/// <summary>
/// Check if a buildable is saved or not.
/// </summary>
public UniTask<bool> IsBuildableSavedAsync(IBuildable buildable, CancellationToken token = default)
{
return IsBuildableSavedAsync(buildable.InstanceId, buildable.IsStructure, token);
}

/// <summary>
/// Check if a barricade is saved or not.
/// </summary>
Expand All @@ -380,24 +368,36 @@ public UniTask<bool> IsStructureSavedAsync(uint instanceId, CancellationToken to
/// </summary>
public async UniTask<bool> IsBuildableSavedAsync(uint instanceId, bool isStructure, CancellationToken token = default)
{
await _semaphore.WaitAsync(token);
await _semaphore.WaitAsync(token).ConfigureAwait(false);
try
{
byte region = _region;
int mapId = _mapScheduler.Current;

return await _dbContext.Saves
bool any = await _dbContext.Saves
.AsNoTracking()
.Where(save => save.IsStructure == isStructure
&& save.MapId.HasValue && save.MapId.Value == mapId
&& save.InstanceIds!.Any(instId => instId.RegionId == region && instId.InstanceId == instanceId))
.AnyAsync(token);

_dbContext.ChangeTracker.Clear();
return any;
}
finally
{
_semaphore.Release();
}
}

/// <summary>
/// Get the save info of a buildable, or <see langword="null"/> if it's not saved.
/// </summary>
public UniTask<BuildableSave?> GetBuildableSaveAsync(IBuildable buildable, CancellationToken token = default)
{
return GetBuildableSaveAsync(buildable.InstanceId, buildable.IsStructure, token);
}

/// <summary>
/// Get the save info of a barricade, or <see langword="null"/> if it's not saved.
/// </summary>
Expand All @@ -419,17 +419,57 @@ public async UniTask<bool> IsBuildableSavedAsync(uint instanceId, bool isStructu
/// </summary>
public async UniTask<BuildableSave?> GetBuildableSaveAsync(uint instanceId, bool isStructure, CancellationToken token = default)
{
await _semaphore.WaitAsync(token);
await _semaphore.WaitAsync(token).ConfigureAwait(false);
try
{
byte region = _region;
int mapId = _mapScheduler.Current;

return await _dbContext.Saves
BuildableSave? save = await _dbContext.Saves
.AsNoTracking()
.Where(save => save.IsStructure == isStructure
&& save.MapId.HasValue && save.MapId.Value == mapId
&& save.InstanceIds!.Any(instId => instId.RegionId == region && instId.InstanceId == instanceId))
.FirstOrDefaultAsync(token);

_dbContext.ChangeTracker.Clear();
return save;
}
finally
{
_semaphore.Release();
}
}

/// <summary>
/// Gets a list of all buildables that are saved.
/// </summary>
public async Task<List<BuildableSave>> GetAllSavesAsync(CancellationToken token = default)
{
await _semaphore.WaitAsync(token).ConfigureAwait(false);
try
{
byte region = _region;
int mapId = _mapScheduler.Current;

List<BuildableSave> saves = await _dbContext.Saves
.AsNoTracking()
.Include(save => save.DisplayData)
.Include(save => save.InstanceIds)
.Include(save => save.Items)
.Where(save => save.MapId.HasValue
&& save.MapId.Value == mapId
&& save.InstanceIds!.Any(instId => instId.RegionId == region)
)
.ToListAsync(token);

foreach (BuildableSave save in saves)
{
save.InstanceId = save.InstanceIds!.First(instanceId => instanceId.RegionId == _region).InstanceId;
}

_dbContext.ChangeTracker.Clear();
return saves;
}
finally
{
Expand Down Expand Up @@ -472,7 +512,7 @@ public async UniTask<bool> DiscardBuildableAsync(uint instanceId, bool isStructu
{
await UniTask.SwitchToThreadPool();

await _semaphore.WaitAsync(token);
await _semaphore.WaitAsync(token).ConfigureAwait(false);
try
{
byte region = _region;
Expand All @@ -497,6 +537,7 @@ public async UniTask<bool> DiscardBuildableAsync(uint instanceId, bool isStructu
/// <summary>
/// Sync an exitsing buildable with a buildable save, or replace the buildable if it's missing.
/// </summary>
/// <returns>If the save needs to be re-synced with the database.</returns>
private bool RestoreSave(List<BuildableSave>? saves, int index, BuildableSave save)
{
object? drop = save.IsStructure
Expand Down
18 changes: 11 additions & 7 deletions UncreatedWarfare/Commands/Clear/ClearBuildablesCommand.cs
Original file line number Diff line number Diff line change
@@ -1,27 +1,31 @@
using Uncreated.Warfare.Interaction.Commands;
using Uncreated.Warfare.Buildables;
using Uncreated.Warfare.Interaction.Commands;
using Uncreated.Warfare.Logging;
using Uncreated.Warfare.Translations;
using Uncreated.Warfare.Util;

namespace Uncreated.Warfare.Commands;

[Command("buildables", "structures", "barricades", "buildable", "structure", "barricade", "struct", "b", "s"), SubCommandOf(typeof(ClearCommand))]
public class ClearBuildablesCommand : IExecutableCommand
{
private readonly BuildableSaver _buildableSaver;
private readonly ClearTranslations _translations;

public CommandContext Context { get; set; }
public ClearBuildablesCommand(TranslationInjection<ClearTranslations> translations)
public ClearBuildablesCommand(TranslationInjection<ClearTranslations> translations, BuildableSaver buildableSaver)
{
_buildableSaver = buildableSaver;
_translations = translations.Value;
}

public UniTask ExecuteAsync(CancellationToken token)
public async UniTask ExecuteAsync(CancellationToken token)
{
// todo
//Data.Gamemode.ReplaceBarricadesAndStructures();
await _buildableSaver.DestroyUnsavedBuildables(Context.CallerId, token).ConfigureAwait(false);

await UniTask.SwitchToMainThread(token);

Context.LogAction(ActionLogType.ClearStructures);
Context.Reply(_translations.ClearStructures);

return UniTask.CompletedTask;
}
}
2 changes: 0 additions & 2 deletions UncreatedWarfare/Commands/Kit/KitGiveAccessCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,6 @@ public async UniTask ExecuteAsync(CancellationToken token)
throw Context.Reply(_translations.KitAlreadyHasAccess, player, kit);
}

// todo KitSync.OnAccessChanged(steam64.m_SteamID);

await UniTask.SwitchToMainThread(token);

Context.LogAction(ActionLogType.ChangeKitAccess, steam64.m_SteamID.ToString(CultureInfo.InvariantCulture) + " GIVEN ACCESS TO " + kitName + ", REASON: " + accessType);
Expand Down
Loading

0 comments on commit 400c936

Please sign in to comment.