online multiplayer chess game (note server currently down)
rejoin support(!!!!)
bendn 2022-06-04
parent dc5ceb7 · commit fbc55b0
-rw-r--r--Debug.gd2
-rw-r--r--Globals.gd1
-rw-r--r--Grid.gd73
-rw-r--r--PGN/PGN.gd38
-rw-r--r--PGN/test_pgns.gd26
-rw-r--r--PGN/test_pgns.tscn20
-rw-r--r--README.md7
-rw-r--r--SanParse/Move.gd12
-rw-r--r--SanParse/SanParse.gd4
-rw-r--r--Utils.gd13
-rw-r--r--assets/ui/circle.png3
-rw-r--r--assets/ui/circle.png.import35
-rw-r--r--assets/ui/svg/circle.svg3
-rw-r--r--assets/ui/svg/circle_part.svg3
-rw-r--r--export_presets.cfg2
-rw-r--r--html/custom.html280
-rw-r--r--networking/Network.gd36
-rw-r--r--networking/PacketHandler.gd60
-rw-r--r--pieces/King.gd4
-rw-r--r--pieces/Pawn.gd32
-rw-r--r--pieces/Piece.gd23
-rw-r--r--project.godot7
-rw-r--r--saveload.gd4
-rw-r--r--test.gd8
-rw-r--r--ui/Log.gd31
-rw-r--r--ui/Settings.gd12
-rw-r--r--ui/StartMenu.tscn6
-rw-r--r--ui/account/Account.gd64
-rw-r--r--ui/account/Account.tscn2
-rw-r--r--ui/account/usernamepass.gd21
-rw-r--r--ui/animations/LoadingAnimation.tscn9
31 files changed, 616 insertions, 225 deletions
diff --git a/Debug.gd b/Debug.gd
index 1742653..f110d51 100644
--- a/Debug.gd
+++ b/Debug.gd
@@ -14,7 +14,7 @@ const vertical := 15
static func is_debug() -> bool:
var args := Utils.get_args()
if "debug" in args:
- return bool(args.debug)
+ return Utils.str_bool(args.debug)
return OS.is_debug_build()
diff --git a/Globals.gd b/Globals.gd
index 58a738e..607fd74 100644
--- a/Globals.gd
+++ b/Globals.gd
@@ -55,7 +55,6 @@ func add_turn() -> void:
else:
halfmove += 1
turn = not turn
- Log.debug("Turn over signal emmited")
Events.emit_signal("turn_over")
diff --git a/Grid.gd b/Grid.gd
index 514fc94..7205146 100644
--- a/Grid.gd
+++ b/Grid.gd
@@ -1,7 +1,7 @@
extends Node2D
class_name Grid
-const Piece := preload("res://Piece.tscn")
+const PieceScene := preload("res://Piece.tscn")
const Square := preload("res://Square.tscn")
const BottomLeftLabel := preload("res://ui/boardlabels/BottomLeftLabel.tscn")
const TopRightLabel := preload("res://ui/boardlabels/TopRightLabel.tscn")
@@ -23,7 +23,7 @@ export(Color) var clockrunninglow := Color(0.47451, 0.172549, 0.164706)
export(Color) var clocklow := Color(0.313726, 0.156863, 0.14902)
var matrix := []
-var stop_input := false
+var stop_input := true
var background_matrix := []
var history_matrixes := {}
var last_clicked: Piece = null
@@ -43,6 +43,8 @@ func _init() -> void:
func _ready() -> void:
+ if Globals.network:
+ Globals.network.connect("move_data", self, "play_san")
init_board() # create the tile squares
init_matrix() # create the pieces
init_labels() # add the labels
@@ -52,6 +54,7 @@ func _ready() -> void:
Debug.monitor(self, "last_clicked")
Debug.monitor(self, "matrix", "matrix[8]")
Debug.monitor(self, "highest value in 3fold", "threefoldrepetition()")
+ stop_input = false
func _exit_tree() -> void:
@@ -208,7 +211,7 @@ func init_matrix() -> void: # create the matrix
func make_piece(position: Vector2, script: String, white: bool = true) -> void: # make peace
- var piece := Piece.instance() # create a piece
+ var piece := PieceScene.instance() # create a piece
piece.script = load("res://pieces/%s.gd" % script) # set the script
piece.real_position = position # set the real position
piece.global_position = position * piece_size # set the global position
@@ -369,15 +372,13 @@ func _on_outoftime(who: bool) -> void:
func _on_turn_over() -> void:
- stop_input = false
- Log.debug("turn over. new turn: " + Globals.get_turn())
var matstr := mat2str()
- Log.debug("matstr: " + matstr)
+ # Log.debug("matstr: " + matstr)
if !matstr in history_matrixes:
- Log.debug("new matrix entry")
+ # Log.debug("new matrix entry")
history_matrixes[matstr] = 1
else:
- Log.debug(["matrix entry = ", history_matrixes[matstr], "+ 1"])
+ # Log.debug(["matrix entry = ", history_matrixes[matstr], "+ 1"])
history_matrixes[matstr] += 1
Globals.checking_piece = null # reset checking_piece
Globals.in_check = false # reset in_check
@@ -391,3 +392,59 @@ func _on_turn_over() -> void:
drawed("stalemate")
elif threefoldrepetition() >= 3:
drawed("threefold repetition")
+
+
+func play_pgn(pgn: String, instant := false):
+ for san in Pgn.parse(pgn).moves:
+ play_san(san) # instant is not working right right now
+ # so just change the delay :>
+ if instant:
+ yield(get_tree(), "idle_frame")
+ else:
+ yield(get_tree().create_timer(.3), "timeout")
+
+
+func play_san(san: String, instant := false) -> void:
+ stop_input = true
+ Log.debug("playing " + san)
+ var san_to_add := san
+ var mov = SanParse.parse(san)
+ mov.make_long()
+ Globals.add_turn()
+ match mov.move_kind.type:
+ Move.MoveKind.CASTLE:
+ var side = 0 if Globals.turn else 7
+ var rook: Rook
+ var rook_goto: Vector2
+ var kingpos = Vector2(4, side)
+ var king: King = Piece.at_pos(kingpos)
+ var king_goto: Vector2
+ match mov.move_kind.data:
+ Move.MoveKind.CASTLETYPES.KING_SIDE:
+ rook = Piece.at_pos(Vector2(7, side))
+ rook_goto = Vector2(5, side)
+ king_goto = Vector2(6, side)
+ Move.MoveKind.CASTLETYPES.QUEEN_SIDE:
+ rook = Piece.at_pos(Vector2(0, side))
+ rook_goto = Vector2(3, side)
+ king_goto = Vector2(2, side)
+ rook.moveto(rook_goto, instant)
+ king.castle(king_goto, instant)
+ Move.MoveKind.NORMAL:
+ # this handles promotion, taking, enpassant, and moves.
+ var positions = mov.move_kind.data
+ if mov.promotion != -1: # promotion part
+ var promote_to = Utils.to_str(mov.promotion)
+ Piece.at_pos(positions[0]).promote_to(promote_to, mov.is_capture, positions[1], instant)
+
+ elif mov.is_capture: # taking part
+ if Piece.at_pos(positions[1]):
+ Piece.at_pos(positions[0]).take(Piece.at_pos(positions[1]), instant)
+ elif mov.piece == SanParser.PAWN: # enpassant part
+ var pawn: Pawn = Piece.at_pos(positions[0])
+ pawn.passant(positions[1], instant)
+ san_to_add += " e.p."
+ else: # a very normal move
+ Piece.at_pos(positions[0]).moveto(positions[1], instant)
+ Utils.add_move(san_to_add)
+ stop_input = false
diff --git a/PGN/PGN.gd b/PGN/PGN.gd
index 32ca121..52d15bc 100644
--- a/PGN/PGN.gd
+++ b/PGN/PGN.gd
@@ -2,7 +2,7 @@ extends Node
class_name PGN
-func parse(string):
+func parse(string) -> Dictionary:
# put tags into a dictionary,
# and the moves into a array
@@ -17,13 +17,15 @@ func parse(string):
var headers := {}
var lines = Array(string.split("\n"))
while !lines.empty():
- var line = lines.pop_front().strip_edges()
+ var line = lines[0].strip_edges()
if !line or line[0] in ["%", ";"]:
+ lines.pop_front()
continue
if line[0] != "[":
break
+ lines.pop_front()
var tag_match = tagex.search(line)
if tag_match:
var cap = tag_match.strings
@@ -32,7 +34,7 @@ func parse(string):
else:
# invalid headers
push_error("invalid headers")
- return
+ return {}
else:
break
@@ -44,30 +46,6 @@ func parse(string):
if line[0] in ["%", ";"]:
continue
for found in movetextex.search_all(line):
- movetext.append(found.strings[1])
-
- return [headers, movetext]
-
-
-func _ready():
- var parsed = parse(
- """
- [Event \"F/S Return Match\"]
- [Site \"Belgrade, Serbia JUG\"]
- [Date \"1992.11.04\"]
- [Round \"29\"]
- [White \"Fischer, Robert J.\"]
- [Black \"Spassky, Boris V.\"]
- [Result \"1/2-1/2\"]
-
- 1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 {This opening is called the Ruy Lopez.}
- 4. Ba4 Nf6 5. O-O Be7 6. Re1 b5 7. Bb3 d6 8. c3 O-O 9. h3 Nb8 10. d4 Nbd7
- 11. c4 c6 12. cxb5 axb5 13. Nc3 Bb7 14. Bg5 b4 15. Nb1 h6 16. Bh4 c5 17. dxe5
- Nxe4 18. Bxe7 Qxe7 19. exd6 Qf6 20. Nbd2 Nxd6 21. Nc4 Nxc4 22. Bxc4 Nb6
- 23. Ne5 Rae8 24. Bxf7+ Rxf7 25. Nxf7 Rxe1+ 26. Qxe1 Kxf7 27. Qe3 Qg5 28. Qxg5
- hxg5 29. b3 Ke6 30. a3 Kd6 31. axb4 cxb4 32. Ra5 Nd5 33. f3 Bc8 34. Kf2 Bf5
- 35. Ra7 g6 36. Ra6+ Kc5 37. Ke1 Nf4 38. g3 Nxh3 39. Kd2 Kb5 40. Rd6 Kc5 41. Ra6
- Nf2 42. g4 Bd3 43. Re6 1/2-1/2
- """
- )
- print(parsed)
+ if found.strings[1]:
+ movetext.append(found.strings[1])
+ return {"headers": headers, "moves": movetext}
diff --git a/PGN/test_pgns.gd b/PGN/test_pgns.gd
new file mode 100644
index 0000000..d46d4ff
--- /dev/null
+++ b/PGN/test_pgns.gd
@@ -0,0 +1,26 @@
+extends VBoxContainer
+
+export(PoolStringArray) var pgns = []
+
+var in_sim = false
+
+
+func _ready():
+ if !Debug.debug:
+ queue_free()
+
+
+func _load(i: int):
+ in_sim = true
+ var boar = load("res://Board.tscn").instance()
+ get_tree().get_root().add_child(boar)
+ boar.get_node("Grid").play_pgn(pgns[i])
+ get_parent().hide()
+
+
+func _input(_event):
+ if Input.is_action_pressed("ui_cancel") and in_sim:
+ in_sim = false
+ get_node("/root/Board").queue_free()
+ get_parent().show()
+ Globals.reset_vars()
diff --git a/PGN/test_pgns.tscn b/PGN/test_pgns.tscn
new file mode 100644
index 0000000..a73b96e
--- /dev/null
+++ b/PGN/test_pgns.tscn
@@ -0,0 +1,20 @@
+[gd_scene load_steps=3 format=2]
+
+[ext_resource path="res://ui/theme/main.tres" type="Theme" id=1]
+[ext_resource path="res://PGN/test_pgns.gd" type="Script" id=2]
+
+[node name="tests" type="VBoxContainer"]
+anchor_right = 1.0
+anchor_bottom = 1.0
+theme = ExtResource( 1 )
+script = ExtResource( 2 )
+pgns = PoolStringArray( "1.Nf3 Nf6 2.c4 g6 3.Nc3 Bg7 4.d4 O-O 5.Bf4 d5 6.Qb3 dxc4 7.Qxc4 c6 8.e4 Nbd7 9.Rd1 Nb6 10.Qc5 Bg4 11.Bg5 Na4 12.Qa3 Nxc3 13.bxc3 Nxe4 14.Bxe7 Qb6 15.Bc4 Nxc3 16.Bc5 Rfe8+ 17.Kf1 Be6 18.Bxb6 Bxc4+ 19.Kg1 Ne2+ 20.Kf1 Nxd4+ 21.Kg1 Ne2+ 22.Kf1 Nc3+ 23.Kg1 axb6 24.Qb4 Ra4 25.Qxb6 Nxd1 26.h3 Rxa2 27.Kh2 Nxf2 28.Re1 Rxe1 29.Qd8+ Bf8 30.Nxe1 Bd5 31.Nf3 Ne4 32.Qb8 b5 33.h4 h5 34.Ne5 Kg7 35.Kg1 Bc5+ 36.Kf1 Ng3+ 37.Ke1 Bb4+ 38.Kd1 Bb3+ 39.Kc1 Ne2+ 40.Kb1 Nc3+ 41.Kc1 Rc2# 0-1" )
+
+[node name="gameofthecentury" type="Button" parent="."]
+margin_left = 454.0
+margin_right = 967.0
+margin_bottom = 106.0
+size_flags_horizontal = 4
+text = "game of the century"
+
+[connection signal="pressed" from="gameofthecentury" to="." method="_load" binds= [ 0 ]]
diff --git a/README.md b/README.md
index 82fe92d..508d4f6 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,8 @@
-![img](https://github.com/bend-n/chess/blob/main/icon.png)
+[![logo](https://github.com/bend-n/chess/blob/main/icon.png)](https://github.com/bend-n/chess/blob/main/icon.png "Icon")
+[![bend-n - chess](https://img.shields.io/static/v1?label=bend-n&message=chess&color=blue&logo=github)](https://github.com/bend-n/chess "Go to GitHub repo")
+[![build](https://github.com/bend-n/chess/actions/workflows/export.yml/badge.svg)](https://github.com/bend-n/chess/actions/workflows/export.yml "Build workflow")
+[![GitHub tag](https://img.shields.io/github/tag/bend-n/chess?include_prereleases=&sort=semver&color=blue)](https://github.com/bend-n/chess/releases/ "GitHub releases")
+[![License](https://img.shields.io/badge/License-MIT-blue)](https://github.com/bend-n/chess/blob/main/LICENSE "License")
+[![issues - chess](https://img.shields.io/github/issues/bend-n/chess)](https://github.com/bend-n/chess/issues "Issues")
completly works (real)
diff --git a/SanParse/Move.gd b/SanParse/Move.gd
index f5e40d8..afa07a9 100644
--- a/SanParse/Move.gd
+++ b/SanParse/Move.gd
@@ -61,6 +61,8 @@ func compile() -> String: # compiles the structure to a san
# print(Utils.to_algebraic(make_long(SanParse.parse("N1xc3").move_kind.data, false, SanParser.KNIGHT)[0]) == "b1")
### fix short san
func make_long():
+ if move_kind.type == MoveKind.CASTLE:
+ return
var newvecs: PoolVector2Array = []
var vectors = move_kind.data
@@ -85,21 +87,25 @@ func long_helper(vec: Vector2, attack: bool, move: bool, touch: Vector2):
if vec.y == -1 and vec.x != -1:
for y in range(8):
var spot = Piece.at_pos(Vector2(vec.x, y))
- if Utils.spotispiece(piece, spot) and spot.can_touch(touch, attack, move):
+ if long_helper_helper(spot, touch, attack, move):
return Vector2(vec.x, y)
elif vec.x == -1 and vec.y != -1:
for x in range(8):
var spot = Piece.at_pos(Vector2(x, vec.y))
- if Utils.spotispiece(piece, spot) and spot.can_touch(touch, attack, move):
+ if long_helper_helper(spot, touch, attack, move):
return Vector2(x, vec.y)
elif vec == Vector2(-1, -1):
for x in range(8):
for y in range(8):
var spot = Piece.at_pos(Vector2(x, y))
- if Utils.spotispiece(piece, spot) and spot.can_touch(touch, attack, move):
+ if long_helper_helper(spot, touch, attack, move):
return Vector2(x, y)
+func long_helper_helper(spot, touch, attack, move):
+ return Utils.spotispiece(piece, spot) and spot.white == Globals.turn and spot.can_touch(touch, attack, move)
+
+
class MoveKind:
extends Resource
enum CASTLETYPES { NONE, QUEEN_SIDE, KING_SIDE }
diff --git a/SanParse/SanParse.gd b/SanParse/SanParse.gd
index 9a1f130..a93b430 100644
--- a/SanParse/SanParse.gd
+++ b/SanParse/SanParse.gd
@@ -112,8 +112,8 @@ func regexmatch(san: String) -> Move:
re = regexs.piece_capture.search(san)
if re:
var cap = re.strings
- var mov = Move.new(from_str(cap[1]), [Vector2(Utils.col_pos(cap[2]), -1), pos(cap[3], cap[4])], true)
- mov.set_check_type(cap[5])
+ var mov = Move.new(from_str(cap[1]), [UNKNOWN_POS, pos(cap[2], cap[3])], true)
+ mov.set_check_type(cap[4])
return mov
re = regexs.specific_column_piece_capture.search(san)
diff --git a/Utils.gd b/Utils.gd
index 9b6d7b2..49232c3 100644
--- a/Utils.gd
+++ b/Utils.gd
@@ -65,6 +65,15 @@ func get_fen() -> String:
) # pos # turn # castling # enpassant # halfmove # fullmove
+static func str_bool(string: String) -> bool:
+ string = string.to_lower()
+ if string == "true":
+ return true
+ if string == "false":
+ return false
+ return false
+
+
func add_move(move: String) -> void:
if Globals.turn == false:
moves_list.append("%s. %s" % [Globals.fullmove, move])
@@ -174,11 +183,7 @@ func format_seconds(time: float, use_milliseconds: bool = false) -> 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.stopgame("quit")
- yield(get_tree(), "idle_frame") # wait for the packet to send
Log.debug("Bye!")
- get_tree().quit()
static func to_algebraic(pos: Vector2) -> String:
diff --git a/assets/ui/circle.png b/assets/ui/circle.png
new file mode 100644
index 0000000..c871f5d
--- /dev/null
+++ b/assets/ui/circle.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:fb308529d4020815eafa35781958ebae9108d3a5ff3b538b90acd7beb0f9ddc9
+size 3529
diff --git a/assets/ui/circle.png.import b/assets/ui/circle.png.import
new file mode 100644
index 0000000..e7344bf
--- /dev/null
+++ b/assets/ui/circle.png.import
@@ -0,0 +1,35 @@
+[remap]
+
+importer="texture"
+type="StreamTexture"
+path="res://.import/circle.png-56c8a136dc4ef80f0ed3434a9d801ecd.stex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://assets/ui/circle.png"
+dest_files=[ "res://.import/circle.png-56c8a136dc4ef80f0ed3434a9d801ecd.stex" ]
+
+[params]
+
+compress/mode=0
+compress/lossy_quality=0.7
+compress/hdr_mode=0
+compress/bptc_ldr=0
+compress/normal_map=0
+flags/repeat=0
+flags/filter=true
+flags/mipmaps=false
+flags/anisotropic=false
+flags/srgb=2
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/HDR_as_SRGB=false
+process/invert_color=false
+process/normal_map_invert_y=false
+stream=false
+size_limit=0
+detect_3d=false
+svg/scale=1.0
diff --git a/assets/ui/svg/circle.svg b/assets/ui/svg/circle.svg
new file mode 100644
index 0000000..5a75abf
--- /dev/null
+++ b/assets/ui/svg/circle.svg
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:4fd81ff2586de5ac118998c6baec1f644c7d4363751d1967a217204f995b1495
+size 1575
diff --git a/assets/ui/svg/circle_part.svg b/assets/ui/svg/circle_part.svg
new file mode 100644
index 0000000..cc4127a
--- /dev/null
+++ b/assets/ui/svg/circle_part.svg
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:bfbce10b6ce47cac5ee274572543cee7a42576ac52a8110ff9a626aa0296c095
+size 2045
diff --git a/export_presets.cfg b/export_presets.cfg
index 0da1268..86fe2bc 100644
--- a/export_presets.cfg
+++ b/export_presets.cfg
@@ -52,7 +52,7 @@ variant/export_type=0
vram_texture_compression/for_desktop=true
vram_texture_compression/for_mobile=false
html/export_icon=true
-html/custom_html_shell=""
+html/custom_html_shell="res://html/custom.html"
html/head_include=""
html/canvas_resize_policy=2
html/focus_canvas_on_start=true
diff --git a/html/custom.html b/html/custom.html
new file mode 100644
index 0000000..b17b095
--- /dev/null
+++ b/html/custom.html
@@ -0,0 +1,280 @@
+<!DOCTYPE html>
+<html xmlns="https://www.w3.org/1999/xhtml" lang="" xml:lang="">
+ <head>
+ <meta charset="utf-8" />
+ <meta name="viewport" content="width=device-width, user-scalable=no" />
+ <title>$GODOT_PROJECT_NAME</title>
+ <style type="text/css">
+ body {
+ touch-action: none;
+ margin: 0;
+ border: 0 none;
+ padding: 0;
+ min-width: 100%;
+ min-height: 100%;
+ text-align: center;
+ background-size: cover;
+ background-repeat: no-repeat;
+ background: linear-gradient(to right, yellow, orange 60%, cyan);
+ }
+
+ #canvas {
+ display: block;
+ margin: 0;
+ color: white;
+ }
+
+ #canvas:focus {
+ outline: none;
+ }
+
+ .godot {
+ font-family: verdana;
+ font-weight: bold;
+ color: #e0e0e0;
+ background-color: black;
+ }
+
+ /* Status display
+ * ============== */
+
+ #status {
+ position: absolute;
+ left: 0;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ /* don't consume click events - make children visible explicitly */
+ visibility: hidden;
+ }
+
+ #status-progress {
+ width: 600px;
+ height: 50px;
+ background-color: #dcc621;
+ background-image: linear-gradient(to left, cyan, orange 60%, yellow);
+ border: 5px solid black;
+ padding: 3px;
+ border-radius: 30px;
+ visibility: visible;
+ }
+
+ @media only screen and (orientation: portrait) {
+ #status-progress {
+ width: 61.8%;
+ }
+ }
+
+ #status-progress-inner {
+ height: 100%;
+ width: 0;
+ box-sizing: border-box;
+ transition: width 0.5s linear;
+ background-image: linear-gradient(45deg, blue 30%, red);
+ border: 3px solid black;
+ border-radius: 30px;
+ }
+
+ #status-indeterminate {
+ height: 42px;
+ visibility: visible;
+ position: relative;
+ }
+
+ #status-indeterminate > div {
+ width: 4.5px;
+ height: 0;
+ border-style: solid;
+ border-width: 9px 3px 0 3px;
+ border-color: black transparent transparent transparent;
+ transform-origin: center 21px;
+ position: absolute;
+ }
+
+ #status-indeterminate > div:nth-child(1) {
+ transform: rotate(22.5deg);
+ }
+ #status-indeterminate > div:nth-child(2) {
+ transform: rotate(67.5deg);
+ }
+ #status-indeterminate > div:nth-child(3) {
+ transform: rotate(112.5deg);
+ }
+ #status-indeterminate > div:nth-child(4) {
+ transform: rotate(157.5deg);
+ }
+ #status-indeterminate > div:nth-child(5) {
+ transform: rotate(202.5deg);
+ }
+ #status-indeterminate > div:nth-child(6) {
+ transform: rotate(247.5deg);
+ }
+ #status-indeterminate > div:nth-child(7) {
+ transform: rotate(292.5deg);
+ }
+ #status-indeterminate > div:nth-child(8) {
+ transform: rotate(337.5deg);
+ }
+
+ #status-notice {
+ margin: 0 100px;
+ line-height: 1.3;
+ visibility: visible;
+ padding: 4px 6px;
+ visibility: visible;
+ }
+ </style>
+ $GODOT_HEAD_INCLUDE
+ </head>
+ <body>
+ <canvas id="canvas">
+ HTML5 canvas appears to be unsupported in the current browser.<br />
+ Please try updating or use a different browser.
+ </canvas>
+ <div id="status">
+ <div
+ id="status-progress"
+ style="display: none"
+ oncontextmenu="event.preventDefault();"
+ >
+ <div id="status-progress-inner"></div>
+ </div>
+ <div
+ id="status-indeterminate"
+ style="display: none"
+ oncontextmenu="event.preventDefault();"
+ >
+ <div></div>
+ <div></div>
+ <div></div>
+ <div></div>
+ <div></div>
+ <div></div>
+ <div></div>
+ <div></div>
+ </div>
+ <div id="status-notice" class="godot" style="display: none"></div>
+ </div>
+
+ <script type="text/javascript" src="$GODOT_URL"></script>
+ <script type="text/javascript">
+ //<![CDATA[
+
+ const GODOT_CONFIG = $GODOT_CONFIG;
+ var engine = new Engine(GODOT_CONFIG);
+
+ (function () {
+ const INDETERMINATE_STATUS_STEP_MS = 100;
+ var statusProgress = document.getElementById("status-progress");
+ var statusProgressInner = document.getElementById(
+ "status-progress-inner"
+ );
+ var statusIndeterminate = document.getElementById(
+ "status-indeterminate"
+ );
+ var statusNotice = document.getElementById("status-notice");
+
+ var initializing = true;
+ var statusMode = "hidden";
+
+ var animationCallbacks = [];
+ function animate(time) {
+ animationCallbacks.forEach((callback) => callback(time));
+ requestAnimationFrame(animate);
+ }
+ requestAnimationFrame(animate);
+
+ function setStatusMode(mode) {
+ if (statusMode === mode || !initializing) return;
+ [statusProgress, statusIndeterminate, statusNotice].forEach(
+ (elem) => {
+ elem.style.display = "none";
+ }
+ );
+ animationCallbacks = animationCallbacks.filter(function (value) {
+ return value != animateStatusIndeterminate;
+ });
+ switch (mode) {
+ case "progress":
+ statusProgress.style.display = "block";
+ break;
+ case "indeterminate":
+ statusIndeterminate.style.display = "block";
+ animationCallbacks.push(animateStatusIndeterminate);
+ break;
+ case "notice":
+ statusNotice.style.display = "block";
+ break;
+ case "hidden":
+ break;
+ default:
+ throw new Error("Invalid status mode");
+ }
+ statusMode = mode;
+ }
+
+ function animateStatusIndeterminate(ms) {
+ var i = Math.floor((ms / INDETERMINATE_STATUS_STEP_MS) % 8);
+ if (statusIndeterminate.children[i].style.borderTopColor == "") {
+ Array.prototype.slice
+ .call(statusIndeterminate.children)
+ .forEach((child) => {
+ child.style.borderTopColor = "";
+ });
+ statusIndeterminate.children[i].style.borderTopColor = "#dfdfdf";
+ }
+ }
+
+ function setStatusNotice(text) {
+ while (statusNotice.lastChild) {
+ statusNotice.removeChild(statusNotice.lastChild);
+ }
+ var lines = text.split("\n");
+ lines.forEach((line) => {
+ statusNotice.appendChild(document.createTextNode(line));
+ statusNotice.appendChild(document.createElement("br"));
+ });
+ }
+
+ function displayFailureNotice(err) {
+ var msg = err.message || err;
+ console.error(msg);
+ setStatusNotice(msg);
+ setStatusMode("notice");
+ initializing = false;
+ }
+
+ if (!Engine.isWebGLAvailable()) {
+ displayFailureNotice("WebGL not available");
+ } else {
+ setStatusMode("indeterminate");
+ engine
+ .startGame({
+ onProgress: function (current, total) {
+ if (total > 0) {
+ statusProgressInner.style.width =
+ (current / total) * 100 + "%";
+ setStatusMode("progress");
+ if (current === total) {
+ // wait for progress bar animation
+ setTimeout(() => {
+ setStatusMode("indeterminate");
+ }, 500);
+ }
+ } else {
+ setStatusMode("indeterminate");
+ }
+ },
+ })
+ .then(() => {
+ setStatusMode("hidden");
+ initializing = false;
+ }, displayFailureNotice);
+ }
+ })();
+ </script>
+ </body>
+</html>
diff --git a/networking/Network.gd b/networking/Network.gd
index 10a21e8..76df375 100644
--- a/networking/Network.gd
+++ b/networking/Network.gd
@@ -10,11 +10,11 @@ const HEADERS := {
"joinrequest": "J",
"hostrequest": "H",
"stopgame": "K",
- "ping": "P",
"signup": "C",
"signin": ">",
"relay": "R", # relay goes to both
"signal": "S", # signal is one way
+ "loadpgn": "L" # server telling me to load a pgn
}
const MOVEHEADERS := { # subheaders for HEADERS.move
@@ -25,7 +25,7 @@ const MOVEHEADERS := { # subheaders for HEADERS.move
"promote": "Q",
}
-const RELAYHEADERS := {"chat": "C", "startgame": "S"}
+const RELAYHEADERS := {"chat": "C"}
const SIGNALHEADERS := {"takeback": "T", "draw": "D", "resign": "R"} # subheaders for HEADERS.signal
var notation := ""
@@ -38,7 +38,7 @@ signal game_over(problem, isok)
signal connection_established
signal signal_recieved(what)
-## for accounts
+## for accounts(mostly)
signal signinresult(what)
signal signupresult(what)
@@ -52,11 +52,6 @@ func _ready() -> void:
ws.connect("connection_error", self, "_connection_error")
ws.connect("data_received", self, "_data_recieved")
ws.connect_to_url(url)
- var t := Timer.new()
- add_child(t)
- t.wait_time = 1
- t.start(1)
- t.connect("timeout", self, "ping")
func signin(data):
@@ -67,10 +62,6 @@ func signup(data):
send_packet(data, HEADERS.signup)
-func ping() -> void:
- send_packet("ping", HEADERS.ping)
-
-
func close() -> void:
ws.disconnect_from_host(0, "Close")
@@ -100,6 +91,14 @@ func signal(body, header: String, keyname := "body", _mainheader := HEADERS.sign
return data
+func join_game(game: String) -> void:
+ send_packet({"gamecode": game, "id": SaveLoad.files.id.data.id}, HEADERS.joinrequest)
+
+
+func host_game(game: String) -> void:
+ send_packet({"gamecode": game, "id": SaveLoad.files.id.data.id}, HEADERS.hostrequest)
+
+
func relay_signal(body, header: String, keyname := "body") -> Dictionary: # its really the same thing as signal()
return signal(body, header, keyname, HEADERS.relay)
@@ -124,12 +123,13 @@ func _data_recieved() -> void:
var relay: Dictionary = text
if relay.type in MOVEHEADERS.values():
emit_signal("move_data", text.move)
- else:
- match relay.type:
- RELAYHEADERS.startgame:
- emit_signal("start_game")
HEADERS.joinrequest:
emit_signal("join_result", text)
+ HEADERS.loadpgn:
+ emit_signal("start_game")
+ yield(get_tree().create_timer(.5), "timeout")
+ Log.info("load pgn " + text)
+ Globals.grid.play_pgn(text, true) # call deferred wont work since grid obj may be null
HEADERS.stopgame:
if !PacketHandler.leaving: # dont emit the signal if its a stophost thing (HACK)
emit_signal("game_over", text, true)
@@ -137,8 +137,6 @@ func _data_recieved() -> void:
HEADERS.signal:
var signal: Dictionary = text
emit_signal("signal_recieved", signal)
- HEADERS.ping:
- pass
HEADERS.signup:
emit_signal("signupresult", text)
HEADERS.signin:
@@ -156,3 +154,5 @@ func _process(_delta: float) -> void:
func send_packet(variant, header: String) -> void:
if ws.get_peer(1).is_connected_to_host():
ws.get_peer(1).put_var({"header": header, "data": variant})
+ else:
+ Log.err("not connected to server: packet %s not sent" % variant)
diff --git a/networking/PacketHandler.gd b/networking/PacketHandler.gd
index 28ee0e8..5529643 100644
--- a/networking/PacketHandler.gd
+++ b/networking/PacketHandler.gd
@@ -19,17 +19,15 @@ func return() -> void: # return to the void
if hosting:
leaving = true
Globals.network.stopgame("") # stop hosting
+ lobby.set_status("", true)
set_hosting(false)
lobby.set_buttons(true)
- lobby.set_status("", true)
func _ready() -> void:
- get_tree().set_auto_accept_quit(false)
if Utils.internet and get_tree().get_root().has_node("StartMenu"):
var net := Network.new()
Events.connect("go_back", self, "_handle_game_over")
- 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")
@@ -43,12 +41,12 @@ func _ready() -> void:
func requestjoin() -> void:
lobby.set_buttons(false)
- Globals.network.send_packet(Globals.network.game_code, Globals.network.HEADERS.joinrequest)
+ Globals.network.join_game(Globals.network.game_code)
func requesthost() -> void:
lobby.set_buttons(false)
- Globals.network.send_packet(Globals.network.game_code, Globals.network.HEADERS.hostrequest)
+ Globals.network.host_game(Globals.network.game_code)
func network_ready() -> void:
@@ -57,8 +55,7 @@ func network_ready() -> void:
func _on_join_result(accepted: String) -> void:
- if handle_result(accepted, "Joined!", false):
- Globals.network.relay_signal("startgame", Network.RELAYHEADERS.startgame)
+ handle_result(accepted, "Joined!", false)
func _on_host_result(accepted: String) -> void:
@@ -78,8 +75,8 @@ func handle_result(accepted: String, resultstring: String, team := true) -> bool
func _handle_game_over(error := "game over", isok := true) -> void:
Globals.network.stopgame(error)
Globals.reset_vars()
- if get_tree().get_root().has_node("Board"):
- get_tree().get_root().get_node("Board").queue_free()
+ if has_node("/root/Board"):
+ get_node("/root/Board").queue_free()
lobby.set_status(error, isok)
lobby.toggle(true)
lobby.set_buttons(true)
@@ -93,48 +90,3 @@ func _start_game() -> void:
lobby.toggle(false)
emit_signal("game_started")
lobby.set_buttons(false)
-
-
-func _on_data(data: String) -> void:
- Globals.add_turn()
- Log.debug([data, " recieved"])
- var san_to_add := data
- var mov = SanParse.parse(data)
- match mov.move_kind.type:
- Move.MoveKind.CASTLE:
- var side = 0 if Globals.turn else 7
- var rook: Rook
- var rook_goto: Vector2
- var kingpos = Vector2(4, side)
- var king: King = Piece.at_pos(kingpos)
- var king_goto: Vector2
- match mov.move_kind.data:
- Move.MoveKind.CASTLETYPES.KING_SIDE:
- rook = Piece.at_pos(Vector2(7, side))
- rook_goto = Vector2(5, side)
- king_goto = Vector2(6, side)
- Move.MoveKind.CASTLETYPES.QUEEN_SIDE:
- rook = Piece.at_pos(Vector2(0, side))
- rook_goto = Vector2(3, side)
- king_goto = Vector2(2, side)
- rook.moveto(rook_goto)
- king.castle(king_goto)
- Move.MoveKind.NORMAL:
- # this handles promotion, taking, enpassant, and moves.
- mov.make_long()
- var positions = mov.move_kind.data
- if mov.promotion != -1: # promotion part
- Globals.grid.print_matrix_pretty(Globals.grid.matrix)
- var promote_to = Utils.to_str(mov.promotion)
- Piece.at_pos(positions[0]).promote_to(promote_to, mov.is_capture, positions[1])
-
- elif mov.is_capture: # taking part
- if Piece.at_pos(positions[1]):
- Piece.at_pos(positions[0]).take(Piece.at_pos(positions[1]))
- elif mov.piece == SanParser.PAWN: # enpassant part
- var pawn: Pawn = Piece.at_pos(positions[0])
- pawn.passant(positions[1])
- san_to_add += " e.p."
- else: # a very normal move
- Piece.at_pos(positions[0]).moveto(positions[1])
- Utils.add_move(san_to_add)
diff --git a/pieces/King.gd b/pieces/King.gd
index 5411676..e0d56d7 100644
--- a/pieces/King.gd
+++ b/pieces/King.gd
@@ -75,7 +75,7 @@ func castleing(justcheckrooks := false) -> Array:
return moves
-func castle(position: Vector2) -> String:
+func castle(position: Vector2, instant := false) -> String:
var return_string := ""
if can_castle.size() == 1:
return_string = can_castle[0][3]
@@ -85,7 +85,7 @@ func castle(position: Vector2) -> String:
return_string = i[3]
break
can_castle.clear()
- moveto(position, true)
+ moveto(position, instant)
return return_string
diff --git a/pieces/Pawn.gd b/pieces/Pawn.gd
index f17bca3..0c44a70 100644
--- a/pieces/Pawn.gd
+++ b/pieces/Pawn.gd
@@ -40,19 +40,17 @@ func _exit_tree() -> void:
Globals.pawns.remove(find)
-func moveto(position: Vector2, real := true) -> void:
+func moveto(position: Vector2, instant := false) -> void:
# check if 2 step
- if real:
- if !just_double_stepped and !has_moved:
- if white and real_position.y - position.y == 2:
- just_double_stepped = true
- just_set = true
- if !white and position.y - real_position.y == 2:
- just_double_stepped = true
- just_set = true
- .moveto(position, real)
- if real:
- Globals.reset_halfmove()
+ if !just_double_stepped and !has_moved:
+ if white and real_position.y - position.y == 2:
+ just_double_stepped = true
+ just_set = true
+ if !white and position.y - real_position.y == 2:
+ just_double_stepped = true
+ just_set = true
+ .moveto(position, instant)
+ Globals.reset_halfmove()
func get_moves(_var := false, check_spots_check := true) -> PoolVector2Array:
@@ -77,11 +75,11 @@ static func can_promote(position: Vector2) -> bool:
return position.y >= 7 or position.y <= 0
-func passant(position: Vector2) -> void:
+func passant(position: Vector2, instant := false) -> void:
var to_take = position + Vector2(0, whiteint)
- at_pos(to_take).took()
+ at_pos(to_take).took(instant)
enpassant.resize(0)
- moveto(position)
+ moveto(position, instant)
func valid_to_passant_take(piece) -> bool:
@@ -137,9 +135,9 @@ func promote(position: Vector2, type: String) -> void:
sprites[i].show()
-func promote_to(promote_to: String, is_capture: bool, position: Vector2):
+func promote_to(promote_to: String, is_capture: bool, position: Vector2, instant := false):
if is_capture and at_pos(position):
- at_pos(position).took()
+ at_pos(position).took(instant)
clear_clicked()
Globals.grid.make_piece(position, piece(promote_to), white)
took()
diff --git a/pieces/Piece.gd b/pieces/Piece.gd
index 07b4b4a..55d680d 100644
--- a/pieces/Piece.gd
+++ b/pieces/Piece.gd
@@ -57,8 +57,7 @@ func algebraic_move_notation(position: Vector2) -> String:
func move(newpos: Vector2) -> void: # dont use directly; use moveto
tween.interpolate_property(self, "position", position, newpos * Globals.grid.piece_size, 0.3, Tween.TRANS_BACK)
- var signresult := sign(newpos.x * Globals.grid.piece_size.x - global_position.x)
- Log.debug("signresult: " + str(signresult))
+ var signresult := int(sign(newpos.x * Globals.grid.piece_size.x - global_position.x))
if signresult == 1:
rotate.play("Right")
elif signresult == -1:
@@ -67,10 +66,10 @@ func move(newpos: Vector2) -> void: # dont use directly; use moveto
tween.start()
-func moveto(pos: Vector2, real := true) -> void:
+func moveto(pos: Vector2, instant := false) -> void:
Globals.grid.matrix[real_position.y][real_position.x] = null
Globals.grid.matrix[pos.y][pos.x] = self
- if real:
+ if !instant:
real_position = pos
move(real_position)
SoundFx.play("Move")
@@ -184,7 +183,8 @@ static func set_circle(positions: Array, type := "move") -> void:
func checkcheck(pos) -> bool: # moves to position, then checks if your king is in check
# TODO: figure out why this function isnt working with can_move()
var mat: Array = Globals.grid.matrix.duplicate(true) # make a copy of the matrix
- moveto(pos, false) # move to the position
+ Globals.grid.matrix[real_position.y][real_position.x] = null # remove the piece from the matrix
+ Globals.grid.matrix[pos.y][pos.x] = self # move the piece to the new position
if Globals.grid.check_in_check(): # if you are still in check
Globals.grid.matrix = mat # revert changes on the matrix
return true
@@ -198,17 +198,18 @@ static func is_on_board(vector: Vector2) -> bool: # limit the vector to the boa
return true
-func take(piece: Piece) -> void:
+func take(piece: Piece, instant := false) -> void:
clear_clicked()
- piece.took()
- moveto(piece.real_position, true)
+ piece.took(instant)
+ moveto(piece.real_position, instant)
Globals.reset_halfmove()
-func took() -> void: # called when piece is taken
- SoundFx.play("Capture")
+func took(instant := false) -> void: # called when piece is taken
Globals.grid.matrix[real_position.y][real_position.x] = null
- anim.play("Take")
+ if !instant:
+ SoundFx.play("Capture")
+ anim.play("Take")
func set_frame(value := true) -> void:
diff --git a/project.godot b/project.godot
index 64e8663..e0b53df 100644
--- a/project.godot
+++ b/project.godot
@@ -79,11 +79,6 @@ _global_script_classes=[ {
"language": "GDScript",
"path": "res://ui/Lobby.gd"
}, {
-"base": "Node",
-"class": "Log",
-"language": "GDScript",
-"path": "res://ui/Log.gd"
-}, {
"base": "Resource",
"class": "Move",
"language": "GDScript",
@@ -179,7 +174,6 @@ _global_script_class_icons={
"King": "res://assets/pieces/california/wK.png",
"Knight": "res://assets/pieces/california/wN.png",
"Lobby": "",
-"Log": "",
"Move": "",
"NetManager": "",
"Network": "",
@@ -222,6 +216,7 @@ PacketHandler="*res://networking/PacketHandler.gd"
Debug="*res://Debug.gd"
SanParse="*res://SanParse/SanParse.gd"
Pgn="*res://PGN/PGN.gd"
+Log="*res://Log.gd"
[debug]
diff --git a/saveload.gd b/saveload.gd
index 7d54b5f..455cc70 100644
--- a/saveload.gd
+++ b/saveload.gd
@@ -14,9 +14,11 @@ const default_settings_data = {
"rainbow": true
}
+const default_id_data = {"id": "", "name": "", "country": "rainbow", "password": ""}
+
var files := {
"settings": {"file": settings_file, "data": default_settings_data.duplicate(true)},
- "id": {"file": id, "data": {"id": "", "name": "", "country": "rainbow", "password": ""}}
+ "id": {"file": id, "data": default_id_data.duplicate()}
} # file types
diff --git a/test.gd b/test.gd
index 3e08022..735500b 100644
--- a/test.gd
+++ b/test.gd
@@ -65,9 +65,12 @@ class TestSan:
func test_pawn_capture_long():
assert_capture("e3xd4", Vector2(4, 5), Vector2(3, 4), PAWN)
- func test_piece_capture():
+ func test_row_piece_capture():
assert_capture("R1xh3", Vector2(-1, 7), Vector2(7, 5), ROOK)
+ func test_piece_capture():
+ assert_capture("Nxe4", Vector2(-1, -1), Vector2(4, 4), KNIGHT)
+
func test_piece_capture_file():
assert_capture("Rexh3", Vector2(4, -1), Vector2(7, 5), ROOK)
@@ -97,6 +100,7 @@ class TestSan:
test_piece_rank()
test_piece_long()
test_pawn_capture()
+ test_row_piece_capture()
test_pawn_capture_promotion()
test_pawn_capture_long()
test_piece_capture()
@@ -107,5 +111,5 @@ class TestSan:
func _ready():
- if Debug.is_debug():
+ if Debug.debug:
TestSan.new()
diff --git a/ui/Log.gd b/ui/Log.gd
deleted file mode 100644
index 83e3e07..0000000
--- a/ui/Log.gd
+++ /dev/null
@@ -1,31 +0,0 @@
-extends Node
-class_name Log
-
-
-static func info(information) -> void: # logs the input string
- print(to_str(information))
-
-
-static func debug(information) -> void: # logs the input string on debug builds
- if OS.is_debug_build():
- print(to_str(information))
-
-
-static func err(information) -> void: # logs the input string to stderr
- printerr(information)
-
-
-static func to_str(arg) -> String:
- if typeof(arg) == TYPE_ARRAY:
- return arr2str(arg)
- elif typeof(arg) == TYPE_STRING:
- return arg
- else:
- return str(arg)
-
-
-static func arr2str(arr: Array) -> String:
- var string := ""
- for i in arr:
- string += str(i) + " "
- return string
diff --git a/ui/Settings.gd b/ui/Settings.gd
index 24c148a..04fffa0 100644
--- a/ui/Settings.gd
+++ b/ui/Settings.gd
@@ -40,21 +40,17 @@ func update_button_visuals(set: Dictionary = settings) -> void:
func _ready() -> void:
if OS.has_feature("HTML5"):
borderlessbutton.queue_free()
- board_color1.color = settings.board_color1
- board_color2.color = settings.board_color2
for i in piece_sets: # add the items
piece_set_button.add_icon_item(load("res://assets/pieces/" + i + "/wP.png"), i)
piece_set_button.selected = Array(piece_sets).find(settings.piece_set)
- Globals.piece_set = piece_sets[piece_set_button.selected]
- Globals.board_color1 = settings.board_color1
- Globals.board_color2 = settings.board_color2
+ update_vars()
update_button_visuals()
func update_vars() -> void:
- Globals.piece_set = piece_sets[piece_set_button.selected]
- Globals.board_color1 = board_color1.color
- Globals.board_color2 = board_color2.color
+ Globals.piece_set = settings.piece_set
+ Globals.board_color1 = settings.board_color1
+ Globals.board_color2 = settings.board_color2
OS.vsync_enabled = settings.vsync
OS.window_fullscreen = settings.fullscreen
OS.window_borderless = settings.borderless
diff --git a/ui/StartMenu.tscn b/ui/StartMenu.tscn
index 0f880c0..b0875cf 100644
--- a/ui/StartMenu.tscn
+++ b/ui/StartMenu.tscn
@@ -1,4 +1,4 @@
-[gd_scene load_steps=9 format=2]
+[gd_scene load_steps=10 format=2]
[ext_resource path="res://ui/theme/main.tres" type="Theme" id=1]
[ext_resource path="res://ui/StartMenu.gd" type="Script" id=2]
@@ -7,6 +7,7 @@
[ext_resource path="res://assets/ui/verdana-bold.ttf" type="DynamicFontData" id=5]
[ext_resource path="res://ui/account/Account.tscn" type="PackedScene" id=6]
[ext_resource path="res://test.gd" type="Script" id=7]
+[ext_resource path="res://PGN/test_pgns.tscn" type="PackedScene" id=8]
[sub_resource type="DynamicFont" id=1]
size = 400
@@ -56,6 +57,9 @@ margin_top = 90.0
margin_right = -30.0
margin_bottom = -30.0
+[node name="tests" parent="tabs" instance=ExtResource( 8 )]
+visible = false
+
[node name="quit" type="Button" parent="tabs"]
visible = false
anchor_right = 1.0
diff --git a/ui/account/Account.gd b/ui/account/Account.gd
index 5ee24cf..19383a0 100644
--- a/ui/account/Account.gd
+++ b/ui/account/Account.gd
@@ -4,11 +4,14 @@ onready var flags: PoolStringArray = ["rainbow"]
onready var flagchoice: OptionButton = $choose/signup/flag
onready var data: Dictionary = SaveLoad.files.id.data
onready var status: StatusLabel = $StatusLabel
-onready var signup: UsernamePass = $choose/signup/usernamepass
-onready var signin: UsernamePass = $choose/signin/usernamepass
-var autologin = false
+onready var tabs := {
+ "signup": $choose/signup/usernamepass,
+ "signin": $choose/signin/usernamepass,
+}
+
var signed_in = false
+var autologin = true
func _ready():
@@ -21,40 +24,55 @@ func _ready():
func attempt_autologin():
- autologin = true
if data.name and data.password:
Globals.network.signin(data)
- Log.info("Attempting autologin")
- autologin = false
+
+
+func _on_signin_pressed():
+ $choose/signin/signinbutton.disabled = true
+ update_data(tabs.signin.username, tabs.signin.pw)
+ Globals.network.signin(data)
func _on_signin_result(result):
+ var status_set = !autologin
+ autologin = false
+ $choose.show()
$choose/signin/signinbutton.disabled = false
if typeof(result) == TYPE_STRING: # ew, error, get it away from me
- Log.err(result)
- return
+ return reset(result, status_set)
data.id = result.id
data.country = result.country
- save_data()
- status.set_text("Sign in sucessfull!")
- signed_in = true # yay
+ _after_result()
+
+
+func _on_signup_pressed():
+ $choose/signup/signupbutton.disabled = true
+ update_data(tabs.signup.username, tabs.signup.pw)
+ Globals.network.signup(data)
func _on_signup_result(result: String):
$choose/signup/signupbutton.disabled = false
if "err:" in result: # ew error go awway
- Log.err(result)
- return
+ return reset(result)
data.id = result
+ _after_result()
+
+
+func reset(reason: String, set_status := true):
+ if set_status:
+ status.set_text(reason)
+ data = SaveLoad.default_id_data
save_data()
- status.set_text("Sign up sucessfull ( you are now logged in )!")
- signed_in = true # yay
+ $choose.show()
-func _on_signup_pressed():
- $choose/signup/signupbutton.disabled = true
- update_data(signup.username, signup.pw)
- Globals.network.signup(data)
+func _after_result():
+ save_data()
+ status.set_text("Signed in to " + SaveLoad.files.id.data.name)
+ signed_in = true # yay
+ $choose.hide()
func update_data(username, pw):
@@ -69,7 +87,7 @@ func save_data():
SaveLoad.save("id")
-func _on_signin_pressed():
- $choose/signin/signinbutton.disabled = true
- update_data(signin.username, signin.pw)
- Globals.network.signin(data)
+func _on_choose_tab_changed(tab: int):
+ var new: VBoxContainer = $choose.get_children()[tab].get_node("usernamepass")
+ var old = $choose.get_children()[1 if tab == 0 else 0].get_node("usernamepass")
+ new.update_data(old.export_data())
diff --git a/ui/account/Account.tscn b/ui/account/Account.tscn
index ae0e072..04dba2c 100644
--- a/ui/account/Account.tscn
+++ b/ui/account/Account.tscn
@@ -41,6 +41,7 @@ margin_bottom = 140.0
script = ExtResource( 7 )
[node name="choose" type="TabContainer" parent="."]
+visible = false
margin_left = 177.0
margin_top = 155.0
margin_right = 1245.0
@@ -116,5 +117,6 @@ size_flags_horizontal = 4
enabled_focus_mode = 0
text = "sign in"
+[connection signal="tab_changed" from="choose" to="." method="_on_choose_tab_changed"]
[connection signal="pressed" from="choose/signup/signupbutton" to="." method="_on_signup_pressed"]
[connection signal="pressed" from="choose/signin/signinbutton" to="." method="_on_signin_pressed"]
diff --git a/ui/account/usernamepass.gd b/ui/account/usernamepass.gd
index 387b806..851152f 100644
--- a/ui/account/usernamepass.gd
+++ b/ui/account/usernamepass.gd
@@ -3,3 +3,24 @@ class_name UsernamePass
onready var username = $Username
onready var pw = $H/Password
+
+
+func update_data(data: Dictionary) -> void:
+ username.text = data.user
+ username.caret_position = data.user_caret
+ pw.text = data.pasw
+ pw.caret_position = data.pasw_caret
+
+
+func export_data() -> Dictionary:
+ return {
+ "user": username.text,
+ "user_caret": username.caret_position,
+ "pasw": pw.text,
+ "pasw_caret": pw.caret_position
+ }
+
+
+func set_enabled(enabled: bool) -> void:
+ username.editable = enabled
+ pw.editable = enabled
diff --git a/ui/animations/LoadingAnimation.tscn b/ui/animations/LoadingAnimation.tscn
new file mode 100644
index 0000000..b92cfc5
--- /dev/null
+++ b/ui/animations/LoadingAnimation.tscn
@@ -0,0 +1,9 @@
+[gd_scene load_steps=2 format=2]
+
+[ext_resource path="res://assets/ui/whitespace.png" type="Texture" id=1]
+
+[node name="LoadingAnimation" type="TextureRect"]
+anchor_right = 1.0
+anchor_bottom = 1.0
+texture = ExtResource( 1 )
+expand = true