From df70d2eac0cfc2d979838900d04cb3e4e41a4566 Mon Sep 17 00:00:00 2001 From: sourpuh <150582765+sourpuh@users.noreply.github.com> Date: Sat, 7 Dec 2024 19:05:28 -0800 Subject: [PATCH] Fix placement bugs --- WaymarkStudio/WaymarkManager.cs | 50 +++++++++++++++++++-------------- 1 file changed, 29 insertions(+), 21 deletions(-) diff --git a/WaymarkStudio/WaymarkManager.cs b/WaymarkStudio/WaymarkManager.cs index 389f81b..b07bfd9 100644 --- a/WaymarkStudio/WaymarkManager.cs +++ b/WaymarkStudio/WaymarkManager.cs @@ -29,6 +29,7 @@ internal class WaymarkManager internal Dictionary placeholders = new(); internal IReadOnlyDictionary hoverPreviews = EmptyWaymarks; private readonly Stopwatch lastPlacementTimer; + private List<(Waymark waymark, Vector3 wPos)> safePlaceQueue = new(); private unsafe delegate byte PlaceWaymark(MarkingController* markingController, uint marker, Vector3 wPos); private readonly PlaceWaymark placeWaymarkFn; @@ -74,6 +75,7 @@ internal void OnTerritoryChange(TerritoryType territory) hoverPreviews = EmptyWaymarks; showGuide = false; guide = new CircleGuide(radius: 1); + safePlaceQueue.Clear(); } internal void ClearPlaceholders() { @@ -103,7 +105,7 @@ private bool IsPointGrounded(Vector3 point) Vector3 castOrigin = point + castOffset; if (BGCollisionModule.RaycastMaterialFilter(castOrigin, -Vector3.UnitY, out RaycastHit hitInfo, castHeight)) { - return point == hitInfo.Point.Round(); + return point.Y == hitInfo.Point.Round().Y; } return false; } @@ -166,25 +168,6 @@ internal void ClearWaymarkPlaceholder(Waymark waymark) placeholders.Remove(waymark); } - internal async void PlaceWaymarkWithRetries(Waymark waymark, Vector3 wPos, bool clearPlaceholder = true) - { - ushort territoryId = this.territoryId; - await Plugin.Framework.Run(async () => - { - // TODO tidy - while (!SafePlaceWaymark(waymark, wPos)) - { - await Plugin.Framework.DelayTicks(100); - if (territoryId != this.territoryId) - { - return; - } - } - if (clearPlaceholder && placeholders.GetValueOrDefault(waymark) == wPos) - placeholders.Remove(waymark); - }); - } - internal bool SafePlaceWaymark(Waymark waymark, Vector3 wPos) { var reason = WaymarkPlacementStatus(wPos); @@ -257,11 +240,36 @@ public void SafePlacePreset(WaymarkPreset preset, bool clearPlaceholder = true, foreach (Waymark w in Enum.GetValues()) { if (preset.MarkerPositions.TryGetValue(w, out var wPos)) - Plugin.WaymarkManager.PlaceWaymarkWithRetries(w, wPos, clearPlaceholder); + safePlaceQueue.Add((w, wPos)); } + processSafePlaceQueue(clearPlaceholder); } } + internal async void processSafePlaceQueue(bool clearPlaceholder = true) + { + await Plugin.Framework.Run(async () => + { + var territoryId = this.territoryId; + int attempts = safePlaceQueue.Count + 2; + while (safePlaceQueue.Count > 0 && territoryId == this.territoryId && attempts-- > 0) + { + (Waymark waymark, Vector3 wPos) = safePlaceQueue[0]; + safePlaceQueue.RemoveAt(0); + if (SafePlaceWaymark(waymark, wPos)) + if (clearPlaceholder && placeholders.GetValueOrDefault(waymark) == wPos) + placeholders.Remove(waymark); + else + // requeue failure in case it was retriable + // TODO actually differentiate between retriable and not + safePlaceQueue.Add((waymark, wPos)); + await Plugin.Framework.DelayTicks(50); + } + safePlaceQueue.Clear(); + Plugin.Chat.Print("Placement complete"); + }); + } + private unsafe bool UnsafeNativePlacePreset(FieldMarkerPreset preset) { var placementStruct = preset.ToMarkerPresetPlacement();