online multiplayer chess game (note server currently down)
| -rw-r--r-- | Grid.gd | 22 | ||||
| -rw-r--r-- | Utils.gd | 2 | ||||
| -rw-r--r-- | networking/Network.gd | 59 | ||||
| -rw-r--r-- | networking/PacketHandler.gd | 61 | ||||
| -rw-r--r-- | pieces/Pawn.gd | 5 | ||||
| -rw-r--r-- | project.godot | 6 | ||||
| -rw-r--r-- | ui/Lobby.gd | 18 | ||||
| -rw-r--r-- | ui/Status.gd | 5 | ||||
| -rw-r--r-- | ui/barbutton/drawbutton.gd | 38 | ||||
| -rw-r--r-- | ui/barbutton/resignbutton.gd | 6 | ||||
| -rw-r--r-- | ui/confirmbar.gd | 2 |
11 files changed, 106 insertions, 118 deletions
@@ -167,7 +167,7 @@ func mat2str(mat: Array = matrix) -> String: func drawed(reason := "") -> void: - ui.set_status("draw by " + reason) + ui.set_status("draw by " + reason, 0) Events.emit_signal("game_over") SoundFx.play("Draw") yield(get_tree().create_timer(5), "timeout") @@ -175,7 +175,7 @@ func drawed(reason := "") -> void: func win(winner: bool, reason := "") -> void: - ui.set_status("%s won the game by %s" % ["white" if winner else "black", reason]) # black won the game by checkmate + ui.set_status("%s won the game by %s" % ["white" if winner else "black", reason], 0) # black won the game by checkmate Events.emit_signal("game_over") Log.info("%s won the game in %s turns!" % ["white" if winner else "black", Globals.turns()]) SoundFx.play("Victory") @@ -329,8 +329,8 @@ func handle_take(position: Vector2) -> void: if Utils.is_pawn(last_clicked): # if its a pawn if check_promote(last_clicked, position, "take"): return - Globals.network.send_move_packet( - PoolVector2Array([last_clicked.real_position, position]), Network.MOVEHEADERS.move + Globals.network.relay_signal( + PoolVector2Array([last_clicked.real_position, position]), Network.MOVEHEADERS.move, "positions" ) # piece taking piece @@ -340,14 +340,15 @@ func handle_move(position: Vector2) -> void: var castle_data = last_clicked.can_castle[i] if castle_data[0] == position: # send some packet - Globals.network.send_move_packet( + Globals.network.relay_signal( { "king": last_clicked.real_position, "rook": castle_data[1].real_position, "rookdestination": castle_data[2], "kingdestination": castle_data[0] }, - Network.MOVEHEADERS.castle + Network.MOVEHEADERS.castle, + "positions" ) return @@ -358,15 +359,16 @@ func handle_move(position: Vector2) -> void: var en_passant_data = pawn.enpassant[i] if en_passant_data[0] == position: # send some packet - Globals.network.send_move_packet( + Globals.network.relay_signal( PoolVector2Array([pawn.real_position, position, en_passant_data[1].real_position]), - Network.MOVEHEADERS.passant + Network.MOVEHEADERS.passant, + "positions" ) return elif check_promote(pawn, position): return - Globals.network.send_move_packet( - PoolVector2Array([last_clicked.real_position, position]), Network.MOVEHEADERS.move + Globals.network.relay_signal( + PoolVector2Array([last_clicked.real_position, position]), Network.MOVEHEADERS.move, "positions" ) # piece moving @@ -177,7 +177,7 @@ func get_fen() -> String: func _notification(what: int) -> void: if what == MainLoop.NOTIFICATION_WM_QUIT_REQUEST or what == MainLoop.NOTIFICATION_WM_GO_BACK_REQUEST: if get_tree().get_root().has_node("Board"): - Globals.network.send_packet(Globals.network.game_code, Network.HEADERS.stopgame) + Globals.network.stopgame("quit") yield(get_tree(), "idle_frame") # wait for the packet to send Log.debug("Bye!") get_tree().quit() diff --git a/networking/Network.gd b/networking/Network.gd index e6fb242..7ac4590 100644 --- a/networking/Network.gd +++ b/networking/Network.gd @@ -7,24 +7,24 @@ var game_code := "" var connected := false const HEADERS := { - "move": "M", "joinrequest": "J", "hostrequest": "H", "stopgame": "K", "ping": "P", - "startgame": "S", - "request": "R" + "relay": "R", # relay goes to both + "signal": "S", # signal is one way } -const MOVEHEADERS := { - "take": "K", +const MOVEHEADERS := { # subheaders for HEADERS.move "move": "M", + "take": "K", "castle": "C", "passant": "P", "promote": "Q", } -const REQUESTHEADERS := {"takeback": "T", "draw": "D", "resign": "R"} # not really a request, but... +const RELAYHEADERS := {"chat": "C", "startgame": "S"} +const SIGNALHEADERS := {"takeback": "T", "draw": "D", "resign": "R"} # subheaders for HEADERS.signal var notation := "" @@ -33,9 +33,8 @@ signal move_data(data) signal host_result(result) signal join_result(result) signal game_over(problem, isok) -signal request_result(result) -signal request(request) signal connection_established +signal signal_recieved(what) const url := "wss://gd-chess-server.herokuapp.com/" @@ -80,45 +79,49 @@ func _connection_error() -> void: emit_signal("game_over", "Connection error", false) -func send_request_answer_packet(request_type: String, answer: bool) -> void: - var data := {"answering": true, "type": request_type, "gamecode": game_code, "answer": answer} - send_packet(data, HEADERS.request) +func signal(body, header: String, keyname := "body", _mainheader := HEADERS.signal) -> Dictionary: + var data := {"type": header, "gamecode": game_code, keyname: body} + send_packet(data, _mainheader) + Log.debug("sending signal %s of type %s" % [body, header]) + return data -func send_request_packet(request_type: String, prompt: String) -> void: - var data := {"answering": false, "type": request_type, "gamecode": game_code, "question": prompt} - send_packet(data, HEADERS.request) +func relay_signal(body, header: String, keyname := "body") -> Dictionary: # its really the same thing as signal() + return signal(body, header, keyname, HEADERS.relay) -func send_move_packet(positions, header: String) -> void: - var packet := {"movetype": header, "gamecode": game_code, "positions": positions} - Log.debug("sending move packet: %s" % packet) - send_packet(packet, HEADERS.move) # your move will wait till the server relays back :> +func stopgame(reason: String) -> void: + var packet := {"reason": reason, "gamecode": game_code} + send_packet(packet, HEADERS.stopgame) func _data_recieved() -> void: var recieve: Dictionary = ws.get_peer(1).get_var() var header: String = recieve.header var text = recieve.data + if header != HEADERS.ping: + Log.debug("recieved %s of header %s" % [text, header]) match header: HEADERS.hostrequest: emit_signal("host_result", text) - HEADERS.move: - emit_signal("move_data", text) + HEADERS.relay: + var relay: Dictionary = text + if relay.type in MOVEHEADERS.values(): + emit_signal("move_data", text) + else: + match relay.type: + RELAYHEADERS.startgame: + print("Start") + emit_signal("start_game") HEADERS.joinrequest: emit_signal("join_result", text) HEADERS.stopgame: if !PacketHandler.leaving: # dont emit the signal if its a stophost thing (HACK) emit_signal("game_over", text, true) PacketHandler.leaving = false - HEADERS.startgame: - emit_signal("start_game") - PacketHandler.emit_signal("set_visible", false) - HEADERS.request: - if text.answering: - emit_signal("request_result", text) - else: - emit_signal("request", text) + HEADERS.signal: + var signal: Dictionary = text + emit_signal("signal_recieved", signal) HEADERS.ping: pass _: diff --git a/networking/PacketHandler.gd b/networking/PacketHandler.gd index ca0da6d..5034a4b 100644 --- a/networking/PacketHandler.gd +++ b/networking/PacketHandler.gd @@ -1,25 +1,14 @@ extends Node class_name NetManager -### for the lobby ui -signal set_buttons(enabled) -signal set_status(status, err, isok) -signal set_visible(visibility) +var lobby: Lobby = null signal hosting(newhosting) - signal game_over signal game_started var hosting := false setget set_hosting var leaving := false -var status := ["", true, false] - - -func set_buttons(enabled: bool) -> void: - status[2] = enabled - emit_signal("set_buttons", enabled) - func set_hosting(newhosting: bool) -> void: hosting = newhosting @@ -29,17 +18,16 @@ func set_hosting(newhosting: bool) -> void: func return() -> void: # return to the void if hosting: leaving = true - Globals.network.send_packet(Globals.network.game_code, Network.HEADERS.stopgame) # stop hosting + Globals.network.stopgame("") # stop hosting set_hosting(false) - set_buttons(true) - set_status("", true) + lobby.set_buttons(true) + lobby.set_status("", true) func _ready() -> void: get_tree().set_auto_accept_quit(false) if Utils.internet: var net := Network.new() - set_status("Connecting", true) Events.connect("go_back", self, "_handle_game_over") net.connect("move_data", self, "_on_data") net.connect("join_result", self, "_on_join_result") @@ -49,33 +37,28 @@ func _ready() -> void: net.connect("connection_established", self, "network_ready") add_child(net) Globals.network = net + yield(get_tree().create_timer(.1), "timeout") + lobby.set_status("Connecting", true) func requestjoin() -> void: - set_buttons(false) + lobby.set_buttons(false) Globals.network.send_packet(Globals.network.game_code, Globals.network.HEADERS.joinrequest) func requesthost() -> void: - set_buttons(false) + lobby.set_buttons(false) Globals.network.send_packet(Globals.network.game_code, Globals.network.HEADERS.hostrequest) func network_ready() -> void: - set_status("", true) - set_buttons(true) - - -func set_status(text: String, isok: bool) -> void: - status[0] = text - status[1] = isok - emit_signal("set_status", text, isok) + lobby.set_status("", true) + lobby.set_buttons(true) func _on_join_result(accepted: String) -> void: if handle_result(accepted, "Joined!", false): - emit_signal("set_visible", false) - Globals.network.send_packet(Globals.network.game_code, Globals.network.HEADERS.startgame) + Globals.network.relay_signal("startgame", Network.RELAYHEADERS.startgame) func _on_host_result(accepted: String) -> void: @@ -85,21 +68,21 @@ func _on_host_result(accepted: String) -> void: func handle_result(accepted: String, resultstring: String, team := true) -> bool: Globals.team = team # what am i doing here??? if accepted == "Y": - set_status(resultstring, true) + lobby.set_status(resultstring, true) return true - set_status(accepted, false) - set_buttons(true) + lobby.set_status(accepted, false) + lobby.set_buttons(true) return false func _handle_game_over(error := "game over", isok := true) -> void: - Globals.network.send_packet({"gamecode": Globals.network.game_code, "reason": error}, Network.HEADERS.stopgame) + Globals.network.stopgame(error) Globals.reset_vars() if get_tree().get_root().has_node("Board"): get_tree().get_root().get_node("Board").queue_free() - set_status(error, isok) - emit_signal("set_visible", true) - set_buttons(true) + lobby.set_status(error, isok) + lobby.toggle(true) + lobby.set_buttons(true) emit_signal("game_over") @@ -107,16 +90,16 @@ func _start_game() -> void: set_hosting(false) var board: Node2D = load("res://Board.tscn").instance() get_tree().get_root().add_child(board) - emit_signal("set_visible", false) + lobby.toggle(false) emit_signal("game_started") - set_buttons(false) + lobby.set_buttons(false) func _on_data(data: Dictionary) -> void: Globals.add_turn() Log.debug([data, " recieved"]) Events.emit_signal("data_recieved") - match data["movetype"]: + match data["type"]: Network.MOVEHEADERS.passant: # en passant var end_pos := dict2vec(data["positions"][1]) @@ -147,6 +130,8 @@ func _on_data(data: Dictionary) -> void: pawn.took() # kill the pawn Utils.add_move(dict_data["notation"]) # add a move Globals.grid.print_matrix_pretty(Globals.grid.matrix) + _: + Log.err("Wtf") static func dict2vec(dict: Dictionary) -> Vector2: diff --git a/pieces/Pawn.gd b/pieces/Pawn.gd index ab9ea15..a4078ec 100644 --- a/pieces/Pawn.gd +++ b/pieces/Pawn.gd @@ -141,7 +141,7 @@ func handle_sprite_input_event(node: Node2D) -> void: ) Log.debug(promote_to) var notation := "%s=%s" % [first, promote_to] - Globals.network.send_move_packet( + Globals.network.relay_signal( { "start_position": real_position, "destination": promoteposition, @@ -149,7 +149,8 @@ func handle_sprite_input_event(node: Node2D) -> void: "notation": notation, "white": white }, - Network.MOVEHEADERS.promote + Network.MOVEHEADERS.promote, + "positions" ) diff --git a/project.godot b/project.godot index 1fe7c99..dcd2743 100644 --- a/project.godot +++ b/project.godot @@ -74,6 +74,11 @@ _global_script_classes=[ { "language": "GDScript", "path": "res://pieces/Knight.gd" }, { +"base": "Control", +"class": "Lobby", +"language": "GDScript", +"path": "res://ui/Lobby.gd" +}, { "base": "Node", "class": "Log", "language": "GDScript", @@ -148,6 +153,7 @@ _global_script_class_icons={ "HueSlider": "", "King": "res://assets/pieces/california/wK.png", "Knight": "res://assets/pieces/california/wN.png", +"Lobby": "", "Log": "", "NetManager": "", "Network": "", diff --git a/ui/Lobby.gd b/ui/Lobby.gd index bc8dd3f..a696ed5 100644 --- a/ui/Lobby.gd +++ b/ui/Lobby.gd @@ -1,4 +1,5 @@ extends Control +class_name Lobby onready var address: LineEdit = find_node("Address") onready var buttons := find_node("buttons") @@ -11,19 +12,14 @@ func toggle(onoff: bool) -> void: func _ready() -> void: - PacketHandler.connect("set_status", self, "_set_status") - PacketHandler.connect("set_buttons", self, "_set_buttons") - PacketHandler.connect("set_visible", self, "toggle") + PacketHandler.lobby = self PacketHandler.connect("hosting", find_node("stophost"), "set_visible") - _set_status(PacketHandler.status[0], PacketHandler.status[1]) if !Utils.internet: - _set_status("no internet", false) - _set_buttons(false) - else: - _set_buttons(PacketHandler.status[2]) + set_status("no internet", false) + set_buttons(false) -func _set_status(text: String, isok: bool) -> void: # Simple way to show status. +func set_status(text: String, isok: bool) -> void: # Simple way to show status. if isok: status_ok.set_text(text) status_fail.set_text("") @@ -34,7 +30,7 @@ func _set_status(text: String, isok: bool) -> void: # Simple way to show status status_fail.visible = len(status_fail.text) > 0 -func _set_buttons(enabled := true) -> void: +func set_buttons(enabled := true) -> void: for c in buttons.get_children(): c.disabled = !enabled address.editable = enabled @@ -65,7 +61,7 @@ func _on_Address_text_entered(new_text: String) -> void: func _on_tabs_tab_changed(tab: int): - if tab != get_parent().get_children().find(self): + if self != get_parent().get_children()[tab]: PacketHandler.return() diff --git a/ui/Status.gd b/ui/Status.gd index 6a68c79..351f523 100644 --- a/ui/Status.gd +++ b/ui/Status.gd @@ -5,5 +5,6 @@ class_name StatusLabel func set_text(newtext: String, time := 7) -> void: print("set to ", newtext) text = newtext - yield(get_tree().create_timer(time), "timeout") - text = "" + if time != 0: + yield(get_tree().create_timer(time), "timeout") + text = "" diff --git a/ui/barbutton/drawbutton.gd b/ui/barbutton/drawbutton.gd index c5fb8ef..13f4965 100644 --- a/ui/barbutton/drawbutton.gd +++ b/ui/barbutton/drawbutton.gd @@ -7,18 +7,21 @@ export(NodePath) onready var confirmbar = get_node(confirmbar) as Confirm var waiting_on_answer := false -func _ready() -> void: - Globals.network.connect("request", self, "draw_request") - Globals.network.connect("request_result", self, "_on_draw_result") +func _ready(): + Globals.network.connect("signal_recieved", self, "_on_signal") -func draw_request(what: Dictionary): - if what.type == Network.REQUESTHEADERS.draw: - if "questions" in what: - Log.err("Draw request without prompt") - return - confirmbar.confirm(self, what.question, 20) - waiting_on_answer = true +func _on_signal(what: Dictionary): + if what.type == Network.SIGNALHEADERS.draw: + if "question" in what: + confirmbar.confirm(self, "Your opponent requests a draw", 20) + waiting_on_answer = true + else: + disabled = false + if what.accepted: + drawed() + else: + status.set_text("Your opponent rejected the draw") func drawed() -> GDScriptFunctionState: @@ -35,25 +38,14 @@ func _pressed() -> void: confirmbar.stop_looking() else: disabled = true - Globals.network.send_request_packet( - Network.REQUESTHEADERS.draw, "Your opponent wishes to draw, do you accept?" - ) + Globals.network.signal("", Network.SIGNALHEADERS.draw, "question") status.set_text("Draw request sent") -func _on_draw_result(accepted: Dictionary) -> void: # called from _handle_confirm - disabled = false - if accepted.type == Network.REQUESTHEADERS.draw: - if accepted.answer: - drawed() - else: - status.set_text("Your opponent has rejected the draw request.") - - func _handle_confirm(yes: bool) -> void: # called from confirmbar.confirmed if waiting_on_answer: disabled = false waiting_on_answer = false - Globals.network.send_request_answer_packet(Network.REQUESTHEADERS.draw, yes) + Globals.network.signal(yes, Network.SIGNALHEADERS.draw, "accepted") if yes: drawed() diff --git a/ui/barbutton/resignbutton.gd b/ui/barbutton/resignbutton.gd index 3ca7490..2a03c3e 100644 --- a/ui/barbutton/resignbutton.gd +++ b/ui/barbutton/resignbutton.gd @@ -9,11 +9,11 @@ var waiting_on_answer = false func _ready() -> void: - Globals.network.connect("request", self, "resigned") + Globals.network.connect("signal_recieved", self, "resigned") func resigned(what: Dictionary): - if what.type == Network.REQUESTHEADERS.resign: + if what.type == Network.SIGNALHEADERS.resign: Globals.grid.win(Globals.team, "resignation") @@ -36,6 +36,6 @@ func _confirmed(what: bool): waiting_on_answer = false drawbutton.disabled = what # dont un disable it if the game is over if what: - Globals.network.send_request_packet(Network.REQUESTHEADERS.resign, "") + Globals.network.signal("", Network.SIGNALHEADERS.resign) Globals.grid.win(!Globals.team, "resignation") disabled = true diff --git a/ui/confirmbar.gd b/ui/confirmbar.gd index f378f59..8b188aa 100644 --- a/ui/confirmbar.gd +++ b/ui/confirmbar.gd @@ -34,6 +34,8 @@ func confirm(who: Node, what: String, timeout := 5): func _pressed(what: bool): + for i in $H.get_children(): + i._focused(false) status.set_text("", 0) emit_signal("confirmed", what) stop_looking() |