| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  | import argparse | 
					
						
							| 
									
										
										
										
											2020-02-02 06:20:08 +01:00
										 |  |  | import atexit | 
					
						
							| 
									
										
										
										
											2020-04-24 20:07:28 -07:00
										 |  |  | import time | 
					
						
							| 
									
										
											  
											
												WebUI (#100)
* Object-Oriented base changes for web-ui prep
* remove debug raise
* optimize broadcast to serialize once
* Implement WebUI socket, static assets, and classes
- Still need to wrap logging functions and send output to UI
- UI commands are successfully being sent to the server
* GUI operational. Wrap logging functions, implement server address selection on GUI, automatically launch web browser when client websocket is served
* Update MultiServer status when a user disconnects / reconnects
* Implement colored item and hint checks, improve GUI readability
* Fix improper formatting on received items
* Update SNES connection status on disconnect / reconnect. Implement itemFound, prevent accidentally printing JS objects
* Minor text change for itemFound
* Fixed a very wrong comment
* Fixed client commands not working, fixed un-helpful error messages appearing in GUI
* Fix a bug causing a failure to connect to a multiworld server if a previously existing cached address was present and the client was loaded without an address passed in
* Convert WebUI to React /w Redux. WebSocket communications not yet operational.
* WebUI fully converted to React / Redux.
- Websocket communication operational
- Added a button to connect to the multiserver which appears only when a SNES is connected and a server connection is not active
* Restore some features lost in WebUI
- Restore (found) notification on hints if the item has already been obtained
- Restore (x/y) indicator on received items, which indicates the number of items the client is waiting to receive from the client in a queue
* Fix a grammatical UI big causing player names to show only an apostrophe when possessive
* Add support for multiple SNES Devices, and switching between them
* freeze support for client
* make sure flask works when frozen
* UI Improvements
- Hint messages now actually show a found status via ✔ and ❌ emoji
- Active player name is always a different color than other players (orange for now)
- Add a toggle to show only entries relevant to the active player
- Added a WidgetArea
- Added a notes widget
* Received items now marked as relevant
* Include production build for deployment
* Notes now survive a browser close. Minimum width applied to monitor to prevent CSS issues.
* include webUi folder in setup.py
* Bugfixes for Monitor
- Fix a bug causing the monitor window to grow beyond it's intended content limit
- Reduced monitor content limit to 200 items
- Ensured each monitor entry has a unique key
* Prevent eslint from yelling at me about stupid things
* Add button to collapse sidebar, press enter on empty server input to disconnect on purpose
* WebUI is now aware of client disconnect, message log limit increased to 350, fix !missing output
* Update WebUI to v2.2.1
- Added color to WebUI for entrance-span
- Make !missing show total count at bottom of list to match /missing behavior
* Fix a bug causing clients version <= 2.2.0 to crash when anyone asks for a hint
- Also fix a bug in the WebUI causing the entrance location to always show as "somewhere"
* Update WebUI color palette (this cost me $50)
* allow text console input alongside web-ui
* remove Flask
a bit overkill for what we're doing
* remove jinja2
* Update WebUI to work with new hosting mechanism
* with flask gone, we no longer need subprocess shenanigans
* If multiple web ui clients try to run, at least present a working console
* Update MultiClient and WebUI to handle multiple clients simultaneously.
- The port on which the websocket for the WebUI is hosted is not chosen randomly from 5000 - 5999. This port is passed to the browser so it knows which MultiClient to connect to
- Removed failure condition if a web server is already running, as there is no need to run more than one web server on a single system. If an exception is thrown while attempting to launch a web server, a check is made for the port being unavailable. If the port is unavailable, it probably means the user is launching a second MultiClient. A web browser is then opened with a connection to the correct webui_socket_port.
- Add a /web command to the MultiClient to repoen the appropriate browser window and get params in case a user accidentally closes the tab
* Use proper name for WebUI
* move webui into /data with other data files
* make web ui optional
This is mostly for laptop users wanting to preserve some battery, should not be needed outside of that.
* fix direct server start
* re-add connection timer
* fix indentation
Co-authored-by: Chris <chris@legendserver.info>
											
										 
											2020-06-03 21:29:43 +02:00
										 |  |  | import multiprocessing | 
					
						
							| 
									
										
										
										
											2020-07-15 17:19:16 +02:00
										 |  |  | import os | 
					
						
							|  |  |  | import subprocess | 
					
						
							| 
									
										
										
										
											2020-10-19 08:26:31 +02:00
										 |  |  | import base64 | 
					
						
							| 
									
										
										
										
											2021-01-21 23:58:30 +01:00
										 |  |  | import shutil | 
					
						
							| 
									
										
										
										
											2021-02-21 23:54:08 +01:00
										 |  |  | from json import loads, dumps | 
					
						
							| 
									
										
										
										
											2020-06-04 21:27:29 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-07 22:05:07 +01:00
										 |  |  | from Utils import get_item_name_from_id | 
					
						
							| 
									
										
										
										
											2020-02-02 06:20:08 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | exit_func = atexit.register(input, "Press enter to close.") | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-18 15:45:52 +01:00
										 |  |  | import ModuleUpdate | 
					
						
							| 
									
										
										
										
											2020-03-06 01:27:02 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-18 15:45:52 +01:00
										 |  |  | ModuleUpdate.update() | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-18 15:04:39 +01:00
										 |  |  | import colorama | 
					
						
							| 
									
										
										
										
											2020-06-06 22:54:09 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-21 23:37:58 +01:00
										 |  |  | from NetUtils import * | 
					
						
							| 
									
										
										
										
											2020-01-18 15:45:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-30 23:43:15 +01:00
										 |  |  | from worlds.alttp import Regions, Shops | 
					
						
							| 
									
										
										
										
											2021-02-21 20:17:24 +01:00
										 |  |  | from worlds.alttp import Items | 
					
						
							| 
									
										
										
										
											2020-02-16 15:32:40 +01:00
										 |  |  | import Utils | 
					
						
							| 
									
										
										
										
											2021-04-01 11:40:58 +02:00
										 |  |  | from CommonClient import CommonContext, server_loop, logger, console_loop, ClientCommandProcessor | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-19 06:37:35 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-01 11:40:58 +02:00
										 |  |  | from MultiServer import mark_raw | 
					
						
							| 
									
										
										
										
											2020-02-22 19:42:44 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-21 23:37:58 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-01 11:40:58 +02:00
										 |  |  | class LttPCommandProcessor(ClientCommandProcessor): | 
					
						
							|  |  |  |     def _cmd_slow_mode(self, toggle: str = ""): | 
					
						
							|  |  |  |         """Toggle slow mode, which limits how fast you send / receive items.""" | 
					
						
							|  |  |  |         if toggle: | 
					
						
							|  |  |  |             self.ctx.slow_mode = toggle.lower() in {"1", "true", "on"} | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             self.ctx.slow_mode = not self.ctx.slow_mode | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.output(f"Setting slow mode to {self.ctx.slow_mode}") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @mark_raw | 
					
						
							|  |  |  |     def _cmd_snes(self, snes_address: str = "") -> bool: | 
					
						
							|  |  |  |         """Connect to a snes. Optionally include network address of a snes to connect to, otherwise show available devices""" | 
					
						
							|  |  |  |         self.ctx.snes_reconnect_address = None | 
					
						
							|  |  |  |         asyncio.create_task(snes_connect(self.ctx, snes_address if snes_address else self.ctx.snes_address)) | 
					
						
							|  |  |  |         return True | 
					
						
							| 
									
										
										
										
											2021-01-21 23:37:58 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-01 11:40:58 +02:00
										 |  |  |     def _cmd_snes_close(self) -> bool: | 
					
						
							|  |  |  |         """Close connection to a currently connected snes""" | 
					
						
							|  |  |  |         self.ctx.snes_reconnect_address = None | 
					
						
							|  |  |  |         if self.ctx.snes_socket is not None and not self.ctx.snes_socket.closed: | 
					
						
							|  |  |  |             asyncio.create_task(self.ctx.snes_socket.close()) | 
					
						
							|  |  |  |             return True | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             return False | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class Context(CommonContext): | 
					
						
							|  |  |  |     command_processor = LttPCommandProcessor | 
					
						
							| 
									
										
										
										
											2021-05-14 01:25:41 +02:00
										 |  |  |     def __init__(self, snes_address, server_address, password, found_items): | 
					
						
							| 
									
										
										
										
											2021-04-01 11:40:58 +02:00
										 |  |  |         super(Context, self).__init__(server_address, password, found_items) | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-01 11:40:58 +02:00
										 |  |  |         # snes stuff | 
					
						
							|  |  |  |         self.snes_address = snes_address | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  |         self.snes_socket = None | 
					
						
							| 
									
										
										
										
											2021-03-07 22:05:07 +01:00
										 |  |  |         self.snes_state = SNESState.SNES_DISCONNECTED | 
					
						
							| 
									
										
										
										
											2020-01-13 03:55:33 +01:00
										 |  |  |         self.snes_attached_device = None | 
					
						
							|  |  |  |         self.snes_reconnect_address = None | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  |         self.snes_recv_queue = asyncio.Queue() | 
					
						
							|  |  |  |         self.snes_request_lock = asyncio.Lock() | 
					
						
							|  |  |  |         self.is_sd2snes = False | 
					
						
							|  |  |  |         self.snes_write_buffer = [] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-14 10:42:27 +01:00
										 |  |  |         self.awaiting_rom = False | 
					
						
							|  |  |  |         self.rom = None | 
					
						
							| 
									
										
										
										
											2020-06-02 07:38:23 -07:00
										 |  |  |         self.prev_rom = None | 
					
						
							| 
									
										
											  
											
												WebUI (#100)
* Object-Oriented base changes for web-ui prep
* remove debug raise
* optimize broadcast to serialize once
* Implement WebUI socket, static assets, and classes
- Still need to wrap logging functions and send output to UI
- UI commands are successfully being sent to the server
* GUI operational. Wrap logging functions, implement server address selection on GUI, automatically launch web browser when client websocket is served
* Update MultiServer status when a user disconnects / reconnects
* Implement colored item and hint checks, improve GUI readability
* Fix improper formatting on received items
* Update SNES connection status on disconnect / reconnect. Implement itemFound, prevent accidentally printing JS objects
* Minor text change for itemFound
* Fixed a very wrong comment
* Fixed client commands not working, fixed un-helpful error messages appearing in GUI
* Fix a bug causing a failure to connect to a multiworld server if a previously existing cached address was present and the client was loaded without an address passed in
* Convert WebUI to React /w Redux. WebSocket communications not yet operational.
* WebUI fully converted to React / Redux.
- Websocket communication operational
- Added a button to connect to the multiserver which appears only when a SNES is connected and a server connection is not active
* Restore some features lost in WebUI
- Restore (found) notification on hints if the item has already been obtained
- Restore (x/y) indicator on received items, which indicates the number of items the client is waiting to receive from the client in a queue
* Fix a grammatical UI big causing player names to show only an apostrophe when possessive
* Add support for multiple SNES Devices, and switching between them
* freeze support for client
* make sure flask works when frozen
* UI Improvements
- Hint messages now actually show a found status via ✔ and ❌ emoji
- Active player name is always a different color than other players (orange for now)
- Add a toggle to show only entries relevant to the active player
- Added a WidgetArea
- Added a notes widget
* Received items now marked as relevant
* Include production build for deployment
* Notes now survive a browser close. Minimum width applied to monitor to prevent CSS issues.
* include webUi folder in setup.py
* Bugfixes for Monitor
- Fix a bug causing the monitor window to grow beyond it's intended content limit
- Reduced monitor content limit to 200 items
- Ensured each monitor entry has a unique key
* Prevent eslint from yelling at me about stupid things
* Add button to collapse sidebar, press enter on empty server input to disconnect on purpose
* WebUI is now aware of client disconnect, message log limit increased to 350, fix !missing output
* Update WebUI to v2.2.1
- Added color to WebUI for entrance-span
- Make !missing show total count at bottom of list to match /missing behavior
* Fix a bug causing clients version <= 2.2.0 to crash when anyone asks for a hint
- Also fix a bug in the WebUI causing the entrance location to always show as "somewhere"
* Update WebUI color palette (this cost me $50)
* allow text console input alongside web-ui
* remove Flask
a bit overkill for what we're doing
* remove jinja2
* Update WebUI to work with new hosting mechanism
* with flask gone, we no longer need subprocess shenanigans
* If multiple web ui clients try to run, at least present a working console
* Update MultiClient and WebUI to handle multiple clients simultaneously.
- The port on which the websocket for the WebUI is hosted is not chosen randomly from 5000 - 5999. This port is passed to the browser so it knows which MultiClient to connect to
- Removed failure condition if a web server is already running, as there is no need to run more than one web server on a single system. If an exception is thrown while attempting to launch a web server, a check is made for the port being unavailable. If the port is unavailable, it probably means the user is launching a second MultiClient. A web browser is then opened with a connection to the correct webui_socket_port.
- Add a /web command to the MultiClient to repoen the appropriate browser window and get params in case a user accidentally closes the tab
* Use proper name for WebUI
* move webui into /data with other data files
* make web ui optional
This is mostly for laptop users wanting to preserve some battery, should not be needed outside of that.
* fix direct server start
* re-add connection timer
* fix indentation
Co-authored-by: Chris <chris@legendserver.info>
											
										 
											2020-06-03 21:29:43 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-01 11:40:58 +02:00
										 |  |  |     async def connection_closed(self): | 
					
						
							|  |  |  |         await super(Context, self).connection_closed() | 
					
						
							|  |  |  |         self.awaiting_rom = False | 
					
						
							| 
									
										
											  
											
												WebUI (#100)
* Object-Oriented base changes for web-ui prep
* remove debug raise
* optimize broadcast to serialize once
* Implement WebUI socket, static assets, and classes
- Still need to wrap logging functions and send output to UI
- UI commands are successfully being sent to the server
* GUI operational. Wrap logging functions, implement server address selection on GUI, automatically launch web browser when client websocket is served
* Update MultiServer status when a user disconnects / reconnects
* Implement colored item and hint checks, improve GUI readability
* Fix improper formatting on received items
* Update SNES connection status on disconnect / reconnect. Implement itemFound, prevent accidentally printing JS objects
* Minor text change for itemFound
* Fixed a very wrong comment
* Fixed client commands not working, fixed un-helpful error messages appearing in GUI
* Fix a bug causing a failure to connect to a multiworld server if a previously existing cached address was present and the client was loaded without an address passed in
* Convert WebUI to React /w Redux. WebSocket communications not yet operational.
* WebUI fully converted to React / Redux.
- Websocket communication operational
- Added a button to connect to the multiserver which appears only when a SNES is connected and a server connection is not active
* Restore some features lost in WebUI
- Restore (found) notification on hints if the item has already been obtained
- Restore (x/y) indicator on received items, which indicates the number of items the client is waiting to receive from the client in a queue
* Fix a grammatical UI big causing player names to show only an apostrophe when possessive
* Add support for multiple SNES Devices, and switching between them
* freeze support for client
* make sure flask works when frozen
* UI Improvements
- Hint messages now actually show a found status via ✔ and ❌ emoji
- Active player name is always a different color than other players (orange for now)
- Add a toggle to show only entries relevant to the active player
- Added a WidgetArea
- Added a notes widget
* Received items now marked as relevant
* Include production build for deployment
* Notes now survive a browser close. Minimum width applied to monitor to prevent CSS issues.
* include webUi folder in setup.py
* Bugfixes for Monitor
- Fix a bug causing the monitor window to grow beyond it's intended content limit
- Reduced monitor content limit to 200 items
- Ensured each monitor entry has a unique key
* Prevent eslint from yelling at me about stupid things
* Add button to collapse sidebar, press enter on empty server input to disconnect on purpose
* WebUI is now aware of client disconnect, message log limit increased to 350, fix !missing output
* Update WebUI to v2.2.1
- Added color to WebUI for entrance-span
- Make !missing show total count at bottom of list to match /missing behavior
* Fix a bug causing clients version <= 2.2.0 to crash when anyone asks for a hint
- Also fix a bug in the WebUI causing the entrance location to always show as "somewhere"
* Update WebUI color palette (this cost me $50)
* allow text console input alongside web-ui
* remove Flask
a bit overkill for what we're doing
* remove jinja2
* Update WebUI to work with new hosting mechanism
* with flask gone, we no longer need subprocess shenanigans
* If multiple web ui clients try to run, at least present a working console
* Update MultiClient and WebUI to handle multiple clients simultaneously.
- The port on which the websocket for the WebUI is hosted is not chosen randomly from 5000 - 5999. This port is passed to the browser so it knows which MultiClient to connect to
- Removed failure condition if a web server is already running, as there is no need to run more than one web server on a single system. If an exception is thrown while attempting to launch a web server, a check is made for the port being unavailable. If the port is unavailable, it probably means the user is launching a second MultiClient. A web browser is then opened with a connection to the correct webui_socket_port.
- Add a /web command to the MultiClient to repoen the appropriate browser window and get params in case a user accidentally closes the tab
* Use proper name for WebUI
* move webui into /data with other data files
* make web ui optional
This is mostly for laptop users wanting to preserve some battery, should not be needed outside of that.
* fix direct server start
* re-add connection timer
* fix indentation
Co-authored-by: Chris <chris@legendserver.info>
											
										 
											2020-06-03 21:29:43 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-01 11:40:58 +02:00
										 |  |  |     def event_invalid_slot(self): | 
					
						
							|  |  |  |         if self.snes_socket is not None and not self.snes_socket.closed: | 
					
						
							|  |  |  |             asyncio.create_task(self.snes_socket.close()) | 
					
						
							|  |  |  |         raise Exception('Invalid ROM detected, ' | 
					
						
							|  |  |  |                         'please verify that you have loaded the correct rom and reconnect your snes (/snes)') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     async def server_auth(self, password_requested): | 
					
						
							|  |  |  |         if password_requested and not self.password: | 
					
						
							|  |  |  |             await super(Context, self).server_auth(password_requested) | 
					
						
							|  |  |  |         if self.rom is None: | 
					
						
							|  |  |  |             self.awaiting_rom = True | 
					
						
							|  |  |  |             logger.info( | 
					
						
							|  |  |  |                 'No ROM detected, awaiting snes connection to authenticate to the multiworld server (/snes)') | 
					
						
							| 
									
										
											  
											
												WebUI (#100)
* Object-Oriented base changes for web-ui prep
* remove debug raise
* optimize broadcast to serialize once
* Implement WebUI socket, static assets, and classes
- Still need to wrap logging functions and send output to UI
- UI commands are successfully being sent to the server
* GUI operational. Wrap logging functions, implement server address selection on GUI, automatically launch web browser when client websocket is served
* Update MultiServer status when a user disconnects / reconnects
* Implement colored item and hint checks, improve GUI readability
* Fix improper formatting on received items
* Update SNES connection status on disconnect / reconnect. Implement itemFound, prevent accidentally printing JS objects
* Minor text change for itemFound
* Fixed a very wrong comment
* Fixed client commands not working, fixed un-helpful error messages appearing in GUI
* Fix a bug causing a failure to connect to a multiworld server if a previously existing cached address was present and the client was loaded without an address passed in
* Convert WebUI to React /w Redux. WebSocket communications not yet operational.
* WebUI fully converted to React / Redux.
- Websocket communication operational
- Added a button to connect to the multiserver which appears only when a SNES is connected and a server connection is not active
* Restore some features lost in WebUI
- Restore (found) notification on hints if the item has already been obtained
- Restore (x/y) indicator on received items, which indicates the number of items the client is waiting to receive from the client in a queue
* Fix a grammatical UI big causing player names to show only an apostrophe when possessive
* Add support for multiple SNES Devices, and switching between them
* freeze support for client
* make sure flask works when frozen
* UI Improvements
- Hint messages now actually show a found status via ✔ and ❌ emoji
- Active player name is always a different color than other players (orange for now)
- Add a toggle to show only entries relevant to the active player
- Added a WidgetArea
- Added a notes widget
* Received items now marked as relevant
* Include production build for deployment
* Notes now survive a browser close. Minimum width applied to monitor to prevent CSS issues.
* include webUi folder in setup.py
* Bugfixes for Monitor
- Fix a bug causing the monitor window to grow beyond it's intended content limit
- Reduced monitor content limit to 200 items
- Ensured each monitor entry has a unique key
* Prevent eslint from yelling at me about stupid things
* Add button to collapse sidebar, press enter on empty server input to disconnect on purpose
* WebUI is now aware of client disconnect, message log limit increased to 350, fix !missing output
* Update WebUI to v2.2.1
- Added color to WebUI for entrance-span
- Make !missing show total count at bottom of list to match /missing behavior
* Fix a bug causing clients version <= 2.2.0 to crash when anyone asks for a hint
- Also fix a bug in the WebUI causing the entrance location to always show as "somewhere"
* Update WebUI color palette (this cost me $50)
* allow text console input alongside web-ui
* remove Flask
a bit overkill for what we're doing
* remove jinja2
* Update WebUI to work with new hosting mechanism
* with flask gone, we no longer need subprocess shenanigans
* If multiple web ui clients try to run, at least present a working console
* Update MultiClient and WebUI to handle multiple clients simultaneously.
- The port on which the websocket for the WebUI is hosted is not chosen randomly from 5000 - 5999. This port is passed to the browser so it knows which MultiClient to connect to
- Removed failure condition if a web server is already running, as there is no need to run more than one web server on a single system. If an exception is thrown while attempting to launch a web server, a check is made for the port being unavailable. If the port is unavailable, it probably means the user is launching a second MultiClient. A web browser is then opened with a connection to the correct webui_socket_port.
- Add a /web command to the MultiClient to repoen the appropriate browser window and get params in case a user accidentally closes the tab
* Use proper name for WebUI
* move webui into /data with other data files
* make web ui optional
This is mostly for laptop users wanting to preserve some battery, should not be needed outside of that.
* fix direct server start
* re-add connection timer
* fix indentation
Co-authored-by: Chris <chris@legendserver.info>
											
										 
											2020-06-03 21:29:43 +02:00
										 |  |  |             return | 
					
						
							| 
									
										
										
										
											2021-04-01 11:40:58 +02:00
										 |  |  |         self.awaiting_rom = False | 
					
						
							|  |  |  |         self.auth = self.rom | 
					
						
							|  |  |  |         auth = base64.b64encode(self.rom).decode() | 
					
						
							|  |  |  |         await self.send_msgs([{"cmd": 'Connect', | 
					
						
							|  |  |  |                               'password': self.password, 'name': auth, 'version': Utils._version_tuple, | 
					
						
							|  |  |  |                               'tags': get_tags(self), | 
					
						
							|  |  |  |                               'uuid': Utils.get_unique_identifier(), 'game': "A Link to the Past" | 
					
						
							|  |  |  |                               }]) | 
					
						
							| 
									
										
										
										
											2021-02-21 20:17:24 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-19 06:37:35 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-03 03:19:25 +01:00
										 |  |  | def color_item(item_id: int, green: bool = False) -> str: | 
					
						
							|  |  |  |     item_name = get_item_name_from_id(item_id) | 
					
						
							|  |  |  |     item_colors = ['green' if green else 'cyan'] | 
					
						
							|  |  |  |     if item_name in Items.progression_items: | 
					
						
							|  |  |  |         item_colors.append("white_bg") | 
					
						
							|  |  |  |     return color(item_name, *item_colors) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-21 23:46:05 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-01 21:45:01 +02:00
										 |  |  | SNES_RECONNECT_DELAY = 5 | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | ROM_START = 0x000000 | 
					
						
							|  |  |  | WRAM_START = 0xF50000 | 
					
						
							|  |  |  | WRAM_SIZE = 0x20000 | 
					
						
							|  |  |  | SRAM_START = 0xE00000 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ROMNAME_START = SRAM_START + 0x2000 | 
					
						
							|  |  |  | ROMNAME_SIZE = 0x15 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | INGAME_MODES = {0x07, 0x09, 0x0b} | 
					
						
							| 
									
										
										
										
											2020-04-24 20:07:28 -07:00
										 |  |  | ENDGAME_MODES = {0x19, 0x1a} | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | SAVEDATA_START = WRAM_START + 0xF000 | 
					
						
							|  |  |  | SAVEDATA_SIZE = 0x500 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-18 09:50:12 +01:00
										 |  |  | RECV_PROGRESS_ADDR = SAVEDATA_START + 0x4D0         # 2 bytes | 
					
						
							|  |  |  | RECV_ITEM_ADDR = SAVEDATA_START + 0x4D2             # 1 byte | 
					
						
							|  |  |  | RECV_ITEM_PLAYER_ADDR = SAVEDATA_START + 0x4D3      # 1 byte | 
					
						
							|  |  |  | ROOMID_ADDR = SAVEDATA_START + 0x4D4                # 2 bytes | 
					
						
							|  |  |  | ROOMDATA_ADDR = SAVEDATA_START + 0x4D6              # 1 byte | 
					
						
							|  |  |  | SCOUT_LOCATION_ADDR = SAVEDATA_START + 0x4D7        # 1 byte | 
					
						
							|  |  |  | SCOUTREPLY_LOCATION_ADDR = SAVEDATA_START + 0x4D8   # 1 byte | 
					
						
							|  |  |  | SCOUTREPLY_ITEM_ADDR = SAVEDATA_START + 0x4D9       # 1 byte | 
					
						
							|  |  |  | SCOUTREPLY_PLAYER_ADDR = SAVEDATA_START + 0x4DA     # 1 byte | 
					
						
							| 
									
										
										
										
											2020-12-15 02:34:22 -06:00
										 |  |  | SHOP_ADDR = SAVEDATA_START + 0x302                  # 2 bytes | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-21 23:46:05 +01:00
										 |  |  | location_shop_order = [name for name, info in | 
					
						
							|  |  |  |                        Shops.shop_table.items()]  # probably don't leave this here.  This relies on python 3.6+ dictionary keys having defined order | 
					
						
							| 
									
										
										
										
											2021-01-16 02:23:23 +01:00
										 |  |  | location_shop_ids = set([info[0] for name, info in Shops.shop_table.items()]) | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | location_table_uw = {"Blind's Hideout - Top": (0x11d, 0x10), | 
					
						
							|  |  |  |                      "Blind's Hideout - Left": (0x11d, 0x20), | 
					
						
							|  |  |  |                      "Blind's Hideout - Right": (0x11d, 0x40), | 
					
						
							|  |  |  |                      "Blind's Hideout - Far Left": (0x11d, 0x80), | 
					
						
							|  |  |  |                      "Blind's Hideout - Far Right": (0x11d, 0x100), | 
					
						
							|  |  |  |                      'Secret Passage': (0x55, 0x10), | 
					
						
							|  |  |  |                      'Waterfall Fairy - Left': (0x114, 0x10), | 
					
						
							|  |  |  |                      'Waterfall Fairy - Right': (0x114, 0x20), | 
					
						
							|  |  |  |                      "King's Tomb": (0x113, 0x10), | 
					
						
							|  |  |  |                      'Floodgate Chest': (0x10b, 0x10), | 
					
						
							|  |  |  |                      "Link's House": (0x104, 0x10), | 
					
						
							|  |  |  |                      'Kakariko Tavern': (0x103, 0x10), | 
					
						
							|  |  |  |                      'Chicken House': (0x108, 0x10), | 
					
						
							|  |  |  |                      "Aginah's Cave": (0x10a, 0x10), | 
					
						
							|  |  |  |                      "Sahasrahla's Hut - Left": (0x105, 0x10), | 
					
						
							|  |  |  |                      "Sahasrahla's Hut - Middle": (0x105, 0x20), | 
					
						
							|  |  |  |                      "Sahasrahla's Hut - Right": (0x105, 0x40), | 
					
						
							|  |  |  |                      'Kakariko Well - Top': (0x2f, 0x10), | 
					
						
							|  |  |  |                      'Kakariko Well - Left': (0x2f, 0x20), | 
					
						
							|  |  |  |                      'Kakariko Well - Middle': (0x2f, 0x40), | 
					
						
							|  |  |  |                      'Kakariko Well - Right': (0x2f, 0x80), | 
					
						
							|  |  |  |                      'Kakariko Well - Bottom': (0x2f, 0x100), | 
					
						
							|  |  |  |                      'Lost Woods Hideout': (0xe1, 0x200), | 
					
						
							|  |  |  |                      'Lumberjack Tree': (0xe2, 0x200), | 
					
						
							|  |  |  |                      'Cave 45': (0x11b, 0x400), | 
					
						
							|  |  |  |                      'Graveyard Cave': (0x11b, 0x200), | 
					
						
							|  |  |  |                      'Checkerboard Cave': (0x126, 0x200), | 
					
						
							|  |  |  |                      'Mini Moldorm Cave - Far Left': (0x123, 0x10), | 
					
						
							|  |  |  |                      'Mini Moldorm Cave - Left': (0x123, 0x20), | 
					
						
							|  |  |  |                      'Mini Moldorm Cave - Right': (0x123, 0x40), | 
					
						
							|  |  |  |                      'Mini Moldorm Cave - Far Right': (0x123, 0x80), | 
					
						
							|  |  |  |                      'Mini Moldorm Cave - Generous Guy': (0x123, 0x400), | 
					
						
							|  |  |  |                      'Ice Rod Cave': (0x120, 0x10), | 
					
						
							|  |  |  |                      'Bonk Rock Cave': (0x124, 0x10), | 
					
						
							|  |  |  |                      'Desert Palace - Big Chest': (0x73, 0x10), | 
					
						
							|  |  |  |                      'Desert Palace - Torch': (0x73, 0x400), | 
					
						
							|  |  |  |                      'Desert Palace - Map Chest': (0x74, 0x10), | 
					
						
							|  |  |  |                      'Desert Palace - Compass Chest': (0x85, 0x10), | 
					
						
							|  |  |  |                      'Desert Palace - Big Key Chest': (0x75, 0x10), | 
					
						
							| 
									
										
										
										
											2020-10-28 01:48:22 -07:00
										 |  |  |                      'Desert Palace - Desert Tiles 1 Pot Key': (0x63, 0x400), | 
					
						
							|  |  |  |                      'Desert Palace - Beamos Hall Pot Key': (0x53, 0x400), | 
					
						
							|  |  |  |                      'Desert Palace - Desert Tiles 2 Pot Key': (0x43, 0x400), | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  |                      'Desert Palace - Boss': (0x33, 0x800), | 
					
						
							|  |  |  |                      'Eastern Palace - Compass Chest': (0xa8, 0x10), | 
					
						
							|  |  |  |                      'Eastern Palace - Big Chest': (0xa9, 0x10), | 
					
						
							| 
									
										
										
										
											2020-10-28 01:48:22 -07:00
										 |  |  |                      'Eastern Palace - Dark Square Pot Key': (0xba, 0x400), | 
					
						
							|  |  |  |                      'Eastern Palace - Dark Eyegore Key Drop': (0x99, 0x400), | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  |                      'Eastern Palace - Cannonball Chest': (0xb9, 0x10), | 
					
						
							|  |  |  |                      'Eastern Palace - Big Key Chest': (0xb8, 0x10), | 
					
						
							|  |  |  |                      'Eastern Palace - Map Chest': (0xaa, 0x10), | 
					
						
							|  |  |  |                      'Eastern Palace - Boss': (0xc8, 0x800), | 
					
						
							|  |  |  |                      'Hyrule Castle - Boomerang Chest': (0x71, 0x10), | 
					
						
							| 
									
										
										
										
											2020-10-28 01:48:22 -07:00
										 |  |  |                      'Hyrule Castle - Boomerang Guard Key Drop': (0x71, 0x400), | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  |                      'Hyrule Castle - Map Chest': (0x72, 0x10), | 
					
						
							| 
									
										
										
										
											2020-10-28 01:48:22 -07:00
										 |  |  |                      'Hyrule Castle - Map Guard Key Drop': (0x72, 0x400), | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  |                      "Hyrule Castle - Zelda's Chest": (0x80, 0x10), | 
					
						
							| 
									
										
										
										
											2020-10-28 01:48:22 -07:00
										 |  |  |                      'Hyrule Castle - Big Key Drop': (0x80, 0x400), | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  |                      'Sewers - Dark Cross': (0x32, 0x10), | 
					
						
							| 
									
										
										
										
											2020-10-28 01:48:22 -07:00
										 |  |  |                      'Hyrule Castle - Key Rat Key Drop': (0x21, 0x400), | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  |                      'Sewers - Secret Room - Left': (0x11, 0x10), | 
					
						
							|  |  |  |                      'Sewers - Secret Room - Middle': (0x11, 0x20), | 
					
						
							|  |  |  |                      'Sewers - Secret Room - Right': (0x11, 0x40), | 
					
						
							|  |  |  |                      'Sanctuary': (0x12, 0x10), | 
					
						
							|  |  |  |                      'Castle Tower - Room 03': (0xe0, 0x10), | 
					
						
							|  |  |  |                      'Castle Tower - Dark Maze': (0xd0, 0x10), | 
					
						
							| 
									
										
										
										
											2020-10-28 01:48:22 -07:00
										 |  |  |                      'Castle Tower - Dark Archer Key Drop': (0xc0, 0x400), | 
					
						
							|  |  |  |                      'Castle Tower - Circle of Pots Key Drop': (0xb0, 0x400), | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  |                      'Spectacle Rock Cave': (0xea, 0x400), | 
					
						
							|  |  |  |                      'Paradox Cave Lower - Far Left': (0xef, 0x10), | 
					
						
							|  |  |  |                      'Paradox Cave Lower - Left': (0xef, 0x20), | 
					
						
							|  |  |  |                      'Paradox Cave Lower - Right': (0xef, 0x40), | 
					
						
							|  |  |  |                      'Paradox Cave Lower - Far Right': (0xef, 0x80), | 
					
						
							|  |  |  |                      'Paradox Cave Lower - Middle': (0xef, 0x100), | 
					
						
							|  |  |  |                      'Paradox Cave Upper - Left': (0xff, 0x10), | 
					
						
							|  |  |  |                      'Paradox Cave Upper - Right': (0xff, 0x20), | 
					
						
							|  |  |  |                      'Spiral Cave': (0xfe, 0x10), | 
					
						
							|  |  |  |                      'Tower of Hera - Basement Cage': (0x87, 0x400), | 
					
						
							|  |  |  |                      'Tower of Hera - Map Chest': (0x77, 0x10), | 
					
						
							|  |  |  |                      'Tower of Hera - Big Key Chest': (0x87, 0x10), | 
					
						
							|  |  |  |                      'Tower of Hera - Compass Chest': (0x27, 0x20), | 
					
						
							|  |  |  |                      'Tower of Hera - Big Chest': (0x27, 0x10), | 
					
						
							|  |  |  |                      'Tower of Hera - Boss': (0x7, 0x800), | 
					
						
							|  |  |  |                      'Hype Cave - Top': (0x11e, 0x10), | 
					
						
							|  |  |  |                      'Hype Cave - Middle Right': (0x11e, 0x20), | 
					
						
							|  |  |  |                      'Hype Cave - Middle Left': (0x11e, 0x40), | 
					
						
							|  |  |  |                      'Hype Cave - Bottom': (0x11e, 0x80), | 
					
						
							|  |  |  |                      'Hype Cave - Generous Guy': (0x11e, 0x400), | 
					
						
							|  |  |  |                      'Peg Cave': (0x127, 0x400), | 
					
						
							|  |  |  |                      'Pyramid Fairy - Left': (0x116, 0x10), | 
					
						
							|  |  |  |                      'Pyramid Fairy - Right': (0x116, 0x20), | 
					
						
							|  |  |  |                      'Brewery': (0x106, 0x10), | 
					
						
							|  |  |  |                      'C-Shaped House': (0x11c, 0x10), | 
					
						
							|  |  |  |                      'Chest Game': (0x106, 0x400), | 
					
						
							|  |  |  |                      'Mire Shed - Left': (0x10d, 0x10), | 
					
						
							|  |  |  |                      'Mire Shed - Right': (0x10d, 0x20), | 
					
						
							|  |  |  |                      'Superbunny Cave - Top': (0xf8, 0x10), | 
					
						
							|  |  |  |                      'Superbunny Cave - Bottom': (0xf8, 0x20), | 
					
						
							|  |  |  |                      'Spike Cave': (0x117, 0x10), | 
					
						
							|  |  |  |                      'Hookshot Cave - Top Right': (0x3c, 0x10), | 
					
						
							|  |  |  |                      'Hookshot Cave - Top Left': (0x3c, 0x20), | 
					
						
							|  |  |  |                      'Hookshot Cave - Bottom Right': (0x3c, 0x80), | 
					
						
							|  |  |  |                      'Hookshot Cave - Bottom Left': (0x3c, 0x40), | 
					
						
							|  |  |  |                      'Mimic Cave': (0x10c, 0x10), | 
					
						
							|  |  |  |                      'Swamp Palace - Entrance': (0x28, 0x10), | 
					
						
							|  |  |  |                      'Swamp Palace - Map Chest': (0x37, 0x10), | 
					
						
							| 
									
										
										
										
											2020-10-28 01:48:22 -07:00
										 |  |  |                      'Swamp Palace - Pot Row Pot Key': (0x38, 0x400), | 
					
						
							|  |  |  |                      'Swamp Palace - Trench 1 Pot Key': (0x37, 0x400), | 
					
						
							|  |  |  |                      'Swamp Palace - Hookshot Pot Key': (0x36, 0x400), | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  |                      'Swamp Palace - Big Chest': (0x36, 0x10), | 
					
						
							|  |  |  |                      'Swamp Palace - Compass Chest': (0x46, 0x10), | 
					
						
							| 
									
										
										
										
											2020-10-28 01:48:22 -07:00
										 |  |  |                      'Swamp Palace - Trench 2 Pot Key': (0x35, 0x400), | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  |                      'Swamp Palace - Big Key Chest': (0x35, 0x10), | 
					
						
							|  |  |  |                      'Swamp Palace - West Chest': (0x34, 0x10), | 
					
						
							|  |  |  |                      'Swamp Palace - Flooded Room - Left': (0x76, 0x10), | 
					
						
							|  |  |  |                      'Swamp Palace - Flooded Room - Right': (0x76, 0x20), | 
					
						
							|  |  |  |                      'Swamp Palace - Waterfall Room': (0x66, 0x10), | 
					
						
							| 
									
										
										
										
											2020-10-28 01:48:22 -07:00
										 |  |  |                      'Swamp Palace - Waterway Pot Key': (0x16, 0x400), | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  |                      'Swamp Palace - Boss': (0x6, 0x800), | 
					
						
							|  |  |  |                      "Thieves' Town - Big Key Chest": (0xdb, 0x20), | 
					
						
							|  |  |  |                      "Thieves' Town - Map Chest": (0xdb, 0x10), | 
					
						
							|  |  |  |                      "Thieves' Town - Compass Chest": (0xdc, 0x10), | 
					
						
							|  |  |  |                      "Thieves' Town - Ambush Chest": (0xcb, 0x10), | 
					
						
							| 
									
										
										
										
											2020-10-28 01:48:22 -07:00
										 |  |  |                      "Thieves' Town - Hallway Pot Key": (0xbc, 0x400), | 
					
						
							|  |  |  |                      "Thieves' Town - Spike Switch Pot Key": (0xab, 0x400), | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  |                      "Thieves' Town - Attic": (0x65, 0x10), | 
					
						
							|  |  |  |                      "Thieves' Town - Big Chest": (0x44, 0x10), | 
					
						
							|  |  |  |                      "Thieves' Town - Blind's Cell": (0x45, 0x10), | 
					
						
							|  |  |  |                      "Thieves' Town - Boss": (0xac, 0x800), | 
					
						
							|  |  |  |                      'Skull Woods - Compass Chest': (0x67, 0x10), | 
					
						
							|  |  |  |                      'Skull Woods - Map Chest': (0x58, 0x20), | 
					
						
							|  |  |  |                      'Skull Woods - Big Chest': (0x58, 0x10), | 
					
						
							|  |  |  |                      'Skull Woods - Pot Prison': (0x57, 0x20), | 
					
						
							|  |  |  |                      'Skull Woods - Pinball Room': (0x68, 0x10), | 
					
						
							|  |  |  |                      'Skull Woods - Big Key Chest': (0x57, 0x10), | 
					
						
							| 
									
										
										
										
											2020-10-28 01:48:22 -07:00
										 |  |  |                      'Skull Woods - West Lobby Pot Key': (0x56, 0x400), | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  |                      'Skull Woods - Bridge Room': (0x59, 0x10), | 
					
						
							| 
									
										
										
										
											2020-10-28 01:48:22 -07:00
										 |  |  |                      'Skull Woods - Spike Corner Key Drop': (0x39, 0x400), | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  |                      'Skull Woods - Boss': (0x29, 0x800), | 
					
						
							| 
									
										
										
										
											2020-10-28 01:48:22 -07:00
										 |  |  |                      'Ice Palace - Jelly Key Drop': (0x0e, 0x400), | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  |                      'Ice Palace - Compass Chest': (0x2e, 0x10), | 
					
						
							| 
									
										
										
										
											2020-10-28 01:48:22 -07:00
										 |  |  |                      'Ice Palace - Conveyor Key Drop': (0x3e, 0x400), | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  |                      'Ice Palace - Freezor Chest': (0x7e, 0x10), | 
					
						
							|  |  |  |                      'Ice Palace - Big Chest': (0x9e, 0x10), | 
					
						
							|  |  |  |                      'Ice Palace - Iced T Room': (0xae, 0x10), | 
					
						
							| 
									
										
										
										
											2020-10-28 01:48:22 -07:00
										 |  |  |                      'Ice Palace - Many Pots Pot Key': (0x9f, 0x400), | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  |                      'Ice Palace - Spike Room': (0x5f, 0x10), | 
					
						
							|  |  |  |                      'Ice Palace - Big Key Chest': (0x1f, 0x10), | 
					
						
							| 
									
										
										
										
											2020-10-28 01:48:22 -07:00
										 |  |  |                      'Ice Palace - Hammer Block Key Drop': (0x3f, 0x400), | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  |                      'Ice Palace - Map Chest': (0x3f, 0x10), | 
					
						
							|  |  |  |                      'Ice Palace - Boss': (0xde, 0x800), | 
					
						
							|  |  |  |                      'Misery Mire - Big Chest': (0xc3, 0x10), | 
					
						
							|  |  |  |                      'Misery Mire - Map Chest': (0xc3, 0x20), | 
					
						
							|  |  |  |                      'Misery Mire - Main Lobby': (0xc2, 0x10), | 
					
						
							|  |  |  |                      'Misery Mire - Bridge Chest': (0xa2, 0x10), | 
					
						
							| 
									
										
										
										
											2020-10-28 01:48:22 -07:00
										 |  |  |                      'Misery Mire - Spikes Pot Key': (0xb3, 0x400), | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  |                      'Misery Mire - Spike Chest': (0xb3, 0x10), | 
					
						
							| 
									
										
										
										
											2020-10-28 01:48:22 -07:00
										 |  |  |                      'Misery Mire - Fishbone Pot Key': (0xa1, 0x400), | 
					
						
							|  |  |  |                      'Misery Mire - Conveyor Crystal Key Drop': (0xc1, 0x400), | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  |                      'Misery Mire - Compass Chest': (0xc1, 0x10), | 
					
						
							|  |  |  |                      'Misery Mire - Big Key Chest': (0xd1, 0x10), | 
					
						
							|  |  |  |                      'Misery Mire - Boss': (0x90, 0x800), | 
					
						
							|  |  |  |                      'Turtle Rock - Compass Chest': (0xd6, 0x10), | 
					
						
							|  |  |  |                      'Turtle Rock - Roller Room - Left': (0xb7, 0x10), | 
					
						
							|  |  |  |                      'Turtle Rock - Roller Room - Right': (0xb7, 0x20), | 
					
						
							| 
									
										
										
										
											2020-10-28 01:48:22 -07:00
										 |  |  |                      'Turtle Rock - Pokey 1 Key Drop': (0xb6, 0x400), | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  |                      'Turtle Rock - Chain Chomps': (0xb6, 0x10), | 
					
						
							| 
									
										
										
										
											2020-10-28 01:48:22 -07:00
										 |  |  |                      'Turtle Rock - Pokey 2 Key Drop': (0x13, 0x400), | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  |                      'Turtle Rock - Big Key Chest': (0x14, 0x10), | 
					
						
							|  |  |  |                      'Turtle Rock - Big Chest': (0x24, 0x10), | 
					
						
							|  |  |  |                      'Turtle Rock - Crystaroller Room': (0x4, 0x10), | 
					
						
							|  |  |  |                      'Turtle Rock - Eye Bridge - Bottom Left': (0xd5, 0x80), | 
					
						
							|  |  |  |                      'Turtle Rock - Eye Bridge - Bottom Right': (0xd5, 0x40), | 
					
						
							|  |  |  |                      'Turtle Rock - Eye Bridge - Top Left': (0xd5, 0x20), | 
					
						
							|  |  |  |                      'Turtle Rock - Eye Bridge - Top Right': (0xd5, 0x10), | 
					
						
							|  |  |  |                      'Turtle Rock - Boss': (0xa4, 0x800), | 
					
						
							|  |  |  |                      'Palace of Darkness - Shooter Room': (0x9, 0x10), | 
					
						
							|  |  |  |                      'Palace of Darkness - The Arena - Bridge': (0x2a, 0x20), | 
					
						
							|  |  |  |                      'Palace of Darkness - Stalfos Basement': (0xa, 0x10), | 
					
						
							|  |  |  |                      'Palace of Darkness - Big Key Chest': (0x3a, 0x10), | 
					
						
							|  |  |  |                      'Palace of Darkness - The Arena - Ledge': (0x2a, 0x10), | 
					
						
							|  |  |  |                      'Palace of Darkness - Map Chest': (0x2b, 0x10), | 
					
						
							|  |  |  |                      'Palace of Darkness - Compass Chest': (0x1a, 0x20), | 
					
						
							|  |  |  |                      'Palace of Darkness - Dark Basement - Left': (0x6a, 0x10), | 
					
						
							|  |  |  |                      'Palace of Darkness - Dark Basement - Right': (0x6a, 0x20), | 
					
						
							|  |  |  |                      'Palace of Darkness - Dark Maze - Top': (0x19, 0x10), | 
					
						
							|  |  |  |                      'Palace of Darkness - Dark Maze - Bottom': (0x19, 0x20), | 
					
						
							|  |  |  |                      'Palace of Darkness - Big Chest': (0x1a, 0x10), | 
					
						
							|  |  |  |                      'Palace of Darkness - Harmless Hellway': (0x1a, 0x40), | 
					
						
							|  |  |  |                      'Palace of Darkness - Boss': (0x5a, 0x800), | 
					
						
							| 
									
										
										
										
											2020-10-28 01:48:22 -07:00
										 |  |  |                      'Ganons Tower - Conveyor Cross Pot Key': (0x8b, 0x400), | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  |                      "Ganons Tower - Bob's Torch": (0x8c, 0x400), | 
					
						
							|  |  |  |                      'Ganons Tower - Hope Room - Left': (0x8c, 0x20), | 
					
						
							|  |  |  |                      'Ganons Tower - Hope Room - Right': (0x8c, 0x40), | 
					
						
							|  |  |  |                      'Ganons Tower - Tile Room': (0x8d, 0x10), | 
					
						
							|  |  |  |                      'Ganons Tower - Compass Room - Top Left': (0x9d, 0x10), | 
					
						
							|  |  |  |                      'Ganons Tower - Compass Room - Top Right': (0x9d, 0x20), | 
					
						
							|  |  |  |                      'Ganons Tower - Compass Room - Bottom Left': (0x9d, 0x40), | 
					
						
							|  |  |  |                      'Ganons Tower - Compass Room - Bottom Right': (0x9d, 0x80), | 
					
						
							| 
									
										
										
										
											2020-10-28 01:48:22 -07:00
										 |  |  |                      'Ganons Tower - Conveyor Star Pits Pot Key': (0x7b, 0x400), | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  |                      'Ganons Tower - DMs Room - Top Left': (0x7b, 0x10), | 
					
						
							|  |  |  |                      'Ganons Tower - DMs Room - Top Right': (0x7b, 0x20), | 
					
						
							|  |  |  |                      'Ganons Tower - DMs Room - Bottom Left': (0x7b, 0x40), | 
					
						
							|  |  |  |                      'Ganons Tower - DMs Room - Bottom Right': (0x7b, 0x80), | 
					
						
							|  |  |  |                      'Ganons Tower - Map Chest': (0x8b, 0x10), | 
					
						
							| 
									
										
										
										
											2020-10-28 01:48:22 -07:00
										 |  |  |                      'Ganons Tower - Double Switch Pot Key': (0x9b, 0x400), | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  |                      'Ganons Tower - Firesnake Room': (0x7d, 0x10), | 
					
						
							|  |  |  |                      'Ganons Tower - Randomizer Room - Top Left': (0x7c, 0x10), | 
					
						
							|  |  |  |                      'Ganons Tower - Randomizer Room - Top Right': (0x7c, 0x20), | 
					
						
							|  |  |  |                      'Ganons Tower - Randomizer Room - Bottom Left': (0x7c, 0x40), | 
					
						
							|  |  |  |                      'Ganons Tower - Randomizer Room - Bottom Right': (0x7c, 0x80), | 
					
						
							|  |  |  |                      "Ganons Tower - Bob's Chest": (0x8c, 0x80), | 
					
						
							|  |  |  |                      'Ganons Tower - Big Chest': (0x8c, 0x10), | 
					
						
							|  |  |  |                      'Ganons Tower - Big Key Room - Left': (0x1c, 0x20), | 
					
						
							|  |  |  |                      'Ganons Tower - Big Key Room - Right': (0x1c, 0x40), | 
					
						
							|  |  |  |                      'Ganons Tower - Big Key Chest': (0x1c, 0x10), | 
					
						
							|  |  |  |                      'Ganons Tower - Mini Helmasaur Room - Left': (0x3d, 0x10), | 
					
						
							|  |  |  |                      'Ganons Tower - Mini Helmasaur Room - Right': (0x3d, 0x20), | 
					
						
							| 
									
										
										
										
											2020-10-28 01:48:22 -07:00
										 |  |  |                      'Ganons Tower - Mini Helmasaur Key Drop': (0x3d, 0x400), | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  |                      'Ganons Tower - Pre-Moldorm Chest': (0x3d, 0x40), | 
					
						
							|  |  |  |                      'Ganons Tower - Validation Chest': (0x4d, 0x10)} | 
					
						
							| 
									
										
										
										
											2021-03-07 22:05:07 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | location_table_uw_id = {Regions.lookup_name_to_id[name] : data for name, data in location_table_uw.items()} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  | location_table_npc = {'Mushroom': 0x1000, | 
					
						
							|  |  |  |                       'King Zora': 0x2, | 
					
						
							|  |  |  |                       'Sahasrahla': 0x10, | 
					
						
							|  |  |  |                       'Blacksmith': 0x400, | 
					
						
							|  |  |  |                       'Magic Bat': 0x8000, | 
					
						
							|  |  |  |                       'Sick Kid': 0x4, | 
					
						
							|  |  |  |                       'Library': 0x80, | 
					
						
							|  |  |  |                       'Potion Shop': 0x2000, | 
					
						
							|  |  |  |                       'Old Man': 0x1, | 
					
						
							|  |  |  |                       'Ether Tablet': 0x100, | 
					
						
							|  |  |  |                       'Catfish': 0x20, | 
					
						
							|  |  |  |                       'Stumpy': 0x8, | 
					
						
							|  |  |  |                       'Bombos Tablet': 0x200} | 
					
						
							| 
									
										
										
										
											2021-03-07 22:05:07 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | location_table_npc_id = {Regions.lookup_name_to_id[name] : data for name, data in location_table_npc.items()} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  | location_table_ow = {'Flute Spot': 0x2a, | 
					
						
							|  |  |  |                      'Sunken Treasure': 0x3b, | 
					
						
							|  |  |  |                      "Zora's Ledge": 0x81, | 
					
						
							|  |  |  |                      'Lake Hylia Island': 0x35, | 
					
						
							|  |  |  |                      'Maze Race': 0x28, | 
					
						
							|  |  |  |                      'Desert Ledge': 0x30, | 
					
						
							|  |  |  |                      'Master Sword Pedestal': 0x80, | 
					
						
							|  |  |  |                      'Spectacle Rock': 0x3, | 
					
						
							|  |  |  |                      'Pyramid': 0x5b, | 
					
						
							|  |  |  |                      'Digging Game': 0x68, | 
					
						
							|  |  |  |                      'Bumper Cave Ledge': 0x4a, | 
					
						
							|  |  |  |                      'Floating Island': 0x5} | 
					
						
							| 
									
										
										
										
											2021-03-07 22:05:07 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | location_table_ow_id = {Regions.lookup_name_to_id[name] : data for name, data in location_table_ow.items()} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  | location_table_misc = {'Bottle Merchant': (0x3c9, 0x2), | 
					
						
							|  |  |  |                        'Purple Chest': (0x3c9, 0x10), | 
					
						
							|  |  |  |                        "Link's Uncle": (0x3c6, 0x1), | 
					
						
							|  |  |  |                        'Hobo': (0x3c9, 0x1)} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-07 22:05:07 +01:00
										 |  |  | location_table_misc_id = {Regions.lookup_name_to_id[name] : data for name, data in location_table_misc.items()} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class SNESState(enum.IntEnum): | 
					
						
							|  |  |  |     SNES_DISCONNECTED = 0 | 
					
						
							|  |  |  |     SNES_CONNECTING = 1 | 
					
						
							|  |  |  |     SNES_CONNECTED = 2 | 
					
						
							|  |  |  |     SNES_ATTACHED = 3 | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
											  
											
												WebUI (#100)
* Object-Oriented base changes for web-ui prep
* remove debug raise
* optimize broadcast to serialize once
* Implement WebUI socket, static assets, and classes
- Still need to wrap logging functions and send output to UI
- UI commands are successfully being sent to the server
* GUI operational. Wrap logging functions, implement server address selection on GUI, automatically launch web browser when client websocket is served
* Update MultiServer status when a user disconnects / reconnects
* Implement colored item and hint checks, improve GUI readability
* Fix improper formatting on received items
* Update SNES connection status on disconnect / reconnect. Implement itemFound, prevent accidentally printing JS objects
* Minor text change for itemFound
* Fixed a very wrong comment
* Fixed client commands not working, fixed un-helpful error messages appearing in GUI
* Fix a bug causing a failure to connect to a multiworld server if a previously existing cached address was present and the client was loaded without an address passed in
* Convert WebUI to React /w Redux. WebSocket communications not yet operational.
* WebUI fully converted to React / Redux.
- Websocket communication operational
- Added a button to connect to the multiserver which appears only when a SNES is connected and a server connection is not active
* Restore some features lost in WebUI
- Restore (found) notification on hints if the item has already been obtained
- Restore (x/y) indicator on received items, which indicates the number of items the client is waiting to receive from the client in a queue
* Fix a grammatical UI big causing player names to show only an apostrophe when possessive
* Add support for multiple SNES Devices, and switching between them
* freeze support for client
* make sure flask works when frozen
* UI Improvements
- Hint messages now actually show a found status via ✔ and ❌ emoji
- Active player name is always a different color than other players (orange for now)
- Add a toggle to show only entries relevant to the active player
- Added a WidgetArea
- Added a notes widget
* Received items now marked as relevant
* Include production build for deployment
* Notes now survive a browser close. Minimum width applied to monitor to prevent CSS issues.
* include webUi folder in setup.py
* Bugfixes for Monitor
- Fix a bug causing the monitor window to grow beyond it's intended content limit
- Reduced monitor content limit to 200 items
- Ensured each monitor entry has a unique key
* Prevent eslint from yelling at me about stupid things
* Add button to collapse sidebar, press enter on empty server input to disconnect on purpose
* WebUI is now aware of client disconnect, message log limit increased to 350, fix !missing output
* Update WebUI to v2.2.1
- Added color to WebUI for entrance-span
- Make !missing show total count at bottom of list to match /missing behavior
* Fix a bug causing clients version <= 2.2.0 to crash when anyone asks for a hint
- Also fix a bug in the WebUI causing the entrance location to always show as "somewhere"
* Update WebUI color palette (this cost me $50)
* allow text console input alongside web-ui
* remove Flask
a bit overkill for what we're doing
* remove jinja2
* Update WebUI to work with new hosting mechanism
* with flask gone, we no longer need subprocess shenanigans
* If multiple web ui clients try to run, at least present a working console
* Update MultiClient and WebUI to handle multiple clients simultaneously.
- The port on which the websocket for the WebUI is hosted is not chosen randomly from 5000 - 5999. This port is passed to the browser so it knows which MultiClient to connect to
- Removed failure condition if a web server is already running, as there is no need to run more than one web server on a single system. If an exception is thrown while attempting to launch a web server, a check is made for the port being unavailable. If the port is unavailable, it probably means the user is launching a second MultiClient. A web browser is then opened with a connection to the correct webui_socket_port.
- Add a /web command to the MultiClient to repoen the appropriate browser window and get params in case a user accidentally closes the tab
* Use proper name for WebUI
* move webui into /data with other data files
* make web ui optional
This is mostly for laptop users wanting to preserve some battery, should not be needed outside of that.
* fix direct server start
* re-add connection timer
* fix indentation
Co-authored-by: Chris <chris@legendserver.info>
											
										 
											2020-06-03 21:29:43 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-06 23:46:28 +02:00
										 |  |  | def launch_qusb2snes(ctx: Context): | 
					
						
							| 
									
										
										
										
											2021-04-01 11:40:58 +02:00
										 |  |  |     qusb2snes_path = Utils.get_options()["lttp_options"]["qusb2snes"] | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-06 23:46:28 +02:00
										 |  |  |     if not os.path.isfile(qusb2snes_path): | 
					
						
							|  |  |  |         qusb2snes_path = Utils.local_path(qusb2snes_path) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if os.path.isfile(qusb2snes_path): | 
					
						
							| 
									
										
										
										
											2021-01-19 06:37:35 +01:00
										 |  |  |         logger.info(f"Attempting to start {qusb2snes_path}") | 
					
						
							| 
									
										
										
										
											2020-06-06 23:46:28 +02:00
										 |  |  |         import subprocess | 
					
						
							|  |  |  |         subprocess.Popen(qusb2snes_path, cwd=os.path.dirname(qusb2snes_path)) | 
					
						
							|  |  |  |     else: | 
					
						
							| 
									
										
										
										
											2021-01-19 06:37:35 +01:00
										 |  |  |         logger.info( | 
					
						
							| 
									
										
										
										
											2020-06-06 23:46:28 +02:00
										 |  |  |             f"Attempt to start (Q)Usb2Snes was aborted as path {qusb2snes_path} was not found, " | 
					
						
							|  |  |  |             f"please start it yourself if it is not running") | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-06 23:46:28 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | async def _snes_connect(ctx: Context, address: str): | 
					
						
							| 
									
										
										
										
											2020-01-13 03:55:33 +01:00
										 |  |  |     address = f"ws://{address}" if "://" not in address else address | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-19 06:37:35 +01:00
										 |  |  |     logger.info("Connecting to QUsb2snes at %s ..." % address) | 
					
						
							| 
									
										
										
										
											2020-03-07 00:07:32 +01:00
										 |  |  |     seen_problems = set() | 
					
						
							| 
									
										
										
										
											2020-06-06 23:46:28 +02:00
										 |  |  |     succesful = False | 
					
						
							|  |  |  |     while not succesful: | 
					
						
							| 
									
										
										
										
											2020-03-07 00:07:32 +01:00
										 |  |  |         try: | 
					
						
							| 
									
										
										
										
											2020-06-06 23:46:28 +02:00
										 |  |  |             snes_socket = await websockets.connect(address, ping_timeout=None, ping_interval=None) | 
					
						
							|  |  |  |             succesful = True | 
					
						
							| 
									
										
										
										
											2020-03-07 00:07:32 +01:00
										 |  |  |         except Exception as e: | 
					
						
							|  |  |  |             problem = "%s" % e | 
					
						
							|  |  |  |             # only tell the user about new problems, otherwise silently lay in wait for a working connection | 
					
						
							|  |  |  |             if problem not in seen_problems: | 
					
						
							|  |  |  |                 seen_problems.add(problem) | 
					
						
							| 
									
										
										
										
											2021-01-19 06:37:35 +01:00
										 |  |  |                 logger.error(f"Error connecting to QUsb2snes ({problem})") | 
					
						
							| 
									
										
											  
											
												WebUI (#100)
* Object-Oriented base changes for web-ui prep
* remove debug raise
* optimize broadcast to serialize once
* Implement WebUI socket, static assets, and classes
- Still need to wrap logging functions and send output to UI
- UI commands are successfully being sent to the server
* GUI operational. Wrap logging functions, implement server address selection on GUI, automatically launch web browser when client websocket is served
* Update MultiServer status when a user disconnects / reconnects
* Implement colored item and hint checks, improve GUI readability
* Fix improper formatting on received items
* Update SNES connection status on disconnect / reconnect. Implement itemFound, prevent accidentally printing JS objects
* Minor text change for itemFound
* Fixed a very wrong comment
* Fixed client commands not working, fixed un-helpful error messages appearing in GUI
* Fix a bug causing a failure to connect to a multiworld server if a previously existing cached address was present and the client was loaded without an address passed in
* Convert WebUI to React /w Redux. WebSocket communications not yet operational.
* WebUI fully converted to React / Redux.
- Websocket communication operational
- Added a button to connect to the multiserver which appears only when a SNES is connected and a server connection is not active
* Restore some features lost in WebUI
- Restore (found) notification on hints if the item has already been obtained
- Restore (x/y) indicator on received items, which indicates the number of items the client is waiting to receive from the client in a queue
* Fix a grammatical UI big causing player names to show only an apostrophe when possessive
* Add support for multiple SNES Devices, and switching between them
* freeze support for client
* make sure flask works when frozen
* UI Improvements
- Hint messages now actually show a found status via ✔ and ❌ emoji
- Active player name is always a different color than other players (orange for now)
- Add a toggle to show only entries relevant to the active player
- Added a WidgetArea
- Added a notes widget
* Received items now marked as relevant
* Include production build for deployment
* Notes now survive a browser close. Minimum width applied to monitor to prevent CSS issues.
* include webUi folder in setup.py
* Bugfixes for Monitor
- Fix a bug causing the monitor window to grow beyond it's intended content limit
- Reduced monitor content limit to 200 items
- Ensured each monitor entry has a unique key
* Prevent eslint from yelling at me about stupid things
* Add button to collapse sidebar, press enter on empty server input to disconnect on purpose
* WebUI is now aware of client disconnect, message log limit increased to 350, fix !missing output
* Update WebUI to v2.2.1
- Added color to WebUI for entrance-span
- Make !missing show total count at bottom of list to match /missing behavior
* Fix a bug causing clients version <= 2.2.0 to crash when anyone asks for a hint
- Also fix a bug in the WebUI causing the entrance location to always show as "somewhere"
* Update WebUI color palette (this cost me $50)
* allow text console input alongside web-ui
* remove Flask
a bit overkill for what we're doing
* remove jinja2
* Update WebUI to work with new hosting mechanism
* with flask gone, we no longer need subprocess shenanigans
* If multiple web ui clients try to run, at least present a working console
* Update MultiClient and WebUI to handle multiple clients simultaneously.
- The port on which the websocket for the WebUI is hosted is not chosen randomly from 5000 - 5999. This port is passed to the browser so it knows which MultiClient to connect to
- Removed failure condition if a web server is already running, as there is no need to run more than one web server on a single system. If an exception is thrown while attempting to launch a web server, a check is made for the port being unavailable. If the port is unavailable, it probably means the user is launching a second MultiClient. A web browser is then opened with a connection to the correct webui_socket_port.
- Add a /web command to the MultiClient to repoen the appropriate browser window and get params in case a user accidentally closes the tab
* Use proper name for WebUI
* move webui into /data with other data files
* make web ui optional
This is mostly for laptop users wanting to preserve some battery, should not be needed outside of that.
* fix direct server start
* re-add connection timer
* fix indentation
Co-authored-by: Chris <chris@legendserver.info>
											
										 
											2020-06-03 21:29:43 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-07 04:18:26 +02:00
										 |  |  |                 if len(seen_problems) == 1: | 
					
						
							| 
									
										
										
										
											2020-04-12 04:38:57 +02:00
										 |  |  |                     # this is the first problem. Let's try launching QUsb2snes if it isn't already running | 
					
						
							| 
									
										
										
										
											2020-06-06 23:46:28 +02:00
										 |  |  |                     launch_qusb2snes(ctx) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             await asyncio.sleep(1) | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             return snes_socket | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-12 04:44:03 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-06 23:46:28 +02:00
										 |  |  | async def get_snes_devices(ctx: Context): | 
					
						
							|  |  |  |     socket = await _snes_connect(ctx, ctx.snes_address)  # establish new connection to poll | 
					
						
							|  |  |  |     DeviceList_Request = { | 
					
						
							|  |  |  |         "Opcode": "DeviceList", | 
					
						
							|  |  |  |         "Space": "SNES" | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-10-19 08:26:31 +02:00
										 |  |  |     await socket.send(dumps(DeviceList_Request)) | 
					
						
							| 
									
										
										
										
											2020-04-12 04:44:03 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-19 08:26:31 +02:00
										 |  |  |     reply = loads(await socket.recv()) | 
					
						
							| 
									
										
										
										
											2020-06-06 23:46:28 +02:00
										 |  |  |     devices = reply['Results'] if 'Results' in reply and len(reply['Results']) > 0 else None | 
					
						
							| 
									
										
										
										
											2020-04-07 04:18:26 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-06 23:46:28 +02:00
										 |  |  |     if not devices: | 
					
						
							| 
									
										
										
										
											2021-01-19 06:37:35 +01:00
										 |  |  |         logger.info('No SNES device found. Ensure QUsb2Snes is running and connect it to the multibridge.') | 
					
						
							| 
									
										
										
										
											2020-06-06 23:46:28 +02:00
										 |  |  |         while not devices: | 
					
						
							| 
									
										
										
										
											2020-03-07 00:07:32 +01:00
										 |  |  |             await asyncio.sleep(1) | 
					
						
							| 
									
										
										
										
											2020-10-19 08:26:31 +02:00
										 |  |  |             await socket.send(dumps(DeviceList_Request)) | 
					
						
							|  |  |  |             reply = loads(await socket.recv()) | 
					
						
							| 
									
										
										
										
											2020-06-06 23:46:28 +02:00
										 |  |  |             devices = reply['Results'] if 'Results' in reply and len(reply['Results']) > 0 else None | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-14 01:25:41 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-06 23:46:28 +02:00
										 |  |  |     await socket.close() | 
					
						
							|  |  |  |     return devices | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-06 23:46:28 +02:00
										 |  |  | async def snes_connect(ctx: Context, address): | 
					
						
							| 
									
										
										
										
											2020-09-01 21:45:01 +02:00
										 |  |  |     global SNES_RECONNECT_DELAY | 
					
						
							| 
									
										
										
										
											2021-03-07 22:05:07 +01:00
										 |  |  |     if ctx.snes_socket is not None and ctx.snes_state == SNESState.SNES_CONNECTED: | 
					
						
							| 
									
										
										
										
											2021-01-19 06:37:35 +01:00
										 |  |  |         logger.error('Already connected to snes') | 
					
						
							| 
									
										
										
										
											2020-06-06 23:46:28 +02:00
										 |  |  |         return | 
					
						
							| 
									
										
											  
											
												WebUI (#100)
* Object-Oriented base changes for web-ui prep
* remove debug raise
* optimize broadcast to serialize once
* Implement WebUI socket, static assets, and classes
- Still need to wrap logging functions and send output to UI
- UI commands are successfully being sent to the server
* GUI operational. Wrap logging functions, implement server address selection on GUI, automatically launch web browser when client websocket is served
* Update MultiServer status when a user disconnects / reconnects
* Implement colored item and hint checks, improve GUI readability
* Fix improper formatting on received items
* Update SNES connection status on disconnect / reconnect. Implement itemFound, prevent accidentally printing JS objects
* Minor text change for itemFound
* Fixed a very wrong comment
* Fixed client commands not working, fixed un-helpful error messages appearing in GUI
* Fix a bug causing a failure to connect to a multiworld server if a previously existing cached address was present and the client was loaded without an address passed in
* Convert WebUI to React /w Redux. WebSocket communications not yet operational.
* WebUI fully converted to React / Redux.
- Websocket communication operational
- Added a button to connect to the multiserver which appears only when a SNES is connected and a server connection is not active
* Restore some features lost in WebUI
- Restore (found) notification on hints if the item has already been obtained
- Restore (x/y) indicator on received items, which indicates the number of items the client is waiting to receive from the client in a queue
* Fix a grammatical UI big causing player names to show only an apostrophe when possessive
* Add support for multiple SNES Devices, and switching between them
* freeze support for client
* make sure flask works when frozen
* UI Improvements
- Hint messages now actually show a found status via ✔ and ❌ emoji
- Active player name is always a different color than other players (orange for now)
- Add a toggle to show only entries relevant to the active player
- Added a WidgetArea
- Added a notes widget
* Received items now marked as relevant
* Include production build for deployment
* Notes now survive a browser close. Minimum width applied to monitor to prevent CSS issues.
* include webUi folder in setup.py
* Bugfixes for Monitor
- Fix a bug causing the monitor window to grow beyond it's intended content limit
- Reduced monitor content limit to 200 items
- Ensured each monitor entry has a unique key
* Prevent eslint from yelling at me about stupid things
* Add button to collapse sidebar, press enter on empty server input to disconnect on purpose
* WebUI is now aware of client disconnect, message log limit increased to 350, fix !missing output
* Update WebUI to v2.2.1
- Added color to WebUI for entrance-span
- Make !missing show total count at bottom of list to match /missing behavior
* Fix a bug causing clients version <= 2.2.0 to crash when anyone asks for a hint
- Also fix a bug in the WebUI causing the entrance location to always show as "somewhere"
* Update WebUI color palette (this cost me $50)
* allow text console input alongside web-ui
* remove Flask
a bit overkill for what we're doing
* remove jinja2
* Update WebUI to work with new hosting mechanism
* with flask gone, we no longer need subprocess shenanigans
* If multiple web ui clients try to run, at least present a working console
* Update MultiClient and WebUI to handle multiple clients simultaneously.
- The port on which the websocket for the WebUI is hosted is not chosen randomly from 5000 - 5999. This port is passed to the browser so it knows which MultiClient to connect to
- Removed failure condition if a web server is already running, as there is no need to run more than one web server on a single system. If an exception is thrown while attempting to launch a web server, a check is made for the port being unavailable. If the port is unavailable, it probably means the user is launching a second MultiClient. A web browser is then opened with a connection to the correct webui_socket_port.
- Add a /web command to the MultiClient to repoen the appropriate browser window and get params in case a user accidentally closes the tab
* Use proper name for WebUI
* move webui into /data with other data files
* make web ui optional
This is mostly for laptop users wanting to preserve some battery, should not be needed outside of that.
* fix direct server start
* re-add connection timer
* fix indentation
Co-authored-by: Chris <chris@legendserver.info>
											
										 
											2020-06-03 21:29:43 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-06 23:46:28 +02:00
										 |  |  |     recv_task = None | 
					
						
							| 
									
										
										
										
											2021-03-07 22:05:07 +01:00
										 |  |  |     ctx.snes_state = SNESState.SNES_CONNECTING | 
					
						
							| 
									
										
										
										
											2020-06-06 23:46:28 +02:00
										 |  |  |     socket = await _snes_connect(ctx, address) | 
					
						
							|  |  |  |     ctx.snes_socket = socket | 
					
						
							| 
									
										
										
										
											2021-03-07 22:05:07 +01:00
										 |  |  |     ctx.snes_state = SNESState.SNES_CONNECTED | 
					
						
							| 
									
										
										
										
											2020-06-06 23:46:28 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     try: | 
					
						
							|  |  |  |         devices = await get_snes_devices(ctx) | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-13 03:55:33 +01:00
										 |  |  |         if len(devices) == 1: | 
					
						
							|  |  |  |             device = devices[0] | 
					
						
							|  |  |  |         elif ctx.snes_reconnect_address: | 
					
						
							|  |  |  |             if ctx.snes_attached_device[1] in devices: | 
					
						
							|  |  |  |                 device = ctx.snes_attached_device[1] | 
					
						
							|  |  |  |             else: | 
					
						
							|  |  |  |                 device = devices[ctx.snes_attached_device[0]] | 
					
						
							|  |  |  |         else: | 
					
						
							| 
									
										
											  
											
												WebUI (#100)
* Object-Oriented base changes for web-ui prep
* remove debug raise
* optimize broadcast to serialize once
* Implement WebUI socket, static assets, and classes
- Still need to wrap logging functions and send output to UI
- UI commands are successfully being sent to the server
* GUI operational. Wrap logging functions, implement server address selection on GUI, automatically launch web browser when client websocket is served
* Update MultiServer status when a user disconnects / reconnects
* Implement colored item and hint checks, improve GUI readability
* Fix improper formatting on received items
* Update SNES connection status on disconnect / reconnect. Implement itemFound, prevent accidentally printing JS objects
* Minor text change for itemFound
* Fixed a very wrong comment
* Fixed client commands not working, fixed un-helpful error messages appearing in GUI
* Fix a bug causing a failure to connect to a multiworld server if a previously existing cached address was present and the client was loaded without an address passed in
* Convert WebUI to React /w Redux. WebSocket communications not yet operational.
* WebUI fully converted to React / Redux.
- Websocket communication operational
- Added a button to connect to the multiserver which appears only when a SNES is connected and a server connection is not active
* Restore some features lost in WebUI
- Restore (found) notification on hints if the item has already been obtained
- Restore (x/y) indicator on received items, which indicates the number of items the client is waiting to receive from the client in a queue
* Fix a grammatical UI big causing player names to show only an apostrophe when possessive
* Add support for multiple SNES Devices, and switching between them
* freeze support for client
* make sure flask works when frozen
* UI Improvements
- Hint messages now actually show a found status via ✔ and ❌ emoji
- Active player name is always a different color than other players (orange for now)
- Add a toggle to show only entries relevant to the active player
- Added a WidgetArea
- Added a notes widget
* Received items now marked as relevant
* Include production build for deployment
* Notes now survive a browser close. Minimum width applied to monitor to prevent CSS issues.
* include webUi folder in setup.py
* Bugfixes for Monitor
- Fix a bug causing the monitor window to grow beyond it's intended content limit
- Reduced monitor content limit to 200 items
- Ensured each monitor entry has a unique key
* Prevent eslint from yelling at me about stupid things
* Add button to collapse sidebar, press enter on empty server input to disconnect on purpose
* WebUI is now aware of client disconnect, message log limit increased to 350, fix !missing output
* Update WebUI to v2.2.1
- Added color to WebUI for entrance-span
- Make !missing show total count at bottom of list to match /missing behavior
* Fix a bug causing clients version <= 2.2.0 to crash when anyone asks for a hint
- Also fix a bug in the WebUI causing the entrance location to always show as "somewhere"
* Update WebUI color palette (this cost me $50)
* allow text console input alongside web-ui
* remove Flask
a bit overkill for what we're doing
* remove jinja2
* Update WebUI to work with new hosting mechanism
* with flask gone, we no longer need subprocess shenanigans
* If multiple web ui clients try to run, at least present a working console
* Update MultiClient and WebUI to handle multiple clients simultaneously.
- The port on which the websocket for the WebUI is hosted is not chosen randomly from 5000 - 5999. This port is passed to the browser so it knows which MultiClient to connect to
- Removed failure condition if a web server is already running, as there is no need to run more than one web server on a single system. If an exception is thrown while attempting to launch a web server, a check is made for the port being unavailable. If the port is unavailable, it probably means the user is launching a second MultiClient. A web browser is then opened with a connection to the correct webui_socket_port.
- Add a /web command to the MultiClient to repoen the appropriate browser window and get params in case a user accidentally closes the tab
* Use proper name for WebUI
* move webui into /data with other data files
* make web ui optional
This is mostly for laptop users wanting to preserve some battery, should not be needed outside of that.
* fix direct server start
* re-add connection timer
* fix indentation
Co-authored-by: Chris <chris@legendserver.info>
											
										 
											2020-06-03 21:29:43 +02:00
										 |  |  |             await snes_disconnect(ctx) | 
					
						
							|  |  |  |             return | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-19 06:37:35 +01:00
										 |  |  |         logger.info("Attaching to " + device) | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         Attach_Request = { | 
					
						
							| 
									
										
											  
											
												WebUI (#100)
* Object-Oriented base changes for web-ui prep
* remove debug raise
* optimize broadcast to serialize once
* Implement WebUI socket, static assets, and classes
- Still need to wrap logging functions and send output to UI
- UI commands are successfully being sent to the server
* GUI operational. Wrap logging functions, implement server address selection on GUI, automatically launch web browser when client websocket is served
* Update MultiServer status when a user disconnects / reconnects
* Implement colored item and hint checks, improve GUI readability
* Fix improper formatting on received items
* Update SNES connection status on disconnect / reconnect. Implement itemFound, prevent accidentally printing JS objects
* Minor text change for itemFound
* Fixed a very wrong comment
* Fixed client commands not working, fixed un-helpful error messages appearing in GUI
* Fix a bug causing a failure to connect to a multiworld server if a previously existing cached address was present and the client was loaded without an address passed in
* Convert WebUI to React /w Redux. WebSocket communications not yet operational.
* WebUI fully converted to React / Redux.
- Websocket communication operational
- Added a button to connect to the multiserver which appears only when a SNES is connected and a server connection is not active
* Restore some features lost in WebUI
- Restore (found) notification on hints if the item has already been obtained
- Restore (x/y) indicator on received items, which indicates the number of items the client is waiting to receive from the client in a queue
* Fix a grammatical UI big causing player names to show only an apostrophe when possessive
* Add support for multiple SNES Devices, and switching between them
* freeze support for client
* make sure flask works when frozen
* UI Improvements
- Hint messages now actually show a found status via ✔ and ❌ emoji
- Active player name is always a different color than other players (orange for now)
- Add a toggle to show only entries relevant to the active player
- Added a WidgetArea
- Added a notes widget
* Received items now marked as relevant
* Include production build for deployment
* Notes now survive a browser close. Minimum width applied to monitor to prevent CSS issues.
* include webUi folder in setup.py
* Bugfixes for Monitor
- Fix a bug causing the monitor window to grow beyond it's intended content limit
- Reduced monitor content limit to 200 items
- Ensured each monitor entry has a unique key
* Prevent eslint from yelling at me about stupid things
* Add button to collapse sidebar, press enter on empty server input to disconnect on purpose
* WebUI is now aware of client disconnect, message log limit increased to 350, fix !missing output
* Update WebUI to v2.2.1
- Added color to WebUI for entrance-span
- Make !missing show total count at bottom of list to match /missing behavior
* Fix a bug causing clients version <= 2.2.0 to crash when anyone asks for a hint
- Also fix a bug in the WebUI causing the entrance location to always show as "somewhere"
* Update WebUI color palette (this cost me $50)
* allow text console input alongside web-ui
* remove Flask
a bit overkill for what we're doing
* remove jinja2
* Update WebUI to work with new hosting mechanism
* with flask gone, we no longer need subprocess shenanigans
* If multiple web ui clients try to run, at least present a working console
* Update MultiClient and WebUI to handle multiple clients simultaneously.
- The port on which the websocket for the WebUI is hosted is not chosen randomly from 5000 - 5999. This port is passed to the browser so it knows which MultiClient to connect to
- Removed failure condition if a web server is already running, as there is no need to run more than one web server on a single system. If an exception is thrown while attempting to launch a web server, a check is made for the port being unavailable. If the port is unavailable, it probably means the user is launching a second MultiClient. A web browser is then opened with a connection to the correct webui_socket_port.
- Add a /web command to the MultiClient to repoen the appropriate browser window and get params in case a user accidentally closes the tab
* Use proper name for WebUI
* move webui into /data with other data files
* make web ui optional
This is mostly for laptop users wanting to preserve some battery, should not be needed outside of that.
* fix direct server start
* re-add connection timer
* fix indentation
Co-authored-by: Chris <chris@legendserver.info>
											
										 
											2020-06-03 21:29:43 +02:00
										 |  |  |             "Opcode": "Attach", | 
					
						
							|  |  |  |             "Space": "SNES", | 
					
						
							|  |  |  |             "Operands": [device] | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2020-10-19 08:26:31 +02:00
										 |  |  |         await ctx.snes_socket.send(dumps(Attach_Request)) | 
					
						
							| 
									
										
										
										
											2021-03-07 22:05:07 +01:00
										 |  |  |         ctx.snes_state = SNESState.SNES_ATTACHED | 
					
						
							| 
									
										
										
										
											2020-01-13 03:55:33 +01:00
										 |  |  |         ctx.snes_attached_device = (devices.index(device), device) | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-01 22:23:37 +01:00
										 |  |  |         if 'sd2snes' in device.lower() or 'COM' in device: | 
					
						
							| 
									
										
										
										
											2021-01-19 06:37:35 +01:00
										 |  |  |             logger.info("SD2SNES/FXPAK Detected") | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  |             ctx.is_sd2snes = True | 
					
						
							| 
									
										
										
										
											2021-01-21 23:37:58 +01:00
										 |  |  |             await ctx.snes_socket.send(dumps({"Opcode": "Info", "Space": "SNES"})) | 
					
						
							| 
									
										
										
										
											2020-10-19 08:26:31 +02:00
										 |  |  |             reply = loads(await ctx.snes_socket.recv()) | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  |             if reply and 'Results' in reply: | 
					
						
							| 
									
										
										
										
											2021-01-19 06:37:35 +01:00
										 |  |  |                 logger.info(reply['Results']) | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  |         else: | 
					
						
							|  |  |  |             ctx.is_sd2snes = False | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-13 03:55:33 +01:00
										 |  |  |         ctx.snes_reconnect_address = address | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  |         recv_task = asyncio.create_task(snes_recv_loop(ctx)) | 
					
						
							| 
									
										
										
										
											2021-04-01 11:40:58 +02:00
										 |  |  |         SNES_RECONNECT_DELAY = ctx.starting_reconnect_delay | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     except Exception as e: | 
					
						
							|  |  |  |         if recv_task is not None: | 
					
						
							|  |  |  |             if not ctx.snes_socket.closed: | 
					
						
							|  |  |  |                 await ctx.snes_socket.close() | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             if ctx.snes_socket is not None: | 
					
						
							|  |  |  |                 if not ctx.snes_socket.closed: | 
					
						
							|  |  |  |                     await ctx.snes_socket.close() | 
					
						
							|  |  |  |                 ctx.snes_socket = None | 
					
						
							| 
									
										
										
										
											2021-03-07 22:05:07 +01:00
										 |  |  |             ctx.snes_state = SNESState.SNES_DISCONNECTED | 
					
						
							| 
									
										
										
										
											2020-01-13 03:55:33 +01:00
										 |  |  |         if not ctx.snes_reconnect_address: | 
					
						
							| 
									
										
										
										
											2021-01-19 06:37:35 +01:00
										 |  |  |             logger.error("Error connecting to snes (%s)" % e) | 
					
						
							| 
									
										
										
										
											2020-01-13 03:55:33 +01:00
										 |  |  |         else: | 
					
						
							| 
									
										
										
										
											2021-01-19 06:37:35 +01:00
										 |  |  |             logger.error(f"Error connecting to snes, attempt again in {SNES_RECONNECT_DELAY}s") | 
					
						
							| 
									
										
										
										
											2020-01-14 10:42:27 +01:00
										 |  |  |             asyncio.create_task(snes_autoreconnect(ctx)) | 
					
						
							| 
									
										
										
										
											2020-09-01 21:45:01 +02:00
										 |  |  |         SNES_RECONNECT_DELAY *= 2 | 
					
						
							| 
									
										
										
										
											2020-01-13 03:55:33 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-13 03:53:20 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
											  
											
												WebUI (#100)
* Object-Oriented base changes for web-ui prep
* remove debug raise
* optimize broadcast to serialize once
* Implement WebUI socket, static assets, and classes
- Still need to wrap logging functions and send output to UI
- UI commands are successfully being sent to the server
* GUI operational. Wrap logging functions, implement server address selection on GUI, automatically launch web browser when client websocket is served
* Update MultiServer status when a user disconnects / reconnects
* Implement colored item and hint checks, improve GUI readability
* Fix improper formatting on received items
* Update SNES connection status on disconnect / reconnect. Implement itemFound, prevent accidentally printing JS objects
* Minor text change for itemFound
* Fixed a very wrong comment
* Fixed client commands not working, fixed un-helpful error messages appearing in GUI
* Fix a bug causing a failure to connect to a multiworld server if a previously existing cached address was present and the client was loaded without an address passed in
* Convert WebUI to React /w Redux. WebSocket communications not yet operational.
* WebUI fully converted to React / Redux.
- Websocket communication operational
- Added a button to connect to the multiserver which appears only when a SNES is connected and a server connection is not active
* Restore some features lost in WebUI
- Restore (found) notification on hints if the item has already been obtained
- Restore (x/y) indicator on received items, which indicates the number of items the client is waiting to receive from the client in a queue
* Fix a grammatical UI big causing player names to show only an apostrophe when possessive
* Add support for multiple SNES Devices, and switching between them
* freeze support for client
* make sure flask works when frozen
* UI Improvements
- Hint messages now actually show a found status via ✔ and ❌ emoji
- Active player name is always a different color than other players (orange for now)
- Add a toggle to show only entries relevant to the active player
- Added a WidgetArea
- Added a notes widget
* Received items now marked as relevant
* Include production build for deployment
* Notes now survive a browser close. Minimum width applied to monitor to prevent CSS issues.
* include webUi folder in setup.py
* Bugfixes for Monitor
- Fix a bug causing the monitor window to grow beyond it's intended content limit
- Reduced monitor content limit to 200 items
- Ensured each monitor entry has a unique key
* Prevent eslint from yelling at me about stupid things
* Add button to collapse sidebar, press enter on empty server input to disconnect on purpose
* WebUI is now aware of client disconnect, message log limit increased to 350, fix !missing output
* Update WebUI to v2.2.1
- Added color to WebUI for entrance-span
- Make !missing show total count at bottom of list to match /missing behavior
* Fix a bug causing clients version <= 2.2.0 to crash when anyone asks for a hint
- Also fix a bug in the WebUI causing the entrance location to always show as "somewhere"
* Update WebUI color palette (this cost me $50)
* allow text console input alongside web-ui
* remove Flask
a bit overkill for what we're doing
* remove jinja2
* Update WebUI to work with new hosting mechanism
* with flask gone, we no longer need subprocess shenanigans
* If multiple web ui clients try to run, at least present a working console
* Update MultiClient and WebUI to handle multiple clients simultaneously.
- The port on which the websocket for the WebUI is hosted is not chosen randomly from 5000 - 5999. This port is passed to the browser so it knows which MultiClient to connect to
- Removed failure condition if a web server is already running, as there is no need to run more than one web server on a single system. If an exception is thrown while attempting to launch a web server, a check is made for the port being unavailable. If the port is unavailable, it probably means the user is launching a second MultiClient. A web browser is then opened with a connection to the correct webui_socket_port.
- Add a /web command to the MultiClient to repoen the appropriate browser window and get params in case a user accidentally closes the tab
* Use proper name for WebUI
* move webui into /data with other data files
* make web ui optional
This is mostly for laptop users wanting to preserve some battery, should not be needed outside of that.
* fix direct server start
* re-add connection timer
* fix indentation
Co-authored-by: Chris <chris@legendserver.info>
											
										 
											2020-06-03 21:29:43 +02:00
										 |  |  | async def snes_disconnect(ctx: Context): | 
					
						
							|  |  |  |     if ctx.snes_socket: | 
					
						
							|  |  |  |         if not ctx.snes_socket.closed: | 
					
						
							|  |  |  |             await ctx.snes_socket.close() | 
					
						
							|  |  |  |         ctx.snes_socket = None | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-14 10:42:27 +01:00
										 |  |  | async def snes_autoreconnect(ctx: Context): | 
					
						
							| 
									
										
										
										
											2020-03-13 03:53:20 +01:00
										 |  |  |     # unfortunately currently broken. See: https://github.com/prompt-toolkit/python-prompt-toolkit/issues/1033 | 
					
						
							|  |  |  |     # with prompt_toolkit.shortcuts.ProgressBar() as pb: | 
					
						
							|  |  |  |     #    for _ in pb(range(100)): | 
					
						
							|  |  |  |     #        await asyncio.sleep(RECONNECT_DELAY/100) | 
					
						
							| 
									
										
										
										
											2020-09-01 21:45:01 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     await asyncio.sleep(SNES_RECONNECT_DELAY) | 
					
						
							| 
									
										
										
										
											2020-01-13 03:55:33 +01:00
										 |  |  |     if ctx.snes_reconnect_address and ctx.snes_socket is None: | 
					
						
							|  |  |  |         await snes_connect(ctx, ctx.snes_reconnect_address) | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
											  
											
												WebUI (#100)
* Object-Oriented base changes for web-ui prep
* remove debug raise
* optimize broadcast to serialize once
* Implement WebUI socket, static assets, and classes
- Still need to wrap logging functions and send output to UI
- UI commands are successfully being sent to the server
* GUI operational. Wrap logging functions, implement server address selection on GUI, automatically launch web browser when client websocket is served
* Update MultiServer status when a user disconnects / reconnects
* Implement colored item and hint checks, improve GUI readability
* Fix improper formatting on received items
* Update SNES connection status on disconnect / reconnect. Implement itemFound, prevent accidentally printing JS objects
* Minor text change for itemFound
* Fixed a very wrong comment
* Fixed client commands not working, fixed un-helpful error messages appearing in GUI
* Fix a bug causing a failure to connect to a multiworld server if a previously existing cached address was present and the client was loaded without an address passed in
* Convert WebUI to React /w Redux. WebSocket communications not yet operational.
* WebUI fully converted to React / Redux.
- Websocket communication operational
- Added a button to connect to the multiserver which appears only when a SNES is connected and a server connection is not active
* Restore some features lost in WebUI
- Restore (found) notification on hints if the item has already been obtained
- Restore (x/y) indicator on received items, which indicates the number of items the client is waiting to receive from the client in a queue
* Fix a grammatical UI big causing player names to show only an apostrophe when possessive
* Add support for multiple SNES Devices, and switching between them
* freeze support for client
* make sure flask works when frozen
* UI Improvements
- Hint messages now actually show a found status via ✔ and ❌ emoji
- Active player name is always a different color than other players (orange for now)
- Add a toggle to show only entries relevant to the active player
- Added a WidgetArea
- Added a notes widget
* Received items now marked as relevant
* Include production build for deployment
* Notes now survive a browser close. Minimum width applied to monitor to prevent CSS issues.
* include webUi folder in setup.py
* Bugfixes for Monitor
- Fix a bug causing the monitor window to grow beyond it's intended content limit
- Reduced monitor content limit to 200 items
- Ensured each monitor entry has a unique key
* Prevent eslint from yelling at me about stupid things
* Add button to collapse sidebar, press enter on empty server input to disconnect on purpose
* WebUI is now aware of client disconnect, message log limit increased to 350, fix !missing output
* Update WebUI to v2.2.1
- Added color to WebUI for entrance-span
- Make !missing show total count at bottom of list to match /missing behavior
* Fix a bug causing clients version <= 2.2.0 to crash when anyone asks for a hint
- Also fix a bug in the WebUI causing the entrance location to always show as "somewhere"
* Update WebUI color palette (this cost me $50)
* allow text console input alongside web-ui
* remove Flask
a bit overkill for what we're doing
* remove jinja2
* Update WebUI to work with new hosting mechanism
* with flask gone, we no longer need subprocess shenanigans
* If multiple web ui clients try to run, at least present a working console
* Update MultiClient and WebUI to handle multiple clients simultaneously.
- The port on which the websocket for the WebUI is hosted is not chosen randomly from 5000 - 5999. This port is passed to the browser so it knows which MultiClient to connect to
- Removed failure condition if a web server is already running, as there is no need to run more than one web server on a single system. If an exception is thrown while attempting to launch a web server, a check is made for the port being unavailable. If the port is unavailable, it probably means the user is launching a second MultiClient. A web browser is then opened with a connection to the correct webui_socket_port.
- Add a /web command to the MultiClient to repoen the appropriate browser window and get params in case a user accidentally closes the tab
* Use proper name for WebUI
* move webui into /data with other data files
* make web ui optional
This is mostly for laptop users wanting to preserve some battery, should not be needed outside of that.
* fix direct server start
* re-add connection timer
* fix indentation
Co-authored-by: Chris <chris@legendserver.info>
											
										 
											2020-06-03 21:29:43 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | async def snes_recv_loop(ctx: Context): | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  |     try: | 
					
						
							|  |  |  |         async for msg in ctx.snes_socket: | 
					
						
							|  |  |  |             ctx.snes_recv_queue.put_nowait(msg) | 
					
						
							| 
									
										
										
										
											2021-01-19 06:37:35 +01:00
										 |  |  |         logger.warning("Snes disconnected") | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  |     except Exception as e: | 
					
						
							| 
									
										
										
										
											2019-12-16 18:39:00 +01:00
										 |  |  |         if not isinstance(e, websockets.WebSocketException): | 
					
						
							| 
									
										
										
										
											2021-01-19 06:37:35 +01:00
										 |  |  |             logger.exception(e) | 
					
						
							|  |  |  |         logger.error("Lost connection to the snes, type /snes to reconnect") | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  |     finally: | 
					
						
							|  |  |  |         socket, ctx.snes_socket = ctx.snes_socket, None | 
					
						
							|  |  |  |         if socket is not None and not socket.closed: | 
					
						
							|  |  |  |             await socket.close() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-07 22:05:07 +01:00
										 |  |  |         ctx.snes_state = SNESState.SNES_DISCONNECTED | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  |         ctx.snes_recv_queue = asyncio.Queue() | 
					
						
							|  |  |  |         ctx.hud_message_queue = [] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-14 10:42:27 +01:00
										 |  |  |         ctx.rom = None | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-13 03:55:33 +01:00
										 |  |  |         if ctx.snes_reconnect_address: | 
					
						
							| 
									
										
										
										
											2021-01-19 06:37:35 +01:00
										 |  |  |             logger.info(f"...reconnecting in {SNES_RECONNECT_DELAY}s") | 
					
						
							| 
									
										
										
										
											2020-01-14 10:42:27 +01:00
										 |  |  |             asyncio.create_task(snes_autoreconnect(ctx)) | 
					
						
							| 
									
										
										
										
											2020-01-13 03:55:33 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
											  
											
												WebUI (#100)
* Object-Oriented base changes for web-ui prep
* remove debug raise
* optimize broadcast to serialize once
* Implement WebUI socket, static assets, and classes
- Still need to wrap logging functions and send output to UI
- UI commands are successfully being sent to the server
* GUI operational. Wrap logging functions, implement server address selection on GUI, automatically launch web browser when client websocket is served
* Update MultiServer status when a user disconnects / reconnects
* Implement colored item and hint checks, improve GUI readability
* Fix improper formatting on received items
* Update SNES connection status on disconnect / reconnect. Implement itemFound, prevent accidentally printing JS objects
* Minor text change for itemFound
* Fixed a very wrong comment
* Fixed client commands not working, fixed un-helpful error messages appearing in GUI
* Fix a bug causing a failure to connect to a multiworld server if a previously existing cached address was present and the client was loaded without an address passed in
* Convert WebUI to React /w Redux. WebSocket communications not yet operational.
* WebUI fully converted to React / Redux.
- Websocket communication operational
- Added a button to connect to the multiserver which appears only when a SNES is connected and a server connection is not active
* Restore some features lost in WebUI
- Restore (found) notification on hints if the item has already been obtained
- Restore (x/y) indicator on received items, which indicates the number of items the client is waiting to receive from the client in a queue
* Fix a grammatical UI big causing player names to show only an apostrophe when possessive
* Add support for multiple SNES Devices, and switching between them
* freeze support for client
* make sure flask works when frozen
* UI Improvements
- Hint messages now actually show a found status via ✔ and ❌ emoji
- Active player name is always a different color than other players (orange for now)
- Add a toggle to show only entries relevant to the active player
- Added a WidgetArea
- Added a notes widget
* Received items now marked as relevant
* Include production build for deployment
* Notes now survive a browser close. Minimum width applied to monitor to prevent CSS issues.
* include webUi folder in setup.py
* Bugfixes for Monitor
- Fix a bug causing the monitor window to grow beyond it's intended content limit
- Reduced monitor content limit to 200 items
- Ensured each monitor entry has a unique key
* Prevent eslint from yelling at me about stupid things
* Add button to collapse sidebar, press enter on empty server input to disconnect on purpose
* WebUI is now aware of client disconnect, message log limit increased to 350, fix !missing output
* Update WebUI to v2.2.1
- Added color to WebUI for entrance-span
- Make !missing show total count at bottom of list to match /missing behavior
* Fix a bug causing clients version <= 2.2.0 to crash when anyone asks for a hint
- Also fix a bug in the WebUI causing the entrance location to always show as "somewhere"
* Update WebUI color palette (this cost me $50)
* allow text console input alongside web-ui
* remove Flask
a bit overkill for what we're doing
* remove jinja2
* Update WebUI to work with new hosting mechanism
* with flask gone, we no longer need subprocess shenanigans
* If multiple web ui clients try to run, at least present a working console
* Update MultiClient and WebUI to handle multiple clients simultaneously.
- The port on which the websocket for the WebUI is hosted is not chosen randomly from 5000 - 5999. This port is passed to the browser so it knows which MultiClient to connect to
- Removed failure condition if a web server is already running, as there is no need to run more than one web server on a single system. If an exception is thrown while attempting to launch a web server, a check is made for the port being unavailable. If the port is unavailable, it probably means the user is launching a second MultiClient. A web browser is then opened with a connection to the correct webui_socket_port.
- Add a /web command to the MultiClient to repoen the appropriate browser window and get params in case a user accidentally closes the tab
* Use proper name for WebUI
* move webui into /data with other data files
* make web ui optional
This is mostly for laptop users wanting to preserve some battery, should not be needed outside of that.
* fix direct server start
* re-add connection timer
* fix indentation
Co-authored-by: Chris <chris@legendserver.info>
											
										 
											2020-06-03 21:29:43 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-21 23:37:58 +01:00
										 |  |  | async def snes_read(ctx: Context, address, size): | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  |     try: | 
					
						
							|  |  |  |         await ctx.snes_request_lock.acquire() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-07 22:05:07 +01:00
										 |  |  |         if ctx.snes_state != SNESState.SNES_ATTACHED or ctx.snes_socket is None or not ctx.snes_socket.open or ctx.snes_socket.closed: | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  |             return None | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         GetAddress_Request = { | 
					
						
							| 
									
										
										
										
											2021-01-21 23:37:58 +01:00
										 |  |  |             "Opcode": "GetAddress", | 
					
						
							|  |  |  |             "Space": "SNES", | 
					
						
							|  |  |  |             "Operands": [hex(address)[2:], hex(size)[2:]] | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  |         } | 
					
						
							|  |  |  |         try: | 
					
						
							| 
									
										
										
										
											2020-10-19 08:26:31 +02:00
										 |  |  |             await ctx.snes_socket.send(dumps(GetAddress_Request)) | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  |         except websockets.ConnectionClosed: | 
					
						
							|  |  |  |             return None | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         data = bytes() | 
					
						
							|  |  |  |         while len(data) < size: | 
					
						
							|  |  |  |             try: | 
					
						
							|  |  |  |                 data += await asyncio.wait_for(ctx.snes_recv_queue.get(), 5) | 
					
						
							|  |  |  |             except asyncio.TimeoutError: | 
					
						
							|  |  |  |                 break | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if len(data) != size: | 
					
						
							| 
									
										
										
										
											2021-01-19 06:37:35 +01:00
										 |  |  |             logger.error('Error reading %s, requested %d bytes, received %d' % (hex(address), size, len(data))) | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  |             if len(data): | 
					
						
							| 
									
										
										
										
											2021-01-19 06:37:35 +01:00
										 |  |  |                 logger.error(str(data)) | 
					
						
							|  |  |  |                 logger.warning('Unable to connect to SNES Device because QUsb2Snes broke temporarily.' | 
					
						
							| 
									
										
										
										
											2021-01-21 23:37:58 +01:00
										 |  |  |                                'Try un-selecting and re-selecting the SNES Device.') | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  |             if ctx.snes_socket is not None and not ctx.snes_socket.closed: | 
					
						
							|  |  |  |                 await ctx.snes_socket.close() | 
					
						
							|  |  |  |             return None | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return data | 
					
						
							|  |  |  |     finally: | 
					
						
							|  |  |  |         ctx.snes_request_lock.release() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
											  
											
												WebUI (#100)
* Object-Oriented base changes for web-ui prep
* remove debug raise
* optimize broadcast to serialize once
* Implement WebUI socket, static assets, and classes
- Still need to wrap logging functions and send output to UI
- UI commands are successfully being sent to the server
* GUI operational. Wrap logging functions, implement server address selection on GUI, automatically launch web browser when client websocket is served
* Update MultiServer status when a user disconnects / reconnects
* Implement colored item and hint checks, improve GUI readability
* Fix improper formatting on received items
* Update SNES connection status on disconnect / reconnect. Implement itemFound, prevent accidentally printing JS objects
* Minor text change for itemFound
* Fixed a very wrong comment
* Fixed client commands not working, fixed un-helpful error messages appearing in GUI
* Fix a bug causing a failure to connect to a multiworld server if a previously existing cached address was present and the client was loaded without an address passed in
* Convert WebUI to React /w Redux. WebSocket communications not yet operational.
* WebUI fully converted to React / Redux.
- Websocket communication operational
- Added a button to connect to the multiserver which appears only when a SNES is connected and a server connection is not active
* Restore some features lost in WebUI
- Restore (found) notification on hints if the item has already been obtained
- Restore (x/y) indicator on received items, which indicates the number of items the client is waiting to receive from the client in a queue
* Fix a grammatical UI big causing player names to show only an apostrophe when possessive
* Add support for multiple SNES Devices, and switching between them
* freeze support for client
* make sure flask works when frozen
* UI Improvements
- Hint messages now actually show a found status via ✔ and ❌ emoji
- Active player name is always a different color than other players (orange for now)
- Add a toggle to show only entries relevant to the active player
- Added a WidgetArea
- Added a notes widget
* Received items now marked as relevant
* Include production build for deployment
* Notes now survive a browser close. Minimum width applied to monitor to prevent CSS issues.
* include webUi folder in setup.py
* Bugfixes for Monitor
- Fix a bug causing the monitor window to grow beyond it's intended content limit
- Reduced monitor content limit to 200 items
- Ensured each monitor entry has a unique key
* Prevent eslint from yelling at me about stupid things
* Add button to collapse sidebar, press enter on empty server input to disconnect on purpose
* WebUI is now aware of client disconnect, message log limit increased to 350, fix !missing output
* Update WebUI to v2.2.1
- Added color to WebUI for entrance-span
- Make !missing show total count at bottom of list to match /missing behavior
* Fix a bug causing clients version <= 2.2.0 to crash when anyone asks for a hint
- Also fix a bug in the WebUI causing the entrance location to always show as "somewhere"
* Update WebUI color palette (this cost me $50)
* allow text console input alongside web-ui
* remove Flask
a bit overkill for what we're doing
* remove jinja2
* Update WebUI to work with new hosting mechanism
* with flask gone, we no longer need subprocess shenanigans
* If multiple web ui clients try to run, at least present a working console
* Update MultiClient and WebUI to handle multiple clients simultaneously.
- The port on which the websocket for the WebUI is hosted is not chosen randomly from 5000 - 5999. This port is passed to the browser so it knows which MultiClient to connect to
- Removed failure condition if a web server is already running, as there is no need to run more than one web server on a single system. If an exception is thrown while attempting to launch a web server, a check is made for the port being unavailable. If the port is unavailable, it probably means the user is launching a second MultiClient. A web browser is then opened with a connection to the correct webui_socket_port.
- Add a /web command to the MultiClient to repoen the appropriate browser window and get params in case a user accidentally closes the tab
* Use proper name for WebUI
* move webui into /data with other data files
* make web ui optional
This is mostly for laptop users wanting to preserve some battery, should not be needed outside of that.
* fix direct server start
* re-add connection timer
* fix indentation
Co-authored-by: Chris <chris@legendserver.info>
											
										 
											2020-06-03 21:29:43 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-21 23:37:58 +01:00
										 |  |  | async def snes_write(ctx: Context, write_list): | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  |     try: | 
					
						
							|  |  |  |         await ctx.snes_request_lock.acquire() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-07 22:05:07 +01:00
										 |  |  |         if ctx.snes_state != SNESState.SNES_ATTACHED or ctx.snes_socket is None or \ | 
					
						
							|  |  |  |                 not ctx.snes_socket.open or ctx.snes_socket.closed: | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  |             return False | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-11 12:36:02 +01:00
										 |  |  |         PutAddress_Request = {"Opcode": "PutAddress", "Operands": [], 'Space': 'SNES'} | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         if ctx.is_sd2snes: | 
					
						
							|  |  |  |             cmd = b'\x00\xE2\x20\x48\xEB\x48' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             for address, data in write_list: | 
					
						
							|  |  |  |                 if (address < WRAM_START) or ((address + len(data)) > (WRAM_START + WRAM_SIZE)): | 
					
						
							| 
									
										
										
										
											2021-01-19 06:37:35 +01:00
										 |  |  |                     logger.error("SD2SNES: Write out of range %s (%d)" % (hex(address), len(data))) | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  |                     return False | 
					
						
							|  |  |  |                 for ptr, byte in enumerate(data, address + 0x7E0000 - WRAM_START): | 
					
						
							| 
									
										
										
										
											2021-01-21 23:37:58 +01:00
										 |  |  |                     cmd += b'\xA9'  # LDA | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  |                     cmd += bytes([byte]) | 
					
						
							| 
									
										
										
										
											2021-01-21 23:37:58 +01:00
										 |  |  |                     cmd += b'\x8F'  # STA.l | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  |                     cmd += bytes([ptr & 0xFF, (ptr >> 8) & 0xFF, (ptr >> 16) & 0xFF]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             cmd += b'\xA9\x00\x8F\x00\x2C\x00\x68\xEB\x68\x28\x6C\xEA\xFF\x08' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             PutAddress_Request['Space'] = 'CMD' | 
					
						
							| 
									
										
										
										
											2021-01-21 23:37:58 +01:00
										 |  |  |             PutAddress_Request['Operands'] = ["2C00", hex(len(cmd) - 1)[2:], "2C00", "1"] | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  |             try: | 
					
						
							|  |  |  |                 if ctx.snes_socket is not None: | 
					
						
							| 
									
										
										
										
											2020-10-19 08:26:31 +02:00
										 |  |  |                     await ctx.snes_socket.send(dumps(PutAddress_Request)) | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  |                     await ctx.snes_socket.send(cmd) | 
					
						
							| 
									
										
										
										
											2020-12-01 21:57:18 +01:00
										 |  |  |                 else: | 
					
						
							| 
									
										
										
										
											2021-01-19 06:37:35 +01:00
										 |  |  |                     logger.warning(f"Could not send data to SNES: {cmd}") | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  |             except websockets.ConnectionClosed: | 
					
						
							|  |  |  |                 return False | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             PutAddress_Request['Space'] = 'SNES' | 
					
						
							|  |  |  |             try: | 
					
						
							| 
									
										
										
										
											2021-01-21 23:37:58 +01:00
										 |  |  |                 # will pack those requests as soon as qusb2snes actually supports that for real | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  |                 for address, data in write_list: | 
					
						
							|  |  |  |                     PutAddress_Request['Operands'] = [hex(address)[2:], hex(len(data))[2:]] | 
					
						
							|  |  |  |                     if ctx.snes_socket is not None: | 
					
						
							| 
									
										
										
										
											2020-10-19 08:26:31 +02:00
										 |  |  |                         await ctx.snes_socket.send(dumps(PutAddress_Request)) | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  |                         await ctx.snes_socket.send(data) | 
					
						
							| 
									
										
										
										
											2020-12-01 22:23:37 +01:00
										 |  |  |                     else: | 
					
						
							| 
									
										
										
										
											2021-01-19 06:37:35 +01:00
										 |  |  |                         logger.warning(f"Could not send data to SNES: {data}") | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  |             except websockets.ConnectionClosed: | 
					
						
							|  |  |  |                 return False | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return True | 
					
						
							|  |  |  |     finally: | 
					
						
							|  |  |  |         ctx.snes_request_lock.release() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
											  
											
												WebUI (#100)
* Object-Oriented base changes for web-ui prep
* remove debug raise
* optimize broadcast to serialize once
* Implement WebUI socket, static assets, and classes
- Still need to wrap logging functions and send output to UI
- UI commands are successfully being sent to the server
* GUI operational. Wrap logging functions, implement server address selection on GUI, automatically launch web browser when client websocket is served
* Update MultiServer status when a user disconnects / reconnects
* Implement colored item and hint checks, improve GUI readability
* Fix improper formatting on received items
* Update SNES connection status on disconnect / reconnect. Implement itemFound, prevent accidentally printing JS objects
* Minor text change for itemFound
* Fixed a very wrong comment
* Fixed client commands not working, fixed un-helpful error messages appearing in GUI
* Fix a bug causing a failure to connect to a multiworld server if a previously existing cached address was present and the client was loaded without an address passed in
* Convert WebUI to React /w Redux. WebSocket communications not yet operational.
* WebUI fully converted to React / Redux.
- Websocket communication operational
- Added a button to connect to the multiserver which appears only when a SNES is connected and a server connection is not active
* Restore some features lost in WebUI
- Restore (found) notification on hints if the item has already been obtained
- Restore (x/y) indicator on received items, which indicates the number of items the client is waiting to receive from the client in a queue
* Fix a grammatical UI big causing player names to show only an apostrophe when possessive
* Add support for multiple SNES Devices, and switching between them
* freeze support for client
* make sure flask works when frozen
* UI Improvements
- Hint messages now actually show a found status via ✔ and ❌ emoji
- Active player name is always a different color than other players (orange for now)
- Add a toggle to show only entries relevant to the active player
- Added a WidgetArea
- Added a notes widget
* Received items now marked as relevant
* Include production build for deployment
* Notes now survive a browser close. Minimum width applied to monitor to prevent CSS issues.
* include webUi folder in setup.py
* Bugfixes for Monitor
- Fix a bug causing the monitor window to grow beyond it's intended content limit
- Reduced monitor content limit to 200 items
- Ensured each monitor entry has a unique key
* Prevent eslint from yelling at me about stupid things
* Add button to collapse sidebar, press enter on empty server input to disconnect on purpose
* WebUI is now aware of client disconnect, message log limit increased to 350, fix !missing output
* Update WebUI to v2.2.1
- Added color to WebUI for entrance-span
- Make !missing show total count at bottom of list to match /missing behavior
* Fix a bug causing clients version <= 2.2.0 to crash when anyone asks for a hint
- Also fix a bug in the WebUI causing the entrance location to always show as "somewhere"
* Update WebUI color palette (this cost me $50)
* allow text console input alongside web-ui
* remove Flask
a bit overkill for what we're doing
* remove jinja2
* Update WebUI to work with new hosting mechanism
* with flask gone, we no longer need subprocess shenanigans
* If multiple web ui clients try to run, at least present a working console
* Update MultiClient and WebUI to handle multiple clients simultaneously.
- The port on which the websocket for the WebUI is hosted is not chosen randomly from 5000 - 5999. This port is passed to the browser so it knows which MultiClient to connect to
- Removed failure condition if a web server is already running, as there is no need to run more than one web server on a single system. If an exception is thrown while attempting to launch a web server, a check is made for the port being unavailable. If the port is unavailable, it probably means the user is launching a second MultiClient. A web browser is then opened with a connection to the correct webui_socket_port.
- Add a /web command to the MultiClient to repoen the appropriate browser window and get params in case a user accidentally closes the tab
* Use proper name for WebUI
* move webui into /data with other data files
* make web ui optional
This is mostly for laptop users wanting to preserve some battery, should not be needed outside of that.
* fix direct server start
* re-add connection timer
* fix indentation
Co-authored-by: Chris <chris@legendserver.info>
											
										 
											2020-06-03 21:29:43 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-21 23:37:58 +01:00
										 |  |  | def snes_buffered_write(ctx: Context, address, data): | 
					
						
							| 
									
										
										
										
											2020-12-01 21:57:18 +01:00
										 |  |  |     if ctx.snes_write_buffer and (ctx.snes_write_buffer[-1][0] + len(ctx.snes_write_buffer[-1][1])) == address: | 
					
						
							|  |  |  |         # append to existing write command, bundling them | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  |         ctx.snes_write_buffer[-1] = (ctx.snes_write_buffer[-1][0], ctx.snes_write_buffer[-1][1] + data) | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  |         ctx.snes_write_buffer.append((address, data)) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
											  
											
												WebUI (#100)
* Object-Oriented base changes for web-ui prep
* remove debug raise
* optimize broadcast to serialize once
* Implement WebUI socket, static assets, and classes
- Still need to wrap logging functions and send output to UI
- UI commands are successfully being sent to the server
* GUI operational. Wrap logging functions, implement server address selection on GUI, automatically launch web browser when client websocket is served
* Update MultiServer status when a user disconnects / reconnects
* Implement colored item and hint checks, improve GUI readability
* Fix improper formatting on received items
* Update SNES connection status on disconnect / reconnect. Implement itemFound, prevent accidentally printing JS objects
* Minor text change for itemFound
* Fixed a very wrong comment
* Fixed client commands not working, fixed un-helpful error messages appearing in GUI
* Fix a bug causing a failure to connect to a multiworld server if a previously existing cached address was present and the client was loaded without an address passed in
* Convert WebUI to React /w Redux. WebSocket communications not yet operational.
* WebUI fully converted to React / Redux.
- Websocket communication operational
- Added a button to connect to the multiserver which appears only when a SNES is connected and a server connection is not active
* Restore some features lost in WebUI
- Restore (found) notification on hints if the item has already been obtained
- Restore (x/y) indicator on received items, which indicates the number of items the client is waiting to receive from the client in a queue
* Fix a grammatical UI big causing player names to show only an apostrophe when possessive
* Add support for multiple SNES Devices, and switching between them
* freeze support for client
* make sure flask works when frozen
* UI Improvements
- Hint messages now actually show a found status via ✔ and ❌ emoji
- Active player name is always a different color than other players (orange for now)
- Add a toggle to show only entries relevant to the active player
- Added a WidgetArea
- Added a notes widget
* Received items now marked as relevant
* Include production build for deployment
* Notes now survive a browser close. Minimum width applied to monitor to prevent CSS issues.
* include webUi folder in setup.py
* Bugfixes for Monitor
- Fix a bug causing the monitor window to grow beyond it's intended content limit
- Reduced monitor content limit to 200 items
- Ensured each monitor entry has a unique key
* Prevent eslint from yelling at me about stupid things
* Add button to collapse sidebar, press enter on empty server input to disconnect on purpose
* WebUI is now aware of client disconnect, message log limit increased to 350, fix !missing output
* Update WebUI to v2.2.1
- Added color to WebUI for entrance-span
- Make !missing show total count at bottom of list to match /missing behavior
* Fix a bug causing clients version <= 2.2.0 to crash when anyone asks for a hint
- Also fix a bug in the WebUI causing the entrance location to always show as "somewhere"
* Update WebUI color palette (this cost me $50)
* allow text console input alongside web-ui
* remove Flask
a bit overkill for what we're doing
* remove jinja2
* Update WebUI to work with new hosting mechanism
* with flask gone, we no longer need subprocess shenanigans
* If multiple web ui clients try to run, at least present a working console
* Update MultiClient and WebUI to handle multiple clients simultaneously.
- The port on which the websocket for the WebUI is hosted is not chosen randomly from 5000 - 5999. This port is passed to the browser so it knows which MultiClient to connect to
- Removed failure condition if a web server is already running, as there is no need to run more than one web server on a single system. If an exception is thrown while attempting to launch a web server, a check is made for the port being unavailable. If the port is unavailable, it probably means the user is launching a second MultiClient. A web browser is then opened with a connection to the correct webui_socket_port.
- Add a /web command to the MultiClient to repoen the appropriate browser window and get params in case a user accidentally closes the tab
* Use proper name for WebUI
* move webui into /data with other data files
* make web ui optional
This is mostly for laptop users wanting to preserve some battery, should not be needed outside of that.
* fix direct server start
* re-add connection timer
* fix indentation
Co-authored-by: Chris <chris@legendserver.info>
											
										 
											2020-06-03 21:29:43 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-21 23:37:58 +01:00
										 |  |  | async def snes_flush_writes(ctx: Context): | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  |     if not ctx.snes_write_buffer: | 
					
						
							|  |  |  |         return | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-01 21:57:18 +01:00
										 |  |  |     # swap buffers | 
					
						
							|  |  |  |     ctx.snes_write_buffer, writes = [], ctx.snes_write_buffer | 
					
						
							|  |  |  |     await snes_write(ctx, writes) | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
											  
											
												WebUI (#100)
* Object-Oriented base changes for web-ui prep
* remove debug raise
* optimize broadcast to serialize once
* Implement WebUI socket, static assets, and classes
- Still need to wrap logging functions and send output to UI
- UI commands are successfully being sent to the server
* GUI operational. Wrap logging functions, implement server address selection on GUI, automatically launch web browser when client websocket is served
* Update MultiServer status when a user disconnects / reconnects
* Implement colored item and hint checks, improve GUI readability
* Fix improper formatting on received items
* Update SNES connection status on disconnect / reconnect. Implement itemFound, prevent accidentally printing JS objects
* Minor text change for itemFound
* Fixed a very wrong comment
* Fixed client commands not working, fixed un-helpful error messages appearing in GUI
* Fix a bug causing a failure to connect to a multiworld server if a previously existing cached address was present and the client was loaded without an address passed in
* Convert WebUI to React /w Redux. WebSocket communications not yet operational.
* WebUI fully converted to React / Redux.
- Websocket communication operational
- Added a button to connect to the multiserver which appears only when a SNES is connected and a server connection is not active
* Restore some features lost in WebUI
- Restore (found) notification on hints if the item has already been obtained
- Restore (x/y) indicator on received items, which indicates the number of items the client is waiting to receive from the client in a queue
* Fix a grammatical UI big causing player names to show only an apostrophe when possessive
* Add support for multiple SNES Devices, and switching between them
* freeze support for client
* make sure flask works when frozen
* UI Improvements
- Hint messages now actually show a found status via ✔ and ❌ emoji
- Active player name is always a different color than other players (orange for now)
- Add a toggle to show only entries relevant to the active player
- Added a WidgetArea
- Added a notes widget
* Received items now marked as relevant
* Include production build for deployment
* Notes now survive a browser close. Minimum width applied to monitor to prevent CSS issues.
* include webUi folder in setup.py
* Bugfixes for Monitor
- Fix a bug causing the monitor window to grow beyond it's intended content limit
- Reduced monitor content limit to 200 items
- Ensured each monitor entry has a unique key
* Prevent eslint from yelling at me about stupid things
* Add button to collapse sidebar, press enter on empty server input to disconnect on purpose
* WebUI is now aware of client disconnect, message log limit increased to 350, fix !missing output
* Update WebUI to v2.2.1
- Added color to WebUI for entrance-span
- Make !missing show total count at bottom of list to match /missing behavior
* Fix a bug causing clients version <= 2.2.0 to crash when anyone asks for a hint
- Also fix a bug in the WebUI causing the entrance location to always show as "somewhere"
* Update WebUI color palette (this cost me $50)
* allow text console input alongside web-ui
* remove Flask
a bit overkill for what we're doing
* remove jinja2
* Update WebUI to work with new hosting mechanism
* with flask gone, we no longer need subprocess shenanigans
* If multiple web ui clients try to run, at least present a working console
* Update MultiClient and WebUI to handle multiple clients simultaneously.
- The port on which the websocket for the WebUI is hosted is not chosen randomly from 5000 - 5999. This port is passed to the browser so it knows which MultiClient to connect to
- Removed failure condition if a web server is already running, as there is no need to run more than one web server on a single system. If an exception is thrown while attempting to launch a web server, a check is made for the port being unavailable. If the port is unavailable, it probably means the user is launching a second MultiClient. A web browser is then opened with a connection to the correct webui_socket_port.
- Add a /web command to the MultiClient to repoen the appropriate browser window and get params in case a user accidentally closes the tab
* Use proper name for WebUI
* move webui into /data with other data files
* make web ui optional
This is mostly for laptop users wanting to preserve some battery, should not be needed outside of that.
* fix direct server start
* re-add connection timer
* fix indentation
Co-authored-by: Chris <chris@legendserver.info>
											
										 
											2020-06-03 21:29:43 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-03 01:57:12 +01:00
										 |  |  | # kept as function for easier wrapping by plugins | 
					
						
							| 
									
										
										
										
											2020-03-23 02:47:07 -07:00
										 |  |  | def get_tags(ctx: Context): | 
					
						
							| 
									
										
										
										
											2020-10-18 23:07:48 +02:00
										 |  |  |     tags = ['AP'] | 
					
						
							| 
									
										
										
										
											2020-03-23 02:47:07 -07:00
										 |  |  |     return tags | 
					
						
							| 
									
										
										
										
											2020-02-16 15:32:40 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
											  
											
												WebUI (#100)
* Object-Oriented base changes for web-ui prep
* remove debug raise
* optimize broadcast to serialize once
* Implement WebUI socket, static assets, and classes
- Still need to wrap logging functions and send output to UI
- UI commands are successfully being sent to the server
* GUI operational. Wrap logging functions, implement server address selection on GUI, automatically launch web browser when client websocket is served
* Update MultiServer status when a user disconnects / reconnects
* Implement colored item and hint checks, improve GUI readability
* Fix improper formatting on received items
* Update SNES connection status on disconnect / reconnect. Implement itemFound, prevent accidentally printing JS objects
* Minor text change for itemFound
* Fixed a very wrong comment
* Fixed client commands not working, fixed un-helpful error messages appearing in GUI
* Fix a bug causing a failure to connect to a multiworld server if a previously existing cached address was present and the client was loaded without an address passed in
* Convert WebUI to React /w Redux. WebSocket communications not yet operational.
* WebUI fully converted to React / Redux.
- Websocket communication operational
- Added a button to connect to the multiserver which appears only when a SNES is connected and a server connection is not active
* Restore some features lost in WebUI
- Restore (found) notification on hints if the item has already been obtained
- Restore (x/y) indicator on received items, which indicates the number of items the client is waiting to receive from the client in a queue
* Fix a grammatical UI big causing player names to show only an apostrophe when possessive
* Add support for multiple SNES Devices, and switching between them
* freeze support for client
* make sure flask works when frozen
* UI Improvements
- Hint messages now actually show a found status via ✔ and ❌ emoji
- Active player name is always a different color than other players (orange for now)
- Add a toggle to show only entries relevant to the active player
- Added a WidgetArea
- Added a notes widget
* Received items now marked as relevant
* Include production build for deployment
* Notes now survive a browser close. Minimum width applied to monitor to prevent CSS issues.
* include webUi folder in setup.py
* Bugfixes for Monitor
- Fix a bug causing the monitor window to grow beyond it's intended content limit
- Reduced monitor content limit to 200 items
- Ensured each monitor entry has a unique key
* Prevent eslint from yelling at me about stupid things
* Add button to collapse sidebar, press enter on empty server input to disconnect on purpose
* WebUI is now aware of client disconnect, message log limit increased to 350, fix !missing output
* Update WebUI to v2.2.1
- Added color to WebUI for entrance-span
- Make !missing show total count at bottom of list to match /missing behavior
* Fix a bug causing clients version <= 2.2.0 to crash when anyone asks for a hint
- Also fix a bug in the WebUI causing the entrance location to always show as "somewhere"
* Update WebUI color palette (this cost me $50)
* allow text console input alongside web-ui
* remove Flask
a bit overkill for what we're doing
* remove jinja2
* Update WebUI to work with new hosting mechanism
* with flask gone, we no longer need subprocess shenanigans
* If multiple web ui clients try to run, at least present a working console
* Update MultiClient and WebUI to handle multiple clients simultaneously.
- The port on which the websocket for the WebUI is hosted is not chosen randomly from 5000 - 5999. This port is passed to the browser so it knows which MultiClient to connect to
- Removed failure condition if a web server is already running, as there is no need to run more than one web server on a single system. If an exception is thrown while attempting to launch a web server, a check is made for the port being unavailable. If the port is unavailable, it probably means the user is launching a second MultiClient. A web browser is then opened with a connection to the correct webui_socket_port.
- Add a /web command to the MultiClient to repoen the appropriate browser window and get params in case a user accidentally closes the tab
* Use proper name for WebUI
* move webui into /data with other data files
* make web ui optional
This is mostly for laptop users wanting to preserve some battery, should not be needed outside of that.
* fix direct server start
* re-add connection timer
* fix indentation
Co-authored-by: Chris <chris@legendserver.info>
											
										 
											2020-06-03 21:29:43 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-14 20:22:42 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-21 23:37:58 +01:00
										 |  |  | async def track_locations(ctx: Context, roomid, roomdata): | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  |     new_locations = [] | 
					
						
							| 
									
										
											  
											
												WebUI (#100)
* Object-Oriented base changes for web-ui prep
* remove debug raise
* optimize broadcast to serialize once
* Implement WebUI socket, static assets, and classes
- Still need to wrap logging functions and send output to UI
- UI commands are successfully being sent to the server
* GUI operational. Wrap logging functions, implement server address selection on GUI, automatically launch web browser when client websocket is served
* Update MultiServer status when a user disconnects / reconnects
* Implement colored item and hint checks, improve GUI readability
* Fix improper formatting on received items
* Update SNES connection status on disconnect / reconnect. Implement itemFound, prevent accidentally printing JS objects
* Minor text change for itemFound
* Fixed a very wrong comment
* Fixed client commands not working, fixed un-helpful error messages appearing in GUI
* Fix a bug causing a failure to connect to a multiworld server if a previously existing cached address was present and the client was loaded without an address passed in
* Convert WebUI to React /w Redux. WebSocket communications not yet operational.
* WebUI fully converted to React / Redux.
- Websocket communication operational
- Added a button to connect to the multiserver which appears only when a SNES is connected and a server connection is not active
* Restore some features lost in WebUI
- Restore (found) notification on hints if the item has already been obtained
- Restore (x/y) indicator on received items, which indicates the number of items the client is waiting to receive from the client in a queue
* Fix a grammatical UI big causing player names to show only an apostrophe when possessive
* Add support for multiple SNES Devices, and switching between them
* freeze support for client
* make sure flask works when frozen
* UI Improvements
- Hint messages now actually show a found status via ✔ and ❌ emoji
- Active player name is always a different color than other players (orange for now)
- Add a toggle to show only entries relevant to the active player
- Added a WidgetArea
- Added a notes widget
* Received items now marked as relevant
* Include production build for deployment
* Notes now survive a browser close. Minimum width applied to monitor to prevent CSS issues.
* include webUi folder in setup.py
* Bugfixes for Monitor
- Fix a bug causing the monitor window to grow beyond it's intended content limit
- Reduced monitor content limit to 200 items
- Ensured each monitor entry has a unique key
* Prevent eslint from yelling at me about stupid things
* Add button to collapse sidebar, press enter on empty server input to disconnect on purpose
* WebUI is now aware of client disconnect, message log limit increased to 350, fix !missing output
* Update WebUI to v2.2.1
- Added color to WebUI for entrance-span
- Make !missing show total count at bottom of list to match /missing behavior
* Fix a bug causing clients version <= 2.2.0 to crash when anyone asks for a hint
- Also fix a bug in the WebUI causing the entrance location to always show as "somewhere"
* Update WebUI color palette (this cost me $50)
* allow text console input alongside web-ui
* remove Flask
a bit overkill for what we're doing
* remove jinja2
* Update WebUI to work with new hosting mechanism
* with flask gone, we no longer need subprocess shenanigans
* If multiple web ui clients try to run, at least present a working console
* Update MultiClient and WebUI to handle multiple clients simultaneously.
- The port on which the websocket for the WebUI is hosted is not chosen randomly from 5000 - 5999. This port is passed to the browser so it knows which MultiClient to connect to
- Removed failure condition if a web server is already running, as there is no need to run more than one web server on a single system. If an exception is thrown while attempting to launch a web server, a check is made for the port being unavailable. If the port is unavailable, it probably means the user is launching a second MultiClient. A web browser is then opened with a connection to the correct webui_socket_port.
- Add a /web command to the MultiClient to repoen the appropriate browser window and get params in case a user accidentally closes the tab
* Use proper name for WebUI
* move webui into /data with other data files
* make web ui optional
This is mostly for laptop users wanting to preserve some battery, should not be needed outside of that.
* fix direct server start
* re-add connection timer
* fix indentation
Co-authored-by: Chris <chris@legendserver.info>
											
										 
											2020-06-03 21:29:43 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-07 22:05:07 +01:00
										 |  |  |     def new_check(location_id): | 
					
						
							|  |  |  |         new_locations.append(location_id) | 
					
						
							|  |  |  |         ctx.locations_checked.add(location_id) | 
					
						
							|  |  |  |         location = ctx.location_name_getter(location_id) | 
					
						
							|  |  |  |         logger.info(f'New Check: {location} ({len(ctx.locations_checked)}/{len(ctx.missing_locations) + len(ctx.checked_locations)})') | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-20 03:17:08 +01:00
										 |  |  |     try: | 
					
						
							| 
									
										
										
										
											2020-12-15 02:34:22 -06:00
										 |  |  |         if roomid in location_shop_ids: | 
					
						
							| 
									
										
										
										
											2021-02-21 23:46:05 +01:00
										 |  |  |             misc_data = await snes_read(ctx, SHOP_ADDR, (len(location_shop_order) * 3) + 5) | 
					
						
							| 
									
										
										
										
											2020-12-15 02:34:22 -06:00
										 |  |  |             for cnt, b in enumerate(misc_data): | 
					
						
							| 
									
										
										
										
											2021-03-07 22:05:07 +01:00
										 |  |  |                 if int(b) and (Shops.SHOP_ID_START + cnt) not in ctx.locations_checked: | 
					
						
							|  |  |  |                     new_check(Shops.SHOP_ID_START + cnt) | 
					
						
							| 
									
										
										
										
											2020-12-15 02:34:22 -06:00
										 |  |  |     except Exception as e: | 
					
						
							| 
									
										
										
										
											2021-01-20 00:30:54 -08:00
										 |  |  |         logger.info(f"Exception: {e}") | 
					
						
							| 
									
										
										
										
											2021-01-20 03:17:08 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-07 22:05:07 +01:00
										 |  |  |     for location_id, (loc_roomid, loc_mask) in location_table_uw_id.items(): | 
					
						
							| 
									
										
										
										
											2020-10-27 00:47:59 -07:00
										 |  |  |         try: | 
					
						
							| 
									
										
										
										
											2021-03-07 22:05:07 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |             if location_id not in ctx.locations_checked and loc_roomid == roomid and ( | 
					
						
							| 
									
										
										
										
											2021-01-21 23:37:58 +01:00
										 |  |  |                     roomdata << 4) & loc_mask != 0: | 
					
						
							| 
									
										
										
										
											2021-03-07 22:05:07 +01:00
										 |  |  |                 new_check(location_id) | 
					
						
							| 
									
										
										
										
											2020-10-27 00:47:59 -07:00
										 |  |  |         except Exception as e: | 
					
						
							| 
									
										
										
										
											2021-01-21 05:34:45 +01:00
										 |  |  |             logger.exception(f"Exception: {e}") | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     uw_begin = 0x129 | 
					
						
							| 
									
										
										
										
											2021-01-21 23:37:58 +01:00
										 |  |  |     ow_end = uw_end = 0 | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  |     uw_unchecked = {} | 
					
						
							|  |  |  |     for location, (roomid, mask) in location_table_uw.items(): | 
					
						
							| 
									
										
										
										
											2021-03-07 22:05:07 +01:00
										 |  |  |         location_id = Regions.lookup_name_to_id[location] | 
					
						
							|  |  |  |         if location_id not in ctx.locations_checked: | 
					
						
							|  |  |  |             uw_unchecked[location_id] = (roomid, mask) | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  |             uw_begin = min(uw_begin, roomid) | 
					
						
							|  |  |  |             uw_end = max(uw_end, roomid + 1) | 
					
						
							| 
									
										
										
										
											2021-03-07 22:05:07 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  |     if uw_begin < uw_end: | 
					
						
							|  |  |  |         uw_data = await snes_read(ctx, SAVEDATA_START + (uw_begin * 2), (uw_end - uw_begin) * 2) | 
					
						
							|  |  |  |         if uw_data is not None: | 
					
						
							| 
									
										
										
										
											2021-03-07 22:05:07 +01:00
										 |  |  |             for location_id, (roomid, mask) in uw_unchecked.items(): | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  |                 offset = (roomid - uw_begin) * 2 | 
					
						
							|  |  |  |                 roomdata = uw_data[offset] | (uw_data[offset + 1] << 8) | 
					
						
							|  |  |  |                 if roomdata & mask != 0: | 
					
						
							| 
									
										
										
										
											2021-03-07 22:05:07 +01:00
										 |  |  |                     new_check(location_id) | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     ow_begin = 0x82 | 
					
						
							|  |  |  |     ow_unchecked = {} | 
					
						
							| 
									
										
										
										
											2021-03-07 22:05:07 +01:00
										 |  |  |     for location_id, screenid in location_table_ow_id.items(): | 
					
						
							|  |  |  |         if location_id not in ctx.locations_checked: | 
					
						
							|  |  |  |             ow_unchecked[location_id] = screenid | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  |             ow_begin = min(ow_begin, screenid) | 
					
						
							|  |  |  |             ow_end = max(ow_end, screenid + 1) | 
					
						
							| 
									
										
										
										
											2021-03-07 22:05:07 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  |     if ow_begin < ow_end: | 
					
						
							|  |  |  |         ow_data = await snes_read(ctx, SAVEDATA_START + 0x280 + ow_begin, ow_end - ow_begin) | 
					
						
							|  |  |  |         if ow_data is not None: | 
					
						
							| 
									
										
										
										
											2021-03-07 22:05:07 +01:00
										 |  |  |             for location_id, screenid in ow_unchecked.items(): | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  |                 if ow_data[screenid - ow_begin] & 0x40 != 0: | 
					
						
							| 
									
										
										
										
											2021-03-07 22:05:07 +01:00
										 |  |  |                     new_check(location_id) | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-07 22:05:07 +01:00
										 |  |  |     if not ctx.locations_checked.issuperset(location_table_npc_id): | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  |         npc_data = await snes_read(ctx, SAVEDATA_START + 0x410, 2) | 
					
						
							|  |  |  |         if npc_data is not None: | 
					
						
							|  |  |  |             npc_value = npc_data[0] | (npc_data[1] << 8) | 
					
						
							| 
									
										
										
										
											2021-03-07 22:05:07 +01:00
										 |  |  |             for location_id, mask in location_table_npc_id.items(): | 
					
						
							|  |  |  |                 if npc_value & mask != 0 and location_id not in ctx.locations_checked: | 
					
						
							|  |  |  |                     new_check(location_id) | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-07 22:05:07 +01:00
										 |  |  |     if not ctx.locations_checked.issuperset(location_table_misc_id): | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  |         misc_data = await snes_read(ctx, SAVEDATA_START + 0x3c6, 4) | 
					
						
							|  |  |  |         if misc_data is not None: | 
					
						
							| 
									
										
										
										
											2021-03-07 22:05:07 +01:00
										 |  |  |             for location_id, (offset, mask) in location_table_misc_id.items(): | 
					
						
							| 
									
										
										
										
											2021-01-21 23:37:58 +01:00
										 |  |  |                 assert (0x3c6 <= offset <= 0x3c9) | 
					
						
							| 
									
										
										
										
											2021-03-07 22:05:07 +01:00
										 |  |  |                 if misc_data[offset - 0x3c6] & mask != 0 and location_id not in ctx.locations_checked: | 
					
						
							|  |  |  |                     new_check(location_id) | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-09 22:37:59 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-21 23:37:58 +01:00
										 |  |  |     if new_locations: | 
					
						
							| 
									
										
										
										
											2021-02-21 23:46:05 +01:00
										 |  |  |         await ctx.send_msgs([{"cmd": 'LocationChecks', "locations": new_locations}]) | 
					
						
							| 
									
										
											  
											
												WebUI (#100)
* Object-Oriented base changes for web-ui prep
* remove debug raise
* optimize broadcast to serialize once
* Implement WebUI socket, static assets, and classes
- Still need to wrap logging functions and send output to UI
- UI commands are successfully being sent to the server
* GUI operational. Wrap logging functions, implement server address selection on GUI, automatically launch web browser when client websocket is served
* Update MultiServer status when a user disconnects / reconnects
* Implement colored item and hint checks, improve GUI readability
* Fix improper formatting on received items
* Update SNES connection status on disconnect / reconnect. Implement itemFound, prevent accidentally printing JS objects
* Minor text change for itemFound
* Fixed a very wrong comment
* Fixed client commands not working, fixed un-helpful error messages appearing in GUI
* Fix a bug causing a failure to connect to a multiworld server if a previously existing cached address was present and the client was loaded without an address passed in
* Convert WebUI to React /w Redux. WebSocket communications not yet operational.
* WebUI fully converted to React / Redux.
- Websocket communication operational
- Added a button to connect to the multiserver which appears only when a SNES is connected and a server connection is not active
* Restore some features lost in WebUI
- Restore (found) notification on hints if the item has already been obtained
- Restore (x/y) indicator on received items, which indicates the number of items the client is waiting to receive from the client in a queue
* Fix a grammatical UI big causing player names to show only an apostrophe when possessive
* Add support for multiple SNES Devices, and switching between them
* freeze support for client
* make sure flask works when frozen
* UI Improvements
- Hint messages now actually show a found status via ✔ and ❌ emoji
- Active player name is always a different color than other players (orange for now)
- Add a toggle to show only entries relevant to the active player
- Added a WidgetArea
- Added a notes widget
* Received items now marked as relevant
* Include production build for deployment
* Notes now survive a browser close. Minimum width applied to monitor to prevent CSS issues.
* include webUi folder in setup.py
* Bugfixes for Monitor
- Fix a bug causing the monitor window to grow beyond it's intended content limit
- Reduced monitor content limit to 200 items
- Ensured each monitor entry has a unique key
* Prevent eslint from yelling at me about stupid things
* Add button to collapse sidebar, press enter on empty server input to disconnect on purpose
* WebUI is now aware of client disconnect, message log limit increased to 350, fix !missing output
* Update WebUI to v2.2.1
- Added color to WebUI for entrance-span
- Make !missing show total count at bottom of list to match /missing behavior
* Fix a bug causing clients version <= 2.2.0 to crash when anyone asks for a hint
- Also fix a bug in the WebUI causing the entrance location to always show as "somewhere"
* Update WebUI color palette (this cost me $50)
* allow text console input alongside web-ui
* remove Flask
a bit overkill for what we're doing
* remove jinja2
* Update WebUI to work with new hosting mechanism
* with flask gone, we no longer need subprocess shenanigans
* If multiple web ui clients try to run, at least present a working console
* Update MultiClient and WebUI to handle multiple clients simultaneously.
- The port on which the websocket for the WebUI is hosted is not chosen randomly from 5000 - 5999. This port is passed to the browser so it knows which MultiClient to connect to
- Removed failure condition if a web server is already running, as there is no need to run more than one web server on a single system. If an exception is thrown while attempting to launch a web server, a check is made for the port being unavailable. If the port is unavailable, it probably means the user is launching a second MultiClient. A web browser is then opened with a connection to the correct webui_socket_port.
- Add a /web command to the MultiClient to repoen the appropriate browser window and get params in case a user accidentally closes the tab
* Use proper name for WebUI
* move webui into /data with other data files
* make web ui optional
This is mostly for laptop users wanting to preserve some battery, should not be needed outside of that.
* fix direct server start
* re-add connection timer
* fix indentation
Co-authored-by: Chris <chris@legendserver.info>
											
										 
											2020-06-03 21:29:43 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-21 23:37:58 +01:00
										 |  |  | async def game_watcher(ctx: Context): | 
					
						
							| 
									
										
										
										
											2020-04-24 20:07:28 -07:00
										 |  |  |     prev_game_timer = 0 | 
					
						
							|  |  |  |     perf_counter = time.perf_counter() | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  |     while not ctx.exit_event.is_set(): | 
					
						
							| 
									
										
										
										
											2020-01-18 11:28:08 +01:00
										 |  |  |         try: | 
					
						
							| 
									
										
										
										
											2020-04-24 20:07:28 -07:00
										 |  |  |             await asyncio.wait_for(ctx.watcher_event.wait(), 0.125) | 
					
						
							| 
									
										
										
										
											2020-01-18 11:28:08 +01:00
										 |  |  |         except asyncio.TimeoutError: | 
					
						
							|  |  |  |             pass | 
					
						
							|  |  |  |         ctx.watcher_event.clear() | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-14 10:42:27 +01:00
										 |  |  |         if not ctx.rom: | 
					
						
							| 
									
										
										
										
											2020-04-24 20:07:28 -07:00
										 |  |  |             ctx.finished_game = False | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  |             rom = await snes_read(ctx, ROMNAME_START, ROMNAME_SIZE) | 
					
						
							|  |  |  |             if rom is None or rom == bytes([0] * ROMNAME_SIZE): | 
					
						
							|  |  |  |                 continue | 
					
						
							| 
									
										
										
										
											2020-01-14 10:42:27 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-19 08:26:31 +02:00
										 |  |  |             ctx.rom = rom | 
					
						
							| 
									
										
										
										
											2020-06-02 07:38:23 -07:00
										 |  |  |             if not ctx.prev_rom or ctx.prev_rom != ctx.rom: | 
					
						
							|  |  |  |                 ctx.locations_checked = set() | 
					
						
							|  |  |  |                 ctx.locations_scouted = set() | 
					
						
							| 
									
										
										
										
											2020-07-14 04:48:56 +02:00
										 |  |  |             ctx.prev_rom = ctx.rom | 
					
						
							| 
									
										
										
										
											2020-06-02 07:38:23 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-14 10:42:27 +01:00
										 |  |  |             if ctx.awaiting_rom: | 
					
						
							| 
									
										
										
										
											2021-04-01 11:40:58 +02:00
										 |  |  |                 await ctx.server_auth(False) | 
					
						
							| 
									
										
										
										
											2020-01-14 10:42:27 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         if ctx.auth and ctx.auth != ctx.rom: | 
					
						
							| 
									
										
										
										
											2021-01-19 06:37:35 +01:00
										 |  |  |             logger.warning("ROM change detected, please reconnect to the multiworld server") | 
					
						
							| 
									
										
											  
											
												WebUI (#100)
* Object-Oriented base changes for web-ui prep
* remove debug raise
* optimize broadcast to serialize once
* Implement WebUI socket, static assets, and classes
- Still need to wrap logging functions and send output to UI
- UI commands are successfully being sent to the server
* GUI operational. Wrap logging functions, implement server address selection on GUI, automatically launch web browser when client websocket is served
* Update MultiServer status when a user disconnects / reconnects
* Implement colored item and hint checks, improve GUI readability
* Fix improper formatting on received items
* Update SNES connection status on disconnect / reconnect. Implement itemFound, prevent accidentally printing JS objects
* Minor text change for itemFound
* Fixed a very wrong comment
* Fixed client commands not working, fixed un-helpful error messages appearing in GUI
* Fix a bug causing a failure to connect to a multiworld server if a previously existing cached address was present and the client was loaded without an address passed in
* Convert WebUI to React /w Redux. WebSocket communications not yet operational.
* WebUI fully converted to React / Redux.
- Websocket communication operational
- Added a button to connect to the multiserver which appears only when a SNES is connected and a server connection is not active
* Restore some features lost in WebUI
- Restore (found) notification on hints if the item has already been obtained
- Restore (x/y) indicator on received items, which indicates the number of items the client is waiting to receive from the client in a queue
* Fix a grammatical UI big causing player names to show only an apostrophe when possessive
* Add support for multiple SNES Devices, and switching between them
* freeze support for client
* make sure flask works when frozen
* UI Improvements
- Hint messages now actually show a found status via ✔ and ❌ emoji
- Active player name is always a different color than other players (orange for now)
- Add a toggle to show only entries relevant to the active player
- Added a WidgetArea
- Added a notes widget
* Received items now marked as relevant
* Include production build for deployment
* Notes now survive a browser close. Minimum width applied to monitor to prevent CSS issues.
* include webUi folder in setup.py
* Bugfixes for Monitor
- Fix a bug causing the monitor window to grow beyond it's intended content limit
- Reduced monitor content limit to 200 items
- Ensured each monitor entry has a unique key
* Prevent eslint from yelling at me about stupid things
* Add button to collapse sidebar, press enter on empty server input to disconnect on purpose
* WebUI is now aware of client disconnect, message log limit increased to 350, fix !missing output
* Update WebUI to v2.2.1
- Added color to WebUI for entrance-span
- Make !missing show total count at bottom of list to match /missing behavior
* Fix a bug causing clients version <= 2.2.0 to crash when anyone asks for a hint
- Also fix a bug in the WebUI causing the entrance location to always show as "somewhere"
* Update WebUI color palette (this cost me $50)
* allow text console input alongside web-ui
* remove Flask
a bit overkill for what we're doing
* remove jinja2
* Update WebUI to work with new hosting mechanism
* with flask gone, we no longer need subprocess shenanigans
* If multiple web ui clients try to run, at least present a working console
* Update MultiClient and WebUI to handle multiple clients simultaneously.
- The port on which the websocket for the WebUI is hosted is not chosen randomly from 5000 - 5999. This port is passed to the browser so it knows which MultiClient to connect to
- Removed failure condition if a web server is already running, as there is no need to run more than one web server on a single system. If an exception is thrown while attempting to launch a web server, a check is made for the port being unavailable. If the port is unavailable, it probably means the user is launching a second MultiClient. A web browser is then opened with a connection to the correct webui_socket_port.
- Add a /web command to the MultiClient to repoen the appropriate browser window and get params in case a user accidentally closes the tab
* Use proper name for WebUI
* move webui into /data with other data files
* make web ui optional
This is mostly for laptop users wanting to preserve some battery, should not be needed outside of that.
* fix direct server start
* re-add connection timer
* fix indentation
Co-authored-by: Chris <chris@legendserver.info>
											
										 
											2020-06-03 21:29:43 +02:00
										 |  |  |             await ctx.disconnect() | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         gamemode = await snes_read(ctx, WRAM_START + 0x10, 1) | 
					
						
							| 
									
										
										
										
											2020-04-24 20:07:28 -07:00
										 |  |  |         gameend = await snes_read(ctx, SAVEDATA_START + 0x443, 1) | 
					
						
							|  |  |  |         game_timer = await snes_read(ctx, SAVEDATA_START + 0x42E, 4) | 
					
						
							|  |  |  |         if gamemode is None or gameend is None or game_timer is None or \ | 
					
						
							|  |  |  |                 (gamemode[0] not in INGAME_MODES and gamemode[0] not in ENDGAME_MODES): | 
					
						
							|  |  |  |             continue | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         delay = 7 if ctx.slow_mode else 2 | 
					
						
							|  |  |  |         if gameend[0]: | 
					
						
							|  |  |  |             if not ctx.finished_game: | 
					
						
							| 
									
										
										
										
											2021-04-01 11:40:58 +02:00
										 |  |  |                 await ctx.send_msgs([{"cmd": "StatusUpdate", "status": ClientStatus.CLIENT_GOAL}]) | 
					
						
							| 
									
										
										
										
											2021-03-03 01:57:12 +01:00
										 |  |  |                 ctx.finished_game = True | 
					
						
							| 
									
										
										
										
											2020-04-24 20:07:28 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |             if time.perf_counter() - perf_counter < delay: | 
					
						
							|  |  |  |                 continue | 
					
						
							|  |  |  |             else: | 
					
						
							|  |  |  |                 perf_counter = time.perf_counter() | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             game_timer = game_timer[0] | (game_timer[1] << 8) | (game_timer[2] << 16) | (game_timer[3] << 24) | 
					
						
							|  |  |  |             if abs(game_timer - prev_game_timer) < (delay * 60): | 
					
						
							|  |  |  |                 continue | 
					
						
							|  |  |  |             else: | 
					
						
							|  |  |  |                 prev_game_timer = game_timer | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-25 13:50:32 +02:00
										 |  |  |         if gamemode in ENDGAME_MODES:  # triforce room and credits | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  |             continue | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-18 09:50:12 +01:00
										 |  |  |         data = await snes_read(ctx, RECV_PROGRESS_ADDR, 8) | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  |         if data is None: | 
					
						
							|  |  |  |             continue | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         recv_index = data[0] | (data[1] << 8) | 
					
						
							|  |  |  |         recv_item = data[2] | 
					
						
							|  |  |  |         roomid = data[4] | (data[5] << 8) | 
					
						
							|  |  |  |         roomdata = data[6] | 
					
						
							| 
									
										
										
										
											2020-01-18 09:50:12 +01:00
										 |  |  |         scout_location = data[7] | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         if recv_index < len(ctx.items_received) and recv_item == 0: | 
					
						
							|  |  |  |             item = ctx.items_received[recv_index] | 
					
						
							| 
									
										
										
										
											2020-01-18 12:21:57 +01:00
										 |  |  |             logging.info('Received %s from %s (%s) (%d/%d in list)' % ( | 
					
						
							| 
									
										
										
										
											2021-02-25 02:07:28 +01:00
										 |  |  |                 color(ctx.item_name_getter(item.item), 'red', 'bold'), color(ctx.player_names[item.player], 'yellow'), | 
					
						
							|  |  |  |                 ctx.location_name_getter(item.location), recv_index + 1, len(ctx.items_received))) | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  |             recv_index += 1 | 
					
						
							|  |  |  |             snes_buffered_write(ctx, RECV_PROGRESS_ADDR, bytes([recv_index & 0xFF, (recv_index >> 8) & 0xFF])) | 
					
						
							|  |  |  |             snes_buffered_write(ctx, RECV_ITEM_ADDR, bytes([item.item])) | 
					
						
							| 
									
										
										
										
											2020-01-18 09:50:12 +01:00
										 |  |  |             snes_buffered_write(ctx, RECV_ITEM_PLAYER_ADDR, bytes([item.player if item.player != ctx.slot else 0])) | 
					
						
							|  |  |  |         if scout_location > 0 and scout_location in ctx.locations_info: | 
					
						
							|  |  |  |             snes_buffered_write(ctx, SCOUTREPLY_LOCATION_ADDR, bytes([scout_location])) | 
					
						
							|  |  |  |             snes_buffered_write(ctx, SCOUTREPLY_ITEM_ADDR, bytes([ctx.locations_info[scout_location][0]])) | 
					
						
							|  |  |  |             snes_buffered_write(ctx, SCOUTREPLY_PLAYER_ADDR, bytes([ctx.locations_info[scout_location][1]])) | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         await snes_flush_writes(ctx) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-18 11:28:08 +01:00
										 |  |  |         if scout_location > 0 and scout_location not in ctx.locations_scouted: | 
					
						
							|  |  |  |             ctx.locations_scouted.add(scout_location) | 
					
						
							| 
									
										
										
										
											2021-02-21 23:46:05 +01:00
										 |  |  |             await ctx.send_msgs([{"cmd": "LocationScouts", "locations": [scout_location]}]) | 
					
						
							| 
									
										
										
										
											2020-01-18 11:28:08 +01:00
										 |  |  |         await track_locations(ctx, roomid, roomdata) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-10 00:38:29 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | async def run_game(romfile): | 
					
						
							| 
									
										
										
										
											2021-04-01 11:40:58 +02:00
										 |  |  |     auto_start = Utils.get_options()["lttp_options"].get("rom_start", True) | 
					
						
							| 
									
										
										
										
											2020-07-15 17:19:16 +02:00
										 |  |  |     if auto_start is True: | 
					
						
							|  |  |  |         import webbrowser | 
					
						
							|  |  |  |         webbrowser.open(romfile) | 
					
						
							|  |  |  |     elif os.path.isfile(auto_start): | 
					
						
							|  |  |  |         subprocess.Popen([auto_start, romfile], | 
					
						
							|  |  |  |                          stdin=subprocess.DEVNULL, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) | 
					
						
							| 
									
										
										
										
											2020-03-10 00:38:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  | async def main(): | 
					
						
							| 
									
										
											  
											
												WebUI (#100)
* Object-Oriented base changes for web-ui prep
* remove debug raise
* optimize broadcast to serialize once
* Implement WebUI socket, static assets, and classes
- Still need to wrap logging functions and send output to UI
- UI commands are successfully being sent to the server
* GUI operational. Wrap logging functions, implement server address selection on GUI, automatically launch web browser when client websocket is served
* Update MultiServer status when a user disconnects / reconnects
* Implement colored item and hint checks, improve GUI readability
* Fix improper formatting on received items
* Update SNES connection status on disconnect / reconnect. Implement itemFound, prevent accidentally printing JS objects
* Minor text change for itemFound
* Fixed a very wrong comment
* Fixed client commands not working, fixed un-helpful error messages appearing in GUI
* Fix a bug causing a failure to connect to a multiworld server if a previously existing cached address was present and the client was loaded without an address passed in
* Convert WebUI to React /w Redux. WebSocket communications not yet operational.
* WebUI fully converted to React / Redux.
- Websocket communication operational
- Added a button to connect to the multiserver which appears only when a SNES is connected and a server connection is not active
* Restore some features lost in WebUI
- Restore (found) notification on hints if the item has already been obtained
- Restore (x/y) indicator on received items, which indicates the number of items the client is waiting to receive from the client in a queue
* Fix a grammatical UI big causing player names to show only an apostrophe when possessive
* Add support for multiple SNES Devices, and switching between them
* freeze support for client
* make sure flask works when frozen
* UI Improvements
- Hint messages now actually show a found status via ✔ and ❌ emoji
- Active player name is always a different color than other players (orange for now)
- Add a toggle to show only entries relevant to the active player
- Added a WidgetArea
- Added a notes widget
* Received items now marked as relevant
* Include production build for deployment
* Notes now survive a browser close. Minimum width applied to monitor to prevent CSS issues.
* include webUi folder in setup.py
* Bugfixes for Monitor
- Fix a bug causing the monitor window to grow beyond it's intended content limit
- Reduced monitor content limit to 200 items
- Ensured each monitor entry has a unique key
* Prevent eslint from yelling at me about stupid things
* Add button to collapse sidebar, press enter on empty server input to disconnect on purpose
* WebUI is now aware of client disconnect, message log limit increased to 350, fix !missing output
* Update WebUI to v2.2.1
- Added color to WebUI for entrance-span
- Make !missing show total count at bottom of list to match /missing behavior
* Fix a bug causing clients version <= 2.2.0 to crash when anyone asks for a hint
- Also fix a bug in the WebUI causing the entrance location to always show as "somewhere"
* Update WebUI color palette (this cost me $50)
* allow text console input alongside web-ui
* remove Flask
a bit overkill for what we're doing
* remove jinja2
* Update WebUI to work with new hosting mechanism
* with flask gone, we no longer need subprocess shenanigans
* If multiple web ui clients try to run, at least present a working console
* Update MultiClient and WebUI to handle multiple clients simultaneously.
- The port on which the websocket for the WebUI is hosted is not chosen randomly from 5000 - 5999. This port is passed to the browser so it knows which MultiClient to connect to
- Removed failure condition if a web server is already running, as there is no need to run more than one web server on a single system. If an exception is thrown while attempting to launch a web server, a check is made for the port being unavailable. If the port is unavailable, it probably means the user is launching a second MultiClient. A web browser is then opened with a connection to the correct webui_socket_port.
- Add a /web command to the MultiClient to repoen the appropriate browser window and get params in case a user accidentally closes the tab
* Use proper name for WebUI
* move webui into /data with other data files
* make web ui optional
This is mostly for laptop users wanting to preserve some battery, should not be needed outside of that.
* fix direct server start
* re-add connection timer
* fix indentation
Co-authored-by: Chris <chris@legendserver.info>
											
										 
											2020-06-03 21:29:43 +02:00
										 |  |  |     multiprocessing.freeze_support() | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  |     parser = argparse.ArgumentParser() | 
					
						
							| 
									
										
										
										
											2020-03-06 00:48:23 +01:00
										 |  |  |     parser.add_argument('diff_file', default="", type=str, nargs="?", | 
					
						
							| 
									
										
										
										
											2021-01-03 14:32:32 +01:00
										 |  |  |                         help='Path to a Archipelago Binary Patch file') | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  |     parser.add_argument('--snes', default='localhost:8080', help='Address of the QUsb2snes server.') | 
					
						
							|  |  |  |     parser.add_argument('--connect', default=None, help='Address of the multiworld host.') | 
					
						
							|  |  |  |     parser.add_argument('--password', default=None, help='Password of the multiworld host.') | 
					
						
							| 
									
										
										
										
											2020-01-18 12:21:57 +01:00
										 |  |  |     parser.add_argument('--loglevel', default='info', choices=['debug', 'info', 'warning', 'error', 'critical']) | 
					
						
							| 
									
										
											  
											
												WebUI (#100)
* Object-Oriented base changes for web-ui prep
* remove debug raise
* optimize broadcast to serialize once
* Implement WebUI socket, static assets, and classes
- Still need to wrap logging functions and send output to UI
- UI commands are successfully being sent to the server
* GUI operational. Wrap logging functions, implement server address selection on GUI, automatically launch web browser when client websocket is served
* Update MultiServer status when a user disconnects / reconnects
* Implement colored item and hint checks, improve GUI readability
* Fix improper formatting on received items
* Update SNES connection status on disconnect / reconnect. Implement itemFound, prevent accidentally printing JS objects
* Minor text change for itemFound
* Fixed a very wrong comment
* Fixed client commands not working, fixed un-helpful error messages appearing in GUI
* Fix a bug causing a failure to connect to a multiworld server if a previously existing cached address was present and the client was loaded without an address passed in
* Convert WebUI to React /w Redux. WebSocket communications not yet operational.
* WebUI fully converted to React / Redux.
- Websocket communication operational
- Added a button to connect to the multiserver which appears only when a SNES is connected and a server connection is not active
* Restore some features lost in WebUI
- Restore (found) notification on hints if the item has already been obtained
- Restore (x/y) indicator on received items, which indicates the number of items the client is waiting to receive from the client in a queue
* Fix a grammatical UI big causing player names to show only an apostrophe when possessive
* Add support for multiple SNES Devices, and switching between them
* freeze support for client
* make sure flask works when frozen
* UI Improvements
- Hint messages now actually show a found status via ✔ and ❌ emoji
- Active player name is always a different color than other players (orange for now)
- Add a toggle to show only entries relevant to the active player
- Added a WidgetArea
- Added a notes widget
* Received items now marked as relevant
* Include production build for deployment
* Notes now survive a browser close. Minimum width applied to monitor to prevent CSS issues.
* include webUi folder in setup.py
* Bugfixes for Monitor
- Fix a bug causing the monitor window to grow beyond it's intended content limit
- Reduced monitor content limit to 200 items
- Ensured each monitor entry has a unique key
* Prevent eslint from yelling at me about stupid things
* Add button to collapse sidebar, press enter on empty server input to disconnect on purpose
* WebUI is now aware of client disconnect, message log limit increased to 350, fix !missing output
* Update WebUI to v2.2.1
- Added color to WebUI for entrance-span
- Make !missing show total count at bottom of list to match /missing behavior
* Fix a bug causing clients version <= 2.2.0 to crash when anyone asks for a hint
- Also fix a bug in the WebUI causing the entrance location to always show as "somewhere"
* Update WebUI color palette (this cost me $50)
* allow text console input alongside web-ui
* remove Flask
a bit overkill for what we're doing
* remove jinja2
* Update WebUI to work with new hosting mechanism
* with flask gone, we no longer need subprocess shenanigans
* If multiple web ui clients try to run, at least present a working console
* Update MultiClient and WebUI to handle multiple clients simultaneously.
- The port on which the websocket for the WebUI is hosted is not chosen randomly from 5000 - 5999. This port is passed to the browser so it knows which MultiClient to connect to
- Removed failure condition if a web server is already running, as there is no need to run more than one web server on a single system. If an exception is thrown while attempting to launch a web server, a check is made for the port being unavailable. If the port is unavailable, it probably means the user is launching a second MultiClient. A web browser is then opened with a connection to the correct webui_socket_port.
- Add a /web command to the MultiClient to repoen the appropriate browser window and get params in case a user accidentally closes the tab
* Use proper name for WebUI
* move webui into /data with other data files
* make web ui optional
This is mostly for laptop users wanting to preserve some battery, should not be needed outside of that.
* fix direct server start
* re-add connection timer
* fix indentation
Co-authored-by: Chris <chris@legendserver.info>
											
										 
											2020-06-03 21:29:43 +02:00
										 |  |  |     parser.add_argument('--founditems', default=False, action='store_true', | 
					
						
							|  |  |  |                         help='Show items found by other players for themselves.') | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  |     args = parser.parse_args() | 
					
						
							| 
									
										
										
										
											2020-03-10 00:38:29 +01:00
										 |  |  |     logging.basicConfig(format='%(message)s', level=getattr(logging, args.loglevel.upper(), logging.INFO)) | 
					
						
							| 
									
										
										
										
											2020-03-06 00:48:23 +01:00
										 |  |  |     if args.diff_file: | 
					
						
							|  |  |  |         import Patch | 
					
						
							| 
									
										
										
										
											2020-04-26 15:14:30 +02:00
										 |  |  |         logging.info("Patch file was supplied. Creating sfc rom..") | 
					
						
							| 
									
										
										
										
											2020-03-10 00:38:29 +01:00
										 |  |  |         meta, romfile = Patch.create_rom_file(args.diff_file) | 
					
						
							|  |  |  |         args.connect = meta["server"] | 
					
						
							|  |  |  |         logging.info(f"Wrote rom file to {romfile}") | 
					
						
							| 
									
										
										
										
											2020-06-07 12:04:33 -07:00
										 |  |  |         adjustedromfile, adjusted = Utils.get_adjuster_settings(romfile) | 
					
						
							|  |  |  |         if adjusted: | 
					
						
							|  |  |  |             try: | 
					
						
							| 
									
										
										
										
											2021-01-21 23:58:30 +01:00
										 |  |  |                 shutil.move(adjustedromfile, romfile) | 
					
						
							| 
									
										
										
										
											2020-06-07 12:04:33 -07:00
										 |  |  |                 adjustedromfile = romfile | 
					
						
							|  |  |  |             except Exception as e: | 
					
						
							|  |  |  |                 logging.exception(e) | 
					
						
							|  |  |  |         asyncio.create_task(run_game(adjustedromfile if adjusted else romfile)) | 
					
						
							| 
									
										
										
										
											2020-01-18 12:21:57 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-11 21:59:43 +02:00
										 |  |  |     port = None | 
					
						
							| 
									
										
										
										
											2021-05-14 01:25:41 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     ctx = Context(args.snes, args.connect, args.password, args.founditems) | 
					
						
							| 
									
										
										
										
											2021-04-01 11:40:58 +02:00
										 |  |  |     input_task = asyncio.create_task(console_loop(ctx), name="Input") | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if ctx.server_task is None: | 
					
						
							| 
									
										
										
										
											2021-04-01 11:40:58 +02:00
										 |  |  |         ctx.server_task = asyncio.create_task(server_loop(ctx), name="ServerLoop") | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-01 11:40:58 +02:00
										 |  |  |     watcher_task = asyncio.create_task(game_watcher(ctx), name="GameWatcher") | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     await ctx.exit_event.wait() | 
					
						
							| 
									
										
										
										
											2020-01-14 10:42:27 +01:00
										 |  |  |     ctx.server_address = None | 
					
						
							| 
									
										
										
										
											2020-01-13 03:55:33 +01:00
										 |  |  |     ctx.snes_reconnect_address = None | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     await watcher_task | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
											  
											
												WebUI (#100)
* Object-Oriented base changes for web-ui prep
* remove debug raise
* optimize broadcast to serialize once
* Implement WebUI socket, static assets, and classes
- Still need to wrap logging functions and send output to UI
- UI commands are successfully being sent to the server
* GUI operational. Wrap logging functions, implement server address selection on GUI, automatically launch web browser when client websocket is served
* Update MultiServer status when a user disconnects / reconnects
* Implement colored item and hint checks, improve GUI readability
* Fix improper formatting on received items
* Update SNES connection status on disconnect / reconnect. Implement itemFound, prevent accidentally printing JS objects
* Minor text change for itemFound
* Fixed a very wrong comment
* Fixed client commands not working, fixed un-helpful error messages appearing in GUI
* Fix a bug causing a failure to connect to a multiworld server if a previously existing cached address was present and the client was loaded without an address passed in
* Convert WebUI to React /w Redux. WebSocket communications not yet operational.
* WebUI fully converted to React / Redux.
- Websocket communication operational
- Added a button to connect to the multiserver which appears only when a SNES is connected and a server connection is not active
* Restore some features lost in WebUI
- Restore (found) notification on hints if the item has already been obtained
- Restore (x/y) indicator on received items, which indicates the number of items the client is waiting to receive from the client in a queue
* Fix a grammatical UI big causing player names to show only an apostrophe when possessive
* Add support for multiple SNES Devices, and switching between them
* freeze support for client
* make sure flask works when frozen
* UI Improvements
- Hint messages now actually show a found status via ✔ and ❌ emoji
- Active player name is always a different color than other players (orange for now)
- Add a toggle to show only entries relevant to the active player
- Added a WidgetArea
- Added a notes widget
* Received items now marked as relevant
* Include production build for deployment
* Notes now survive a browser close. Minimum width applied to monitor to prevent CSS issues.
* include webUi folder in setup.py
* Bugfixes for Monitor
- Fix a bug causing the monitor window to grow beyond it's intended content limit
- Reduced monitor content limit to 200 items
- Ensured each monitor entry has a unique key
* Prevent eslint from yelling at me about stupid things
* Add button to collapse sidebar, press enter on empty server input to disconnect on purpose
* WebUI is now aware of client disconnect, message log limit increased to 350, fix !missing output
* Update WebUI to v2.2.1
- Added color to WebUI for entrance-span
- Make !missing show total count at bottom of list to match /missing behavior
* Fix a bug causing clients version <= 2.2.0 to crash when anyone asks for a hint
- Also fix a bug in the WebUI causing the entrance location to always show as "somewhere"
* Update WebUI color palette (this cost me $50)
* allow text console input alongside web-ui
* remove Flask
a bit overkill for what we're doing
* remove jinja2
* Update WebUI to work with new hosting mechanism
* with flask gone, we no longer need subprocess shenanigans
* If multiple web ui clients try to run, at least present a working console
* Update MultiClient and WebUI to handle multiple clients simultaneously.
- The port on which the websocket for the WebUI is hosted is not chosen randomly from 5000 - 5999. This port is passed to the browser so it knows which MultiClient to connect to
- Removed failure condition if a web server is already running, as there is no need to run more than one web server on a single system. If an exception is thrown while attempting to launch a web server, a check is made for the port being unavailable. If the port is unavailable, it probably means the user is launching a second MultiClient. A web browser is then opened with a connection to the correct webui_socket_port.
- Add a /web command to the MultiClient to repoen the appropriate browser window and get params in case a user accidentally closes the tab
* Use proper name for WebUI
* move webui into /data with other data files
* make web ui optional
This is mostly for laptop users wanting to preserve some battery, should not be needed outside of that.
* fix direct server start
* re-add connection timer
* fix indentation
Co-authored-by: Chris <chris@legendserver.info>
											
										 
											2020-06-03 21:29:43 +02:00
										 |  |  |     if ctx.server is not None and not ctx.server.socket.closed: | 
					
						
							|  |  |  |         await ctx.server.socket.close() | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  |     if ctx.server_task is not None: | 
					
						
							|  |  |  |         await ctx.server_task | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ctx.snes_socket is not None and not ctx.snes_socket.closed: | 
					
						
							|  |  |  |         await ctx.snes_socket.close() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     while ctx.input_requests > 0: | 
					
						
							|  |  |  |         ctx.input_queue.put_nowait(None) | 
					
						
							|  |  |  |         ctx.input_requests -= 1 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     await input_task | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-21 23:37:58 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  | if __name__ == '__main__': | 
					
						
							| 
									
										
										
										
											2020-01-18 10:05:59 +01:00
										 |  |  |     colorama.init() | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  |     loop = asyncio.get_event_loop() | 
					
						
							|  |  |  |     loop.run_until_complete(main()) | 
					
						
							|  |  |  |     loop.close() | 
					
						
							| 
									
										
										
										
											2020-01-18 10:05:59 +01:00
										 |  |  |     colorama.deinit() | 
					
						
							| 
									
										
										
										
											2020-02-02 06:20:08 +01:00
										 |  |  |     atexit.unregister(exit_func) |