fixes, renames, cleanup

This commit is contained in:
Tyfon
2024-06-17 12:41:42 -07:00
parent 2824f684cc
commit da3ffc170d
7 changed files with 93 additions and 36 deletions

View File

@@ -47,7 +47,7 @@ namespace UIFixes
public static void Clear()
{
// ToList() because we'll be modifying the collection
// ToList() because modifying the collection
foreach (GridItemView itemView in SelectedItemViews.Keys.ToList())
{
Deselect(itemView);

View File

@@ -91,31 +91,36 @@ namespace UIFixes
public class CreateSubInteractionsInventoryPatch : ModulePatch
{
private static bool LoadingInsuranceActions = false;
protected override MethodBase GetTargetMethod()
{
return AccessTools.Method(InventoryRootInteractionsType, "CreateSubInteractions");
}
private static int GetPlayerRubles(ItemUiContext itemUiContext)
{
StashClass stash = itemUiContext.R().InventoryController.Inventory.Stash;
if (stash == null)
{
return 0;
}
return R.Money.GetMoneySums(stash.Grid.ContainedItems.Keys)[ECurrencyType.RUB];
}
[PatchPrefix]
public static bool Prefix(EItemInfoButton parentInteraction, ISubInteractions subInteractionsWrapper, Item ___item_0, ItemUiContext ___itemUiContext_1)
{
// Clear this, since something else should be active (even a different mouseover of the insurance button)
LoadingInsuranceActions = false;
if (parentInteraction == EItemInfoButton.Insure)
{
int playerRubles = GetPlayerRubles(___itemUiContext_1);
CurrentInsuranceInteractions = new(___item_0, ___itemUiContext_1, playerRubles);
CurrentInsuranceInteractions.LoadAsync(() => subInteractionsWrapper.SetSubInteractions(CurrentInsuranceInteractions));
// Because this is async, need to protect against a different subInteractions activating before loading is done
// This isn't thread-safe at all but now the race condition is a microsecond instead of hundreds of milliseconds.
LoadingInsuranceActions = true;
CurrentInsuranceInteractions.LoadAsync(() =>
{
if (LoadingInsuranceActions)
{
subInteractionsWrapper.SetSubInteractions(CurrentInsuranceInteractions);
LoadingInsuranceActions = false;
}
});
return false;
}
@@ -150,6 +155,8 @@ namespace UIFixes
public class CreateSubInteractionsTradingPatch : ModulePatch
{
private static bool LoadingInsuranceActions = false;
protected override MethodBase GetTargetMethod()
{
return AccessTools.Method(TradingRootInteractionsType, "CreateSubInteractions");
@@ -158,22 +165,40 @@ namespace UIFixes
[PatchPrefix]
public static bool Prefix(object __instance, EItemInfoButton parentInteraction, ISubInteractions subInteractionsWrapper, ItemUiContext ___itemUiContext_0)
{
Dictionary<ECurrencyType, int> playerCurrencies = R.Money.GetMoneySums(___itemUiContext_0.R().InventoryController.Inventory.Stash.Grid.ContainedItems.Keys);
int playerRubles = playerCurrencies[ECurrencyType.RUB];
// CreateSubInteractions is only on the base class here, which doesn't have an Item. But __instance is actually a GClass3032
Item item = (Item)TradingRootInteractionsItemField.GetValue(__instance);
// Clear this, since something else should be active (even a different mouseover of the insurance button)
LoadingInsuranceActions = false;
if (parentInteraction == EItemInfoButton.Insure)
{
int playerRubles = GetPlayerRubles(___itemUiContext_0);
// CreateSubInteractions is only on the base class here, which doesn't have an Item. But __instance is actually a GClass3032
Item item = (Item)TradingRootInteractionsItemField.GetValue(__instance);
CurrentInsuranceInteractions = new(item, ___itemUiContext_0, playerRubles);
CurrentInsuranceInteractions.LoadAsync(() => subInteractionsWrapper.SetSubInteractions(CurrentInsuranceInteractions));
// Because this is async, need to protect against a different subInteractions activating before loading is done
// This isn't thread-safe at all but now the race condition is a microsecond instead of hundreds of milliseconds.
LoadingInsuranceActions = true;
CurrentInsuranceInteractions.LoadAsync(() =>
{
if (LoadingInsuranceActions)
{
subInteractionsWrapper.SetSubInteractions(CurrentInsuranceInteractions);
LoadingInsuranceActions = false;
}
});
return false;
}
if (parentInteraction == EItemInfoButton.Repair)
{
int playerRubles = GetPlayerRubles(___itemUiContext_0);
// CreateSubInteractions is only on the base class here, which doesn't have an Item. But __instance is actually a GClass3032
Item item = (Item)TradingRootInteractionsItemField.GetValue(__instance);
CurrentRepairInteractions = new(item, ___itemUiContext_0, playerRubles);
subInteractionsWrapper.SetSubInteractions(CurrentRepairInteractions);
@@ -276,5 +301,16 @@ namespace UIFixes
return true;
}
}
private static int GetPlayerRubles(ItemUiContext itemUiContext)
{
StashClass stash = itemUiContext.R().InventoryController.Inventory.Stash;
if (stash == null)
{
return 0;
}
return R.Money.GetMoneySums(stash.Grid.ContainedItems.Keys)[ECurrencyType.RUB];
}
}
}

View File

@@ -113,7 +113,7 @@ namespace UIFixes
return;
}
// Restore scroll position now that the we're loaded
// Restore scroll position now that offers are loaded
if (History.Any())
{
offerViewList.R().Scroller.SetScrollPosition(History.Peek().scrollPosition);
@@ -239,7 +239,7 @@ namespace UIFixes
newRule.SortType = filterRule.SortType;
newRule.SortDirection = filterRule.SortDirection;
// We can't set handbookId yet - it limits the result set and that in turn limits what categories even display
// Can't set handbookId yet - it limits the result set and that in turn limits what categories even display
DelayedHandbookId = filterRule.HandbookId;
ragfair.SetFilterRule(newRule, true, true);
@@ -339,7 +339,7 @@ namespace UIFixes
return AccessTools.Method(typeof(OfferViewList), nameof(OfferViewList.method_10));
}
// The firs thing this method does is set scrollposition to 0, so we need to grab it first
// The first thing this method does is set scrollposition to 0, so grab it first
[PatchPrefix]
public static void Prefix(LightScroller ____scroller)
{

View File

@@ -72,7 +72,7 @@ namespace UIFixes
inventoryController.LoadMagazine(bullets, magazine, count, false).HandleExceptions();
}
// The calling code in this instance doesn't do anything with the task, but it does await it, so if we don't return a Task it nullrefs
// The calling code in this instance doesn't do anything with the task, but it does await it, so if this doesn't return a Task it nullrefs
__result = Task.CompletedTask;
return false;
}

View File

@@ -240,7 +240,7 @@ namespace UIFixes
}
[PatchPrefix]
public static bool Prefix(GridView __instance, ItemContextClass itemContext, ItemContextAbstractClass targetItemContext, ref GStruct413 operation, ref bool __result)
public static bool Prefix(GridView __instance, ItemContextClass itemContext, ItemContextAbstractClass targetItemContext, ref GStruct413 operation, ref bool __result, ItemUiContext ___itemUiContext_0)
{
if (!Settings.EnableMultiSelect.Value || InPatch || !MultiSelect.Active)
{
@@ -311,6 +311,12 @@ namespace UIFixes
}
else
{
// Wrap this error to display it
if (operation.Error is GClass3292 noRoomError)
{
operation = new(new DisplayableErrorWrapper(noRoomError));
}
break;
}
@@ -326,7 +332,7 @@ namespace UIFixes
HidePreviews();
}
// We didn't simulate so now we undo
// Didn't simulate so now undo
while (operations.Any())
{
operations.Pop().Value?.RollBack();
@@ -335,6 +341,21 @@ namespace UIFixes
// result and operation are set to the last one that completed - so success if they all passed, or the first failure
return false;
}
// GridView.HighlightItemViewPosition has a blacklist of errors it won't show, but it shows other types.
// Wrapping an error can get past that
private class DisplayableErrorWrapper(InventoryError error) : InventoryError
{
public override string ToString()
{
return error.ToString();
}
public override string GetLocalizedDescription()
{
return error.GetLocalizedDescription();
}
}
}
public class GridViewAcceptItemPatch : ModulePatch
@@ -470,7 +491,7 @@ namespace UIFixes
}
[PatchPrefix]
public static bool Prefix(SlotView __instance, ItemContextAbstractClass targetItemContext, ref GStruct413 operation, ref bool __result, InventoryControllerClass ___InventoryController)
public static bool Prefix(SlotView __instance, ItemContextAbstractClass targetItemContext, ref GStruct413 operation, ref bool __result, InventoryControllerClass ___InventoryController, ItemUiContext ___ItemUiContext)
{
if (!Settings.EnableMultiSelect.Value || InPatch || !MultiSelect.Active)
{
@@ -500,7 +521,7 @@ namespace UIFixes
}
}
// We didn't simulate so now we undo
// Didn't simulate so now undo
while (operations.Any())
{
operations.Pop().Value?.RollBack();
@@ -599,7 +620,7 @@ namespace UIFixes
HidePreviews();
}
// We didn't simulate so now we undo
// Didn't simulate so now undo
while (operations.Any())
{
operations.Pop().Value?.RollBack();
@@ -631,7 +652,7 @@ namespace UIFixes
traderAssortmentController.PrepareToSell(itemContext.Item, locationInGrid);
itemContext.CloseDependentWindows();
// For the rest of the items we still need to use quickfind
// For the rest of the items, still need to use quickfind
foreach (ItemContextClass selectedItemContext in MultiSelect.ItemContexts.Where(ic => ic.Item != itemContext.Item))
{
GStruct413 operation = InteractionsHandlerClass.QuickFindAppropriatePlace(selectedItemContext.Item, traderAssortmentController.TraderController, [__instance.Grid.ParentItem as LootItemClass], InteractionsHandlerClass.EMoveItemOrder.Apply, true);

View File

@@ -15,10 +15,10 @@ namespace UIFixes
{
public static class SwapPatches
{
// Source container for the drag - we have to grab this early to check it
// Source container for the drag - grab this early to check it
private static IContainer SourceContainer;
// Whether we're being called from the "check every slot" loop
// Whether it's being called from the "check every slot" loop
private static bool InHighlight = false;
// The most recent CheckItemFilter result - needed to differentiate "No room" from incompatible
@@ -237,7 +237,7 @@ namespace UIFixes
// This is the location you're dragging it, including rotation
LocationInGrid itemToLocation = __instance.CalculateItemLocation(itemContext);
// Target is a grid because we're in the GridView patch, i.e. you're dragging it over a grid
// Target is a grid because this is the GridView patch, i.e. you're dragging it over a grid
var targetGridItemAddress = new R.GridItemAddress(targetItemAddress);
ItemAddress itemToAddress = R.GridItemAddress.Create(targetGridItemAddress.Grid, itemToLocation);
@@ -276,7 +276,7 @@ namespace UIFixes
}
}
// If we're coming from a grid, try rotating the target object
// If coming from a grid, try rotating the target object
if (R.GridItemAddress.Type.IsInstanceOfType(itemAddress))
{
var targetToLocation = new R.GridItemAddress(targetToAddress).LocationInGrid;
@@ -286,7 +286,7 @@ namespace UIFixes
var result = InteractionsHandlerClass.Swap(item, itemToAddress, targetItem, targetToAddress, traderControllerClass, true);
if (result.Succeeded)
{
// Only save this operation result if it succeeded, otherwise we return the non-rotated result from above
// Only save this operation result if it succeeded, otherwise return the non-rotated result from above
operation = new R.SwapOperation(result).ToGridViewCanAcceptOperation();
__result = true;
return;
@@ -443,7 +443,7 @@ namespace UIFixes
}
// CanApply, when dealing with containers, eventually calls down into FindPlaceForItem, which calls CheckItemFilter. For reasons,
// if an item fails the filters, it returns the error "no space", instead of "no action". Try to detect this, so we can swap.
// if an item fails the filters, it returns the error "no space", instead of "no action". Try to detect this in order to swap.
public class DetectFilterForSwapPatch : ModulePatch
{
protected override MethodBase GetTargetMethod()
@@ -461,7 +461,7 @@ namespace UIFixes
}
// When dragging an item around, by default it updates an ItemSpecificationPanel when you drag an item on top of a slot
// It doesn't do anything when you drag an item from a slot onto some other item elsewhere. But with swap, we should update the item panel then too.
// It doesn't do anything when you drag an item from a slot onto some other item elsewhere. But with swap, update the item panel then too.
public class InspectWindowUpdateStatsOnSwapPatch : ModulePatch
{
protected override MethodBase GetTargetMethod()