diff --git a/godot_ship/project.godot b/godot_ship/project.godot index 658c27a..1e4cd1c 100644 --- a/godot_ship/project.godot +++ b/godot_ship/project.godot @@ -20,7 +20,7 @@ MessageBus="*res://script/Message Bus.gd" AudioBus="*res://script/audio controller/Audio Bus.gd" OptionsController="*res://script/options/OptionsController.gd" AudioController="*res://scenes/AudioController.tscn" -Network="*res://script/network/Network.gd" +Net="*res://script/network/Net.gd" [display] @@ -31,6 +31,10 @@ window/per_pixel_transparency/allowed=true window/stretch/mode="viewport" window/stretch/aspect="keep" +[global] + +verbose=false + [input] ui_left={ diff --git a/godot_ship/script/game/Gameplay/Game.gd b/godot_ship/script/game/Gameplay/Game.gd index 705f4a1..41ff096 100644 --- a/godot_ship/script/game/Gameplay/Game.gd +++ b/godot_ship/script/game/Gameplay/Game.gd @@ -5,13 +5,13 @@ var dark_theme = load("res://dark_theme.tres") # Path to Player class, for instantiating new Players in code -onready var Player = preload("res://scenes/Game/Player.tscn") +var Player = preload("res://scenes/Game/Player.tscn") -onready var Victory = preload("res://scenes/Game/Victory.tscn") +var Victory = preload("res://scenes/Game/Victory.tscn") # Array of instances of the Player class; stores the Players -var players = {} # = player1, player2, ... +var players = [] # = player1, player2, ... var players_ready = [] # turn counter var turn = 0 @@ -37,56 +37,40 @@ func _ready(): game_setup() # Function used to keep track of which players are ready -mastersync func player_ready(): +func player_ready(): var who = get_tree().get_rpc_sender_id() - if get_tree().is_network_server() and who in Network.peer_info and not who in players_ready: + if get_tree().is_network_server() and who in Net.peer_info and not who in players_ready: print ("ASSERT SUCCESS") players_ready.append(who) - if players_ready.size() == Network.peer_info.size(): + if players_ready.size() == Net.peer_info.size(): rpc("game_start") # Member functions: # game_start: starts the game -func game_setup(): +sync func game_setup(): # If there's no server connected, create one - if not Network.connected: + if not Net.connected: # TODO: Create a fake peer who we can automate, for single-player mode - Network.start_server() - network_id = Network.get_network_id() - var count = 0 - # Create players for every player in Network.peer_info - for k in Network.peer_info.keys(): + Net.start_host() + network_id = Net.get_network_id() + # Create players for every player in Net.peer_info + for k in Net.peer_info.keys(): # Create a new player var player = Player.instance() - # Set the player's opponent, for now - player.opponent_pid = Network.peer_info.keys()[1 - count] # Give the player a recognizable name, like "1", instead of "@@97" player.name = str(k) # The player controls themselves player.set_network_master(k) # Add the player to the list of players - players[k] = player + players.append(player) # Add the player to the scene tree add_child(player) - count += 1 pass - # Connect to your own player_ready signal - players[network_id].connect("player_ready", self, "_on_player_ready") - # Have your player set up the board: - players[network_id].set_up_begin() -mastersync func game_start(): +func game_start(): # Make sure we're the server - assert(get_tree().is_network_server()) - while not winner: - for id in players.keys(): - # TODO: RPC always returns nothing. - # Figure out how to work around this. - var hit = players[id].rpc_id(id, "turn_start") - var result = players[hit["id"]].rpc_id(hit["id"], "hit", hit["target"]) - players[id].rpc_id(id, "mark", hit["target"], result) - pass + pass func _on_player_ready(): print ("_on_player_ready") diff --git a/godot_ship/script/game/Gameplay/Player.gd b/godot_ship/script/game/Gameplay/Player.gd index 382bfd0..8b87022 100644 --- a/godot_ship/script/game/Gameplay/Player.gd +++ b/godot_ship/script/game/Gameplay/Player.gd @@ -3,7 +3,6 @@ extends Node # Emitted when the player is ready signal player_ready - # Preloaded assets, to be used later # Path to Board class, for instantiating new Boards in code var Board = preload("res://scenes/Game/Board.tscn") @@ -12,33 +11,33 @@ var Setup = preload("res://scenes/Game/Setup.tscn") # Path to Fire menu, so the player may fire on the opponent var Fire = preload("res://scenes/Game/Fire.tscn") -var pid # Player ID +# Members +var pid # Player ID var board # Board var fire_at_position # Position to fire at -var opponent_pid # PID of opponent # Called when the node enters the scene tree for the first time. func _ready(): # Set the player ID according to which network peer ID we are pid = int(name) - board = Board.instance() -mastersync func set_up_begin(): +func set_up_begin(): var setup = Setup.instance() setup.connect("board_ready", self, "set_up") add_child(setup) + board = Board.instance() # Member functions: # hit: Called when opponent fires on us. # Update internal state, and return hit/miss/sunk -mastersync func hit(pos): +func hit(pos): var res = board.hit(pos) return res # mark: Called when the opponent returns hit/miss/sunk # Update internal state, return ack/nak -mastersync func mark(pos, value): +func mark(pos, value): # Mark the position on the top board board.fire(pos, value) @@ -62,7 +61,7 @@ func set_up(ships): # turn_start: start player's turn # Initiates the player's turn, and blocks until the player selects a location to fire upon # returns: fire = [player id, target coordinates] -mastersync func turn_start(): +func turn_start(): print("turn_start") var fire = Fire.instance() @@ -70,10 +69,9 @@ mastersync func turn_start(): yield(fire, "fire_at") while not fire_at_position: pass - var player_id = opponent_pid var target = fire_at_position fire_at_position = null - return {"id": player_id, "target": target} + return target # getBoard: returns the player's board # returns: board diff --git a/godot_ship/script/network/Network.gd b/godot_ship/script/network/Net.gd similarity index 52% rename from godot_ship/script/network/Network.gd rename to godot_ship/script/network/Net.gd index 770e49a..188b552 100644 --- a/godot_ship/script/network/Network.gd +++ b/godot_ship/script/network/Net.gd @@ -3,36 +3,72 @@ extends Node const DEFAULT_PORT = 35879 const LOCALHOST = "127.0.0.1" +signal incoming + +class Mail: + var from + var message + var type + func _init(f, m, t): + from = f; message = m; type = t + enum {REPLY, REQUEST} + # Store peer info in a dictionary, by player ID var peer_info = {} # Store this player's hostname var local_info = {"hostname": ""} var connected = false +var hosting = false + +# FIFO queue of Mails +var inbox = [] # Network -- handles server and client setup, and facilitates communication between the two +# receive: Called when an incoming message is received +# item: The message received from the sender +remote func receive(mail:Mail): + # Get the sender's ID and force letter to be properly addressed + mail.from = get_tree().get_rpc_sender_id() + print_debug(mail.from, mail.message, mail.type) + # Sent it off to anything that expects mail + emit_signal("incoming", mail) + +func send(id, mail:Mail): + # Make the recipient receive the mail + rpc_id(id, "receive", mail) + # start_server: Host the game # port: TCP port # max_players: Largest number of players allowed to connect at a time -func start_server(port = DEFAULT_PORT, max_players = 2): +func start_host(port = DEFAULT_PORT, max_players = 2): get_hostname() peer_info[1] = local_info var peer = NetworkedMultiplayerENet.new() peer.create_server(port, max_players) get_tree().network_peer = peer connected = true + hosting = true return -func connect_server(ip = LOCALHOST, port = DEFAULT_PORT): +# connect_server: Connect to a host +func connect_host(ip = LOCALHOST, port = DEFAULT_PORT): get_hostname() var peer = NetworkedMultiplayerENet.new() peer.create_client(ip, port) get_tree().network_peer = peer - return -func disconnect_server(): - get_tree().network_peer = null +func disconnect_host(): + # Set state to disconnected connected = false + hosting = false + # Attempt disconnection + if get_tree().network_peer: + get_tree().network_peer.close_connection() + # Disconnect + get_tree().network_peer = null + # Clear peer info + peer_info = {} func get_hostname(): if local_info["hostname"] == "": @@ -50,11 +86,12 @@ func get_ip(): func _ready(): var _trash - _trash = get_tree().connect("network_peer_connected", self, "_peer_connected") + _trash = get_tree().connect("network_peer_connected", self, "_peer_connected" ) _trash = get_tree().connect("network_peer_disconnected", self, "_peer_disconnected") - _trash = get_tree().connect("connected_to_server", self, "_server_connected") - _trash = get_tree().connect("connection_failed", self, "_connection_fail") - _trash = get_tree().connect("server_disconnected", self, "_server_disconnected") + _trash = get_tree().connect("connected_to_server", self, "_host_connected" ) + _trash = get_tree().connect("server_disconnected", self, "_host_disconnected") + _trash = get_tree().connect("connection_failed", self, "_connection_fail" ) + func _peer_connected(id): rpc_id(id, "register_peer", local_info) @@ -64,20 +101,21 @@ func _peer_disconnected(id): peer_info.erase(id) pass -func _server_connected(): + +func _host_connected(): # On connection to the server, you get a global network id # Save your info at this id peer_info[get_network_id()] = local_info + # Set state to connected connected = true - pass -func _server_disconnected(): - connected = false - pass +func _host_disconnected(): + # Ensure host is disconnected + disconnect_host() func _connection_fail(): - connected = false - pass + # Ensure Net state is clear + disconnect_host() remote func register_peer(info): # Save player information under the sender id's peer info