11from __future__ import annotations
22import time
33import sys
4- from typing import Any
4+ from typing import Any , Optional
55import typing
66from worlds import AutoWorldRegister , network_data_package
77import json
@@ -192,11 +192,11 @@ def on_package(self, cmd: str, args: dict):
192192 logger .info (f"Slot data: { args ['slot_data' ]} " )
193193
194194 self .ui .build_tracker_and_locations_table ()
195- self .ui .update_tracker_and_locations_table (update_highlights = True )
195+ self .ui .request_update_tracker_and_locations_table (update_highlights = True )
196196 elif cmd in {"ReceivedItems" }:
197- self .ui .update_tracker_and_locations_table (update_highlights = True )
197+ self .ui .request_update_tracker_and_locations_table (update_highlights = True )
198198 elif cmd in {"RoomUpdate" }:
199- self .ui .update_tracker_and_locations_table (update_highlights = False )
199+ self .ui .request_update_tracker_and_locations_table (update_highlights = False )
200200
201201 def on_deathlink (self , data : typing .Dict [str , typing .Any ]) -> None :
202202 super ().on_deathlink (data )
@@ -206,12 +206,12 @@ def on_deathlink(self, data: typing.Dict[str, typing.Any]) -> None:
206206
207207 def on_tracker_updated (self , reachable_locations : list [str ]):
208208 self .tracker_reachable_locations = reachable_locations
209- self .ui .update_tracker_and_locations_table (update_highlights = True )
209+ self .ui .request_update_tracker_and_locations_table (update_highlights = True )
210210
211211 def on_tracker_events (self , events : list [str ]):
212212 self .tracker_reachable_events = events
213213 if events :
214- self .ui .update_tracker_and_locations_table (update_highlights = True )
214+ self .ui .request_update_tracker_and_locations_table (update_highlights = True )
215215
216216 def run_gui (self ):
217217 """Import kivy UI system from make_gui() and start running it as self.ui_task."""
@@ -282,6 +282,9 @@ class ManualManager(ui):
282282 active_item_accordion = 0
283283 active_location_accordion = 0
284284
285+ update_requested_time : Optional [float ] = None
286+ update_requested_highlights : bool = False
287+
285288 ctx : ManualContext
286289
287290 def __init__ (self , ctx ):
@@ -369,7 +372,7 @@ def update_hints(self):
369372
370373 if rebuild :
371374 self .build_tracker_and_locations_table ()
372- self .update_tracker_and_locations_table ()
375+ self .request_update_tracker_and_locations_table ()
373376
374377 def build_tracker_and_locations_table (self ):
375378 self .tracker_and_locations_panel .clear_widgets ()
@@ -438,6 +441,9 @@ def build_tracker_and_locations_table(self):
438441 if not victory_categories :
439442 victory_categories .add ("(No Category)" )
440443
444+ for category in self .listed_locations :
445+ self .listed_locations [category ].sort (key = self .ctx .location_names .lookup_in_game )
446+
441447 items_length = len (self .ctx .items_received )
442448 tracker_panel_scrollable = TrackerLayoutScrollable (do_scroll = (False , True ), bar_width = 10 )
443449 tracker_panel = TreeView (root_options = dict (text = "Items Received (%d)" % (items_length )), size_hint_y = None )
@@ -501,6 +507,19 @@ def build_tracker_and_locations_table(self):
501507 self .tracker_and_locations_panel .add_widget (tracker_panel_scrollable )
502508 self .tracker_and_locations_panel .add_widget (locations_panel_scrollable )
503509
510+ def check_for_requested_update (self ):
511+ current_time = time .time ()
512+
513+ # wait 0.25 seconds before executing update, in case there are multiple update requests coming in
514+ if self .update_requested_time and current_time - self .update_requested_time >= 0.25 :
515+ self .update_requested_time = None
516+ self .update_tracker_and_locations_table (self .update_requested_highlights )
517+ self .update_requested_highlights = False
518+
519+ def request_update_tracker_and_locations_table (self , update_highlights = False ):
520+ self .update_requested_time = time .time ()
521+ self .update_requested_highlights = update_highlights or self .update_requested_highlights # if any of the requests wanted highlights, do highlight
522+
504523 def update_tracker_and_locations_table (self , update_highlights = False ):
505524 items_length = len (self .ctx .items_received )
506525 locations_length = len (self .ctx .missing_locations )
@@ -532,7 +551,10 @@ def update_tracker_and_locations_table(self, update_highlights=False):
532551 category_count = 0
533552 category_unique_name_count = 0
534553
535- # Label (for existing item listings)
554+ existing_item_labels = []
555+ bold_item_labels = []
556+
557+ # for items that were already listed, determine if the qty changed. if it did, add them to the list to be bolded
536558 for item in category_grid .children :
537559 if type (item ) is Label :
538560 # Get the item name from the item Label, minus quantity, then do a lookup for count
@@ -544,28 +566,37 @@ def update_tracker_and_locations_table(self, update_highlights=False):
544566 # Update the label quantity
545567 item .text = "%s (%s)" % (item_name , item_count )
546568
547- if update_highlights :
548- item .bold = True if old_item_text != item .text else False
569+ if update_highlights and (old_item_text != item .text ):
570+ bold_item_labels .append (item_name )
571+
572+ existing_item_labels .append (item_name )
573+
574+ # instead of reusing existing item listings, clear it all out and re-draw with the sorted list
575+ category_grid .clear_widgets ()
576+ self .listed_items [category_name ].clear ()
549577
550- if item_count > 0 :
551- category_count += item_count
552- category_unique_name_count += 1
578+ # Label (for all item listings)
579+ sorted_items_received = sorted ([
580+ i .item for i in self .ctx .items_received
581+ ], key = self .ctx .item_names .lookup_in_game )
553582
554- # Label (for new item listings)
555- for network_item in self .ctx .items_received :
556- item_name = self .ctx .item_names .lookup_in_game (network_item .item )
583+ for network_item in sorted_items_received :
584+ item_name = self .ctx .item_names .lookup_in_game (network_item )
557585 item_data = self .ctx .get_item_by_name (item_name )
558586
559587 if "category" not in item_data or not item_data ["category" ]:
560588 item_data ["category" ] = ["(No Category)" ]
561589
562- if category_name in item_data ["category" ] and network_item . item not in self .listed_items [category_name ]:
563- item_count = len (list (i for i in self .ctx .items_received if i .item == network_item . item ))
590+ if category_name in item_data ["category" ] and network_item not in self .listed_items [category_name ]:
591+ item_count = len (list (i for i in self .ctx .items_received if i .item == network_item ))
564592 item_text = Label (text = "%s (%s)" % (item_name , item_count ),
565593 size_hint = (None , None ), height = 30 , width = 400 , bold = True )
566594
595+ # if the item was previously listed and was bold, or if it wasn't previously listed at all, make it bold
596+ item_text .bold = (update_highlights and (item_name in bold_item_labels or item_name not in existing_item_labels ))
597+
567598 category_grid .add_widget (item_text )
568- self .listed_items [category_name ].append (network_item . item )
599+ self .listed_items [category_name ].append (network_item )
569600
570601 category_count += item_count
571602 category_unique_name_count += 1
@@ -687,6 +718,9 @@ def victory_button_callback(self, button):
687718
688719async def game_watcher_manual (ctx : ManualContext ):
689720 while not ctx .exit_event .is_set ():
721+ if ctx .ui :
722+ ctx .ui .check_for_requested_update ()
723+
690724 if ctx .syncing == True :
691725 sync_msg = [{'cmd' : 'Sync' }]
692726 if ctx .locations_checked :
0 commit comments