From ba2dd6a8373e94ae1f76c1f781e05a94183362c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lera=20Elvo=C3=A9?= Date: Wed, 8 May 2024 07:59:19 +0000 Subject: [PATCH] remove RPC (#153) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit bye bye Reviewed-on: https://codeberg.org/StreamGraph/StreamGraph/pulls/153 Co-authored-by: Lera ElvoƩ Co-committed-by: Lera ElvoƩ --- classes/deck/deck.gd | 11 - classes/deck/deck_holder.gd | 7 - classes/deck/deck_node.gd | 7 - graph_node_renderer/deck_holder_renderer.gd | 34 +-- graph_node_renderer/deck_holder_renderer.tscn | 6 +- graph_node_renderer/rpc_setup_dialog.gd | 50 ---- graph_node_renderer/rpc_setup_dialog.tscn | 44 --- main.gd | 12 - main.tscn | 6 +- rpc_renderer/rpc_frame.gd | 40 --- rpc_renderer/rpc_renderer.gd | 179 ------------ rpc_renderer/rpc_scope.gd | 103 ------- rpc_renderer/rpc_signal_layer.gd | 88 ------ rpc_renderer/scopes/scope_deck.gd | 255 ----------------- rpc_renderer/scopes/scope_deck_holder.gd | 72 ----- rpc_renderer/scopes/scope_node.gd | 267 ------------------ rpc_renderer/scopes/scope_system.gd | 77 ----- rpc_renderer/types/extended/connection.gd | 20 -- rpc_renderer/types/extended/deck_partial.gd | 17 -- rpc_renderer/types/extended/node_partial.gd | 17 -- rpc_renderer/types/extended/port.gd | 35 --- rpc_renderer/types/rpc_error.gd | 15 - rpc_renderer/types/rpc_event.gd | 37 --- rpc_renderer/types/rpc_operation.gd | 41 --- rpc_renderer/types/rpc_request.gd | 36 --- rpc_renderer/types/rpc_request_response.gd | 44 --- rpc_renderer/web_socket_server.gd | 171 ----------- 27 files changed, 6 insertions(+), 1685 deletions(-) delete mode 100644 graph_node_renderer/rpc_setup_dialog.gd delete mode 100644 graph_node_renderer/rpc_setup_dialog.tscn delete mode 100644 rpc_renderer/rpc_frame.gd delete mode 100644 rpc_renderer/rpc_renderer.gd delete mode 100644 rpc_renderer/rpc_scope.gd delete mode 100644 rpc_renderer/rpc_signal_layer.gd delete mode 100644 rpc_renderer/scopes/scope_deck.gd delete mode 100644 rpc_renderer/scopes/scope_deck_holder.gd delete mode 100644 rpc_renderer/scopes/scope_node.gd delete mode 100644 rpc_renderer/scopes/scope_system.gd delete mode 100644 rpc_renderer/types/extended/connection.gd delete mode 100644 rpc_renderer/types/extended/deck_partial.gd delete mode 100644 rpc_renderer/types/extended/node_partial.gd delete mode 100644 rpc_renderer/types/extended/port.gd delete mode 100644 rpc_renderer/types/rpc_error.gd delete mode 100644 rpc_renderer/types/rpc_event.gd delete mode 100644 rpc_renderer/types/rpc_operation.gd delete mode 100644 rpc_renderer/types/rpc_request.gd delete mode 100644 rpc_renderer/types/rpc_request_response.gd delete mode 100644 rpc_renderer/web_socket_server.gd diff --git a/classes/deck/deck.gd b/classes/deck/deck.gd index 461a0af..ef9ef9c 100644 --- a/classes/deck/deck.gd +++ b/classes/deck/deck.gd @@ -78,16 +78,6 @@ signal node_moved(node_id: String, new_position: Dictionary, deck: Deck) #endregion -func connect_rpc_signals() -> void: - node_added.connect(RPCSignalLayer._on_deck_node_added) - node_removed.connect(RPCSignalLayer._on_deck_node_removed) - - nodes_connected.connect(RPCSignalLayer._on_deck_nodes_connected.bind(id)) - nodes_disconnected.connect(RPCSignalLayer._on_deck_nodes_disconnected.bind(id)) - - variables_updated.connect(RPCSignalLayer._on_deck_variables_updated.bind(id)) - - ## Instantiate a node by its' [member DeckNode.node_type] and add it to this deck.[br] ## See [method add_node_inst] for parameter descriptions. func add_node_type(type: String, assign_id: String = "", assign_to_self: bool = true) -> DeckNode: @@ -138,7 +128,6 @@ func add_node_inst(node: DeckNode, assign_id: String = "", assign_to_self: bool node_moved.emit(node._id, new_position, self) ) - node.connect_rpc_signals() print_verbose("Deck %s::%s: added node %s, id %s" % [id, instance_id, node.node_type, node.get_instance_id()]) return node diff --git a/classes/deck/deck_holder.gd b/classes/deck/deck_holder.gd index f1ac35c..b9b3b57 100644 --- a/classes/deck/deck_holder.gd +++ b/classes/deck/deck_holder.gd @@ -23,9 +23,6 @@ enum Compat { static func _static_init() -> void: - signals.deck_added.connect(RPCSignalLayer._on_deck_added) - signals.deck_closed.connect(RPCSignalLayer._on_deck_closed) - NodeDB.init() @@ -35,7 +32,6 @@ static func add_empty_deck() -> Deck: var uuid := UUID.v4() decks[uuid] = deck deck.id = uuid - deck.connect_rpc_signals() signals.deck_added.emit(uuid) print_verbose("DeckHolder: added empty deck %s, id %s" % [deck.id, deck.get_instance_id()]) return deck @@ -78,7 +74,6 @@ static func open_deck_from_dict(data: Dictionary, path := "") -> Deck: apply_compat_patches(data, get_deck_compat(data)) var deck := Deck.from_dict(data, path) decks[deck.id] = deck - deck.connect_rpc_signals() signals.deck_added.emit(deck.id) print_verbose("DeckHolder: opened deck %s, id %s" % [deck.id, deck.get_instance_id()]) return deck @@ -97,7 +92,6 @@ static func add_group_from_dict(data: Dictionary, deck_id: String, instance_id: connect_group_signals(group) if deck_id not in groups_emitted: - group.connect_rpc_signals() signals.deck_added.emit(deck_id) groups_emitted.append(deck_id) #print(decks) @@ -149,7 +143,6 @@ static func add_empty_group(parent: String = "") -> Deck: decks[group.id] = {group.instance_id: group} connect_group_signals(group) if group.id not in groups_emitted: - group.connect_rpc_signals() signals.deck_added.emit(group.id) groups_emitted.append(group.id) print_verbose("DeckHolder: added empty group %s::%s, id %s" % [group.id, group.instance_id, group.get_instance_id()]) diff --git a/classes/deck/deck_node.gd b/classes/deck/deck_node.gd index cf56827..d37a3c8 100644 --- a/classes/deck/deck_node.gd +++ b/classes/deck/deck_node.gd @@ -74,13 +74,6 @@ signal port_value_updated(port_idx: int, new_value: Variant) signal renamed(new_name: String) -func connect_rpc_signals() -> void: - Util.safe_connect(port_added, RPCSignalLayer._on_node_port_added.bind(self)) - Util.safe_connect(ports_updated, RPCSignalLayer._on_node_ports_updated.bind(self)) - Util.safe_connect(port_value_updated, RPCSignalLayer._on_node_port_value_updated.bind(self)) - Util.safe_connect(renamed, RPCSignalLayer._on_node_renamed.bind(self)) - - ## Add an input port to this node. Usually only used at initialization. func add_input_port( type: DeckType.Types, diff --git a/graph_node_renderer/deck_holder_renderer.gd b/graph_node_renderer/deck_holder_renderer.gd index 9ebb43f..020efa0 100644 --- a/graph_node_renderer/deck_holder_renderer.gd +++ b/graph_node_renderer/deck_holder_renderer.gd @@ -41,6 +41,7 @@ enum ConnectionsMenuId { TWITCH, RPC, } +@onready var connections_popup_menu: PopupMenu = %Connections enum DebugMenuId { DECKS, @@ -71,7 +72,6 @@ var _deck_to_save: WeakRef @onready var obs_setup_dialog := $OBSWebsocketSetupDialog as OBSWebsocketSetupDialog @onready var twitch_setup_dialog := $Twitch_Setup_Dialog as TwitchSetupDialog -@onready var rpc_setup_dialog := $RPCSetupDialog as RPCSetupDialog @onready var bottom_dock: BottomDock = %BottomDock @onready var sidebar_split: HSplitContainer = %SidebarSplit @@ -80,8 +80,6 @@ var _deck_to_save: WeakRef @onready var compat_dialog: ConfirmationDialog = %CompatDialog signal quit_completed() -signal rpc_start_requested(port: int) -signal rpc_stop_requested() func _ready() -> void: @@ -114,32 +112,6 @@ func _ready() -> void: add_recents_to_menu() - var rpc_port: int = RendererPersistence.get_or_create( - PERSISTENCE_NAMESPACE, "config", - "rpc_server_port", 6907 - ) - rpc_setup_dialog.set_port(rpc_port) - rpc_setup_dialog.start_requested.connect( - func(port: int): - rpc_start_requested.emit(port) - RendererPersistence.set_value( - PERSISTENCE_NAMESPACE, "config", - "rpc_server_port", port - ) - ) - rpc_setup_dialog.stop_requested.connect( - func(): - rpc_stop_requested.emit() - ) - - rpc_setup_dialog.confirmed.connect( - func(): - RendererPersistence.set_value( - PERSISTENCE_NAMESPACE, "config", - "rpc_server_port", rpc_setup_dialog.get_port() - ) - ) - tab_container.tab_close_requested.connect( func(tab: int): if tab_container.get_tab_metadata(tab, "dirty") and not tab_container.get_tab_metadata(tab, "group"): @@ -181,6 +153,8 @@ func _ready() -> void: var deck_renderer := get_active_deck_renderer() deck_renderer.focus_node(deck_renderer.get_node_renderer(node)) ) + + connections_popup_menu.set_item_tooltip(ConnectionsMenuId.RPC, "RPC support has been removed and will return in a future version.") func reset_popup_menu_shortcuts() -> void: @@ -516,8 +490,6 @@ func _on_connections_id_pressed(id: int) -> void: obs_setup_dialog.popup_centered() ConnectionsMenuId.TWITCH: twitch_setup_dialog.popup_centered() - ConnectionsMenuId.RPC: - rpc_setup_dialog.popup_centered() func _on_obs_websocket_setup_dialog_connect_button_pressed(state: OBSWebsocketSetupDialog.ConnectionState) -> void: diff --git a/graph_node_renderer/deck_holder_renderer.tscn b/graph_node_renderer/deck_holder_renderer.tscn index bf9e6bf..fbd87bd 100644 --- a/graph_node_renderer/deck_holder_renderer.tscn +++ b/graph_node_renderer/deck_holder_renderer.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=19 format=3 uid="uid://duaah5x0jhkn6"] +[gd_scene load_steps=18 format=3 uid="uid://duaah5x0jhkn6"] [ext_resource type="Script" path="res://graph_node_renderer/deck_holder_renderer.gd" id="1_67g2g"] [ext_resource type="PackedScene" uid="uid://b84f2ngtcm5b8" path="res://graph_node_renderer/tab_container_custom.tscn" id="1_s3ug2"] @@ -15,7 +15,6 @@ [ext_resource type="PackedScene" uid="uid://cuwou2aa7qfc2" path="res://graph_node_renderer/unsaved_changes_dialog_single_deck.tscn" id="8_qf6ve"] [ext_resource type="PackedScene" uid="uid://cvvkj138fg8jg" path="res://graph_node_renderer/unsaved_changes_dialog.tscn" id="9_4n0q6"] [ext_resource type="PackedScene" uid="uid://bu466w2w3q08c" path="res://graph_node_renderer/about_dialog.tscn" id="11_6ln7n"] -[ext_resource type="PackedScene" uid="uid://brfrufvkjwcor" path="res://graph_node_renderer/rpc_setup_dialog.tscn" id="12_1xrfk"] [ext_resource type="PackedScene" uid="uid://dodqetbke5wji" path="res://graph_node_renderer/settings/settings_dialog.tscn" id="16_rktri"] [ext_resource type="PackedScene" uid="uid://cd1t0gvi022gx" path="res://graph_node_renderer/compat_dialog.tscn" id="17_2ndnq"] @@ -104,6 +103,7 @@ item_1/text = "Twitch.." item_1/id = 1 item_2/text = "RPC Server..." item_2/id = 2 +item_2/disabled = true [node name="Debug" type="PopupMenu" parent="MarginContainer/SidebarSplit/BottomSplit/VBoxContainer/MenuBar"] unique_name_in_owner = true @@ -163,8 +163,6 @@ script = ExtResource("5_3n36q") [node name="Twitch_Setup_Dialog" parent="." instance=ExtResource("7_7rhap")] -[node name="RPCSetupDialog" parent="." instance=ExtResource("12_1xrfk")] - [node name="UnsavedChangesDialogSingleDeck" parent="." instance=ExtResource("8_qf6ve")] [node name="UnsavedChangesDialog" parent="." instance=ExtResource("9_4n0q6")] diff --git a/graph_node_renderer/rpc_setup_dialog.gd b/graph_node_renderer/rpc_setup_dialog.gd deleted file mode 100644 index 9a5f81d..0000000 --- a/graph_node_renderer/rpc_setup_dialog.gd +++ /dev/null @@ -1,50 +0,0 @@ -# (c) 2023-present Eroax -# (c) 2023-present Yagich -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) -extends ConfirmationDialog -class_name RPCSetupDialog - -@onready var port_spin_box: SpinBox = %PortSpinBox -@onready var start_server_button: Button = %StartServerButton - -var _old_port: int - -var is_started: bool = false - -signal start_requested(port: int) -signal stop_requested() - - -func _ready() -> void: - canceled.connect( - func(): - port_spin_box.value = float(_old_port) - ) - - confirmed.connect( - func(): - _old_port = int(port_spin_box.value) - ) - - -func _on_start_server_button_pressed() -> void: - if not is_started: - start_server_button.text = "Stop" - _old_port = int(port_spin_box.value) - start_requested.emit(int(port_spin_box.value)) - port_spin_box.editable = true - is_started = true - else: - start_server_button.text = "Start" - stop_requested.emit() - port_spin_box.editable = true - is_started = false - - -func set_port(port: int) -> void: - port_spin_box.value = port - _old_port = port - - -func get_port() -> int: - return int(port_spin_box.value) diff --git a/graph_node_renderer/rpc_setup_dialog.tscn b/graph_node_renderer/rpc_setup_dialog.tscn deleted file mode 100644 index 6198187..0000000 --- a/graph_node_renderer/rpc_setup_dialog.tscn +++ /dev/null @@ -1,44 +0,0 @@ -[gd_scene load_steps=2 format=3 uid="uid://brfrufvkjwcor"] - -[ext_resource type="Script" path="res://graph_node_renderer/rpc_setup_dialog.gd" id="1_7pkns"] - -[node name="RPCSetupDialog" type="ConfirmationDialog"] -title = "RPC Server Setup" -initial_position = 4 -size = Vector2i(320, 135) -script = ExtResource("1_7pkns") - -[node name="VBoxContainer" type="VBoxContainer" parent="."] -anchors_preset = 15 -anchor_right = 1.0 -anchor_bottom = 1.0 -offset_left = 8.0 -offset_top = 8.0 -offset_right = -8.0 -offset_bottom = -49.0 -grow_horizontal = 2 -grow_vertical = 2 -size_flags_vertical = 3 - -[node name="HBoxContainer" type="HBoxContainer" parent="VBoxContainer"] -layout_mode = 2 - -[node name="Label" type="Label" parent="VBoxContainer/HBoxContainer"] -layout_mode = 2 -text = "Port" - -[node name="PortSpinBox" type="SpinBox" parent="VBoxContainer/HBoxContainer"] -unique_name_in_owner = true -layout_mode = 2 -size_flags_horizontal = 3 -max_value = 25565.0 -value = 6907.0 - -[node name="StartServerButton" type="Button" parent="VBoxContainer"] -unique_name_in_owner = true -layout_mode = 2 -size_flags_horizontal = 4 -size_flags_vertical = 6 -text = "Start" - -[connection signal="pressed" from="VBoxContainer/StartServerButton" to="." method="_on_start_server_button_pressed"] diff --git a/main.gd b/main.gd index 6327dce..75545e0 100644 --- a/main.gd +++ b/main.gd @@ -8,8 +8,6 @@ const DEFAULT_RENDERER := preload("res://graph_node_renderer/deck_holder_rendere var deck_holder_renderer: DeckHolderRenderer = null var deck_holder_renderer_finished := false -@onready var rpc_renderer := $RPCRenderer as RPCRenderer - func _ready() -> void: get_tree().auto_accept_quit = false @@ -19,8 +17,6 @@ func _ready() -> void: deck_holder_renderer = DEFAULT_RENDERER.instantiate() add_child(deck_holder_renderer) deck_holder_renderer.quit_completed.connect(_on_deck_holder_renderer_quit_completed) - deck_holder_renderer.rpc_start_requested.connect(_on_deck_holder_renderer_rpc_start_requested) - deck_holder_renderer.rpc_stop_requested.connect(_on_deck_holder_renderer_rpc_stop_requested) func _on_deck_holder_renderer_quit_completed() -> void: @@ -31,14 +27,6 @@ func _on_deck_holder_renderer_quit_completed() -> void: get_tree().quit() -func _on_deck_holder_renderer_rpc_start_requested(port: int) -> void: - rpc_renderer.listen(port) - - -func _on_deck_holder_renderer_rpc_stop_requested() -> void: - rpc_renderer.stop() - - func _notification(what: int) -> void: if what == NOTIFICATION_WM_CLOSE_REQUEST: if deck_holder_renderer: diff --git a/main.tscn b/main.tscn index 34cbfc9..e93eebb 100644 --- a/main.tscn +++ b/main.tscn @@ -1,10 +1,6 @@ -[gd_scene load_steps=3 format=3 uid="uid://clxtes7sdpe65"] +[gd_scene load_steps=2 format=3 uid="uid://clxtes7sdpe65"] [ext_resource type="Script" path="res://main.gd" id="1_rxyjw"] -[ext_resource type="Script" path="res://rpc_renderer/rpc_renderer.gd" id="2_m1ypq"] [node name="Main" type="Node"] script = ExtResource("1_rxyjw") - -[node name="RPCRenderer" type="Node" parent="."] -script = ExtResource("2_m1ypq") diff --git a/rpc_renderer/rpc_frame.gd b/rpc_renderer/rpc_frame.gd deleted file mode 100644 index 31fe921..0000000 --- a/rpc_renderer/rpc_frame.gd +++ /dev/null @@ -1,40 +0,0 @@ -# (c) 2023-present Eroax -# (c) 2023-present Yagich -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) -class_name RPCFrame -## An RPC frame. -## -## A frame is the second smallest unit of data transmittable over RPC, after base types. - -## The name of this frame. When a frame is converted to JSON, -## this will be the key in an object, or if this is the top level frame, -## it will be an object with only one key, which is the value of this property. -var frame_name: String - -## The props (key names) that will be serialized to JSON before sending to remote clients. -var _props: Array[StringName] - - -## Wraps this frame's contents into a dictionary with one key: the [member frame_name]. See [member _props]. -## If any prop in [member _props] is also an [RPCFrame], it will be serialized -## using [method to_inner_dict]. -func to_dict() -> Dictionary: - return {frame_name: to_inner_dict()} - - -## Converts the [i]contents[/i] of this frame to a dictionary. -func to_inner_dict() -> Dictionary: - var res := {} - for prop in _props: - var value = get(prop) - if value is RPCFrame: - res[prop] = value.to_dict() - elif value is Array and not value.is_empty() and value[0] is RPCFrame: - res[prop] = value.map( - func(e: RPCFrame): - return e.to_dict() - ) - else: - res[prop] = value - - return res diff --git a/rpc_renderer/rpc_renderer.gd b/rpc_renderer/rpc_renderer.gd deleted file mode 100644 index 8836e26..0000000 --- a/rpc_renderer/rpc_renderer.gd +++ /dev/null @@ -1,179 +0,0 @@ -# (c) 2023-present Eroax -# (c) 2023-present Yagich -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) -extends Node -class_name RPCRenderer -## A WebSocket API server. -## -## A renderer that exposes a subset of the core API to remote clients using WebSocket. - -const SCOPES_DIR := "res://rpc_renderer/scopes/" - -@export var default_port := 6907 - -var clients: Dictionary # Dictionary[int -> id, Client] - -var _ws: WebSocketServer = WebSocketServer.new() - -var scopes: Array[RPCScope] -var system_scope: RPCScopeSystem -var request_schema: Zodot - - -func load_scopes() -> void: - var d := DirAccess.open(SCOPES_DIR) - d.list_dir_begin() - var current := d.get_next() - while current != "": - if !d.current_is_dir(): - var scope = load(SCOPES_DIR.path_join(current)).new() as RPCScope - scopes.append(scope) - - current = d.get_next() - - for scope in scopes: - if scope.name == "system": - system_scope = scope - - scope.event.connect( - func(event: RPCEvent): - if event.to_peer != 0: - send_frame(event.to_peer, event) - return - for client_id in clients: - var client: Client = get_client(client_id) - if not client.subscriptions.has(event.scope): - continue - if event.type in (client.subscriptions[event.scope] as Array): - send_frame(client_id, event) - ) - - scope.response.connect( - func(response: RPCRequestResponse): - send_frame(response.peer_id, response) - if response.event_counterpart != null: - var event := response.event_counterpart - for client_id in clients: - if client_id == response.peer_id: - continue - var client: Client = get_client(client_id) - if event.name in (client.subscriptions[event.scope] as Array): - send_frame(client_id, event) - ) - - -func build_schema() -> void: - var scope_names = scopes.map( - func(scope: RPCScope): - return scope.name - ) - - var scopes_schema: Array[Zodot] - - scopes_schema.assign(scope_names.map( - func(scope_name: String): - return Z.literal(scope_name) - )) - - request_schema = Z.schema({ - "request": Z.schema({ - "id": Z.string(), - "scope": Z.union(scopes_schema), - "operation": RPCOperation.schema(), - "keep": Z.dictionary().nullable(), - }) - }) - - -func _ready() -> void: - load_scopes() - build_schema() - - add_child(_ws) - _ws.client_connected.connect(_on_ws_client_connected) - _ws.client_disconnected.connect(_on_ws_client_disconnected) - _ws.message_received.connect(_on_ws_message) - - -func listen(port := default_port) -> void: - if _ws.listen(port) != OK: - pass - - -func stop() -> void: - _ws.stop() - - -func send_frame(peer_id: int, frame: RPCFrame) -> void: - _ws.send(peer_id, JSON.stringify(frame.to_dict(), "", false)) - - -func get_client(peer_id: int) -> Client: - return clients.get(peer_id) - - -func drop_client(peer_id: int, reason: String) -> void: - var disconnect_data := { - "disconnect": { - "message": "You have been disconnected: %s" % reason - } - } - - _ws.send(peer_id, JSON.stringify(disconnect_data, "", false)) - _ws.peers.erase(peer_id) - clients.erase(peer_id) - - -func _on_ws_message(peer_id: int, message: Variant) -> void: - if not message is String: - return - - var json := JSON.new() - var err := json.parse(message) - if err != OK: - send_frame(peer_id, RPCError.new(json.get_error_message())) - return - var result = request_schema.parse(json.get_data()) - if not result.ok(): - send_frame(peer_id, RPCError.new(result.error)) - return - - var req := RPCRequest.from_dict(result.data, get_client(peer_id)) - if not get_client(peer_id).identified: - if not (req.scope == "system" and req.operation.type == "identify"): - drop_client(peer_id, "You must identify your client first.") - return - - system_scope.identify(req) - return - - var scope_idx := -1 - for i in scopes.size(): - var scope := scopes[i] - if scope.name == req.scope: - scope_idx = i - break - - if scope_idx == -1: - return # TODO: error - - var scope := scopes[scope_idx] - if scope.can_handle_request(req): - scope.handle_request(req) - - -func _on_ws_client_connected(peer_id: int) -> void: - var c := Client.new() - c.id = peer_id - clients[peer_id] = c - RPCSignalLayer.signals.client_connected.emit(c) - - -func _on_ws_client_disconnected(peer_id: int) -> void: - clients.erase(peer_id) - - -class Client: - var id: int - var identified: bool = false - var subscriptions: Dictionary = {} diff --git a/rpc_renderer/rpc_scope.gd b/rpc_renderer/rpc_scope.gd deleted file mode 100644 index 0b80e2c..0000000 --- a/rpc_renderer/rpc_scope.gd +++ /dev/null @@ -1,103 +0,0 @@ -# (c) 2023-present Eroax -# (c) 2023-present Yagich -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) -class_name RPCScope -## An object that can respond to requests and send events. -## -## A scope is a handler for requests sent by remote clients, and events from the API. It is generally related to different areas of the program. - -## The name of this scope. -var name: String -# Dictionary[String -> RPCOperation.type, Callable] -## The operation types this scope can handle. -## Map of [member RPCOperation.type] to [Callable]. The function will be called -## with one argument: the [RPCRequest] to handle. -var operation_types: Dictionary - -## Emitted when a response to a request is ready to be sent. -signal response(response: RPCRequestResponse) -## Emitted when an event is ready to be sent. -signal event(event: RPCEvent) - - -## Returns [code]true[/code] if this scope can handle the given request. -func can_handle_request(request: RPCRequest) -> bool: - return request.operation.type in operation_types - - -## Wrapper function to handle a request. See [param operation_types]. -func handle_request(request: RPCRequest) -> void: - var c: Callable = operation_types[request.operation.type].callable - c.call(request) - - -## Returns an [RPCRequestResponse] that's set up to respond to the given [param request]. -## Does not emit [signal response]. -func create_response(request: RPCRequest, data: Variant, error: RPCError = null) -> RPCRequestResponse: - var r := RPCRequestResponse.new(request) - r.for_request = request.id - r.scope = name - r.kept = request.keep - r.peer_id = request.peer_id - - if data is RPCFrame: - r.data = data.to_dict() - else: - r.data = data - - if error: - r.errors.append(error) - - return r - - -func create_error(request: RPCRequest, error_text: String) -> RPCRequestResponse: - var r := RPCRequestResponse.new(request) - r.for_request = request.id - r.scope = name - r.kept = request.keep - r.peer_id = request.peer_id - - r.data = {} - - r.errors.append(RPCError.new(error_text)) - - return r - - -func create_generic_success(request: RPCRequest) -> RPCRequestResponse: - var r := RPCRequestResponse.new(request) - r.for_request = request.id - r.scope = name - r.kept = request.keep - r.peer_id = request.peer_id - - r.data = { - "success": true - } - - return r - - -func create_generic_failure(request: RPCRequest) -> RPCRequestResponse: - var r := RPCRequestResponse.new(request) - r.for_request = request.id - r.scope = name - r.kept = request.keep - r.peer_id = request.peer_id - - r.data = { - "success": false - } - - return r - - -func create_event(type: String, data: Variant, condition := {}) -> RPCEvent: - return RPCEvent.new(type, name, data, condition) - - -func reconnect(p_signal: Signal, connect_to: Callable, to_call: Callable) -> void: - p_signal.disconnect(connect_to) - to_call.call() - p_signal.connect(connect_to) diff --git a/rpc_renderer/rpc_signal_layer.gd b/rpc_renderer/rpc_signal_layer.gd deleted file mode 100644 index e5844d5..0000000 --- a/rpc_renderer/rpc_signal_layer.gd +++ /dev/null @@ -1,88 +0,0 @@ -# (c) 2023-present Eroax -# (c) 2023-present Yagich -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) -class_name RPCSignalLayer - - -static var signals := Signals.new() - - -#region deck holder -static func _on_deck_added(deck_id: String) -> void: - signals.deck_added.emit(deck_id) - - -static func _on_deck_closed(deck_id: String) -> void: - signals.deck_closed.emit(deck_id) -#endregion - - -#region deck -static func _on_deck_node_added(node: DeckNode) -> void: - signals.deck_node_added.emit(node._belonging_to.id, node._id) - - -static func _on_deck_node_removed(node: DeckNode) -> void: - signals.deck_node_removed.emit(node._belonging_to.id, node._id) - - -static func _on_deck_nodes_connected(from_node_id: String, to_node_id: String, from_output_port: int, to_input_port: int, deck_id: String) -> void: - signals.deck_nodes_connected.emit(deck_id, from_node_id, to_node_id, from_output_port, to_input_port) - - -static func _on_deck_nodes_disconnected(from_node_id: String, to_node_id: String, from_output_port: int, to_input_port: int, deck_id: String) -> void: - signals.deck_nodes_disconnected.emit(deck_id, from_node_id, to_node_id, from_output_port, to_input_port) - - -static func _on_deck_variables_updated(deck_id: String) -> void: - signals.deck_variables_updated.emit(deck_id) -#endregion - - -#region node -static func _on_node_position_updated(new_position: Dictionary, node: DeckNode) -> void: - signals.node_position_updated.emit(node._belonging_to.id, node._id, new_position) - - -static func _on_node_port_added(port: int, node: DeckNode) -> void: - signals.node_port_added.emit(node._belonging_to.id, node._id, port, node) - - -static func _on_node_ports_updated(node: DeckNode) -> void: - signals.node_ports_updated.emit(node._belonging_to.id, node._id) - - -static func _on_node_port_value_updated(port_idx: int, new_value: Variant, node: DeckNode) -> void: - signals.node_port_value_updated.emit(node._belonging_to.id, node._id, port_idx, new_value) - - -static func _on_node_renamed(new_name: String, node: DeckNode) -> void: - signals.node_renamed.emit(node._belonging_to.id, node._id, new_name) -#endregion - - -class Signals: - #region system - signal client_connected(client: RPCRenderer.Client) - #endregion - - #region deck holder - signal deck_added(deck_id: String) - signal deck_closed(deck_id: String) - #endregion - - #region deck - signal deck_node_added(deck_id: String, node_id: String) - signal deck_node_removed(deck_id: String, node_id: String) - signal deck_nodes_connected(deck_id: String, from_node_id: String, to_node_id: String, from_output_port: int, to_input_port: int) - signal deck_nodes_disconnected(deck_id: String, from_node_id: String, to_node_id: String, from_output_port: int, to_input_port: int) - signal deck_variables_updated(deck_id: String) - #endregion - - #region node - signal node_position_updated(deck_id: String, node_id: String, new_position: Dictionary) - signal node_port_added(deck_id: String, node_id: String, port: int) - signal node_ports_updated(deck_id: String, node_id: String) - signal node_port_value_updated(deck_id: String, node_id: String, port_idx: int, new_value: Variant) - signal node_renamed(deck_id: String, node_id: String, new_name: String) - #endregion diff --git a/rpc_renderer/scopes/scope_deck.gd b/rpc_renderer/scopes/scope_deck.gd deleted file mode 100644 index 4226f2b..0000000 --- a/rpc_renderer/scopes/scope_deck.gd +++ /dev/null @@ -1,255 +0,0 @@ -# (c) 2023-present Eroax -# (c) 2023-present Yagich -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) -extends RPCScope - - -func _init() -> void: - name = "deck" - - operation_types = { - "add_node": {"callable": add_node, "event_name": "node_added"}, - "remove_node": {"callable": remove_node, "event_name": "node_removed"}, - "get_node": {"callable": get_node, "event_name": ""}, - - "is_valid_connection": {"callable": is_valid_connection, "event_name": ""}, - "connect_nodes": {"callable": connect_nodes, "event_name": "nodes_connected"}, - "disconnect_nodes": {"callable": disconnect_nodes, "event_name": "nodes_disconnected"}, - - "group_nodes": {"callable": group_nodes, "event_name": "nodes_grouped"}, - - "set_variable": {"callable": set_variable, "event_name": "variables_updated"}, - "get_variable": {"callable": get_variable, "event_name": ""}, - "get_variable_list": {"callable": get_variable_list, "event_name": ""}, - - "send_event": {"callable": send_event, "event_name": ""}, - "get_referenced_groups": {"callable": get_referenced_groups, "event_name": ""}, - } - - RPCSignalLayer.signals.deck_node_added.connect(_on_deck_node_added) - RPCSignalLayer.signals.deck_node_removed.connect(_on_deck_node_removed) - - RPCSignalLayer.signals.deck_nodes_connected.connect(_on_deck_nodes_connected) - RPCSignalLayer.signals.deck_nodes_disconnected.connect(_on_deck_nodes_disconnected) - RPCSignalLayer.signals.deck_variables_updated.connect(_on_deck_variables_updated) - - -func add_node(r: RPCRequest) -> void: - reconnect( - RPCSignalLayer.signals.deck_node_added, - _on_deck_node_added, - func(): - var deck := DeckHolder.get_deck(r.operation.condition.deck_id) - var node := deck.add_node_type(r.operation.payload.node_type) - - var node_partial := RPCNodePartial.new() - node_partial.deck_id = deck.id - node_partial.id = node._id - - var resp := create_response(r, node_partial) - resp.create_event_counterpart(node_partial, operation_types) - response.emit(resp) - ) - - -func remove_node(r: RPCRequest) -> void: - reconnect( - RPCSignalLayer.signals.deck_node_removed, - _on_deck_node_removed, - func(): - var deck := DeckHolder.get_deck(r.operation.condition.deck_id) - var node_id: String = r.operation.payload.node_id - - deck.remove_node(node_id, true) - - var node_partial := RPCNodePartial.new() - node_partial.deck_id = deck.id - node_partial.id = node_id - - var resp := create_generic_success(r) - resp.create_event_counterpart(node_partial, operation_types) - response.emit(resp) - ) - - -func get_node(r: RPCRequest) -> void: - var deck := DeckHolder.get_deck(r.operation.condition.deck_id) - var node := deck.get_node(r.operation.payload.node_id) - var node_data := node.to_dict() - - var resp := create_response(r, {"node": node_data}) - response.emit(resp) - - -func is_valid_connection(r: RPCRequest) -> void: - var deck := DeckHolder.get_deck(r.operation.condition.deck_id) - var from_node_id: String = r.operation.payload.from_node_id - var from_output_port := int(r.operation.payload.from_output_port) - var to_node_id: String = r.operation.payload.to_node_id - var to_input_port := int(r.operation.payload.to_input_port) - - var is_valid = deck.is_valid_connection(from_node_id, to_node_id, from_output_port, to_input_port) - - var resp := create_response(r, {"valid": is_valid}) - response.emit(resp) - - -func connect_nodes(r: RPCRequest) -> void: - reconnect( - RPCSignalLayer.signals.deck_nodes_connected, - _on_deck_nodes_connected, - func(): - var deck := DeckHolder.get_deck(r.operation.condition.deck_id) - var from_node_id: String = r.operation.payload.from_node_id - var from_output_port := int(r.operation.payload.from_output_port) - var to_node_id: String = r.operation.payload.to_node_id - var to_input_port := int(r.operation.payload.to_input_port) - - var connected := deck.connect_nodes(from_node_id, to_node_id, from_output_port, to_input_port) - if connected: - var connection := RPCNodeConnection.new() - connection.from_node_id = from_node_id - connection.to_node_id = to_node_id - connection.from_output_port = from_output_port - connection.to_input_port = to_input_port - var resp := create_generic_success(r) - resp.create_event_counterpart(connection, operation_types) - response.emit(resp) - else: - var err := create_generic_failure(r) - response.emit(err) - ) - - -func disconnect_nodes(r: RPCRequest) -> void: - reconnect( - RPCSignalLayer.signals.deck_nodes_disconnected, - _on_deck_nodes_disconnected, - func(): - var deck := DeckHolder.get_deck(r.operation.condition.deck_id) - var from_node_id: String = r.operation.payload.from_node_id - var from_output_port := int(r.operation.payload.from_output_port) - var to_node_id: String = r.operation.payload.to_node_id - var to_input_port := int(r.operation.payload.to_input_port) - - deck.disconnect_nodes(from_node_id, to_node_id, from_output_port, to_input_port) - - var connection := RPCNodeConnection.new() - connection.from_node_id = from_node_id - connection.to_node_id = to_node_id - connection.from_output_port = from_output_port - connection.to_input_port = to_input_port - - var resp := create_generic_success(r) - resp.create_event_counterpart(connection, operation_types) - response.emit(resp) - ) - - -func group_nodes(r: RPCRequest) -> void: - reconnect( - RPCSignalLayer.signals.deck_node_removed, - _on_deck_node_removed, - func(): - var deck := DeckHolder.get_deck(r.operation.condition.deck_id) - var node_ids: Array = r.operation.payload.nodes - var nodes := node_ids.map( - func(e: String): - return deck.get_node(e) - ) - var group := deck.group_nodes(nodes) - if group == null: - var err := create_error(r, "Error grouping") - response.emit(err) - else: - var dp := RPCDeckPartial.new(group) - var resp := create_response(r, dp) - resp.create_event_counterpart(node_ids, operation_types) - response.emit(resp) - ) - - -func set_variable(r: RPCRequest) -> void: - reconnect( - RPCSignalLayer.signals.deck_variables_updated, - _on_deck_variables_updated, - func(): - var deck := DeckHolder.get_deck(r.operation.condition.deck_id) - var var_name: String = r.operation.payload.name - var var_value = r.operation.payload.value - - deck.set_variable(var_name, var_value) - var resp := create_generic_success(r) - resp.create_event_counterpart({}, operation_types) - response.emit(resp) - ) - - -func get_variable(r: RPCRequest) -> void: - var deck := DeckHolder.get_deck(r.operation.condition.deck_id) - var var_name: String = r.operation.payload.name - var value = deck.variable_stack.get(var_name) - - var resp := create_response(r, {"name": var_name, "value": value}) - response.emit(resp) - - -func get_variable_list(r: RPCRequest) -> void: - var deck := DeckHolder.get_deck(r.operation.condition.deck_id) - - var resp := create_response(r, {"variables": deck.variable_stack.keys()}) - response.emit(resp) - - -func send_event(r: RPCRequest) -> void: - var deck := DeckHolder.get_deck(r.operation.condition.deck_id) - var event_name: StringName = r.operation.payload.event_name - var event_data: Dictionary = r.operation.payload.get("event_data", {}) - - deck.send_event(event_name, event_data) - - var resp := create_generic_success(r) - response.emit(resp) - - -func get_referenced_groups(r: RPCRequest) -> void: - var deck := DeckHolder.get_deck(r.operation.condition.deck_id) - var groups := deck.get_referenced_groups() - - var resp := create_response(r, {"groups": groups}) - response.emit(resp) - - -func _on_deck_node_added(deck_id: String, node_id: String) -> void: - event.emit(create_event("node_added", {"node_id": node_id}, {"deck_id": deck_id})) - - -func _on_deck_node_removed(deck_id: String, node_id: String) -> void: - event.emit(create_event("node_removed", {"node_id": node_id}, {"deck_id": deck_id})) - - -func _on_deck_nodes_connected(deck_id: String, from_node_id: String, to_node_id: String, from_output_port: int, to_input_port: int) -> void: - var connection := RPCNodeConnection.new() - connection.from_node_id = from_node_id - connection.to_node_id = to_node_id - connection.from_output_port = from_output_port - connection.to_input_port = to_input_port - - var ev := create_event("nodes_connected", connection, {"deck_id": deck_id}) - event.emit(ev) - - -func _on_deck_nodes_disconnected(deck_id: String, from_node_id: String, to_node_id: String, from_output_port: int, to_input_port: int) -> void: - var connection := RPCNodeConnection.new() - connection.from_node_id = from_node_id - connection.to_node_id = to_node_id - connection.from_output_port = from_output_port - connection.to_input_port = to_input_port - - var ev := create_event("nodes_disconnected", connection, {"deck_id": deck_id}) - event.emit(ev) - - -func _on_deck_variables_updated(deck_id: String) -> void: - var ev := create_event("variables_updated", {}, {"deck_id": deck_id}) - event.emit(ev) diff --git a/rpc_renderer/scopes/scope_deck_holder.gd b/rpc_renderer/scopes/scope_deck_holder.gd deleted file mode 100644 index 64e4ed6..0000000 --- a/rpc_renderer/scopes/scope_deck_holder.gd +++ /dev/null @@ -1,72 +0,0 @@ -# (c) 2023-present Eroax -# (c) 2023-present Yagich -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) -extends RPCScope - - -func _init() -> void: - name = "deck_holder" - - operation_types = { - #"new_deck": new_deck, # TODO: evaluate later - "get_deck": {"callable": get_deck, "event_name": ""}, - "send_event": {"callable": send_event, "event_name": ""}, - } - - RPCSignalLayer.signals.deck_added.connect(_on_deck_holder_deck_added) - RPCSignalLayer.signals.deck_closed.connect(_on_deck_holder_deck_closed) - - -func new_deck(r: RPCRequest) -> void: - reconnect( - RPCSignalLayer.signals.deck_added, - _on_deck_holder_deck_added, - func(): - var deck_partial := RPCDeckPartial.new() - deck_partial.id = DeckHolder.add_empty_deck().id - var resp := create_response(r, deck_partial) - resp.create_event_counterpart(deck_partial, operation_types) - response.emit(resp) - ) - - -func get_deck(r: RPCRequest) -> void: - if not r.operation.condition.has("id"): - response.emit(create_error(r, "Invalid Condition")) - return - - var deck := DeckHolder.get_deck(r.operation.condition.id) - if deck == null: - response.emit(create_error(r, "Deck doesn't exist")) - return - - response.emit(create_response(r, deck.to_dict())) - - -func send_event(r: RPCRequest) -> void: - if not r.operation.payload.has("event_name"): - response.emit(create_error(r, "Event name must be present and not empty.")) - return - - var event_data: Dictionary - - if not r.operation.payload.has("event_data"): - event_data = {} - elif not r.operation.payload.event_data is Dictionary: - #response.emit(create_error(r, "Event data must be an Object")) - var err := RPCError.new("Event data must be an Object") - response.emit(create_response(r, {}, err)) - return - else: - event_data = r.operation.payload.event_data - - DeckHolder.send_event(r.operation.payload.event_name, event_data) - response.emit(create_generic_success(r)) - - -func _on_deck_holder_deck_added(deck_id: String) -> void: - event.emit(create_event("new_deck", RPCDeckPartial.new(DeckHolder.get_deck(deck_id)))) - - -func _on_deck_holder_deck_closed(deck_id: String) -> void: - event.emit(create_event("deck_closed", RPCDeckPartial.new(DeckHolder.get_deck(deck_id)))) diff --git a/rpc_renderer/scopes/scope_node.gd b/rpc_renderer/scopes/scope_node.gd deleted file mode 100644 index 2339ba5..0000000 --- a/rpc_renderer/scopes/scope_node.gd +++ /dev/null @@ -1,267 +0,0 @@ -# (c) 2023-present Eroax -# (c) 2023-present Yagich -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) -extends RPCScope - - -func _init() -> void: - name = "node" - - operation_types = { - "send" : {"callable" : send, "event_name" : ""}, - "press_button" : {"callable" : press_button, "event_name" : ""}, - "get_input_ports" : {"callable" : get_input_ports, "event_name" : ""}, - "get_output_ports" : {"callable" : get_output_ports, "event_name" : ""}, - "get_virtual_ports" : {"callable" : get_virtual_ports, "event_name" : ""}, - "get_all_ports" : {"callable" : get_all_ports, "event_name" : ""}, - "get_port_value" : {"callable" : get_port_value, "event_name" : ""}, - "set_port_value" : {"callable" : set_port_value, "event_name" : "node_port_value_updated"}, - "get_position" : {"callable" : get_position, "event_name" : ""}, - "set_position" : {"callable" : set_position, "event_name" : "node_position_updated"}, - "rename" : {"callable" : rename, "event_name" : "node_renamed"}, - "get_group_id" : {"callable" : get_group_id, "event_name" : ""}, - } - - RPCSignalLayer.signals.node_position_updated.connect(_on_node_position_updated) - RPCSignalLayer.signals.node_renamed.connect(_on_node_renamed) - RPCSignalLayer.signals.node_port_value_updated.connect(_on_node_port_value_updated) - -# Get Node workflow = Get Deck from ID > Get Node in Deck from ID - -# Condition -> Target -# Payload -> Data - -func send(req : RPCRequest) -> void: - -# Condition -# deck_id, id, output_port - - var node := _get_deck_node( - req.operation.condition.deck_id, - req.operation.condition.id - ) - - node.send(req.operation.condition.output_port, req.operation.payload.data) - - var resp := create_generic_success(req) - response.emit(resp) - - -func press_button(req : RPCRequest) -> void: - -# Condition -# deck_id, id, global_port - - var node := _get_deck_node( - req.operation.condition.deck_id, - req.operation.condition.id - ) - - node.press_button(req.operation.condition.global_port) - - var resp := create_generic_success(req) - response.emit(resp) - - -#region Port Getters -func get_input_ports(req : RPCRequest) -> void: - - var node := _get_deck_node( - req.operation.condition.deck_id, - req.operation.condition.id - ) - - var ports : Array[RPCPort] - for all in node.get_input_ports(): - - ports.append(RPCPort.new(all)) - - - var resp = create_response(req, ports) - response.emit(resp) - - -func get_output_ports(req : RPCRequest) -> void: - - var node := _get_deck_node( - req.operation.condition.deck_id, - req.operation.condition.id - ) - - var ports : Array[RPCPort] - for all in node.get_output_ports(): - - ports.append(RPCPort.new(all)) - - - var resp = create_response(req, ports) - response.emit(resp) - - -func get_virtual_ports(req : RPCRequest) -> void: - - var node := _get_deck_node( - req.operation.condition.deck_id, - req.operation.condition.id - ) - - var ports : Array[RPCPort] - for all in node.get_virtual_ports(): - - ports.append(RPCPort.new(all)) - - - var resp = create_response(req, ports) - response.emit(resp) - - -func get_all_ports(req : RPCRequest) -> void: - - var node := _get_deck_node( - req.operation.condition.deck_id, - req.operation.condition.id - ) - - var ports : Array[RPCPort] - for all in node.get_all_ports(): - - ports.append(RPCPort.new(all)) - - - var resp = create_response(req, ports) - response.emit(resp) - -#endregion - -#region Port Values -func get_port_value(req : RPCRequest) -> void: - - var node := _get_deck_node( - req.operation.condition.deck_id, - req.operation.condition.id - ) - - var value = node.get_all_ports()[req.operation.condition.global_port].value - - var resp = create_response(req, value) - response.emit(resp) - - -func set_port_value(req : RPCRequest) -> void: - - reconnect( - RPCSignalLayer.signals.node_port_value_updated, - _on_node_port_value_updated, - func(): - - var node := _get_deck_node( - req.operation.condition.deck_id, - req.operation.condition.id - ) - - var port = node.get_all_ports()[req.operation.condition.global_port] - - # Doesn't show in the Renderer - port.set_value(req.operation.payload.port_value) - - var resp = create_generic_success(req) - resp.create_event_counterpart({"new_value" : req.operation.payload.port_value}, operation_types) - response.emit(resp) - ) - -#endregion - -func get_position(req : RPCRequest) -> void: - - var node := _get_deck_node( - req.operation.condition.deck_id, - req.operation.condition.id - ) - - var resp = create_response(req, node.position) - response.emit(resp) - - -func set_position(req : RPCRequest) -> void: - - reconnect( - RPCSignalLayer.signals.node_position_updated, - _on_node_position_updated, - func(): - var node := _get_deck_node( - req.operation.condition.deck_id, - req.operation.condition.id - ) - - node.position = req.operation.payload.position - - var resp := create_generic_success(req) - resp.create_event_counterpart({"new_position" : req.operation.payload.position}, operation_types) - response.emit(resp) - ) - - -func rename(req : RPCRequest) -> void: - - reconnect( - RPCSignalLayer.signals.node_renamed, - _on_node_renamed, - func(): - var node := _get_deck_node( - req.operation.condition.deck_id, - req.operation.condition.id - ) - - node.name = req.operation.payload.name - - var resp := create_generic_success(req) - resp.create_event_counterpart({"new_name" :req.operation.payload.name}, operation_types) - response.emit(resp) - ) - - -# Note, Check if Node IS a group node. -func get_group_id(req : RPCRequest) -> void: - - var node := _get_deck_node( - req.operation.condition.deck_id, - req.operation.condition.id - ) - - var group_id = node.group_id - - var resp := create_response(req, group_id) - response.emit(resp) - - - -func _on_node_position_updated(deck_id: String, node_id: String, position: Dictionary) -> void: - event.emit(create_event("position_updated", position, {"deck_id": deck_id, "id": node_id})) - - -func _on_node_renamed(deck_id: String, node_id: String, new_name: String) -> void: - event.emit(create_event("renamed", {"new_name": new_name}, {"deck_id": deck_id, "id": node_id})) - -func _on_node_port_value_updated(deck_id: String, node_id: String, port_idx: int, new_value: Variant) -> void: - event.emit(create_event( - "port_value_updated", - { - "port": port_idx, - "new_value": new_value, - }, - { - "deck_id": deck_id, - "id": node_id, - } - ) - ) - -#region Utility Functions -## Utility Functions for getting a Deck from a node_id and a deck_id. -func _get_deck_node(deck_id, node_id) -> DeckNode: - - var deck := DeckHolder.get_deck(deck_id) - var node := deck.get_node(node_id) - return node - -#endregion diff --git a/rpc_renderer/scopes/scope_system.gd b/rpc_renderer/scopes/scope_system.gd deleted file mode 100644 index 2f85fbd..0000000 --- a/rpc_renderer/scopes/scope_system.gd +++ /dev/null @@ -1,77 +0,0 @@ -# (c) 2023-present Eroax -# (c) 2023-present Yagich -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) -extends RPCScope -class_name RPCScopeSystem - - -func _init() -> void: - name = "system" - operation_types = { - "identify": {"callable": identify, "event_name": ""}, - "add_subscription": {"callable": add_subscription, "event_name": ""}, - "get_subscriptions": {"callable": get_subscriptions, "event_name": ""}, - "remove_subscriptions": {"callable": remove_subscriptions, "event_name": ""}, - } - - RPCSignalLayer.signals.client_connected.connect(_on_client_connected) - - -func identify(r: RPCRequest) -> void: - var subscriptions: Dictionary = r.operation.payload.get("subscriptions", {}) - if subscriptions.is_empty(): - subscriptions = { - "deck": [ - "node_added", "node_removed", "nodes_connected", "nodes_disconnected", - "nodes_grouped", "variables_updated" - ], - "deck_holder": [ - "new_deck", "deck_closed" - ] - } - r.client.subscriptions = subscriptions - r.client.identified = true - - var resp := create_response(r, {"identified": true}) - response.emit(resp) - - -func add_subscription(r: RPCRequest) -> void: - var new_subscriptions: Dictionary = r.operation.payload.subscriptions - for subscription_scope: String in new_subscriptions: - var event_names: Array = new_subscriptions[subscription_scope] - for event: String in event_names: - if event not in r.client.subscriptions[subscription_scope]: - (r.client.subscriptions[subscription_scope] as Array).append(event) - - response.emit(create_generic_success(r)) - - -func get_subscriptions(r: RPCRequest) -> void: - var resp := create_response(r, {"subscriptions": r.client.subscriptions}) - response.emit(resp) - - -func remove_subscriptions(r: RPCRequest) -> void: - var to_remove: Dictionary = r.operation.payload.subscriptions - - var scopes_to_remove: Array[String] - for subscription_scope: String in to_remove: - if subscription_scope not in r.client.subscriptions: - continue - var event_names: Array = to_remove[subscription_scope] - for event: String in event_names: - (r.client.subscriptions[subscription_scope] as Array).erase(event) - if (r.client.subscriptions[subscription_scope] as Array).is_empty(): - scopes_to_remove.append(subscription_scope) - - for scope in scopes_to_remove: - r.client.subscriptions.erase(scope) - - response.emit(create_generic_success(r)) - - -func _on_client_connected(client: RPCRenderer.Client) -> void: - var ev := create_event("identify", {}) - ev.to_peer = client.id - event.emit(ev) diff --git a/rpc_renderer/types/extended/connection.gd b/rpc_renderer/types/extended/connection.gd deleted file mode 100644 index ec6bb78..0000000 --- a/rpc_renderer/types/extended/connection.gd +++ /dev/null @@ -1,20 +0,0 @@ -# (c) 2023-present Eroax -# (c) 2023-present Yagich -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) -extends RPCFrame -class_name RPCNodeConnection - -var from_node_id: String -var from_output_port: int -var to_node_id: String -var to_input_port: int - - -func _init() -> void: - frame_name = "node_connection" - _props = [ - &"from_node_id", - &"from_output_port", - &"to_node_id", - &"to_input_port", - ] diff --git a/rpc_renderer/types/extended/deck_partial.gd b/rpc_renderer/types/extended/deck_partial.gd deleted file mode 100644 index 2ebb841..0000000 --- a/rpc_renderer/types/extended/deck_partial.gd +++ /dev/null @@ -1,17 +0,0 @@ -# (c) 2023-present Eroax -# (c) 2023-present Yagich -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) -extends RPCFrame -class_name RPCDeckPartial - -var id: String -var is_group: bool - - -func _init(from: Deck = null) -> void: - frame_name = "deck_partial" - _props = [&"id"] - - if from: - id = from.id - is_group = from.is_group diff --git a/rpc_renderer/types/extended/node_partial.gd b/rpc_renderer/types/extended/node_partial.gd deleted file mode 100644 index 1f97f6b..0000000 --- a/rpc_renderer/types/extended/node_partial.gd +++ /dev/null @@ -1,17 +0,0 @@ -# (c) 2023-present Eroax -# (c) 2023-present Yagich -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) -extends RPCFrame -class_name RPCNodePartial - -var id: String -var deck_id: String - - -func _init(from: DeckNode = null) -> void: - frame_name = "node_partial" - _props = [&"id", &"deck_id"] - - if from: - id = from._id - deck_id = from._belonging_to.id diff --git a/rpc_renderer/types/extended/port.gd b/rpc_renderer/types/extended/port.gd deleted file mode 100644 index a675115..0000000 --- a/rpc_renderer/types/extended/port.gd +++ /dev/null @@ -1,35 +0,0 @@ -# (c) 2023-present Eroax -# (c) 2023-present Yagich -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) -extends RPCFrame -class_name RPCPort - -var type: DeckType.Types -var label: String -var index: int -var port_type: DeckNode.PortType -var index_of_type: int -var descriptor: String -var usage_type: Port.UsageType - -func _init(port : Port): - frame_name = "port" - _props = [ - &"type", - &"label", - &"descriptor", - &"port_type", - &"index_of_type", - &"index", - &"usage_type" - ] - - type = port.type - label = port.label - descriptor = port.descriptor - - port_type = port.port_type - index_of_type = port.index_of_type - index = port.index - usage_type = port.usage_type - diff --git a/rpc_renderer/types/rpc_error.gd b/rpc_renderer/types/rpc_error.gd deleted file mode 100644 index ad0431a..0000000 --- a/rpc_renderer/types/rpc_error.gd +++ /dev/null @@ -1,15 +0,0 @@ -# (c) 2023-present Eroax -# (c) 2023-present Yagich -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) -extends RPCFrame -class_name RPCError -## Generic RPC error type. - -var text: String - - -func _init(p_text: String) -> void: - frame_name = "error" - _props = [&"text"] - - text = p_text diff --git a/rpc_renderer/types/rpc_event.gd b/rpc_renderer/types/rpc_event.gd deleted file mode 100644 index 062667c..0000000 --- a/rpc_renderer/types/rpc_event.gd +++ /dev/null @@ -1,37 +0,0 @@ -# (c) 2023-present Eroax -# (c) 2023-present Yagich -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) -extends RPCFrame -class_name RPCEvent -## RPC Event type. -## -## Events are sent when something happens that wasn't initiated by a client. - -var id: String = UUID.v4() -var type: String -var scope: String -var data: Variant -var condition: Dictionary - -var to_peer: int = 0 - - -func _init( - p_type: String, - p_scope: String, - p_data: Variant, - p_condition: Dictionary = {}, - ) -> void: - frame_name = "event" - _props = [ - &"id", - &"type", - &"scope", - &"data", - &"condition", - ] - type = p_type - scope = p_scope - data = p_data - condition = p_condition - diff --git a/rpc_renderer/types/rpc_operation.gd b/rpc_renderer/types/rpc_operation.gd deleted file mode 100644 index 115a4bb..0000000 --- a/rpc_renderer/types/rpc_operation.gd +++ /dev/null @@ -1,41 +0,0 @@ -# (c) 2023-present Eroax -# (c) 2023-present Yagich -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) -extends RPCFrame -class_name RPCOperation -## RPC Operation type. -## -## An operation is a part of a request from a remote client. It describes a request based on the type (what to do), the condition (what to do it to) and the payload (what data to do it with). - -var type: String -## A condition is an object usually describing which object the operation will apply to. -var condition: Dictionary -## The payload is additional data that may be required to perform an action. -var payload: Dictionary - - -func _init(p_type: String, p_condition: Dictionary = {}, p_payload: Dictionary = {}) -> void: - frame_name = "operation" - _props = [&"type", &"condition", &"payload"] - - type = p_type - condition = p_condition - payload = p_payload - - -static func from_dict(d: Dictionary) -> RPCOperation: - var r := RPCOperation.new( - d.type, - d.get("condition", {}), - d.get("payload", {}), - ) - - return r - - -static func schema() -> Zodot: - return Z.schema({ - "type": Z.string(), - "condition": Z.dictionary().nullable(), - "payload": Z.dictionary().nullable() - }) diff --git a/rpc_renderer/types/rpc_request.gd b/rpc_renderer/types/rpc_request.gd deleted file mode 100644 index f5a272e..0000000 --- a/rpc_renderer/types/rpc_request.gd +++ /dev/null @@ -1,36 +0,0 @@ -# (c) 2023-present Eroax -# (c) 2023-present Yagich -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) -class_name RPCRequest -## RPC Request type. -## -## A request is initiated by a remote client that tells the program it wants to do something. - -## Provided by the client. -var id: String -## Broadly, which part of the program should handle this request. See [RPCScope]. -var scope: String -## The action that the client wants to perform. -var operation: RPCOperation -## Any other data that will be kept and returned back to the client when a response is sent. Optional. -var keep: Dictionary - -## Which peer initiated this request. -var peer_id: int - -var client: RPCRenderer.Client - - -static func from_dict(d: Dictionary, p_client: RPCRenderer.Client) -> RPCRequest: - if not d.has("request"): - return null - - var r := RPCRequest.new() - r.id = d.request.id - r.scope = d.request.scope - r.operation = RPCOperation.from_dict(d.request.operation) - r.keep = d.request.get("keep", {}) - r.client = p_client - r.peer_id = p_client.id - - return r diff --git a/rpc_renderer/types/rpc_request_response.gd b/rpc_renderer/types/rpc_request_response.gd deleted file mode 100644 index 082e4cc..0000000 --- a/rpc_renderer/types/rpc_request_response.gd +++ /dev/null @@ -1,44 +0,0 @@ -# (c) 2023-present Eroax -# (c) 2023-present Yagich -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) -extends RPCFrame -class_name RPCRequestResponse -## RPC Request Response type. -## -## A response to a [RPCRequest]. Initiated by the server as a response. Does not inherently indicate a successful operation. - -var id: String = UUID.v4() -## The ID of the request that prompted this response. See [member RPCRequest.id]. -var for_request: String -## Broadly, which part of the program this response comes from. See [RPCScope]. The scope will be the same as the [RPCRequest] this is a response for. -var scope: String -## If non-[code]null[/code], the error that this request represents. -var errors: Array[RPCError] -## Additional data associated with the response. Mandatory, but can be empty. -var data: Variant -## See [member RPCRequest.keep]. -var kept: Dictionary - -## The peer ID this response is intended for. See [member RPCRequest.peer_id]. -var peer_id: int - -var request: RPCRequest -var event_counterpart: RPCEvent - - -func _init(p_request: RPCRequest) -> void: - request = p_request - frame_name = "request_response" - _props = [ - &"id", - &"for_request", - &"scope", - &"errors", - &"data", - &"kept", - ] - - -func create_event_counterpart(data: Variant, operation_types: Dictionary) -> void: - var event_name: String = (operation_types[request.operation.type] as Dictionary).get("event_name", request.operation.type) - event_counterpart = RPCEvent.new(event_name, scope, data, request.operation.condition) diff --git a/rpc_renderer/web_socket_server.gd b/rpc_renderer/web_socket_server.gd deleted file mode 100644 index 29d36b9..0000000 --- a/rpc_renderer/web_socket_server.gd +++ /dev/null @@ -1,171 +0,0 @@ -#Copyright (c) 2014-present Godot Engine contributors. -#Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. -# -#Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -# -#The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -# -#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -extends Node -class_name WebSocketServer - -signal message_received(peer_id: int, message) -signal client_connected(peer_id: int) -signal client_disconnected(peer_id: int) - -@export var handshake_headers := PackedStringArray() -@export var supported_protocols: PackedStringArray -@export var handshake_timout := 3000 -@export var use_tls := false -@export var tls_cert: X509Certificate -@export var tls_key: CryptoKey -@export var refuse_new_connections := false: - set(refuse): - if refuse: - pending_peers.clear() - - -class PendingPeer: - var connect_time: int - var tcp: StreamPeerTCP - var connection: StreamPeer - var ws: WebSocketPeer - - func _init(p_tcp: StreamPeerTCP): - tcp = p_tcp - connection = p_tcp - connect_time = Time.get_ticks_msec() - - -var tcp_server := TCPServer.new() -var pending_peers: Array[PendingPeer] = [] -var peers: Dictionary - - -func listen(port: int) -> int: - assert(not tcp_server.is_listening()) - return tcp_server.listen(port) - - -func stop(): - tcp_server.stop() - pending_peers.clear() - peers.clear() - - -func send(peer_id, message) -> int: - var type = typeof(message) - if peer_id <= 0: - # Send to multiple peers, (zero = brodcast, negative = exclude one) - for id in peers: - if id == -peer_id: - continue - if type == TYPE_STRING: - peers[id].send_text(message) - else: - peers[id].put_packet(message) - return OK - - assert(peers.has(peer_id)) - var socket = peers[peer_id] - if type == TYPE_STRING: - return socket.send_text(message) - return socket.send(var_to_bytes(message)) - - -func get_message(peer_id) -> Variant: - assert(peers.has(peer_id)) - var socket = peers[peer_id] - if socket.get_available_packet_count() < 1: - return null - var pkt = socket.get_packet() - if socket.was_string_packet(): - return pkt.get_string_from_utf8() - return bytes_to_var(pkt) - - -func has_message(peer_id) -> bool: - assert(peers.has(peer_id)) - return peers[peer_id].get_available_packet_count() > 0 - - -func _create_peer() -> WebSocketPeer: - var ws = WebSocketPeer.new() - ws.supported_protocols = supported_protocols - ws.handshake_headers = handshake_headers - return ws - - -func poll() -> void: - if not tcp_server.is_listening(): - return - while not refuse_new_connections and tcp_server.is_connection_available(): - var conn = tcp_server.take_connection() - assert(conn != null) - pending_peers.append(PendingPeer.new(conn)) - var to_remove := [] - for p in pending_peers: - if not _connect_pending(p): - if p.connect_time + handshake_timout < Time.get_ticks_msec(): - # Timeout - to_remove.append(p) - continue # Still pending - to_remove.append(p) - for r in to_remove: - pending_peers.erase(r) - to_remove.clear() - for id in peers: - var p: WebSocketPeer = peers[id] - var packets = p.get_available_packet_count() - p.poll() - if p.get_ready_state() != WebSocketPeer.STATE_OPEN: - client_disconnected.emit(id) - to_remove.append(id) - continue - while p.get_available_packet_count(): - message_received.emit(id, get_message(id)) - for r in to_remove: - peers.erase(r) - to_remove.clear() - - -func _connect_pending(p: PendingPeer) -> bool: - if p.ws != null: - # Poll websocket client if doing handshake - p.ws.poll() - var state = p.ws.get_ready_state() - if state == WebSocketPeer.STATE_OPEN: - var id = randi_range(2, 1 << 30) - peers[id] = p.ws - client_connected.emit(id) - return true # Success. - elif state != WebSocketPeer.STATE_CONNECTING: - return true # Failure. - return false # Still connecting. - elif p.tcp.get_status() != StreamPeerTCP.STATUS_CONNECTED: - return true # TCP disconnected. - elif not use_tls: - # TCP is ready, create WS peer - p.ws = _create_peer() - p.ws.accept_stream(p.tcp) - return false # WebSocketPeer connection is pending. - else: - if p.connection == p.tcp: - assert(tls_key != null and tls_cert != null) - var tls = StreamPeerTLS.new() - tls.accept_stream(p.tcp, TLSOptions.server(tls_key, tls_cert)) - p.connection = tls - p.connection.poll() - var status = p.connection.get_status() - if status == StreamPeerTLS.STATUS_CONNECTED: - p.ws = _create_peer() - p.ws.accept_stream(p.connection) - return false # WebSocketPeer connection is pending. - if status != StreamPeerTLS.STATUS_HANDSHAKING: - return true # Failure. - return false - - -func _process(delta): - poll()