.github/workflows/build.yml --- YAML
1 name: Build
2
3 on:
4 workflow_dispatch:
5 push:
6 branches:
7 - main
8
9 env:
10 INTERNAL_NAME: AllaganMarket
11 CONFIGURATION: Release
12 DOTNET_CLI_TELEMETRY_OPTOUT: true
13
14 jobs:
15 build:
16 runs-on: windows-2022
17 steps:
18 - name: Checkout
19 uses: actions/checkout@v4
20 with:
21 submodules: recursive
22 - name: Setup MSBuild
23 uses: microsoft/[email protected]
24 - name: Download Dalamud
25 run: |
26 Invoke-WebRequest -Uri https://goatcorp.github.io/dalamud-distrib/latest.zip -OutFile latest.zip
27 Expand-Archive -Force latest.zip "$env:AppData\XIVLauncher\addon\Hooks\dev\"
28 - name: Restore
29 run: dotnet restore ${{ env.INTERNAL_NAME }}
30 - name: Build
31 run: dotnet build -c ${{ env.CONFIGURATION }} --no-restore ${{ env.INTERNAL_NAME }}
32 - name: Push artifacts
33 uses: actions/upload-artifact@v4
34 with:
35 name: dist
36 path: |
37 ${{ env.INTERNAL_NAME }}\bin\Release\${{ env.INTERNAL_NAME }}
38
.github/workflows/pr.yml --- YAML
1 name: Create D17 PR
2
3 on:
4 push:
5 tags:
6 - '*'
7
8 env:
9 INTERNAL_NAME: AllaganMarket
10 PLUGIN_NAME: Allagan Market
11 UPDATE_NAME: am
12
13 jobs:
14 update-repo:
15 runs-on: ubuntu-latest
16 permissions:
17 contents: write
18 steps:
19 - name: Checkout this repo
20 uses: actions/checkout@v4
21
22 - name: Extract version and changelog
23 id: changelog
24 run: |
25 VERSION=$(grep -m1 -oP '(?<=## \[)[0-9]+\.[0-9]+\.[0-9]+' ${{ env.INTERNAL_NAME }}/CHANGELOG.md)
26 echo "version=1.$VERSION" >> $GITHUB_OUTPUT
27 CHANGELOG=$(awk -v ver=$VERSION '/^#+ \[/ { if (p) { exit }; if ($2 == "["ver"]") { p=1; next} } p && NF' ${{ env.INTERNAL_NAME }}/CHANGELOG.md)
28 echo "log<<EOF" >> $GITHUB_OUTPUT
29 echo "$CHANGELOG" >> $GITHUB_OUTPUT
30 echo "EOF" >> $GITHUB_OUTPUT
31
32 - name: Extract release notes
33 id: extract-release-notes
34 uses: ffurrer2/extract-release-notes@v2
35 with:
36 release_notes_file: notes.md
37 changelog_file: ${{ env.INTERNAL_NAME }}/CHANGELOG.md
38
39 - name: Create release
40 env:
41 GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
42 run: gh release create ${{ github.ref_name }} --title ${{ github.ref_name }} --notes-file notes.md
43
44 - name: Checkout fork of external repo
45 uses: actions/checkout@v4
46 with:
47 repository: Critical-Impact/DalamudPluginsD17
48 fetch-depth: '1'
49 path: external
50 token: ${{ secrets.PR_PAT }}
51
52 - name: Configure git and create branch
53 run: |
54 cd external
55 git remote add goatcorp https://github.com/goatcorp/DalamudPluginsD17.git
56 git fetch goatcorp
57 git checkout -b ${{ env.UPDATE_NAME }}-${{ steps.changelog.outputs.version }} goatcorp/main
58
59 - name: Configure git author
60 run: |
61 cd external
62 git config user.name "${GITHUB_ACTOR}"
63 git config user.email "${GITHUB_ACTOR}@users.noreply.github.com"
64
65 - name: Update manifest.toml
66 run: |
67 cd external
68 pip install toml
69 python - <<EOF
70 import toml
71 from pathlib import Path
72
73 manifest_path = Path("stable/${{ env.INTERNAL_NAME }}/manifest.toml")
74 data = toml.load(manifest_path)
75
76 # Update commit and changelog
77 data["plugin"]["commit"] = "${GITHUB_SHA}"
78 data["plugin"]["version"] = "${{ steps.changelog.outputs.version }}"
79 data["plugin"]["changelog"] = """${{ steps.changelog.outputs.log }}"""
80
81 with manifest_path.open("w") as f:
82 toml.dump(data, f)
83 EOF
84 git add stable/${{ env.INTERNAL_NAME }}/manifest.toml
85 git commit -m "${{ env.PLUGIN_NAME }} ${{ steps.changelog.outputs.version }}"
86
87 - name: Push branch to fork
88 run: |
89 cd external
90 git push origin -f HEAD:${{ env.UPDATE_NAME }}-${{ steps.changelog.outputs.version }}
91
AllaganMarket/AllaganMarketPlugin.cs --- 1/2 --- C#
68 68 ITitleScreenMenu titleScreenMenu,
69 69 IDtrBar dtrBar,
70 70 IGameGui gameGui,
71 71 ICondition condition
,
.. 72 IObjectTable objectTable,
.. 73 IPlayerState playerState)
72 74 : base(
73 75 pluginInterface,
74 76 pluginLog,
AllaganMarket/AllaganMarketPlugin.cs --- 2/2 --- C#
85 87 titleScreenMenu,
86 88 dtrBar,
87 89 gameGui,
88 90 condition
,
.. 91 objectTable,
.. 92 playerState)
89 93 {
90 94 this.gameGui
= gameGui;
91 95 this.CreateHost();
AllaganMarket/CHANGELOG.md --- 1/2 --- Text
2 2
3 All notable changes to this project will be documented in this file.
3 All notable changes to this project will be documented in this file.
4 4
5 The log versioning the plugin versioning will not match as 1.0.0.0 technically does not match semantic versioning bu 5 The log versioning the plugin versioning will not match as 0.0.0 technically does not match semantic versioning but
. t the headache of trying to change this would be too much. . the headache of trying to change this would be too much.
6 Instead the changelog reader and automation surrounding plugin PRs will add the 1. back in 6 Instead the changelog reader and automation surrounding plugin PRs will add the back in
7 7
8 The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), 8 The format is based on [Keep a Changelog](https://keepachangelog.com/en/0/),
9 and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.html).
9 and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.html).
10 10
11 ## [1.3.0.0] - 2025-22-12 11 ## [3.0.1] - 2026-01-06
12 12
13 ### Fixed
13 ### Fixed
.. 14 - Fixed an issue when a HQ listing attempts to use the NQ pricing for the recommended unit price
.. 15
.. 16 ## [3.0.0] - 2025-22-12
.. 17
.. 18 ### Fixed
14 - Support for 7.4
19 - Support for 7.4
15 20
16 ## [1.2.0.5] - 2025-10-17 21 ## [2.0.5] - 2025-10-17
17 22
18 ### Fixed
23 ### Fixed
19 - Fixed a broken signature, I'll see if I can make this less liable to break later
24 - Fixed a broken signature, I'll see if I can make this less liable to break later
20 25
21 ## [1.2.0.4] - 2025-10-08 26 ## [2.0.4] - 2025-10-08
22 27
23 ### Fixed
28 ### Fixed
24 - Fixed broke signature
29 - Fixed broke signature
25 - Changed the way the retainer order is retrieved, this should fix some edge cases where peoples retainers were in t
30 - Changed the way the retainer order is retrieved, this should fix some edge cases where peoples retainers were in t
.. he wrong order.
.. he wrong order.
26 31
27 ## [1.2.0.3] - 2025-09-05 32 ## [2.0.3] - 2025-09-05
28 33
29 ### Fixed
34 ### Fixed
30 - Fixed signature mismatch
35 - Fixed signature mismatch
31 36
32 ## [1.2.0.2] - 2025-08-31 37 ## [2.0.2] - 2025-08-31
33 38
34 ### Fixed
39 ### Fixed
35 - Fixed a bug causing features/settings to not be loaded within the wizard causing it to never close
40 - Fixed a bug causing features/settings to not be loaded within the wizard causing it to never close
36 41
37 ## [1.2.0.1] - 2025-08-22 42 ## [2.0.1] - 2025-08-22
38 43
39 ### Added
44 ### Added
40 - Added debug windows available for end-users when debugging specific issues
45 - Added debug windows available for end-users when debugging specific issues
AllaganMarket/CHANGELOG.md --- 2/2 --- Text
47 - Fixed how the arrow buttons were rendered
52 - Fixed how the arrow buttons were rendered
48 - Changing the date in the sales summary should update the list instantly instead of needing a reorder
53 - Changing the date in the sales summary should update the list instantly instead of needing a reorder
49 54
50 ## [1.2.0.0] - 2025-08-09 55 ## [2.0.0] - 2025-08-09
51 56
52 ### Fixed
57 ### Fixed
53 - API13 support
58 - API13 support
AllaganMarket/Filtering/SaleFilter.cs --- 1/9 --- C#
21 21 IDataManager dataManager,
22 22 SaleTrackerService saleTrackerService,
23 23 ICharacterMonitorService characterMonitorService,
24 .. ItemUpdatePeriodSetting itemUpdatePeriodSetting,
25 .. Configuration configuration,
26 24 MediatorService mediatorService)
27 25 {
28 .. private readonly IDataManager dataManager = dataManager;
29 .. private readonly MediatorService mediatorService = mediatorService;
30 26 private readonly ExcelSheet<Item> itemSheet
= dataManager.
GetExcelSheet<Item>()
!;
31 27 private long aggSalesTotalGil;
32 28 private long aggSoldTotalGil;
AllaganMarket/Filtering/SaleFilter.cs --- 2/9 --- C#
36 32 private List<SearchResult>? cachedSoldResults;
37 33 private ulong? characterId;
38 34 private bool? showEmpty;
39 .. private bool? needUpdating;
40 35 private bool needsRefresh;
41 36 private uint? worldId;
42 37
AllaganMarket/Filtering/SaleFilter.cs --- 3/9 --- C#
79 74 this.characterId
= null;
80 75 this.worldId
= null;
81 76 this.showEmpty
= null;
82 .. this.needUpdating = null;
83 77 this.needsRefresh
= true;
84 78 }
85 79
AllaganMarket/Filtering/SaleFilter.cs --- 4/9 --- C#
93 return this.itemSheet.GetRow(rowId);
87 return this.itemSheet.GetRow(rowId);
94 }
88 }
95 89
96 private List<SearchResult> recalculateSaleResults()
90 private List<SearchResult> RecalculateSaleResults()
97 {
91 {
98 var saleItems
= this.GetSaleItems();
92 var saleItems
= this.GetSaleItems();
99 var searchResults
= new List<SearchResult>();
93 var searchResults
= new List<SearchResult>();
100 searchResults.AddRange(saleItems.Select(c
=> new SearchResult() { SaleItem
= c }));
94 searchResults.AddRange(saleItems.Select(c
=> new SearchResult() { SaleItem
= c }));
101 return searchResults;
95 return searchResults;
102 }
96 }
103 97
104 private List<SearchResult> recalculateSoldResults()
98 private List<SearchResult> RecalculateSoldResults()
105 {
99 {
106 var soldItems
= this.GetSoldItems();
100 var soldItems
= this.GetSoldItems();
107 var searchResults
= new List<SearchResult>();
101 var searchResults
= new List<SearchResult>();
AllaganMarket/Filtering/SaleFilter.cs --- 5/9 --- C#
111 105
112 106 public void NotifyRefresh()
113 107 {
114 108 this.mediatorService.Publish(
new SaleFilterRefreshedMessage());
115 109 }
116 110
117 111 public List<SaleItem> GetSaleItems()
AllaganMarket/Filtering/SaleFilter.cs --- 6/9 --- C#
120 {
114 {
121 this.cachedSales
= this.RecalculateSaleItems();
115 this.cachedSales
= this.RecalculateSaleItems();
122 this.cachedSoldItems
= this.RecalculateSoldItems();
116 this.cachedSoldItems
= this.RecalculateSoldItems();
123 this.cachedSaleResults
= this.
recalculateSaleResults();
117 this.cachedSaleResults
= this.
RecalculateSaleResults();
124 this.cachedSoldResults
= this.
recalculateSoldResults();
118 this.cachedSoldResults
= this.
RecalculateSoldResults();
125 this.NotifyRefresh();
119 this.NotifyRefresh();
126 }
120 }
127 121
AllaganMarket/Filtering/SaleFilter.cs --- 7/9 --- C#
134 {
128 {
135 this.cachedSales
= this.RecalculateSaleItems();
129 this.cachedSales
= this.RecalculateSaleItems();
136 this.cachedSoldItems
= this.RecalculateSoldItems();
130 this.cachedSoldItems
= this.RecalculateSoldItems();
137 this.cachedSaleResults
= this.
recalculateSaleResults();
131 this.cachedSaleResults
= this.
RecalculateSaleResults();
138 this.cachedSoldResults
= this.
recalculateSoldResults();
132 this.cachedSoldResults
= this.
RecalculateSoldResults();
139 this.NotifyRefresh();
133 this.NotifyRefresh();
140 }
134 }
141 135
AllaganMarket/Filtering/SaleFilter.cs --- 8/9 --- C#
148 {
142 {
149 this.cachedSales
= this.RecalculateSaleItems();
143 this.cachedSales
= this.RecalculateSaleItems();
150 this.cachedSoldItems
= this.RecalculateSoldItems();
144 this.cachedSoldItems
= this.RecalculateSoldItems();
151 this.cachedSaleResults
= this.
recalculateSaleResults();
145 this.cachedSaleResults
= this.
RecalculateSaleResults();
152 this.cachedSoldResults
= this.
recalculateSoldResults();
146 this.cachedSoldResults
= this.
RecalculateSoldResults();
153 this.NotifyRefresh();
147 this.NotifyRefresh();
154 }
148 }
155 149
AllaganMarket/Filtering/SaleFilter.cs --- 9/9 --- C#
162 {
156 {
163 this.cachedSales
= this.RecalculateSaleItems();
157 this.cachedSales
= this.RecalculateSaleItems();
164 this.cachedSoldItems
= this.RecalculateSoldItems();
158 this.cachedSoldItems
= this.RecalculateSoldItems();
165 this.cachedSaleResults
= this.
recalculateSaleResults();
159 this.cachedSaleResults
= this.
RecalculateSaleResults();
166 this.cachedSoldResults
= this.
recalculateSoldResults();
160 this.cachedSoldResults
= this.
RecalculateSoldResults();
167 this.NotifyRefresh();
161 this.NotifyRefresh();
168 }
162 }
169 163
AllaganMarket/Models/MarketPriceCache.cs --- C#
45 45 {
46 46 case MarketPriceCacheType.Game
:
47 47 return "In-Game";
48 .. break;
49 48 case MarketPriceCacheType.UniversalisWS
:
50 .. return "Universalis";
51 .. break;
52 49 case MarketPriceCacheType.UniversalisReq
:
53 50 return "Universalis";
54 .. break;
55 51 case MarketPriceCacheType.Override
:
56 52 return "Forced Update";
57 .. break;
58 53 }
59 54
60 55 return "Unknown";
AllaganMarket/Services/CharacterMonitorService.cs --- 1/4 --- C#
23 23 IClientState clientState,
24 24 IRetainerService retainerService,
25 25 IAddonLifecycle addonLifecycle,
.. 26 IObjectTable objectTable,
.. 27 IPlayerState playerState,
26 28 IPluginLog pluginLog)
: ICharacterMonitorService
27 29 {
28 30 private ulong cachedRetainerId;
AllaganMarket/Services/CharacterMonitorService.cs --- 2/4 --- C#
35 37
36 public ulong ActiveRetainerId
=> retainerService.RetainerId;
38 public ulong ActiveRetainerId
=> retainerService.RetainerId;
37 39
38 public ulong ActiveCharacterId
=> clientState.
LocalContentId;
40 public ulong ActiveCharacterId
=> playerState.
ContentId;
39 41
40 public bool IsLoggedIn
=> clientState.IsLoggedIn;
42 public bool IsLoggedIn
=> clientState.IsLoggedIn;
41 43
AllaganMarket/Services/CharacterMonitorService.cs --- 3/4 --- C#
136 138
137 private void UpdatePlayerCharacter()
139 private void UpdatePlayerCharacter()
138 {
140 {
139 if (
clientState.LocalPlayer
!= null && clientState.
LocalContentId != 0)
141 if (
objectTable.LocalPlayer
!= null && playerState.
ContentId != 0)
140 {
142 {
141 var newCharacter
= new Character(
143 var newCharacter
= new Character(
142 CharacterType.Character,
144 CharacterType.Character,
143 clientState.
LocalContentId,
145 playerState.
ContentId,
144 clientState.LocalPlayer.Name.ToString(),
146 objectTable.LocalPlayer.Name.ToString(),
145 clientState.LocalPlayer.HomeWorld.RowId,
147 objectTable.LocalPlayer.HomeWorld.RowId,
146 clientState.LocalPlayer.ClassJob.RowId,
148 objectTable.LocalPlayer.ClassJob.RowId,
147 clientState.LocalPlayer.Level,
149 objectTable.LocalPlayer.Level,
148 0);
150 0);
149 this.Characters[
clientState.
LocalContentId]
= newCharacter;
151 this.Characters[
playerState.
ContentId]
= newCharacter;
150 }
152 }
151 }
153 }
152 154
153 private unsafe void UpdateRetainer()
155 private unsafe void UpdateRetainer()
154 {
156 {
155 var retainerId
= this.cachedRetainerId;
157 var retainerId
= this.cachedRetainerId;
156 if (retainerId
!= 0
&& clientState.LocalPlayer
!= null)
158 if (retainerId
!= 0
&& objectTable.LocalPlayer
!= null)
157 {
159 {
158 pluginLog.Verbose(
$"Updating retainers: {retainerId}");
160 pluginLog.Verbose(
$"Updating retainers: {retainerId}");
159 for (
byte index
= 0; index
< 10; index
++)
161 for (
byte index
= 0; index
< 10; index
++)
AllaganMarket/Services/CharacterMonitorService.cs --- 4/4 --- C#
169 CharacterType.Retainer,
171 CharacterType.Retainer,
170 retainerId,
172 retainerId,
171 retainerName,
173 retainerName,
172 clientState.LocalPlayer.HomeWorld.RowId,
174 objectTable.LocalPlayer.HomeWorld.RowId,
173 retainer->ClassJob,
175 retainer->ClassJob,
174 retainer->Level,
176 retainer->Level,
175 index);
177 index);
176 newRetainer.RetainerTown
= retainer->Town;
178 newRetainer.RetainerTown
= retainer->Town;
177 newRetainer.OwnerId
= clientState.
LocalContentId;
179 newRetainer.OwnerId
= playerState.
ContentId;
178 this.Characters[retainerId]
= newRetainer;
180 this.Characters[retainerId]
= newRetainer;
179 }
181 }
180 }
182 }
AllaganMarket/Services/HighlightingService.cs --- 1/4 --- C#
45 45 private readonly HighlightingRetainerListSetting retainerListSetting;
46 46 private readonly HighlightingRetainerSellListSetting retainerSellListSetting;
47 47 private readonly IGameGui gameGui;
.. 48 private readonly IPlayerState playerState;
48 49 private bool retainerListModified;
49 50 private bool retainerSellListModified;
50 51 private ByteColor? originalRetainerListColor;
AllaganMarket/Services/HighlightingService.cs --- 2/4 --- C#
62 63 ExcelSheet<Item> itemSheet,
63 64 HighlightingRetainerListSetting retainerListSetting,
64 65 HighlightingRetainerSellListSetting retainerSellListSetting,
65 66 IGameGui gameGui
,
.. 67 IPlayerState playerState)
66 68 {
67 69 this.addonLifecycle
= addonLifecycle;
68 70 this.retainerService
= retainerService;
AllaganMarket/Services/HighlightingService.cs --- 3/4 --- C#
76 78 this.retainerListSetting
= retainerListSetting;
77 79 this.retainerSellListSetting
= retainerSellListSetting;
78 80 this.gameGui
= gameGui;
.. 81 this.playerState = playerState;
79 82 }
80 83
81 84 public static ByteColor ColorFromVector4(
Vector4 hexString)
AllaganMarket/Services/HighlightingService.cs --- 4/4 --- C#
121 var componentList
= addon->GetComponentListById(27);
124 var componentList
= addon->GetComponentListById(27);
122 if (componentList
!= null)
125 if (componentList
!= null)
123 {
126 {
124 var retainers
= this.characterMonitorService.GetRetainers(
this.
clientState.
LocalContentId)
127 var retainers
= this.characterMonitorService.GetRetainers(
this.
playerState.
ContentId)
125 .OrderBy(c
=> c.DisplayOrder).ToArray();
128 .OrderBy(c
=> c.DisplayOrder).ToArray();
126 129
127 foreach (
var index
in Enumerable.Range(0, componentList->ListLength))
130 foreach (
var index
in Enumerable.Range(0, componentList->ListLength))
AllaganMarket/Services/NotificationService.cs --- 1/5 --- C#
40 40 private readonly ChatNotifyUndercutLoginChatTypeSetting notifyUndercutLoginChatTypeSetting;
41 41 private readonly ICharacterMonitorService characterMonitorService;
42 42 private readonly IRetainerService retainerService;
.. 43 private readonly IPlayerState playerState;
43 44 private readonly Subject<(
ulong RetainerId,
uint ItemId)
> undercutQueue
= new();
44 45
45 46 public NotificationService(
AllaganMarket/Services/NotificationService.cs --- 2/5 --- C#
58 59 ChatNotifyUndercutLoginSetting notifyUndercutLoginSetting,
59 60 ChatNotifyUndercutLoginChatTypeSetting notifyUndercutLoginChatTypeSetting,
60 61 ICharacterMonitorService characterMonitorService,
61 62 IRetainerService retainerService
,
.. 63 IPlayerState playerState)
62 64 {
63 65 this.undercutService
= undercutService;
64 66 this.saleTrackerService
= saleTrackerService;
AllaganMarket/Services/NotificationService.cs --- 3/5 --- C#
76 78 this.notifyUndercutLoginChatTypeSetting
= notifyUndercutLoginChatTypeSetting;
77 79 this.characterMonitorService
= characterMonitorService;
78 80 this.retainerService
= retainerService;
.. 81 this.playerState = playerState;
79 82 this.undercutQueue
80 83 .Buffer(()
=> this.undercutQueue.Throttle(TimeSpan.FromSeconds(2)))
81 84 .Subscribe(
AllaganMarket/Services/NotificationService.cs --- 4/5 --- C#
118 ulong? characterId
= null;
121 ulong? characterId
= null;
119 if (characterSetting
== ChatNotifyCharacterEnum.OnlyActiveCharacter)
122 if (characterSetting
== ChatNotifyCharacterEnum.OnlyActiveCharacter)
120 {
123 {
121 characterId
= this.
clientState.
LocalContentId;
124 characterId
= this.
playerState.
ContentId;
122 }
125 }
123 126
124 var undercutHashSet
= undercuts.Distinct().ToHashSet();
127 var undercutHashSet
= undercuts.Distinct().ToHashSet();
AllaganMarket/Services/NotificationService.cs --- 5/5 --- C#
131 {
134 {
132 if (
this.notifyUndercutLoginSetting.CurrentValue(
this.configuration))
135 if (
this.notifyUndercutLoginSetting.CurrentValue(
this.configuration))
133 {
136 {
134 var currentCharacterId
= this.
clientState.
LocalContentId;
137 var currentCharacterId
= this.
playerState.
ContentId;
135 var currentSales
= this.saleTrackerService.GetSales(currentCharacterId,
null);
138 var currentSales
= this.saleTrackerService.GetSales(currentCharacterId,
null);
136 List<SaleItem> undercutItems
= [];
139 List<SaleItem> undercutItems
= [];
137 foreach (
var currentSale
in currentSales)
140 foreach (
var currentSale
in currentSales)
AllaganMarket/Services/RetainerService.cs --- C#
10 /// <summary> 10 /// <summary>
11 /// Wrapper for the item order module's retainer ID. 11 /// Wrapper for the item order module's retainer ID.
12 /// </summary> 12 /// </summary>
13 public class RetainerService(
IClientState clientState)
: IRetainerService 13 public class RetainerService(
IObjectTable objectTable)
: IRetainerService
14 {
14 {
15 public uint RetainerWorldId
=> clientState.LocalPlayer
?.HomeWorld.RowId
?? 0;
15 public uint RetainerWorldId
=> objectTable.LocalPlayer
?.HomeWorld.RowId
?? 0;
16 16
17 public ulong RetainerId
17 public ulong RetainerId
18 {
18 {
AllaganMarket/Services/SaleTrackerService.cs --- C#
38 38 ILogger<SaleTrackerService> logger,
39 39 IDataManager dataManager,
40 40 ICharacterMonitorService characterMonitorService,
41 .. IChatGui chatGui,
42 .. NumberFormatInfo gilNumberFormat,
43 41 MediatorService mediatorService)
: DisposableMediatorSubscriberBase(logger, mediatorService),
IHostedService
44 42 {
45 43 private readonly ExcelSheet<Item> itemSheet
= dataManager.
GetExcelSheet<Item>()
!;
AllaganMarket/Services/UndercutService.cs --- 1/7 --- C#
57 57 private readonly RoundUpDownSetting roundUpDownSetting;
58 58 private readonly RoundToSetting roundToSetting;
59 59 private readonly IFramework framework;
.. 60 private readonly IObjectTable objectTable;
60 61 private uint activeHomeWorld;
61 62
62 63 public delegate void ItemUndercutDelegate(
ulong retainerId,
uint itemId);
AllaganMarket/Services/UndercutService.cs --- 2/7 --- C#
84 85 UndercutAllowFallbackSetting undercutAllowFallbackSetting,
85 86 RoundUpDownSetting roundUpDownSetting,
86 87 RoundToSetting roundToSetting,
87 88 IFramework framework
,
.. 89 IObjectTable objectTable)
88 90 {
89 91 this.websocketService
= websocketService;
90 92 this.mediatorService
= mediatorService;
AllaganMarket/Services/UndercutService.cs --- 3/7 --- C#
105 107 this.roundUpDownSetting
= roundUpDownSetting;
106 108 this.roundToSetting
= roundToSetting;
107 109 this.framework
= framework;
... 110 this.objectTable = objectTable;
108 111 this.mediatorService.
Subscribe<PluginLoadedMessage>(
this,
this.PluginLoaded);
109 112 }
110 113 public MediatorService MediatorService
=> this.mediatorService;
AllaganMarket/Services/UndercutService.cs --- 4/7 --- C#
571 var listings
= this.accumulatedListings;
574 var listings
= this.accumulatedListings;
572 this.accumulatedListings
= new();
575 this.accumulatedListings
= new();
573 576
574 var currentPlayer
= this.
clientState.LocalPlayer;
577 var currentPlayer
= this.
objectTable.LocalPlayer;
575 if (currentPlayer
== null)
578 if (currentPlayer
== null)
576 {
579 {
577 return;
580 return;
AllaganMarket/Services/UndercutService.cs --- 5/7 --- C#
676 this.websocketService.UnsubscribeFromChannel(
679 this.websocketService.UnsubscribeFromChannel(
677 UniversalisWebsocketService.EventType.ListingsAdd,
680 UniversalisWebsocketService.EventType.ListingsAdd,
678 this.activeHomeWorld);
681 this.activeHomeWorld);
... 682 this.websocketService.UnsubscribeFromChannel(
... 683 UniversalisWebsocketService.EventType.ListingsRemove,
... 684 this.activeHomeWorld);
679 this.activeHomeWorld
= 0;
685 this.activeHomeWorld
= 0;
680 }
686 }
681 }
687 }
682 688
683 private void OnLogin()
689 private void OnLogin()
684 {
690 {
685 if (
this.
clientState.LocalPlayer
!= null)
691 if (
this.
objectTable.LocalPlayer
!= null)
686 {
692 {
687 this.pluginLog.Verbose(
$"Subscribing to universalis websocket for world {
this.
clientState.LocalPlayer.H
693 this.pluginLog.Verbose(
$"Subscribing to universalis websocket for world {
this.
objectTable.LocalPlayer.H
... omeWorld.RowId}.");
... omeWorld.RowId}.");
688 this.websocketService.SubscribeToChannel(
694 this.websocketService.SubscribeToChannel(
689 UniversalisWebsocketService.EventType.ListingsAdd,
695 UniversalisWebsocketService.EventType.ListingsAdd,
690 this.
clientState.LocalPlayer.HomeWorld.RowId);
696 this.
objectTable.LocalPlayer.HomeWorld.RowId);
... 697 this.websocketService.SubscribeToChannel(
... 698 UniversalisWebsocketService.EventType.ListingsRemove,
... 699 this.objectTable.LocalPlayer.HomeWorld.RowId);
691 this.activeHomeWorld
= this.
clientState.LocalPlayer.HomeWorld.RowId;
700 this.activeHomeWorld
= this.
objectTable.LocalPlayer.HomeWorld.RowId;
692 }
701 }
693 }
702 }
694 703
AllaganMarket/Services/UndercutService.cs --- 6/7 --- C#
827 836 (
uint)cheapestNqListing.PricePerUnit,
828 837 ownsListing);
829 838 }
830 ... else
831 ... {
832 ... this.pluginLog.Verbose($"No NQ listing received from universalis WS for {itemId}, removing cached prices");
833 ... this.RemoveMarketPriceCache(itemId, false, message.World, DateTime.Now);
834 ... }
835 839
836 840 var cheapestHqListing
= message.Listings.Where(c
=> c.HQ).DefaultIfEmpty(
null).MinBy(c
=> c
?.PricePerUnit
?? 0);
837 841 var oldestReviewTimeHq
= message.Listings.Where(c
=> c.HQ).DefaultIfEmpty(
null).Max(c
=> c
?.LastReviewTime);
AllaganMarket/Services/UndercutService.cs --- 7/7 --- C#
850 (
uint)cheapestHqListing.PricePerUnit,
854 (
uint)cheapestHqListing.PricePerUnit,
851 ownsListing);
855 ownsListing);
852 }
856 }
853 else ...
854 { ...
855 this.pluginLog.Verbose($"No HQ listing received from universalis WS for {itemId}, removing cach ...
... ed prices"); ...
856 this.RemoveMarketPriceCache(itemId, true, message.World, DateTime.Now); ...
857 } ...
858 }
857 }
859 }
858 }
... 859
... 860 if (message.EventType == UniversalisWebsocketService.EventType.ListingsRemove)
... 861 {
... 862 var itemId = message.Item;
... 863 if (this.saleTrackerService.SaleItemsByItemId.TryGetValue(itemId, out var value))
... 864 {
... 865 this.pluginLog.Verbose($"Requesting new prices from universalis for {itemId}");
... 866 //We have no idea what the lowest price is anymore, request the data again(ideally we'd cache all o
... ... f the data but we currently don't and it'd require some restructuring)
... 867 this.universalisApiService.QueuePriceCheck(itemId, message.World);
... 868 }
... 869 }
860 }
870 }
861 }
871 }
AllaganMarket/Windows/MainWindow.cs --- C#
No syntactic changes.
AllaganMarket/Windows/RetainerSellOverlayWindow.cs --- C#
No syntactic changes.
README.md --- Text
37 37 ## Contributing
38 38
39 39 Contributions are welcome! Feel free to open issues or submit pull requests on the GitHub repository.
40
41 ## Check out my other plugins
42
43 - [Allagan Tools](https://github.com/Critical-Impact/InventoryTools)
44 - [Allagan Item Search](https://github.com/Critical-Impact/AllaganItemSearch)
45 - [Allagan Market](https://github.com/Critical-Impact/AllaganMarket)
46 - [Allagan Tetris](https://github.com/Critical-Impact/AllaganTetris)
47 - [Tippy](https://github.com/Critical-Impact/Tippy)
48 - [Automount BGM](https://github.com/Critical-Impact/AutoMountBgm)
49 - [Fantasy Player](https://github.com/Critical-Impact/FantasyPlayer)
50