from os.path import abspath, dirname
import argparse
import inspect
import logging
import importlib

logger = logging.getLogger("pyfrc.sim")


class PyFrcSim:
    """
    Runs the robot using WPILib's GUI HAL Simulator
    """

    def __init__(self, parser: argparse.ArgumentParser):
        parser.add_argument(
            "--nogui",
            default=False,
            action="store_true",
            help="Don't use the WPIlib simulation gui",
        )

    def run(self, options, robot_class, **static_options):

        if not options.nogui:
            try:
                import halsim_gui
            except ImportError:
                print("robotpy-halsim-gui is not installed!")
                exit(1)
            else:
                halsim_gui.loadExtension()

        # initialize physics, attach to the user robot class
        from ..physics.core import PhysicsInterface, PhysicsInitException

        robot_file = abspath(inspect.getfile(robot_class))
        robot_path = dirname(robot_file)

        try:
            physics = PhysicsInterface._create(robot_path)
            if physics:
                robot_class._simulationInit = physics._simulationInit
                robot_class._simulationPeriodic = physics._simulationPeriodic

            # run the robot
            return robot_class.main(robot_class)

        except PhysicsInitException:
            return False

@@ -80,24 +80,91 @@
 ing%0A
-import importlib
+from pkg_resources import iter_entry_points%0Afrom importlib.metadata import metadata
 %0A%0Alo
@@ -524,16 +524,689 @@
      )%0A%0A
+        self.simexts = %7B%7D%0A%0A        for entry_point in iter_entry_points(group=%22robotpysimext%22, name=None):%0A            if entry_point.module_name == %22halsim_gui%22:%0A                continue%0A            try:%0A                sim_ext_module = entry_point.load()%0A            except ImportError:%0A                print(f%22WARNING: Error detected in %7Bentry_point%7D%22)%0A                continue%0A%0A            self.simexts%5Bentry_point.name%5D = sim_ext_module%0A%0A            parser.add_argument(%0A                f%22--%7Bentry_point.name%7D%22,%0A                default=False,%0A                action=%22store_true%22,%0A                help=metadata(entry_point.dist.project_name)%5B%22summary%22%5D,%0A            )%0A%0A
     def 
@@ -1518,16 +1518,297 @@
 sion()%0A%0A
+        for name, module in self.simexts.items():%0A            if getattr(options, name.replace(%22-%22, %22_%22), False):%0A                try:%0A                    module.loadExtension()%0A                except:%0A                    print(f%22Error loading %7Bname%7D!%22)%0A                    raise%0A%0A
         

Add entrypoint based sim extension detection