online multiplayer chess game (note server currently down)
Diffstat (limited to 'ui/Lobby.gd')
-rw-r--r--ui/Lobby.gd228
1 files changed, 127 insertions, 101 deletions
diff --git a/ui/Lobby.gd b/ui/Lobby.gd
index b7332e8..15e609f 100644
--- a/ui/Lobby.gd
+++ b/ui/Lobby.gd
@@ -1,94 +1,29 @@
-# Default game server port. Can be any number between 1024 and 49151.
-# Not on the list of registered or common ports as of November 2020:
-# https://en.wikipedia.org/wiki/List_of_TCP_and_UDP_port_numbers
extends Control
-# Default game server port. Can be any number between 1024 and 49151.
-# Not on the list of registered or common ports as of November 2020:
-# https://en.wikipedia.org/wiki/List_of_TCP_and_UDP_port_numbers
-const DEFAULT_PORT = 8910
-
-var peer = null
-
onready var address: LineEdit = $Back/Center/HBox/VBox/Address
-onready var host_button = $Back/Center/HBox/VBox/HBox/HostButton
-onready var join_button = $Back/Center/HBox/VBox/HBox/JoinButton
+onready var buttons = $Back/Center/HBox/VBox/buttons
onready var status_ok = $Back/Center/HBox/VBox/StatusOK
onready var status_fail = $Back/Center/HBox/VBox/StatusFail
-onready var port_forward_label = $Back/Center/HBox/VBox2/Portforward
-onready var find_public_ip_button = $Back/Center/HBox/VBox2/FindPublicIP
func toggle(onoff) -> void:
visible = onoff
-
-
-func _ready() -> void:
- address.context_menu_enabled = false
- # Connect all the callbacks related to networking.
- get_tree().connect("network_peer_connected", self, "_player_connected")
- get_tree().connect("network_peer_disconnected", self, "_player_disconnected")
- get_tree().connect("connected_to_server", self, "_connected_ok")
- get_tree().connect("connection_failed", self, "_connected_fail")
- get_tree().connect("server_disconnected", self, "_server_disconnected")
-
-
-#### Network callbacks from SceneTree ####
-
-
-# Callback from SceneTree.
-func _player_connected(_id) -> void:
- # Someone connected, start the game!
- var chess = load("res://World.tscn").instance()
- # Connect deferred so we can safely erase it from the callback.
- Utils.connect("game_over", self, "_end_game", [], CONNECT_DEFERRED)
-
- get_tree().get_root().add_child(chess)
-
-
-func _player_disconnected(_id) -> void:
- if get_tree().is_network_server():
- _end_game("Client disconnected")
+ if onoff:
+ for i in get_tree().get_nodes_in_group("control"):
+ i.mouse_filter = MOUSE_FILTER_STOP
else:
- _end_game("Server disconnected")
-
-
-# Callback from SceneTree, only for clients (not server).
-func _connected_ok() -> void:
- pass # This function is not needed for this project.
-
-
-# Callback from SceneTree, only for clients (not server).
-func _connected_fail() -> void:
- _set_status("Couldn't connect", false)
-
- get_tree().set_network_peer(null) # Remove peer.
- host_button.show()
- address.editable = true
-
-
-func _server_disconnected() -> void:
- _end_game("Server disconnected")
-
+ for i in get_tree().get_nodes_in_group("control"):
+ i.mouse_filter = MOUSE_FILTER_IGNORE
-##### Game creation functions ######
+func _handle_game_over(error, isok) -> void:
+ reset_buttons()
+ Globals.reset_vars()
+ end_game()
+ _set_status(error, isok)
-func _end_game(_with_error = "") -> void:
- if has_node("/root/World"):
- # Erase immediately, otherwise network might show
- # errors (this is why we connected deferred above).
- get_node("/root/World").free()
- show()
- get_tree().set_network_peer(null) # Remove peer.
- host_button.show()
- join_button.show()
- address.editable = true
-
-
-func _set_status(text, isok) -> void:
- # Simple way to show status.
+func _set_status(text, isok) -> void: # Simple way to show status.
if isok:
status_ok.set_text(text)
status_fail.set_text("")
@@ -101,35 +36,126 @@ func _set_status(text, isok) -> void:
status_ok.visible = len(status_ok.text) > 0
-func _on_host_pressed() -> void:
- peer = NetworkedMultiplayerENet.new()
- peer.set_compression_mode(NetworkedMultiplayerENet.COMPRESS_RANGE_CODER)
- var err = peer.create_server(DEFAULT_PORT, 1) # Maximum of 1 peer, since it's a 2-player game.
- if err != OK:
- # Is another server running?
- _set_status("Can't host, address in use.", false)
- return
+func _on_join_pressed() -> void:
+ Globals.network.game_code = validate_text()
+ Globals.network.send_packet(Globals.network.game_code, Globals.network.HEADERS.joinrequest)
+ address.editable = false
+ buttons.hide()
+
- get_tree().set_network_peer(peer)
- host_button.hide()
+func _on_HostButton_pressed() -> void:
+ Globals.network.game_code = validate_text()
+ Globals.network.send_packet(Globals.network.game_code, Globals.network.HEADERS.hostrequest)
address.editable = false
- join_button.hide()
- _set_status("Waiting for player...", true)
+ buttons.hide()
- # Only show hosting instructions when relevant.
+func validate_text(text = address.get_text()) -> String:
+ var pos = address.caret_position
+ text = text.strip_edges()
+ text = text.replace(" ", "_")
+ address.text = text
+ address.caret_position = pos
+ return text
-func _on_join_pressed() -> void:
- var ip = address.get_text()
- if not ip.is_valid_ip_address():
- _set_status("IP address is invalid", false)
- return
- peer = NetworkedMultiplayerENet.new()
- peer.set_compression_mode(NetworkedMultiplayerENet.COMPRESS_RANGE_CODER)
- peer.create_client(ip, DEFAULT_PORT)
- get_tree().set_network_peer(peer)
+func _ready() -> void:
+ get_tree().set_auto_accept_quit(false)
+ Events.connect("go_back", self, "end_game")
+ if !is_instance_valid(Globals.network):
+ Globals.network = Network.new()
+ Globals.network.connect("move_data", self, "_on_data")
+ Globals.network.connect("join_result", self, "_on_join_result")
+ Globals.network.connect("host_result", self, "_on_host_result")
+ Globals.network.connect("game_over", self, "_handle_game_over")
+ Globals.network.connect("start_game", self, "_start_game")
+ add_child(Globals.network)
+
+
+func end_game() -> void:
+ if get_tree().get_root().has_node("World"):
+ get_tree().get_root().get_node("World").queue_free()
+ toggle(true)
+
+func create_world() -> void:
+ var world = load("res://World.tscn").instance()
+ get_tree().get_root().add_child(world)
+ toggle(false)
-func _on_find_public_ip_pressed() -> void:
- OS.shell_open("https://icanhazip.com/")
+
+func _start_game() -> void:
+ create_world()
+
+
+func _on_join_result(accepted: String) -> void:
+ Globals.team = false
+ if accepted == "Y":
+ _set_status("Joined!", true)
+ Globals.network.send_packet("", Globals.network.HEADERS.startgame)
+ else:
+ _set_status(accepted, false)
+ reset_buttons()
+
+
+func reset_buttons() -> void:
+ buttons.show()
+ address.editable = true
+
+
+func _on_host_result(accepted: String) -> void:
+ Globals.team = true
+ if accepted == "Y":
+ _set_status("Hosted!", true)
+ else:
+ _set_status(accepted, false)
+ reset_buttons()
+
+
+func add_turn() -> void:
+ Events.emit_signal("just_before_turn_over")
+ Globals.add_turn()
+ Globals.turn = not Globals.turn
+ Events.emit_signal("turn_over")
+
+
+func _on_data(data: Dictionary) -> void:
+ Globals.fullmove = data["fullmove"]
+ Globals.turn = data["turn"]
+ Globals.halfmove = data["halfmove"]
+ match data["movetype"]:
+ Network.MOVEHEADERS.passant:
+ # en passant
+ var end_pos = Vector2(dict2vec(data["positions"][1]))
+ var start_piece = Piece.at_pos(Vector2(dict2vec(data["positions"][0])))
+ Piece.at_pos(Vector2(dict2vec(data["positions"][2]))).took() # kill the unfortunate
+ start_piece.passant(end_pos)
+ Network.MOVEHEADERS.take:
+ var start_piece = Piece.at_pos(Vector2(dict2vec(data["positions"][0])))
+ var end_piece = Piece.at_pos(Vector2(dict2vec(data["positions"][1])))
+ start_piece.take(end_piece)
+ Network.MOVEHEADERS.move:
+ var end_pos = Vector2(dict2vec(data["positions"][1]))
+ var start_piece = Piece.at_pos(Vector2(dict2vec(data["positions"][0])))
+ start_piece.moveto(end_pos)
+ Network.MOVEHEADERS.castle:
+ var king = Piece.at_pos(dict2vec(data["positions"]["king"]))
+ var rook = Piece.at_pos(dict2vec(data["positions"]["rook"]))
+ rook.moveto(dict2vec(data["positions"]["rookdestination"]), true, false, true)
+ Utils.add_move(king.castle(dict2vec(data["positions"]["kingdestination"])))
+
+
+func dict2vec(dict: Dictionary) -> Vector2:
+ return Vector2(dict["x"], dict["y"])
+
+
+func _notification(what: int) -> void:
+ if what == MainLoop.NOTIFICATION_WM_QUIT_REQUEST or what == MainLoop.NOTIFICATION_WM_GO_BACK_REQUEST:
+ Globals.network.send_packet(Globals.network.game_code, Globals.network.HEADERS.stopgame)
+ yield(get_tree(), "idle_frame") # wait for the packet to send
+ get_tree().quit()
+
+
+func _on_Address_text_entered(new_text: String):
+ validate_text(new_text)
+ Globals.network.game_code = new_text