online multiplayer chess game (note server currently down)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
extends Control

onready var address: LineEdit = $Back/Center/HBox/VBox/Address
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


func toggle(onoff) -> void:
	visible = onoff
	if onoff:
		for i in get_tree().get_nodes_in_group("control"):
			i.mouse_filter = MOUSE_FILTER_STOP
	else:
		for i in get_tree().get_nodes_in_group("control"):
			i.mouse_filter = MOUSE_FILTER_IGNORE


func _handle_game_over(error = "game over", isok = true) -> void:
	set_buttons()
	Globals.reset_vars()
	end_game()
	_set_status(error, isok)


func _set_status(text, isok) -> void:  # Simple way to show status.
	if isok:
		status_ok.set_text(text)
		status_fail.set_text("")
	else:
		status_ok.set_text("")
		status_fail.set_text(text)
	status_ok.visible = len(status_ok.text) > 0
	status_fail.visible = len(status_fail.text) > 0


func _on_join_pressed() -> void:
	Globals.network.game_code = validate_text()
	Globals.network.send_packet(Globals.network.game_code, Globals.network.HEADERS.joinrequest)
	set_buttons(false)


func _on_HostButton_pressed() -> void:
	Globals.network.game_code = validate_text()
	Globals.network.send_packet(Globals.network.game_code, Globals.network.HEADERS.hostrequest)
	set_buttons(false)


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 _ready() -> void:
	get_tree().set_auto_accept_quit(false)
	Events.connect("go_back", self, "_handle_game_over")
	if !is_instance_valid(Globals.network):
		if Utils.internet_available():
			_set_status("Connecting...", true)
			var net = Network.new()
			net.connect("move_data", self, "_on_data")
			net.connect("join_result", self, "_on_join_result")
			net.connect("host_result", self, "_on_host_result")
			net.connect("game_over", self, "_handle_game_over")
			net.connect("start_game", self, "_start_game")
			net.connect("connection_established", self, "network_ready")
			add_child(net)
			Globals.network = net
		else:
			set_buttons(false)
			_set_status("No internet connection", false)


func network_ready():
	set_buttons(true)
	_set_status("", true)


func end_game() -> void:
	if get_tree().get_root().has_node("Board"):
		get_tree().get_root().get_node("Board").queue_free()
	toggle(true)


func create_world() -> void:
	var board = load("res://Board.tscn").instance()
	get_tree().get_root().add_child(board)
	toggle(false)


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)
		set_buttons()


func set_buttons(enabled = true) -> void:
	for c in buttons.get_children():
		c.disabled = !enabled
	address.editable = enabled


func _on_host_result(accepted: String) -> void:
	Globals.team = true
	if accepted == "Y":
		_set_status("Hosted!", true)
	else:
		_set_status(accepted, false)
		set_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:
	Log.debug([data, " recieved"])
	Globals.fullmove = data["fullmove"]
	Globals.turn = data["turn"]
	Globals.halfmove = data["halfmove"]
	Events.emit_signal("data_recieved")
	match data["movetype"]:
		Network.MOVEHEADERS.passant:
			# en passant
			var end_pos = dict2vec(data["positions"][1])
			var start_piece = Piece.at_pos(dict2vec(data["positions"][0]))
			Piece.at_pos(dict2vec(data["positions"][2])).took()  # kill the unfortunate
			start_piece.passant(end_pos)
		Network.MOVEHEADERS.move:
			var start_piece = Piece.at_pos(dict2vec(data["positions"][0]))
			var end_pos = dict2vec(data["positions"][1])
			var end_piece = Piece.at_pos(end_pos)
			if end_piece != null:
				start_piece.take(end_piece)
			else:
				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"])))
		Network.MOVEHEADERS.promote:
			var dict_data = data["positions"]  # positions is a dict for readability sometimes
			var pawn = Piece.at_pos(dict2vec(dict_data["start_position"]))
			var dest = dict2vec(dict_data["destination"])
			if Piece.at_pos(dest) != null:
				Piece.at_pos(dest).took()  # move the pawn to the new place, killing if necessary
				pawn.clear_clicked()
			Globals.grid.make_piece(dest, Pawn.piece(dict_data["become"]), dict_data["white"])  # create the promotion
			pawn.took()  # kill the pawn
			Utils.add_move(dict_data["notation"])  # add a move
			Globals.grid.print_matrix_pretty(Globals.grid.matrix)


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:
		if get_tree().get_root().has_node("Board"):
			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