From 359ef78ee0da4404f3cbbf3cbc2723562e808f97 Mon Sep 17 00:00:00 2001 From: Fabio Alessandrelli Date: Sun, 28 Jul 2019 15:25:36 +0200 Subject: [PATCH] Add WebSocket high level multiplayer demo. --- networking/websocket_multiplayer/.gitignore | 3 + .../websocket_multiplayer/default_env.tres | 20 +++ networking/websocket_multiplayer/icon.png | Bin 0 -> 3428 bytes .../websocket_multiplayer/img/crown.png | Bin 0 -> 776 bytes .../websocket_multiplayer/project.godot | 24 +++ .../websocket_multiplayer/scene/game.tscn | 68 ++++++++ .../websocket_multiplayer/scene/main.tscn | 155 ++++++++++++++++++ .../websocket_multiplayer/script/game.gd | 104 ++++++++++++ .../websocket_multiplayer/script/main.gd | 73 +++++++++ 9 files changed, 447 insertions(+) create mode 100644 networking/websocket_multiplayer/.gitignore create mode 100644 networking/websocket_multiplayer/default_env.tres create mode 100644 networking/websocket_multiplayer/icon.png create mode 100644 networking/websocket_multiplayer/img/crown.png create mode 100644 networking/websocket_multiplayer/project.godot create mode 100644 networking/websocket_multiplayer/scene/game.tscn create mode 100644 networking/websocket_multiplayer/scene/main.tscn create mode 100644 networking/websocket_multiplayer/script/game.gd create mode 100644 networking/websocket_multiplayer/script/main.gd diff --git a/networking/websocket_multiplayer/.gitignore b/networking/websocket_multiplayer/.gitignore new file mode 100644 index 00000000..76c28d20 --- /dev/null +++ b/networking/websocket_multiplayer/.gitignore @@ -0,0 +1,3 @@ +.import/* +*.import +export_presets.cfg diff --git a/networking/websocket_multiplayer/default_env.tres b/networking/websocket_multiplayer/default_env.tres new file mode 100644 index 00000000..b9063186 --- /dev/null +++ b/networking/websocket_multiplayer/default_env.tres @@ -0,0 +1,20 @@ +[gd_resource type="Environment" load_steps=2 format=2] + +[sub_resource type="ProceduralSky" id=1] +sky_top_color = Color( 0.0470588, 0.454902, 0.976471, 1 ) +sky_horizon_color = Color( 0.556863, 0.823529, 0.909804, 1 ) +sky_curve = 0.25 +ground_bottom_color = Color( 0.101961, 0.145098, 0.188235, 1 ) +ground_horizon_color = Color( 0.482353, 0.788235, 0.952941, 1 ) +ground_curve = 0.01 +sun_energy = 16.0 +__meta__ = { + +} + +[resource] +background_mode = 2 +background_sky = SubResource( 1 ) +__meta__ = { + +} diff --git a/networking/websocket_multiplayer/icon.png b/networking/websocket_multiplayer/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..e1acbaafde45032c678f31646fe96a5175c7378d GIT binary patch literal 3428 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 _players.size(): + return + for i in range(0, _players.size()): + if i == turn: + _list.set_item_icon(i, _crown) + else: + _list.set_item_icon(i, null) + _action.disabled = _players[turn] != get_tree().get_network_unique_id() + +sync func del_player(id): + var pos = _players.find(id) + if pos == -1: + return + _players.remove(pos) + _list.remove_item(pos) + if _turn > pos: + _turn -= 1 + if get_tree().is_network_server(): + rpc("set_turn", _turn) + +sync func add_player(id, name=""): + _players.append(id) + if name == "": + _list.add_item("... connecting ...", null, false) + else: + _list.add_item(name, null, false) + +func get_player_name(pos): + if pos < _list.get_item_count(): + return _list.get_item_text(pos) + else: + return "Error!" + +func next_turn(): + _turn += 1 + if _turn >= _players.size(): + _turn = 0 + rpc("set_turn", _turn) + +func start(): + set_turn(0) + +func stop(): + _players.clear() + _list.clear() + _turn = 0 + _action.disabled = true + +func on_peer_add(id): + if not get_tree().is_network_server(): + return + for i in range(0, _players.size()): + rpc_id(id, "add_player", _players[i], get_player_name(i)) + rpc("add_player", id) + rpc_id(id, "set_turn", _turn) + +func on_peer_del(id): + if not get_tree().is_network_server(): + return + rpc("del_player", id) + +sync func _log(what): + $HBoxContainer/RichTextLabel.add_text(what + "\n") + +func _on_Action_pressed(): + if get_tree().is_network_server(): + do_action("roll") + next_turn() + else: + rpc_id(1, "request_action", "roll") diff --git a/networking/websocket_multiplayer/script/main.gd b/networking/websocket_multiplayer/script/main.gd new file mode 100644 index 00000000..1dcb0423 --- /dev/null +++ b/networking/websocket_multiplayer/script/main.gd @@ -0,0 +1,73 @@ +extends Control + +const DEF_PORT = 8080 +const PROTO_NAME = "ludus" + +onready var _host_btn = $Panel/VBoxContainer/HBoxContainer2/HBoxContainer/Host +onready var _connect_btn = $Panel/VBoxContainer/HBoxContainer2/HBoxContainer/Connect +onready var _disconnect_btn = $Panel/VBoxContainer/HBoxContainer2/HBoxContainer/Disconnect +onready var _name_edit = $Panel/VBoxContainer/HBoxContainer/NameEdit +onready var _host_edit = $Panel/VBoxContainer/HBoxContainer2/Hostname +onready var _game = $Panel/VBoxContainer/Game + +func _ready(): + get_tree().connect("network_peer_disconnected", self, "_peer_disconnected") + get_tree().connect("network_peer_connected", self, "_peer_connected") + $AcceptDialog.get_label().align = Label.ALIGN_CENTER + $AcceptDialog.get_label().valign = Label.VALIGN_CENTER + +func start_game(): + _host_btn.disabled = true + _name_edit.editable = false + _host_edit.editable = false + _connect_btn.hide() + _disconnect_btn.show() + _game.start() + +func stop_game(): + _host_btn.disabled = false + _name_edit.editable = true + _host_edit.editable = true + _disconnect_btn.hide() + _connect_btn.show() + _game.stop() + +func _close_network(): + if get_tree().is_connected("server_disconnected", self, "_close_network"): + get_tree().disconnect("server_disconnected", self, "_close_network") + if get_tree().is_connected("connection_failed", self, "_close_network"): + get_tree().disconnect("connection_failed", self, "_close_network") + if get_tree().is_connected("connected_to_server", self, "_connected"): + get_tree().disconnect("connected_to_server", self, "_connected") + stop_game() + $AcceptDialog.show_modal() + $AcceptDialog.get_close_button().grab_focus() + get_tree().set_network_peer(null) + +func _connected(): + _game.rpc("set_player_name", _name_edit.text) + +func _peer_connected(id): + _game.on_peer_add(id) + +func _peer_disconnected(id): + _game.on_peer_del(id) + +func _on_Host_pressed(): + var host = WebSocketServer.new() + host.listen(DEF_PORT, PoolStringArray(["ludus"]), true) + get_tree().connect("server_disconnected", self, "_close_network") + get_tree().set_network_peer(host) + _game.add_player(1, _name_edit.text) + start_game() + +func _on_Disconnect_pressed(): + _close_network() + +func _on_Connect_pressed(): + var host = WebSocketClient.new() + host.connect_to_url("ws://" + _host_edit.text + ":" + str(DEF_PORT), PoolStringArray([PROTO_NAME]), true) + get_tree().connect("connection_failed", self, "_close_network") + get_tree().connect("connected_to_server", self, "_connected") + get_tree().set_network_peer(host) + start_game()