master_server.py 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. #! /usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. # SPDX-FileCopyrightText: Copyright (C) 2021-2022 MH3SP Server Project
  4. # SPDX-License-Identifier: AGPL-3.0-or-later
  5. """Monster Hunter master server."""
  6. import threading
  7. import traceback
  8. import opn_server as OPN
  9. import lmp_server as LMP
  10. import fmp_server as FMP
  11. import rfp_server as RFP
  12. from other.debug import register_debug_signal
  13. from other.utils import create_server_from_base
  14. from mh.quest_utils import QuestLoader
  15. def create_servers(binary_loader, silent=False, debug_mode=False):
  16. """Create servers and check if it has ui."""
  17. servers = []
  18. has_ui = False
  19. for module in (OPN, LMP, FMP, RFP):
  20. server, has_window = create_server_from_base(*module.BASE,
  21. binary_loader=binary_loader,
  22. silent=silent,
  23. debug_mode=debug_mode)
  24. has_ui = has_ui or has_window
  25. servers.append(server)
  26. return servers, has_ui
  27. def main(args):
  28. """Master server main function."""
  29. register_debug_signal()
  30. binary_loader = QuestLoader("event/quest_rotation.json")
  31. servers, has_ui = create_servers(binary_loader,
  32. silent=args.silent,
  33. debug_mode=args.debug_mode)
  34. threads = [
  35. threading.Thread(
  36. target=server.serve_forever,
  37. name="{}.serve_forever".format(server.__class__.__name__)
  38. )
  39. for server in servers
  40. ]
  41. for thread in threads:
  42. thread.start()
  43. def interactive_mode(local=locals()):
  44. """Run an interactive python interpreter in another thread."""
  45. import code
  46. code.interact(local=local)
  47. if has_ui:
  48. from other.ui import update as ui_update
  49. ui_update()
  50. try:
  51. if args.interactive:
  52. t = threading.Thread(target=interactive_mode)
  53. t.start()
  54. while threads:
  55. for thread in threads:
  56. if has_ui:
  57. ui_update()
  58. if not thread.is_alive():
  59. threads.remove(thread)
  60. break
  61. thread.join(0.1)
  62. if args.interactive:
  63. t.join()
  64. except KeyboardInterrupt:
  65. print("Interrupt key was pressed, closing server...")
  66. except Exception:
  67. print('Unexpected exception caught...')
  68. traceback.print_exc()
  69. finally:
  70. for server in servers:
  71. server.close()
  72. if __name__ == "__main__":
  73. import argparse
  74. parser = argparse.ArgumentParser()
  75. parser.add_argument("-i", "--interactive", action="store_true",
  76. dest="interactive",
  77. help="create an interactive shell")
  78. parser.add_argument("-s", "--silent", action="store_true",
  79. dest="silent",
  80. help="silent console logs")
  81. parser.add_argument("-d", "--debug_mode", action="store_true",
  82. dest="debug_mode",
  83. help="enable debug mode, disabling timeouts and \
  84. lower logging verbosity level")
  85. args = parser.parse_args()
  86. main(args)