summaryrefslogtreecommitdiff
path: root/scripts
diff options
context:
space:
mode:
Diffstat (limited to 'scripts')
-rw-r--r--scripts/Airplane.gd (renamed from scripts/Plane.gd)3
-rw-r--r--scripts/Board.gd30
-rw-r--r--scripts/GameTable.gd161
-rw-r--r--scripts/Globals.gd3
-rw-r--r--scripts/HexSpace.gd5
-rw-r--r--scripts/MainMenu.gd27
-rw-r--r--scripts/MainScene.gd71
-rw-r--r--scripts/PlaneControlBoard.gd6
-rw-r--r--scripts/ServerBrowser.gd6
9 files changed, 282 insertions, 30 deletions
diff --git a/scripts/Plane.gd b/scripts/Airplane.gd
index 6889e31..b13ed33 100644
--- a/scripts/Plane.gd
+++ b/scripts/Airplane.gd
@@ -1,3 +1,4 @@
+class_name Airplane
extends Area
var starting_altitude: int = 0 # initial altitude for the turn, determines number of actions
@@ -16,6 +17,8 @@ var destination_col: Color # for display purposes only
var destination_name: String # for display purposes
var destination_id: int # determines above ^
+var owner_id : String
+
var rotation_tween: Tween = null
var actions: Array = []
diff --git a/scripts/Board.gd b/scripts/Board.gd
index f18ca74..04f2d90 100644
--- a/scripts/Board.gd
+++ b/scripts/Board.gd
@@ -17,6 +17,8 @@ var airports = {} # id : HexSpace of cell_type airport
var side_len: int
+const BOARD_GEN_ATTEMPTS : int = 5
+
# Y R B G
var airport_colors = [ Color(1, 1, 0), Color(1, 0, 0), Color(0.3, 0.3, 1), Color(0, 0.8, 0) ]
@@ -31,7 +33,7 @@ enum { PLAIN, HILLS, MOUNTAINS, AIRPORT }
const adjacent_offsets = [ [0,1] , [-1, 0], [-1, -1], [0, -1], [1, 0], [1, 1] ]
# indices of the offsets that are valid cells to approach from
-const approaches_i: Array= [ [0, 1, 2, 3, 4, 5], [0,1,3,4], [0,3] ]
+const approaches_i: Array= [ [], [0,3], [0,1,3,4], [0, 1, 2, 3, 4, 5] ]
func _ready():
@@ -87,8 +89,8 @@ func display_board():
var new_cell = hex_space.instance()
new_cell.call_deferred("set", "global_position", Vector3(x, randf()/15, z))
- new_cell.set_up(row[c])
add_child(new_cell)
+ new_cell.set_up(row[c])
row_display[c] = new_cell
board_display.push_back(row_display)
@@ -126,6 +128,7 @@ func populate_board(num_mountains : int, num_hills : int, num_airports : int, ru
airport_display = [ randi() % 9 + 1, randi() % 4 ] # number, color
while airport_display in used_airports:
airport_display = [ randi() % 9 + 1, randi() % 4 ]
+ used_airports.push_back(airport_display)
# find valid spot
var spot_okay:bool = false
var rot:int
@@ -189,25 +192,36 @@ func populate_board(num_mountains : int, num_hills : int, num_airports : int, ru
if not spot_okay:
return false # could not form valid map
- var args = {"cell_type" : AIRPORT , "pos" : [spot_r, spot_c], "orientation" : rot, "airport_id" : airport_id, "runways" : runways, 'valid_approach_offsets' : valid_approaches, "use_names" : use_names}
+ var args = {"cell_type" : AIRPORT , "pos" : [spot_r, spot_c], "orientation" : rot, "airport_id" : airport_id, "runway_count" : runways, 'valid_approach_offsets' : valid_approaches, "use_names" : use_names}
if use_names:
args["airport_name"] = airport_display
else:
- args["airport_color"] = airport_colors[airport_display[COLOR]]
+ args["airport_color"] = airport_colors[airport_display[COLOR]].to_html()
args["airport_number"] = airport_display[NUMBER]
board[spot_r][spot_c] = args
available_board_coords.pop_at(spot_i)
airport_id += 1
return true
-func get_json():
- return board
+func get_board():
+ return self.board
+
+func set_board(board_array):
+ reset_board()
+ self.board = board_array
+ display_board()
+
func generate_board(hex_side_len: int, num_mountains : int, num_hills : int, num_airports : int, runway_count : int, use_names : bool = false) -> bool:
create_board_base(hex_side_len)
- if not populate_board(num_mountains, num_hills, num_airports, runway_count, use_names):
+ var attempts : int = 1
+ while attempts < BOARD_GEN_ATTEMPTS and (not populate_board(num_mountains, num_hills, num_airports, runway_count, use_names)):
+ attempts += 1
+ reset_board()
+
+ if attempts >= BOARD_GEN_ATTEMPTS:
reset_board()
- print("Invalid board creation parameters")
+ display_board()
return false
display_board()
return true
diff --git a/scripts/GameTable.gd b/scripts/GameTable.gd
index b0bedf2..f21d027 100644
--- a/scripts/GameTable.gd
+++ b/scripts/GameTable.gd
@@ -2,7 +2,7 @@ extends Spatial
# MULTIPLAYER DATA
-var gc_client # to be assigned by MainScene upon game creation/joining
+var GC : GCClient # Game Coordinator connection/client, to be assigned by MainScene upon game creation/joining
@@ -33,7 +33,7 @@ var RULES = {
"misc_enabled" : 1,
"new_planes_per_turn" : 4, # 1 - 8
"ramp_up_enabled" : 0, # whether to ramp up to max planes per turn
- "starting_planes_per_player": 4,
+ "starting_planes_per_player": 3,
"round_timer" : 60, # seconds
}
@@ -43,26 +43,163 @@ var PLANES = []
var desired_player_count: int
var is_board_generated: bool = false # determine whether host can begin the game
+var PLAYER_INFO = {} #
+
# END GAME DATA
# directions: E, NE, NW, W, SW, SE
const adjacent_offsets = [ [0,1] , [-1, 0], [-1, -1], [0, -1], [1, 0], [1, 1] ]
+func _ready():
+ pass
+func _process(_delta):
+ var msg = GC.receive()
+ if msg: handle_gc_message(msg)
-func _ready():
+func set_up(gc_client):
+ GC = gc_client
+ GC.connect("join_request_received", self, "on_join_request_received")
+ GC.connect("disconnected_from_lobby", self, "on_disconnect")
+ GC.connect("connection_closed_dirty", self, "on_connection_closed_dirty")
+
+ var titletext = $PregameUI/Header/TitleText.text.replace("$JCODE", GC.lobby_id)
+ titletext = titletext.replace("$LOBBY_NAME", GC.lobby_name)
+ if OS.get_name() == "HTML5": # running on web
+ titletext += " (click to copy)"
+ $PregameUI/Header/TitleText.text = titletext
+
+ # set up pregame controls
+ # TODO : function where editability/enabled is changed on game host change
+ var i = 0
+ for control_group in ["Board Params", "Game Rules"]:
+ var path_root : String = "PregameUI/PregameControls/ControlsTabContainer/"+control_group+"/"
+ var dict = BOARD_GEN_PARAMS if i == 0 else RULES
+ for key in dict.keys():
+ var setting_node = get_node(path_root + key)
+ if setting_node is OptionButton:
+ setting_node.connect("item_selected", self, "on_setting_update", [control_group, key])
+ if not GC.is_host: setting_node.disabled = true
+ elif setting_node is SpinBox:
+ setting_node.connect("value_changed", self, "on_setting_update", [control_group, key])
+ if not GC.is_host: setting_node.editable = false
+ i += 1
+
+ $PregameUI/PregameControls/PlayerTab/StartButton.disabled = not GC.is_host
+ var gen_btn : Button = get_node("PregameUI/PregameControls/ControlsTabContainer/Board Params/GenerateBoardButton")
+ gen_btn.disabled = not GC.is_host
+ gen_btn.connect("pressed", self, "generate_board_ui")
+
+func set_up_args(args):
+ if !(GC.player_id in PLAYER_INFO): PLAYER_INFO[GC.player_id] = {}
+ PLAYER_INFO[GC.player_id]["color_id"] = args["color_id"]
+
+func on_join_request_received(player_id, args):
+ if !GC.is_host: return # just in case
+ var response = { "type" : "lobby_control", "command": "accept_player", "player_id" : player_id }
+
+ GC.send_json(response)
+
+# new_value filled by UI element signal, control_group and setting_name from custom binds
+func on_setting_update(new_value, control_group, setting_name):
+ if !GC.is_host: return # prevent non-hosts from broadcasting updates when setting the value because of https://github.com/godotengine/godot/issues/70821
+ var dict = BOARD_GEN_PARAMS if control_group == "Board Params" else RULES
+ dict[setting_name] = new_value
+
+ var command = "set_board_gen_params" if control_group == "Board Params" else "set_game_rules"
+ var message = {"type" : "broadcast", "command" : command, "payload" : { setting_name : new_value } }
+ GC.send_json(message)
+
+# fields being dictionary of form { field : value }
+func set_setting_remote(control_group, fields):
+ var dict = BOARD_GEN_PARAMS if control_group == "Board Params" else RULES
+ var path_root : String = "PregameUI/PregameControls/ControlsTabContainer/"+control_group+"/"
+ for field in fields:
+ var new_value = fields[field]
+ dict[field] = new_value
+ var setting_node = get_node(path_root + field)
+ if setting_node is SpinBox:
+ setting_node.set_value(new_value)
+ elif setting_node is OptionButton:
+ setting_node.select(new_value) # does not emit signal
+
+func generate_board_ui():
+ is_board_generated = BOARD.generate_board(BOARD_GEN_PARAMS["board_side_length"],
+ BOARD_GEN_PARAMS["num_mountains"],
+ BOARD_GEN_PARAMS["num_hills"],
+ BOARD_GEN_PARAMS["num_airports"],
+ BOARD_GEN_PARAMS["runways_per_airport"],
+ BOARD_GEN_PARAMS["airport_style"]
+ )
+ var message = {"type" : "broadcast", "command" : "set_board", "payload" : BOARD.board }
+ GC.send_json(message)
+
+func on_disconnect(reason):
pass
-func set_up(ws_client, is_host: bool, lobby_id: String, player_id: String, rejoin_key: String):
- self.ws_client = ws_client
- self.is_host = is_host
- self.lobby_id = lobby_id
- self.player_id = player_id
- self.rejoin_key = rejoin_key
+func on_connection_closed_dirty():
+ get_parent()
+
+# messages have been pre-processed by game coordinator client to ensure
+# valid JSON with "type" field
+func handle_gc_message(message):
+ if "current_players" in message: update_player_info() # add new players to PLAYER_INFO, remove disconnected players
+ if message["type"] == "request":
+ #var data = get_data()
+ #var response = { "type" : "request_response", "requested_data" : data, "destination" : event["source"] }
+ #GC.send_json
+ pass
+ elif message["type"] == "request_response":
+ #set_data()
+ pass
+ elif message["type"] == "broadcast" and "command" in message:
+ var cmd : String = message["command"]
+ if cmd == "set_game_rules":
+ set_setting_remote("Game Rules", message["payload"])
+ elif cmd == "set_board_gen_params":
+ set_setting_remote("Board Params", message["payload"])
+ elif cmd == "set_board":
+ BOARD.set_board(message["payload"])
+
+# info being a dictionary of format { player_id : {field : value} }
+func update_player_info(info = null):
+ # ADD NEW PLAYERS
+ var connected_player_ids : Array = []
+ for player in GC.players:
+ connected_player_ids.push_back(player["player_id"])
+ if !(player["player_id"] in PLAYER_INFO):
+ PLAYER_INFO[player["player_id"]] = {"username" : player["username"]}
+
+ # EDIT PLAYER ATTRIBUTES
+ if info is Dictionary:
+ for player_id in info.keys():
+ if !(info[player_id] is Dictionary) or !(player_id in PLAYER_INFO): return
+ for field in info[player_id].keys():
+ PLAYER_INFO[player_id][field] = info[player_id][field]
+
+ # DELETE DISCONNECTED PLAYERS
+ var player_ids_info = PLAYER_INFO.keys()
+ for player_id in player_ids_info:
+ if !(player_id in connected_player_ids) and (player_id in PLAYER_INFO):
+ PLAYER_INFO.erase(player_id)
+ continue
# ask host for complete game state. returned fields will depend on game state
func request_complete_game_state():
- if is_host: return
- var request = { "type" : "request", "source" : host_id, "requested_data" : "ALL" }
-
+ if GC.is_host: return
+ var request = { "type" : "request", "source" : GC.host_id, "requested_data" : "ALL" }
+ GC.send_json(request)
+
+
+func _on_TitleText_gui_input(event):
+ if (event is InputEventMouseButton && event.pressed && event.button_index == 1):
+ if OS.get_name() == "HTML5": # running on web
+ var direct_join_URL : String = JavaScript.eval("window.location.href")
+ direct_join_URL += "?lobby_id="+GC.lobby_id
+ if Globals.GC_URL != Globals.DEFAULT_GC_URL:
+ direct_join_URL += "&gc_url="+Globals.GC_URL
+ if GC.is_private:
+ direct_join_URL += "&pw="+GC.lobby_password
+ OS.set_clipboard(direct_join_URL)
+
diff --git a/scripts/Globals.gd b/scripts/Globals.gd
index 3603dbd..286b579 100644
--- a/scripts/Globals.gd
+++ b/scripts/Globals.gd
@@ -9,6 +9,8 @@ var airport_names : Array = []
const DEFAULT_GC_URL : String = "ws://192.168.7.112:8181"
var GC_URL : String = "ws://192.168.7.112:8181"
+const GAME_TYPE : String = "ATC"
+
func _ready():
load_airport_names()
set_process(false)
@@ -17,7 +19,6 @@ func update_gc_url(new_url : String):
GC_URL = new_url
-
func load_airport_names():
var f = File.new()
f.open(airport_names_file, File.READ)
diff --git a/scripts/HexSpace.gd b/scripts/HexSpace.gd
index bcf64f1..614039a 100644
--- a/scripts/HexSpace.gd
+++ b/scripts/HexSpace.gd
@@ -55,7 +55,7 @@ func set_up(settings):
valid_arrival_bearings.clear()
- if settings["orientation"]: # bearing according to E, NE, etc.
+ if "orientation" in settings: # bearing according to E, NE, etc.
orientation = settings["orientation"]
self.global_rotation.y = orientation * deg2rad(60)
@@ -68,10 +68,11 @@ func set_up(settings):
if settings["use_names"]:
airport_name = settings["airport_name"]
+ $Airport/AirportName.text = airport_name
$Airport/AirportName.visible = true
else:
airport_number = settings["airport_number"]
- airport_color = settings["airport_color"]
+ airport_color = Color(settings["airport_color"])
$Airport/AirportIcon.visible = true
$Airport/AirportIcon.texture = load("res://textures/airport_indicator_%d.png" % airport_number)
$Airport/AirportIcon.modulate = airport_color
diff --git a/scripts/MainMenu.gd b/scripts/MainMenu.gd
index fca6658..3411054 100644
--- a/scripts/MainMenu.gd
+++ b/scripts/MainMenu.gd
@@ -1,7 +1,7 @@
extends Control
-signal game_host_request(args)
-signal game_join_request(args)
+signal game_host_request(game_name, username, max_players, private, password)
+signal game_join_request(lobby_id, password, username, args)
var lobby_name_changed : bool = false # automatically update lobby name to be based on player's name
@@ -14,8 +14,19 @@ func _ready():
$SettingsMenu/GameCoordinatorURL.connect("text_changed", Globals, "update_gc_url")
$PlayerInfo/Username.connect("text_changed", self, "automatically_update_lobby_name")
$HostMenu/GameName.connect("text_changed", self, "set_lobby_name_changed")
+
+ $HostMenu/HostButton.connect("pressed", self, "on_host_button_pressed")
+ $JoinMenu/JoinButton.connect("pressed", self, "on_join_button_pressed")
#main_menu() # in case things are incorrectly visible from editing
+func open_popup(title, message, close_disabled = false):
+ $NotifPopup.popup_centered()
+ $NotifPopup/PopupControl/TitleLabel.text = title
+ $NotifPopup/PopupControl/MessageLabel.text = message
+ $NotifPopup/PopupControl/ClosePopupButton.disabled = close_disabled
+
+func close_popup():
+ $NotifPopup.visible = false
func set_lobby_name_changed(_disregard_new_text):
lobby_name_changed = true
@@ -54,6 +65,8 @@ func set_back_button_visible(visible : bool):
$BackButton.visible = visible
$BackButton.disabled = false # reset in case left disabled by other function
+## MENU CALLBACKS
+
# go to join game menu
func join_menu_button_pressed(lobby_id_from_url : String = "", password_from_url : String = ""):
set_menu_buttons_visible(false)
@@ -82,3 +95,13 @@ func settings_menu_button_pressed():
# return to main menu
func back_button():
main_menu()
+
+## GAME CALLBACKS
+func on_join_button_pressed():
+ open_popup("Connecting...", "Connecting to game coordinator...", true)
+ var args = { "color_pref_1" : $PlayerInfo/PlayerColor.selected, "color_pref_2" : $PlayerInfo/AltPlayerColor.selected }
+ emit_signal("game_join_request", $JoinMenu/LobbyID.text, $JoinMenu/Password.text, $PlayerInfo/Username.text, args)
+
+func on_host_button_pressed():
+ open_popup("Connecting...", "Connecting to game coordinator...", true)
+ emit_signal("game_host_request", $HostMenu/GameName.text, $PlayerInfo/Username.text, $HostMenu/PlayerCount.get_selected_id(), $HostMenu/PrivateToggle.pressed, $HostMenu/Password.text)
diff --git a/scripts/MainScene.gd b/scripts/MainScene.gd
index fc15463..c15ed1c 100644
--- a/scripts/MainScene.gd
+++ b/scripts/MainScene.gd
@@ -1,13 +1,78 @@
extends Control
+onready var GC = $GCClient
+onready var MM = $MainMenu
+
+enum { MENU, INGAME }
+var game_state : int = MENU
+
+onready var game_scene_base : PackedScene = preload("res://pages/GameTable.tscn")
+var game_scene = null
func _ready():
if OS.get_name() == "HTML5": # running on web
var lobby_id = JavaScript.eval("new URLSearchParams(document.location.search).get('lobby_id')")
var gc_url = JavaScript.eval("new URLSearchParams(document.location.search).get('gc_url')")
var password = JavaScript.eval("new URLSearchParams(document.location.search).get('pw')")
- if lobby_id:
- var pw : String = password if password else ""
- $MainMenu.join_menu_button_pressed(lobby_id, pw)
if gc_url:
Globals.update_gc_url(gc_url)
+ if lobby_id:
+ var pw : String = password if password else ""
+ MM.join_menu_button_pressed(lobby_id, pw)
+
+ GC.connect("join_request_success", self, "on_join_request_success")
+ GC.connect("host_success", self, "on_host_success")
+ GC.connect("host_failure", self, "on_host_failure")
+ GC.connect("join_success", self, "on_join_success")
+ GC.connect("join_failure", self, "on_join_failure")
+ GC.connect("gc_connection_failed", self, "on_gc_connection_failure")
+
+ MM.connect("game_host_request", GC, "host_lobby")
+ MM.connect("game_join_request", GC, "join_lobby")
+
+func _process(_delta):
+ if GC.state > 1 and (game_state == MENU):
+ GC.receive()
+
+func to_main_menu():
+ if game_state == MENU: return
+ if game_scene:
+ remove_child(game_scene)
+ game_scene.queue_free()
+ GC.reset_gc_client()
+ GC.close_socket()
+ MM.visible = true
+ game_state = MENU
+
+func to_game(args = null):
+ if game_state == INGAME: return
+ MM.close_popup()
+ MM.visible = false
+ game_scene = game_scene_base.instance()
+ game_scene.set_up(GC)
+ if args:
+ game_scene.set_up_args(args)
+ add_child(game_scene)
+ game_state = INGAME
+
+# GC FUNCTIONS
+
+func on_gc_connection_failure():
+ MM.open_popup("Error", "Could not connect to game coordinator.")
+
+func on_join_request_success():
+ MM.close_popup()
+ MM.open_popup("Connected", "Waiting for acknowledgment from host...")
+
+func on_host_success():
+ to_game()
+
+func on_host_failure(reason):
+ MM.open_popup("Error", "Could not host game: %s" % reason)
+
+func on_join_success(join_args):
+ to_game(join_args)
+
+func on_join_failure(reason):
+ MM.open_popup("Error", "Could not join game: %s" % reason)
+
diff --git a/scripts/PlaneControlBoard.gd b/scripts/PlaneControlBoard.gd
index cfe94b5..8c9c87e 100644
--- a/scripts/PlaneControlBoard.gd
+++ b/scripts/PlaneControlBoard.gd
@@ -28,5 +28,7 @@ func set_destination(number, color):
$DestinationHBOX/DestinationIcon.texture = airport_indicators[number - 1]
$DestinationHBOX/DestinationIcon.modulate = color
-func update_display_from_plane(plane):
- pass
+func on_plane_selected(plane : Airplane, destination):
+
+
+ self.show()
diff --git a/scripts/ServerBrowser.gd b/scripts/ServerBrowser.gd
index 410eec2..41f478a 100644
--- a/scripts/ServerBrowser.gd
+++ b/scripts/ServerBrowser.gd
@@ -18,6 +18,11 @@ func _ready():
$RefreshButton.connect("pressed", self, "refresh_game_list")
$HostPopup/Control/PrivateToggle.connect("toggled", self, "toggle_password_vis")
$Username.connect("text_changed", $HostPopup/Control/GameName, "set_text")
+ $HostPopup/Control/PlayerCount.connect("item_selected", self, "test_select_signal")
+
+
+func test_select_signal(index):
+ print("selected %d" % index)
func join_game():
$HostPopup.visible = false
@@ -53,6 +58,7 @@ func add_games_to_list(games):
game_ids.append( game["id"] )
func toggle_password_vis(pressed):
+ $HostPopup/Control/PlayerCount.select(3)
$HostPopup/Control/Password.visible = pressed