Skip to content

Commit

Permalink
Add networking capability
Browse files Browse the repository at this point in the history
  • Loading branch information
oerc0122 committed Mar 21, 2021
1 parent 1d91f04 commit da4a003
Show file tree
Hide file tree
Showing 14 changed files with 299 additions and 142 deletions.
4 changes: 2 additions & 2 deletions Board.gd
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ func add_piece(colour, type, pos, has_moved:bool = false):
null.get_node("Crash")

var piece = PIECE.instance()
add_child(piece)
piece.init(colour, type)

# Find used names
Expand All @@ -39,7 +40,6 @@ func add_piece(colour, type, pos, has_moved:bool = false):
trial_name = piece.get_ID()+str(i)
piece.ID = trial_name

add_child(piece)
update_piece(piece, pos)
piece.moved = has_moved

Expand All @@ -61,7 +61,7 @@ func update_piece(piece, location: Vector2):
self.positions[piece.gridPos] = piece
piece.move_to_pos()

func move_piece(pos:Vector2, newLoc:Vector2):
remotesync func move_piece(pos:Vector2, newLoc:Vector2):
if not pos in self.positions:
emit_signal("error","Cannot move piece", "No piece in position")
return
Expand Down
129 changes: 73 additions & 56 deletions FileParser.gd
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,22 @@ var halfTurnRER = ("(?<turn>[0-9]+)\\.{3}\\s*" +
"(?:"+commentRER+")?"
)

var rawCommentRE = RegEx.new()
var suggestionRE = RegEx.new()
var nagRE = RegEx.new()
var tagRE = RegEx.new()
var turnRE = RegEx.new()
var finalRE = RegEx.new()
var plyRE = RegEx.new()

func _init():
rawCommentRE.compile(rawCommentRER)
suggestionRE.compile(suggestionRER)
nagRE.compile(NAGRER)
tagRE.compile(tagRER)
turnRE.compile("(?:%s|%s)" % [fullTurnRER, halfTurnRER])
finalRE.compile(finalRER)
plyRE.compile(plyRER)

func read(filepath) -> Array:
self.path = filepath
Expand All @@ -42,22 +58,13 @@ func read(filepath) -> Array:
return []
var content := file.get_as_text()
file.close()
var matches = parse_matches(content)
for game in matches:
if not "DisplayName" in game:
game.data["DisplayName"] = filepath.get_file()
return matches

var rawCommentRE = RegEx.new()
rawCommentRE.compile(rawCommentRER)
var suggestionRE = RegEx.new()
suggestionRE.compile(suggestionRER)
var nagRE = RegEx.new()
nagRE.compile(NAGRER)
var tagRE = RegEx.new()
tagRE.compile(tagRER)
var turnRE = RegEx.new()


turnRE.compile("(?:%s|%s)" % [fullTurnRER, halfTurnRER])
var finalRE = RegEx.new()
finalRE.compile(finalRER)

func parse_matches(content: String) -> Array:
content = rawCommentRE.sub(content, "{$comment}", true).replace("\n", " ").strip_escapes()
# content = suggestionRE.sub(content, "", true) # For now ignore suggestions, later may want to branch
content = nagRE.sub(content, "", true) # Remove NAGing
Expand All @@ -72,49 +79,61 @@ func read(filepath) -> Array:
var games = []
for game in matches:
game = handle_branches(game)
var loaded = Game.new()
loaded.path = filepath.get_file()
for tag in tagRE.search_all(game):
loaded.data[tag.get_string("key")] = tag.get_string("value")
game = game.replace(tag.get_string(), "")

var turns = turnRE.search_all(game)
var parsed_turns = []
for turn in range(len(turns)): # Stitch half turns
var currTurn = turns[turn]
if currTurn.get_string("BlackLocation").empty() and currTurn.get_string("BlackCastle").empty():
pass # Skip: handled by stitch
elif currTurn.get_string("WhiteLocation").empty() and currTurn.get_string("WhiteCastle").empty():
var prevTurn = turns[turn-1]
var stitch = self.stitch_turns(prevTurn, currTurn)
parsed_turns.push_back(turnRE.search(stitch))
else:
parsed_turns.push_back(currTurn)
turns.clear() # Clean up

var currTurn : Turn
if not "SetUp" in loaded.data:
currTurn = Turn.new()
currTurn.raw = "0. Start game"
else:
if not "FEN" in loaded.data:
emit_signal("error", "Bad input pgn", "FEN data not found")
currTurn = parse_FEN(loaded.data["FEN"])
currTurn.raw = "0. Start game"
currTurn.ID = "Start Game"

loaded.turns = [currTurn]

for turn in parsed_turns:
currTurn = Turn.new(Turn.COLOUR.WHITE, currTurn.positions, turn, currTurn.promotions)
loaded.turns.push_back(currTurn)
currTurn = Turn.new(Turn.COLOUR.BLACK, currTurn.positions, turn, currTurn.promotions)
loaded.turns.push_back(currTurn)
var loaded = parse_SAN(game)
games.push_back(loaded)

emit_signal("read", games)
return games

func parse_SAN(SAN: String) -> Game:
var game = Game.new()

for tag in tagRE.search_all(SAN):
game.data[tag.get_string("key")] = tag.get_string("value")
SAN = SAN.replace(tag.get_string(), "")

var turns = turnRE.search_all(SAN)
var parsed_turns = []
for turn in range(len(turns)): # Stitch half turns
var currTurn = turns[turn]
if not has_turn(currTurn, "Black"):
pass # Skip: handled by stitch
elif not has_turn(currTurn, "White"):
var prevTurn = turns[turn-1]
var stitch = self.stitch_turns(prevTurn, currTurn)
parsed_turns.push_back(turnRE.search(stitch))
else:
parsed_turns.push_back(currTurn)

if not has_turn(turns[-1], "Black"): # Catch leftover
parsed_turns.push_back(turns[-1])
turns.clear() # Clean up

var currTurn : Turn
if not "SetUp" in game.data:
currTurn = Turn.new()
currTurn.raw = "0. Start game"
else:
if not "FEN" in game.data:
emit_signal("error", "Bad input pgn", "FEN data not found")
currTurn = parse_FEN(game.data["FEN"])
currTurn.raw = "0. Start game"
currTurn.ID = "Start Game"

game.turns = [currTurn]

for turn in parsed_turns:
currTurn = Turn.new(Turn.COLOUR.WHITE, currTurn.positions, turn, currTurn.promotions)
game.turns.push_back(currTurn)
if has_turn(turn, "Black"): # Catch leftover
currTurn = Turn.new(Turn.COLOUR.BLACK, currTurn.positions, turn, currTurn.promotions)
game.turns.push_back(currTurn)
return game

func has_turn(turn: RegExMatch, colour: String):
return not (turn.get_string(colour+"Location").empty() and
turn.get_string(colour+"Castle").empty())

func parse_FEN(FEN: String):
# Parse FEN notation of the form:
# rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1
Expand Down Expand Up @@ -145,8 +164,6 @@ func parse_FEN(FEN: String):
return turn

func stitch_turns(prevTurn: RegExMatch, currTurn: RegExMatch) -> String:
var plyRE = RegEx.new()
plyRE.compile(plyRER)
if prevTurn.get_string("turn") != currTurn.get_string("turn"):
null.get_node("Crash")

Expand Down
23 changes: 21 additions & 2 deletions Game.gd
Original file line number Diff line number Diff line change
@@ -1,9 +1,28 @@
extends Resource
class_name Game

var data := {}
var data := {"DisplayName": "New Game"}
var turns := [Turn.new()]
var path := ""

func _to_string() -> String:
var string = ""
for elem in data:
string += '["{elem}" "{data}"]\n'.format({"elem":elem, "data":data[elem]})
string += "\n"
var capture: String
var promote: String
var currTurn: Turn
for turn in range(1, len(turns), 2):
string += "{turn}. ".format({"turn":(turn/2)+1})
currTurn = turns[turn]
string += currTurn.to_string()+" "
if turn+1 < len(turns):
currTurn = turns[turn+1]
string += currTurn.to_string()+" "

string += data.get("Result", "0-0")

return string

func nTurns() -> int:
return len(self.turns)
61 changes: 61 additions & 0 deletions Lobby.gd
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
extends Node

signal sync_games(id)

const PLAYERS = 2
const HOST_ID = 1
var pw: String = ""
var my_id: int
var targetIP: String
var targetPort: int

func _ready() -> void:
get_tree().connect("network_peer_connected", self, "_player_connected")
get_tree().connect("network_peer_disconnected", self, "_close_connection")
get_tree().connect("connection_failed", self, "_connection_failed")
get_tree().connect("server_disconnected", self, "_server_disconnected")
self._close_connection()

func host(port: int, pwIn: String):
_close_connection() # In case of restart
var peer = NetworkedMultiplayerENet.new()
peer.create_server(port, PLAYERS)
get_tree().set_network_peer(peer)
my_id = HOST_ID
self.pw = pwIn

func client(ip: String, port: int, pwIn: String):
_close_connection() # In case of restart
self.targetIP = ip
self.targetPort = port
self.pw = pwIn
get_tree().connect("connected_to_server", self, "_connected_to_server")
var peer = NetworkedMultiplayerENet.new()
peer.create_client(self.targetIP, self.targetPort)
get_tree().set_network_peer(peer)

func _check_pw(id, pwIn):
if pwIn != pw:
rpc_id(id, "error", "Cannot join", "Passwords don't match")
get_tree().network_peer.disconnect_peer(id)

remote func _close_connection():
if get_tree().network_peer:
get_tree().network_peer.close_connection()
var peer = NetworkedMultiplayerENet.new()
peer.create_server(10000, 1)
get_tree().set_network_peer(peer)

func _player_connected(id: int):
emit_signal("sync_games", id)

func _connection_failed():
_close_connection()
error("Connection failed", "Could not establish connection to %s:%d" % [self.targetIP, self.targetPort])

func _connected_to_server():
self.my_id = get_tree().get_network_unique_id()
rpc_id(HOST_ID, "check_pw", self.my_id, self.pw)

func error(title, message):
get_parent().error(title, message)
31 changes: 30 additions & 1 deletion MainGame.gd
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
extends Node

var currTurn = 0
signal turn_updated(turn, game)
signal new_turn(game, turn)
signal new_game(game)
signal reload_games

var games := []
var currGameIndex = 0
var currGame : Game
var currPlayer = 0
var currTurn = 0
var tmp

func _input(event: InputEvent) -> void:
if event.is_action_pressed('ui_right'):
Expand All @@ -28,6 +31,9 @@ func prev_turn():
load_turn(currTurn)

func load_turn(turn: int, loadGame: int = -1):
rpc("_load_turn", turn, loadGame)

remotesync func _load_turn(turn: int, loadGame: int = -1):
if loadGame < 0:
loadGame = currGameIndex
if len(games) < loadGame-1:
Expand Down Expand Up @@ -82,5 +88,28 @@ func branch(toCopy: Game = null, turn: int = -1) -> Game:
copy.path = basename + ":" + str(num+1)
return copy

master func sync_games(id: int = 0):
if get_tree().is_network_server():
var encode = ""
for game in self.games:
encode += game.to_string()+"\n\n"

if not id:
rpc("set_games", encode, self.currGameIndex, self.currTurn)
else:
rpc_id(id, "set_games", encode, self.currGameIndex, self.currTurn)

remote func set_games(gameBytes: String, gameIdx: int, turn: int):
var FP = FileParser.new()
self.games = FP.parse_matches(gameBytes)
emit_signal("reload_games")
load_turn(turn, gameIdx)

func _error(title, message):
get_tree().get_root().get_node("Root").error(title, message)

func _on_TopMenu_save_game(file) -> void:
var outFile = File.new()
outFile.open(file, File.WRITE)
outFile.store_string(currGame.to_string())
outFile.close()
9 changes: 6 additions & 3 deletions Piece.gd
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,10 @@ var ID : String

func _process(delta: float) -> void:
if $Draggable.dragging:
self.position = get_global_mouse_position()
rpc_unreliable("set_pos", get_global_mouse_position())

remotesync func set_pos(newPos: Vector2):
self.position = newPos

func init(colour: int, type: int) -> void:
self.colour = colour
Expand Down Expand Up @@ -85,8 +88,8 @@ func can_move(newLoc, capture: bool, boardIn) -> bool:
func _on_Draggable_stopdrag() -> void:
var mousePos = get_global_mouse_position()
var newPos = board.world_to_map(mousePos)
board.move_piece(self.gridPos, newPos)
move_to_pos()
board.rpc("move_piece", self.gridPos, newPos)
rpc("move_to_pos")

func move_to_pos():
self.position = board.map_to_world(self.gridPos) + board.TILE_OFFSET
Expand Down
18 changes: 2 additions & 16 deletions Root.gd
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,7 @@ extends Node

onready var UIMain = $VBoxContainer/HBoxContainer/UIPanel
onready var MainGame = $VBoxContainer/HBoxContainer/ViewportContainer/MainGame
onready var GamesList = $GamesDialog/ScrollContainer/VBoxContainer


func host(port: int, players: int):
var peer = NetworkedMultiplayerENet.new()
peer.create_server(port, players)
get_tree().network_peer = peer

func client(ip: int, port: int):
var peer = NetworkedMultiplayerENet.new()
peer.create_client(ip, port)
get_tree().network_peer = peer

func close_connection(id: int = -1):
get_tree().network_peer = null
onready var GamesList = $GamesDialog/ScrollContainer/VBoxContainer

func new_game(game: Game):
MainGame.new_game(game)
Expand Down Expand Up @@ -46,7 +32,7 @@ func _on_TopMenu_load_game(file) -> void:

func _on_TopMenu_new_game() -> void:
var game = Game.new()
game.path = "New game"
game.data["DisplayName"] = "New game"
new_game(game)

func add_button(game: Game):
Expand Down
Loading

0 comments on commit da4a003

Please sign in to comment.