lobby.gd 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. extends Control
  2. # Default game server port. Can be any number between 1024 and 49151.
  3. # Not present on the list of registered or common ports as of May 2024:
  4. # https://en.wikipedia.org/wiki/List_of_TCP_and_UDP_port_numbers
  5. const DEFAULT_PORT = 8910
  6. @onready var address: LineEdit = $Address
  7. @onready var host_button: Button = $HostButton
  8. @onready var join_button: Button = $JoinButton
  9. @onready var status_ok: Label = $StatusOk
  10. @onready var status_fail: Label = $StatusFail
  11. @onready var port_forward_label: Label = $PortForward
  12. @onready var find_public_ip_button: LinkButton = $FindPublicIP
  13. var peer: ENetMultiplayerPeer
  14. func _ready() -> void:
  15. # Connect all the callbacks related to networking.
  16. multiplayer.peer_connected.connect(_player_connected)
  17. multiplayer.peer_disconnected.connect(_player_disconnected)
  18. multiplayer.connected_to_server.connect(_connected_ok)
  19. multiplayer.connection_failed.connect(_connected_fail)
  20. multiplayer.server_disconnected.connect(_server_disconnected)
  21. #region Network callbacks from SceneTree
  22. # Callback from SceneTree.
  23. func _player_connected(_id: int) -> void:
  24. # Someone connected, start the game!
  25. var pong: Node2D = load("res://pong.tscn").instantiate()
  26. # Connect deferred so we can safely erase it from the callback.
  27. pong.game_finished.connect(_end_game, CONNECT_DEFERRED)
  28. get_tree().get_root().add_child(pong)
  29. hide()
  30. func _player_disconnected(_id: int) -> void:
  31. if multiplayer.is_server():
  32. _end_game("Client disconnected.")
  33. else:
  34. _end_game("Server disconnected.")
  35. # Callback from SceneTree, only for clients (not server).
  36. func _connected_ok() -> void:
  37. pass # This function is not needed for this project.
  38. # Callback from SceneTree, only for clients (not server).
  39. func _connected_fail() -> void:
  40. _set_status("Couldn't connect.", false)
  41. multiplayer.set_multiplayer_peer(null) # Remove peer.
  42. host_button.set_disabled(false)
  43. join_button.set_disabled(false)
  44. func _server_disconnected() -> void:
  45. _end_game("Server disconnected.")
  46. #endregion
  47. #region Game creation methods
  48. func _end_game(with_error: String = "") -> void:
  49. if has_node("/root/Pong"):
  50. # Erase immediately, otherwise network might show
  51. # errors (this is why we connected deferred above).
  52. get_node(^"/root/Pong").free()
  53. show()
  54. multiplayer.set_multiplayer_peer(null) # Remove peer.
  55. host_button.set_disabled(false)
  56. join_button.set_disabled(false)
  57. _set_status(with_error, false)
  58. func _set_status(text: String, is_ok: bool) -> void:
  59. # Simple way to show status.
  60. if is_ok:
  61. status_ok.set_text(text)
  62. status_fail.set_text("")
  63. else:
  64. status_ok.set_text("")
  65. status_fail.set_text(text)
  66. func _on_host_pressed() -> void:
  67. peer = ENetMultiplayerPeer.new()
  68. # Set a maximum of 1 peer, since Pong is a 2-player game.
  69. var err := peer.create_server(DEFAULT_PORT, 1)
  70. if err != OK:
  71. # Is another server running?
  72. _set_status("Can't host, address in use.",false)
  73. return
  74. peer.get_host().compress(ENetConnection.COMPRESS_RANGE_CODER)
  75. multiplayer.set_multiplayer_peer(peer)
  76. host_button.set_disabled(true)
  77. join_button.set_disabled(true)
  78. _set_status("Waiting for player...", true)
  79. get_window().title = ProjectSettings.get_setting("application/config/name") + ": Server"
  80. # Only show hosting instructions when relevant.
  81. port_forward_label.visible = true
  82. find_public_ip_button.visible = true
  83. func _on_join_pressed() -> void:
  84. var ip := address.get_text()
  85. if not ip.is_valid_ip_address():
  86. _set_status("IP address is invalid.", false)
  87. return
  88. peer = ENetMultiplayerPeer.new()
  89. peer.create_client(ip, DEFAULT_PORT)
  90. peer.get_host().compress(ENetConnection.COMPRESS_RANGE_CODER)
  91. multiplayer.set_multiplayer_peer(peer)
  92. _set_status("Connecting...", true)
  93. get_window().title = ProjectSettings.get_setting("application/config/name") + ": Client"
  94. #endregion
  95. func _on_find_public_ip_pressed() -> void:
  96. OS.shell_open("https://icanhazip.com/")