summaryrefslogtreecommitdiff
path: root/scripts/GameTable.gd
diff options
context:
space:
mode:
authorAnson Bridges <bridges.anson@gmail.com>2025-08-22 12:46:04 -0700
committerAnson Bridges <bridges.anson@gmail.com>2025-08-22 12:46:04 -0700
commit64f37f4209d80bfad976dd4a139c98002caef15f (patch)
tree94c91953986e960573ae0092f8ad7120c1c266f0 /scripts/GameTable.gd
parent255fbf19cc9499ef384d41f68515da5e49e8a3ce (diff)
the harmonious transition from menu to gameHEADmaster
Diffstat (limited to 'scripts/GameTable.gd')
-rw-r--r--scripts/GameTable.gd161
1 files changed, 149 insertions, 12 deletions
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)
+