2222using Robust . Shared . Audio . Systems ;
2323using Robust . Shared . Player ;
2424using Robust . Shared . Prototypes ;
25+ using Prometheus ; //Starlight
26+
2527
2628namespace Content . Server . Store . Systems ;
2729
2830public sealed partial class StoreSystem
2931{
32+ #region Starlight
33+ private static readonly Gauge _storePurchasesMetric = Metrics . CreateGauge (
34+ "sl_store_purchases" ,
35+ "Everything bounght from a \" store\" which include ling upgrades, traitor uplinks, wizard grimoires" ,
36+ [ "store_name" , "purchased_item" ]
37+ ) ;
38+ #endregion
39+
3040 [ Dependency ] private readonly IAdminLogManager _admin = default ! ;
3141 [ Dependency ] private readonly SharedHandsSystem _hands = default ! ;
3242 [ Dependency ] private readonly ActionsSystem _actions = default ! ;
@@ -83,17 +93,17 @@ public void CloseUi(EntityUid uid, StoreComponent? component = null)
8393 _ui . CloseUi ( uid , StoreUiKey . Key ) ;
8494 }
8595
86- /// <summary>
87- /// STARLIGHT: Updates the user interface for a store and refreshes the listings
88- /// </summary>
89- /// <param name="user">The person who if opening the store ui. Listings are filtered based on this.</param>
90- /// <param name="store">The store entity itself</param>
91- /// <param name="component">The store component being refreshed.</param>
92- public void UpdateUserInterface ( EntityUid ? user , EntityUid store , StoreComponent ? component = null )
96+ /// <summary>
97+ /// STARLIGHT: Updates the user interface for a store and refreshes the listings
98+ /// </summary>
99+ /// <param name="user">The person who if opening the store ui. Listings are filtered based on this.</param>
100+ /// <param name="store">The store entity itself</param>
101+ /// <param name="component">The store component being refreshed.</param>
102+ public void UpdateUserInterface ( EntityUid ? user , EntityUid store , StoreComponent ? component = null )
93103 {
94104 if ( ! Resolve ( store , ref component ) )
95105 return ;
96-
106+
97107 // STARLIGHT: Check if a rift has been destroyed and update the listing accordingly
98108 // This ensures the rift listing remains unavailable even when the UI is refreshed
99109 _revSupplyRift . CheckRiftDestroyedAndUpdateListing ( component ) ;
@@ -149,11 +159,11 @@ private void OnBuyRequest(EntityUid uid, StoreComponent component, StoreBuyListi
149159 }
150160
151161 var buyer = msg . Actor ;
152-
162+
153163 // STARLIGHT: Raise an event to allow other systems to potentially cancel this purchase
154164 var purchaseAttemptEvent = new StorePurchaseAttemptEvent ( listing . ID , uid , buyer ) ;
155165 RaiseLocalEvent ( ref purchaseAttemptEvent ) ;
156-
166+
157167 // STARLIGHT: If the event handler requested cancellation, cancel the purchase
158168 if ( purchaseAttemptEvent . Cancel )
159169 return ;
@@ -171,7 +181,7 @@ private void OnBuyRequest(EntityUid uid, StoreComponent component, StoreBuyListi
171181 if ( ! conditionsMet )
172182 return ;
173183 }
174-
184+
175185 // Starlight: Check if the listing is unavailable (e.g., out of stock)
176186 // We still want to show the listing in the UI, but prevent purchase
177187 if ( listing . Unavailable )
@@ -288,13 +298,13 @@ private void OnBuyRequest(EntityUid uid, StoreComponent component, StoreBuyListi
288298 //log dat shit.
289299 // Starlight: Get the resolved name without any placeholders
290300 var resolvedName = ListingLocalisationHelpers . GetLocalisedNameOrEntityName ( listing , _proto ) ;
291-
301+
292302 // Remove any stock count or "Out of Stock" text for the log
293303 if ( resolvedName . Contains ( " (" ) )
294304 {
295305 resolvedName = resolvedName . Substring ( 0 , resolvedName . IndexOf ( " (" ) ) ;
296306 }
297-
307+
298308 _admin . Add ( LogType . StorePurchase ,
299309 LogImpact . Low ,
300310 $ "{ ToPrettyString ( buyer ) : player} purchased listing \" { resolvedName } \" from { ToPrettyString ( uid ) } ") ; // Starlight
@@ -315,7 +325,7 @@ private void OnBuyRequest(EntityUid uid, StoreComponent component, StoreBuyListi
315325 {
316326 buyerName = metadata . EntityName ;
317327 }
318-
328+
319329 // Update the stock count and last purchaser
320330 StockLimitedListingCondition . OnItemPurchased ( listing . ID , buyerName , stockCondition . StockLimit ) ;
321331 break ;
@@ -324,20 +334,20 @@ private void OnBuyRequest(EntityUid uid, StoreComponent component, StoreBuyListi
324334 }
325335
326336 // STARLIGHT END
327-
337+
328338 var buyFinished = new StoreBuyFinishedEvent
329339 {
330340 PurchasedItem = listing ,
331341 StoreUid = uid
332342 } ;
333343 RaiseLocalEvent ( ref buyFinished ) ;
334-
344+
335345 // STARLIGHT: Raise an event to notify other systems that a purchase was completed
336346 var purchaseCompletedEvent = new StorePurchaseCompletedEvent ( listing . ID , uid , buyer ) ;
337347 RaiseLocalEvent ( ref purchaseCompletedEvent ) ;
338348
339349 UpdateUserInterface ( buyer , uid , component ) ;
340-
350+
341351 // STARLIGHT START: If this was a stock-limited item, update all USSP uplink UIs
342352 if ( listing . Conditions != null )
343353 {
@@ -350,8 +360,15 @@ private void OnBuyRequest(EntityUid uid, StoreComponent component, StoreBuyListi
350360 }
351361 }
352362 }
363+
364+ #region Starlight statistics
365+ _storePurchasesMetric . WithLabels ( [
366+ ToPrettyString ( uid ) ,
367+ resolvedName
368+ ] ) . Inc ( ) ;
369+ #endregion
353370 }
354-
371+
355372 /// <summary>
356373 /// Updates all USSP uplink UIs to ensure they show the latest stock counts and last purchaser information.
357374 /// </summary>
@@ -364,25 +381,25 @@ public void UpdateAllUSSPUplinkUIs()
364381 // Skip if this is not a USSP uplink
365382 if ( ! storeComp . CurrencyWhitelist . Contains ( "Telebond" ) )
366383 continue ;
367-
384+
368385 // Refresh all listings to ensure they have the latest stock count and last purchaser information
369386 RefreshAllListings ( storeComp ) ;
370-
387+
371388 // Force a refresh of the available listings
372389 if ( storeComp . AccountOwner != null )
373390 {
374391 storeComp . LastAvailableListings = GetAvailableListings ( storeComp . AccountOwner . Value , storeComp . Owner , storeComp )
375392 . ToHashSet ( ) ;
376393 }
377-
394+
378395 // Update the UI to reflect the changes
379396 // We'll just update it with a null user to ensure the listings are refreshed
380397 // The next time someone opens the UI, they'll see the updated listings
381398 UpdateUserInterface ( null , storeComp . Owner , storeComp ) ;
382-
399+
383400 // Force update the UI for all currently connected sessions
384401 ForceUpdateUiForAllSessions ( storeComp . Owner , storeComp ) ;
385-
402+
386403 Logger . DebugS ( "store" , $ "Updated USSP uplink UI for { ToPrettyString ( storeComp . Owner ) } ") ;
387404 }
388405 }
@@ -460,9 +477,9 @@ private void OnRequestWithdraw(EntityUid uid, StoreComponent component, StoreReq
460477 foreach ( var value in sortedCashValues )
461478 {
462479 var cashId = proto . Cash [ value ] ;
463- var amountToSpawn = ( int ) MathF . Floor ( ( float ) ( amountRemaining / value ) ) ;
480+ var amountToSpawn = ( int ) MathF . Floor ( ( float ) ( amountRemaining / value ) ) ;
464481 var ents = _stack . SpawnMultiple ( cashId , amountToSpawn , coordinates ) ;
465- if ( ents . FirstOrDefault ( ) is { } ent )
482+ if ( ents . FirstOrDefault ( ) is { } ent )
466483 _hands . PickupOrDrop ( buyer , ent ) ;
467484 amountRemaining -= value * amountToSpawn ;
468485 }
0 commit comments