Skip to content

Commit 27900b1

Browse files
committed
add mod API to get all stops
1 parent f470dc0 commit 27900b1

File tree

9 files changed

+97
-55
lines changed

9 files changed

+97
-55
lines changed

CentralStation/Api/ICentralStationApi.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,14 @@ namespace Pathoschild.Stardew.CentralStation;
88
/// <summary>The public API for the Central Station mod.</summary>
99
public interface ICentralStationApi
1010
{
11+
/// <summary>Get all destinations which are currently registered, regardless of whether they'd normally be shown to the player.</summary>
12+
/// <param name="network">If set, only return stops connected to these networks.</param>
13+
/// <remarks>
14+
/// <para>Most code should use <see cref="GetAvailableStops"/> instead.</para>
15+
/// <para>This disables all filtering except the <paramref name="network"/> and basic validation. If applicable, you'll need to apply the normal exclusion for destinations in the current location, whose <see cref="IStop.Condition"/> field doesn't match, or whose location can't be found.</para>
16+
/// </remarks>
17+
IEnumerable<IStop> GetAllStops(StopNetworks? network = null);
18+
1119
/// <summary>Get the destinations which are available at this moment from the player's current location.</summary>
1220
/// <param name="network">If set, only return stops connected to these networks.</param>
1321
/// <remarks>The <see cref="IStop.Condition"/> field is checked before returning each stop, so there's no need to check it again.</remarks>

CentralStation/Framework/CentralStationApi.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,12 @@ internal CentralStationApi(IManifest mod, StopManager stopManager)
3434
/****
3535
** Main API
3636
****/
37+
/// <inheritdoc />
38+
public IEnumerable<IStop> GetAllStops(StopNetworks? network = null)
39+
{
40+
return this.StopManager.GetStops(network ?? StopManager.AllNetworks, null);
41+
}
42+
3743
/// <inheritdoc />
3844
public IEnumerable<IStop> GetAvailableStops(StopNetworks? network = null)
3945
{

CentralStation/Framework/ContentManager.cs

Lines changed: 3 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -145,8 +145,8 @@ public uint GetStationVisits()
145145
}
146146

147147
/// <summary>Get the stops which can be selected from the current location.</summary>
148-
/// <param name="networks">The networks for which to get stops.</param>
149-
public IEnumerable<Stop> GetAvailableStops(StopNetworks networks)
148+
/// <param name="shouldEnableStop">A filter which returns true for the stops to return.</param>
149+
public IEnumerable<Stop> GetStops(ShouldEnableStopDelegate shouldEnableStop)
150150
{
151151
foreach ((string id, StopModel? stop) in this.ContentHelper.Load<Dictionary<string, StopModel?>>(AssetNames.Stops))
152152
{
@@ -171,7 +171,7 @@ public IEnumerable<Stop> GetAvailableStops(StopNetworks networks)
171171
}
172172

173173
// match if applicable
174-
if (this.ShouldEnableStop(id, stop.ToLocation, stop.Condition, stop.Network, networks))
174+
if (shouldEnableStop(id, stop.ToLocation, stop.Condition, stop.Network))
175175
{
176176
yield return new Stop(
177177
Id: id,
@@ -192,26 +192,6 @@ public IEnumerable<Stop> GetAvailableStops(StopNetworks networks)
192192
}
193193
}
194194

195-
/// <summary>Get whether a stop should be enabled from the current location.</summary>
196-
/// <param name="id"><inheritdoc cref="Stop.Id"/></param>
197-
/// <param name="stopLocation"><inheritdoc cref="Stop.ToLocation"/></param>
198-
/// <param name="condition"><inheritdoc cref="Stop.Condition"/></param>
199-
/// <param name="stopNetworks"><inheritdoc cref="Stop.Network"/></param>
200-
/// <param name="travelingNetworks">The networks on which the player is traveling.</param>
201-
public bool ShouldEnableStop(string id, string stopLocation, string? condition, StopNetworks stopNetworks, StopNetworks travelingNetworks)
202-
{
203-
if (!stopNetworks.HasAnyFlag(travelingNetworks) || stopLocation == Game1.currentLocation.Name || !GameStateQuery.CheckConditions(condition))
204-
return false;
205-
206-
if (Game1.getLocationFromName(stopLocation) is null)
207-
{
208-
this.Monitor.LogOnce($"Ignored {stopNetworks} destination with ID '{id}' because its target location '{stopLocation}' could not be found.", LogLevel.Warn);
209-
return false;
210-
}
211-
212-
return true;
213-
}
214-
215195
/// <summary>Get a translation provided by the content pack.</summary>
216196
/// <param name="key">The translation key.</param>
217197
/// <param name="tokens">The tokens with which to format the text, if any.</param>

CentralStation/Framework/Integrations/BusLocations/BusLocationsStopProvider.cs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -66,14 +66,11 @@ public bool TryLoadContentPack(IContentPack contentPack)
6666
}
6767

6868
/// <inheritdoc />
69-
public IEnumerable<Stop> GetAvailableStops(StopNetworks networks, ShouldEnableStopDelegate shouldEnableStop)
69+
public IEnumerable<Stop> GetAvailableStops(ShouldEnableStopDelegate shouldEnableStop)
7070
{
71-
if (!networks.HasFlag(StopNetworks.Bus))
72-
yield break;
73-
7471
foreach (Stop stop in this.BusStops)
7572
{
76-
if (shouldEnableStop(stop.Id, stop.ToLocation, stop.Condition, stop.Network, networks))
73+
if (shouldEnableStop(stop.Id, stop.ToLocation, stop.Condition, stop.Network))
7774
yield return stop;
7875
}
7976
}

CentralStation/Framework/Integrations/ICustomStopProvider.cs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,7 @@ namespace Pathoschild.Stardew.CentralStation.Framework.Integrations;
55
/// <summary>A mod integration which adds stops to Central Station networks.</summary>
66
internal interface ICustomStopProvider
77
{
8-
/// <summary>Get the stops which can be selected from the current location.</summary>
9-
/// <param name="networks">The networks for which to get stops.</param>
10-
/// <param name="shouldEnableStop">Get whether a stop should be enabled from the current location.</param>
11-
IEnumerable<Stop> GetAvailableStops(StopNetworks networks, ShouldEnableStopDelegate shouldEnableStop);
8+
/// <summary>Get the stops available from this provider.</summary>
9+
/// <param name="shouldEnableStop">Get whether a stop should be selected.</param>
10+
IEnumerable<Stop> GetAvailableStops(ShouldEnableStopDelegate shouldEnableStop);
1211
}

CentralStation/Framework/Integrations/TrainStation/TrainStationStopProvider.cs

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -76,35 +76,30 @@ public bool TryLoadContentPack(IContentPack contentPack)
7676
}
7777

7878
/// <inheritdoc />
79-
public IEnumerable<Stop> GetAvailableStops(StopNetworks networks, ShouldEnableStopDelegate shouldEnableStop)
79+
public IEnumerable<Stop> GetAvailableStops(ShouldEnableStopDelegate shouldEnableStop)
8080
{
8181
// from reassigned content packs
8282
if (this.ReassignedStops.Count > 0)
8383
{
8484
foreach (Stop stop in this.ReassignedStops)
8585
{
86-
if (shouldEnableStop(stop.Id, stop.ToLocation, stop.Condition, stop.Network, networks))
86+
if (shouldEnableStop(stop.Id, stop.ToLocation, stop.Condition, stop.Network))
8787
yield return stop;
8888
}
8989
}
9090

9191
// from Train Station API
92-
if (this.TrainStation is { IsLoaded: true } api && networks.HasAnyFlag(StopNetworks.Boat | StopNetworks.Train))
92+
if (this.TrainStation is { IsLoaded: true } api)
9393
{
9494
// get enumerator
9595
IEnumerator<ITrainStationStopModel?>? enumerator = null;
9696
try
9797
{
98-
bool isBoat = networks.HasFlag(StopNetworks.Boat);
99-
bool isTrain = networks.HasFlag(StopNetworks.Train);
100-
101-
enumerator = isBoat && isTrain
102-
? api.GetAvailableStops(true).Concat(api.GetAvailableStops(false)).GetEnumerator()
103-
: api.GetAvailableStops(isBoat).GetEnumerator();
98+
enumerator = api.GetAvailableStops(true).Concat(api.GetAvailableStops(false)).GetEnumerator();
10499
}
105100
catch (Exception ex)
106101
{
107-
this.Monitor.Log($"Could not load {networks} stops from the Train Station mod because its API returned an unexpected error.\nTechnical details: {ex}", LogLevel.Warn);
102+
this.Monitor.Log($"Could not load stops from the Train Station mod because its API returned an unexpected error.\nTechnical details: {ex}", LogLevel.Warn);
108103
enumerator?.Dispose();
109104
yield break;
110105
}
@@ -128,10 +123,16 @@ public IEnumerable<Stop> GetAvailableStops(StopNetworks networks, ShouldEnableSt
128123
}
129124
catch (Exception ex)
130125
{
131-
this.Monitor.Log($"Could not load {networks} stops from the Train Station mod because its API returned an unexpected error.\nTechnical details: {ex}", LogLevel.Warn);
126+
this.Monitor.Log($"Could not load stops from the Train Station mod because its API returned an unexpected error.\nTechnical details: {ex}", LogLevel.Warn);
132127
yield break;
133128
}
134129

130+
// skip if not available
131+
StopNetworks network = stop.IsBoat ? StopNetworks.Boat : StopNetworks.Train;
132+
string? condition = this.ConvertExpandedPreconditionsToGameStateQuery(stop.Conditions);
133+
if (!shouldEnableStop(stop.Id, stop.TargetMapName, condition, network))
134+
continue;
135+
135136
// add stop if valid
136137
Stop? loadedStop = this.TryLoadStop(
137138
id: stop.Id,
@@ -141,10 +142,10 @@ public IEnumerable<Stop> GetAvailableStops(StopNetworks networks, ShouldEnableSt
141142
targetY: stop.TargetY,
142143
facingDirectionAfterWarp: stop.FacingDirectionAfterWarp,
143144
cost: stop.Cost,
144-
conditions: stop.Conditions,
145-
network: stop.IsBoat ? StopNetworks.Boat : StopNetworks.Train
145+
condition: condition,
146+
network: network
146147
);
147-
if (loadedStop is not null && shouldEnableStop(loadedStop.Id, loadedStop.ToLocation, loadedStop.Condition, loadedStop.Network, networks))
148+
if (loadedStop is not null)
148149
yield return loadedStop;
149150
}
150151
}
@@ -169,6 +170,7 @@ private IEnumerable<Stop> TryLoadStopsFromContentPackList(IContentPack contentPa
169170
if (stop?.TargetMapName is null)
170171
continue;
171172

173+
string? condition = this.ConvertExpandedPreconditionsToGameStateQuery(stop.Conditions);
172174
Stop? parsedStop = this.TryLoadStop(
173175
id: $"{contentPack.Manifest.UniqueID}_{network}_{index++}", // match generated Train Station IDs
174176
displayName: stop.GetDisplayName,
@@ -177,7 +179,7 @@ private IEnumerable<Stop> TryLoadStopsFromContentPackList(IContentPack contentPa
177179
targetY: stop.TargetY,
178180
facingDirectionAfterWarp: stop.FacingDirectionAfterWarp,
179181
cost: stop.Cost,
180-
conditions: stop.Conditions,
182+
condition: condition,
181183
network: network
182184
);
183185
if (parsedStop is not null)
@@ -193,9 +195,9 @@ private IEnumerable<Stop> TryLoadStopsFromContentPackList(IContentPack contentPa
193195
/// <param name="targetY"><inheritdoc cref="ITrainStationStopModel.TargetY" path="/summary"/></param>
194196
/// <param name="facingDirectionAfterWarp"><inheritdoc cref="ITrainStationStopModel.FacingDirectionAfterWarp" path="/summary"/></param>
195197
/// <param name="cost"><inheritdoc cref="ITrainStationStopModel.Cost" path="/summary"/></param>
196-
/// <param name="conditions"><inheritdoc cref="ITrainStationStopModel.Conditions" path="/summary"/></param>
198+
/// <param name="condition"><inheritdoc cref="Stop.Condition" path="/summary"/></param>
197199
/// <param name="network"><inheritdoc cref="Stop.Network" path="/summary"/></param>
198-
private Stop? TryLoadStop(string id, Func<string> displayName, string targetMapName, int targetX, int targetY, int facingDirectionAfterWarp, int cost, string?[]? conditions, StopNetworks network)
200+
private Stop? TryLoadStop(string id, Func<string> displayName, string targetMapName, int targetX, int targetY, int facingDirectionAfterWarp, int cost, string? condition, StopNetworks network)
199201
{
200202
// ignore stops which duplicate a Central Station stop
201203
if (this.IgnoreStopIds.Contains(id))
@@ -211,7 +213,7 @@ private IEnumerable<Stop> TryLoadStopsFromContentPackList(IContentPack contentPa
211213
ToFacingDirection: facingDirectionAfterWarp,
212214
Cost: cost,
213215
Network: network,
214-
Condition: this.ConvertExpandedPreconditionsToGameStateQuery(conditions)
216+
Condition: condition
215217
);
216218
}
217219

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
11
namespace Pathoschild.Stardew.CentralStation.Framework;
22

3-
/// <inheritdoc cref="ContentManager.ShouldEnableStop"/>
4-
internal delegate bool ShouldEnableStopDelegate(string id, string stopLocation, string? condition, StopNetworks stopNetworks, StopNetworks travelingNetworks);
3+
/// <summary>A filter which indicates whether a stop should be selected.</summary>
4+
/// <param name="id"><inheritdoc cref="Stop.Id"/></param>
5+
/// <param name="stopLocation"><inheritdoc cref="Stop.ToLocation"/></param>
6+
/// <param name="condition"><inheritdoc cref="Stop.Condition"/></param>
7+
/// <param name="stopNetworks"><inheritdoc cref="Stop.Network"/></param>
8+
internal delegate bool ShouldEnableStopDelegate(string id, string stopLocation, string? condition, StopNetworks stopNetworks);

CentralStation/Framework/StopManager.cs

Lines changed: 48 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using Pathoschild.Stardew.CentralStation.Framework.Integrations.BusLocations;
55
using Pathoschild.Stardew.CentralStation.Framework.Integrations.TrainStation;
66
using StardewModdingAPI;
7+
using StardewValley;
78

89
namespace Pathoschild.Stardew.CentralStation.Framework;
910

@@ -16,6 +17,9 @@ internal class StopManager
1617
/// <summary>Manages the Central Station content provided by content packs.</summary>
1718
private readonly ContentManager ContentManager;
1819

20+
/// <summary>Encapsulates monitoring and logging.</summary>
21+
private readonly IMonitor Monitor;
22+
1923
/// <summary>The stop provider which provides compatibility with the Bus Locations mod.</summary>
2024
private readonly BusLocationsStopProvider BusLocationsProvider;
2125

@@ -47,6 +51,7 @@ internal class StopManager
4751
public StopManager(ContentManager contentManager, IMonitor monitor, IModRegistry modRegistry)
4852
{
4953
this.ContentManager = contentManager;
54+
this.Monitor = monitor;
5055

5156
this.BusLocationsProvider = new BusLocationsStopProvider(modRegistry, monitor, this.ContentManager.GetTranslation);
5257
this.TrainStationStopProvider = new TrainStationStopProvider(modRegistry, monitor, this.ContentManager.GetTranslation);
@@ -55,24 +60,44 @@ public StopManager(ContentManager contentManager, IMonitor monitor, IModRegistry
5560
/// <summary>Get the stops which can be selected from the current location.</summary>
5661
/// <param name="networks">The networks for which to get stops.</param>
5762
public IEnumerable<Stop> GetAvailableStops(StopNetworks networks)
63+
{
64+
return this.GetStops(networks, ShouldSelectStop);
65+
66+
bool ShouldSelectStop(string id, string stopLocation, string? condition, StopNetworks stopNetworks)
67+
{
68+
return this.ShouldEnableStop(id, stopLocation, condition, stopNetworks, networks);
69+
}
70+
}
71+
72+
/// <summary>Get the stops which can be selected from the current location.</summary>
73+
/// <param name="networks">The networks for which to get stops.</param>
74+
/// <param name="shouldEnableStop">A filter which returns true for the stops to return; or <c>null</c> for all stops.</param>
75+
public IEnumerable<Stop> GetStops(StopNetworks networks, ShouldEnableStopDelegate? shouldEnableStop)
5876
{
5977
// Central Station stops
60-
foreach (Stop stop in this.ContentManager.GetAvailableStops(networks))
78+
foreach (Stop stop in this.ContentManager.GetStops(ShouldSelectStop))
6179
yield return stop;
6280

6381
// from API
6482
foreach (Stop stop in this.ModApiStops.Values)
6583
{
66-
if (this.ContentManager.ShouldEnableStop(stop.Id, stop.ToLocation, stop.Condition, stop.Network, networks))
84+
if (ShouldSelectStop(stop.Id, stop.ToLocation, stop.Condition, stop.Network))
6785
yield return stop;
6886
}
6987

7088
// from mod integrations
7189
foreach (ICustomStopProvider provider in this.GetCustomStopProviders())
7290
{
73-
foreach (Stop stop in provider.GetAvailableStops(networks, this.ContentManager.ShouldEnableStop))
91+
foreach (Stop stop in provider.GetAvailableStops(ShouldSelectStop))
7492
yield return stop;
7593
}
94+
95+
bool ShouldSelectStop(string id, string stopLocation, string? condition, StopNetworks stopNetworks)
96+
{
97+
return
98+
stopNetworks.HasAnyFlag(networks)
99+
&& shouldEnableStop?.Invoke(id, stopLocation, condition, stopNetworks) is not false;
100+
}
76101
}
77102

78103
/// <summary>Try to load a legacy content pack which was reassigned to Central Station.</summary>
@@ -92,6 +117,26 @@ public bool TryLoadContentPack(IContentPack contentPack)
92117
/*********
93118
** Private methods
94119
*********/
120+
/// <summary>Get whether a stop should be enabled from the current location.</summary>
121+
/// <param name="id"><inheritdoc cref="Stop.Id"/></param>
122+
/// <param name="stopLocation"><inheritdoc cref="Stop.ToLocation"/></param>
123+
/// <param name="condition"><inheritdoc cref="Stop.Condition"/></param>
124+
/// <param name="stopNetworks"><inheritdoc cref="Stop.Network"/></param>
125+
/// <param name="travelingNetworks">The networks on which the player is traveling.</param>
126+
private bool ShouldEnableStop(string id, string stopLocation, string? condition, StopNetworks stopNetworks, StopNetworks travelingNetworks)
127+
{
128+
if (!stopNetworks.HasAnyFlag(travelingNetworks) || stopLocation == Game1.currentLocation.Name || !GameStateQuery.CheckConditions(condition))
129+
return false;
130+
131+
if (Game1.getLocationFromName(stopLocation) is null)
132+
{
133+
this.Monitor.LogOnce($"Ignored {stopNetworks} destination with ID '{id}' because its target location '{stopLocation}' could not be found.", LogLevel.Warn);
134+
return false;
135+
}
136+
137+
return true;
138+
}
139+
95140
/// <summary>Load the integrations with other mods if they're not already loaded.</summary>
96141
[MemberNotNull(nameof(StopManager.CustomStopProviders))]
97142
private List<ICustomStopProvider> GetCustomStopProviders()

CentralStation/docs/author-guide.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -390,6 +390,7 @@ The available methods are:
390390

391391
method | usage
392392
------------------- | -----
393+
`GetAllStops` | Get all currently registered destinations.
393394
`GetAvailableStops` | Get the destinations which are available at this moment from the player's current location.
394395
`RegisterStop` | Add a destination that can be visited by the player, or replace one you previously registered from the same mod.
395396
`RemoveStop` | Remove a stop that was registered by the same mod.

0 commit comments

Comments
 (0)