Skip to content

Commit 48e4848

Browse files
committed
feat(NetworkManager): implement dbus-based network manager and fix OOTBE
1 parent 54771a9 commit 48e4848

32 files changed

+1380
-475
lines changed

addons/core/core.gdextension

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,10 @@ linux.release.x86_64 = "res://addons/core/bin/libopengamepadui-core.linux.templa
1111
BluezInstance = "res://assets/editor-icons/bluetooth.svg"
1212
GamescopeInstance = "res://assets/editor-icons/streamline--desktop-game-solid.svg"
1313
InputPlumberInstance = "res://addons/core/assets/icons/inputplumber.svg"
14+
NetworkManagerInstance = "res://assets/ui/icons/iconoir--network-solid.svg"
1415
PowerStationInstance = "res://assets/editor-icons/game-icons--power-generator.svg"
15-
UPowerInstance = "res://assets/editor-icons/material-symbols--battery-profile-sharp.svg"
16+
Pty = "res://assets/editor-icons/devicon-plain--bash.svg"
1617
ResourceProcessor = "res://addons/core/assets/icons/clarity--process-on-vm-line.svg"
1718
ResourceRegistry = "res://addons/core/assets/icons/carbon--cloud-registry.svg"
18-
Pty = "res://assets/editor-icons/devicon-plain--bash.svg"
19+
UPowerInstance = "res://assets/editor-icons/material-symbols--battery-profile-sharp.svg"
1920
Vdf = "res://addons/core/assets/icons/material-symbols-light--valve.svg"
Lines changed: 1 addition & 0 deletions
Loading
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
[remap]
2+
3+
importer="texture"
4+
type="CompressedTexture2D"
5+
uid="uid://cxcn8w1t87qm1"
6+
path="res://.godot/imported/iconoir--network-solid.svg-668a1b8254e7d06c708068562df9cd81.ctex"
7+
metadata={
8+
"vram_texture": false
9+
}
10+
11+
[deps]
12+
13+
source_file="res://assets/ui/icons/iconoir--network-solid.svg"
14+
dest_files=["res://.godot/imported/iconoir--network-solid.svg-668a1b8254e7d06c708068562df9cd81.ctex"]
15+
16+
[params]
17+
18+
compress/mode=0
19+
compress/high_quality=false
20+
compress/lossy_quality=0.7
21+
compress/hdr_compression=1
22+
compress/normal_map=0
23+
compress/channel_pack=0
24+
mipmaps/generate=false
25+
mipmaps/limit=-1
26+
roughness/mode=0
27+
roughness/src_normal=""
28+
process/fix_alpha_border=true
29+
process/premult_alpha=false
30+
process/normal_map_invert_y=false
31+
process/hdr_as_srgb=false
32+
process/hdr_clamp_exposure=false
33+
process/size_limit=0
34+
detect_3d/compress_to=1
35+
svg/scale=1.0
36+
editor/scale_with_editor_scale=false
37+
editor/convert_colors_with_editor_theme=false
Lines changed: 1 addition & 0 deletions
Loading
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
[remap]
2+
3+
importer="texture"
4+
type="CompressedTexture2D"
5+
uid="uid://ctnsy07oi3jks"
6+
path="res://.godot/imported/material-symbols--lock.svg-ec8320f21f9adbbbebcfe8c41ada06a5.ctex"
7+
metadata={
8+
"vram_texture": false
9+
}
10+
11+
[deps]
12+
13+
source_file="res://assets/ui/icons/material-symbols--lock.svg"
14+
dest_files=["res://.godot/imported/material-symbols--lock.svg-ec8320f21f9adbbbebcfe8c41ada06a5.ctex"]
15+
16+
[params]
17+
18+
compress/mode=0
19+
compress/high_quality=false
20+
compress/lossy_quality=0.7
21+
compress/hdr_compression=1
22+
compress/normal_map=0
23+
compress/channel_pack=0
24+
mipmaps/generate=false
25+
mipmaps/limit=-1
26+
roughness/mode=0
27+
roughness/src_normal=""
28+
process/fix_alpha_border=true
29+
process/premult_alpha=false
30+
process/normal_map_invert_y=false
31+
process/hdr_as_srgb=false
32+
process/hdr_clamp_exposure=false
33+
process/size_limit=0
34+
detect_3d/compress_to=1
35+
svg/scale=1.0
36+
editor/scale_with_editor_scale=false
37+
editor/convert_colors_with_editor_theme=false

assets/ui/icons/mdi--ethernet.svg

Lines changed: 1 addition & 0 deletions
Loading
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
[remap]
2+
3+
importer="texture"
4+
type="CompressedTexture2D"
5+
uid="uid://caygvo6umqvln"
6+
path="res://.godot/imported/mdi--ethernet.svg-c3832d5dc20f540b8d177a4e083b844b.ctex"
7+
metadata={
8+
"vram_texture": false
9+
}
10+
11+
[deps]
12+
13+
source_file="res://assets/ui/icons/mdi--ethernet.svg"
14+
dest_files=["res://.godot/imported/mdi--ethernet.svg-c3832d5dc20f540b8d177a4e083b844b.ctex"]
15+
16+
[params]
17+
18+
compress/mode=0
19+
compress/high_quality=false
20+
compress/lossy_quality=0.7
21+
compress/hdr_compression=1
22+
compress/normal_map=0
23+
compress/channel_pack=0
24+
mipmaps/generate=false
25+
mipmaps/limit=-1
26+
roughness/mode=0
27+
roughness/src_normal=""
28+
process/fix_alpha_border=true
29+
process/premult_alpha=false
30+
process/normal_map_invert_y=false
31+
process/hdr_as_srgb=false
32+
process/hdr_clamp_exposure=false
33+
process/size_limit=0
34+
detect_3d/compress_to=1
35+
svg/scale=1.0
36+
editor/scale_with_editor_scale=false
37+
editor/convert_colors_with_editor_theme=false
Lines changed: 1 addition & 0 deletions
Loading
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
[remap]
2+
3+
importer="texture"
4+
type="CompressedTexture2D"
5+
uid="uid://dghihbwuwab1y"
6+
path="res://.godot/imported/tabler--network-off.svg-191244c146ebb11979e737f2add2c042.ctex"
7+
metadata={
8+
"vram_texture": false
9+
}
10+
11+
[deps]
12+
13+
source_file="res://assets/ui/icons/tabler--network-off.svg"
14+
dest_files=["res://.godot/imported/tabler--network-off.svg-191244c146ebb11979e737f2add2c042.ctex"]
15+
16+
[params]
17+
18+
compress/mode=0
19+
compress/high_quality=false
20+
compress/lossy_quality=0.7
21+
compress/hdr_compression=1
22+
compress/normal_map=0
23+
compress/channel_pack=0
24+
mipmaps/generate=false
25+
mipmaps/limit=-1
26+
roughness/mode=0
27+
roughness/src_normal=""
28+
process/fix_alpha_border=true
29+
process/premult_alpha=false
30+
process/normal_map_invert_y=false
31+
process/hdr_as_srgb=false
32+
process/hdr_clamp_exposure=false
33+
process/size_limit=0
34+
detect_3d/compress_to=1
35+
svg/scale=1.0
36+
editor/scale_with_editor_scale=false
37+
editor/convert_colors_with_editor_theme=false
Lines changed: 12 additions & 125 deletions
Original file line numberDiff line numberDiff line change
@@ -1,106 +1,20 @@
1-
extends RefCounted
1+
@icon("res://assets/ui/icons/iconoir--network-solid.svg")
2+
extends Node
23
class_name NetworkManager
34

4-
## Manage and interact with the system network settings
5+
## Manages NetworkManager.
56
##
6-
## Allows network management through nmcli
7-
## Reference: https://developer-old.gnome.org/NetworkManager/stable/nmcli.html
7+
## The [NetworkManager] class is responsible for loading a [NetworkManagerInstance] and
8+
## calling its 'process()' method each frame.
89

910
const bar_0 := preload("res://assets/ui/icons/wifi-none.svg")
1011
const bar_1 := preload("res://assets/ui/icons/wifi-low.svg")
1112
const bar_2 := preload("res://assets/ui/icons/wifi-medium.svg")
1213
const bar_3 := preload("res://assets/ui/icons/wifi-high.svg")
14+
const no_network := preload("res://assets/ui/icons/tabler--network-off.svg")
15+
const ethernet := preload("res://assets/ui/icons/mdi--ethernet.svg")
1316

14-
const common_args := ["--terse", "--color", "no"]
15-
16-
17-
## Wireless Access Point
18-
class WifiAP:
19-
var in_use: bool
20-
var bssid: String
21-
var ssid: String
22-
var mode: String
23-
var channel: int
24-
var rate: String
25-
var strength: int
26-
var security: String
27-
28-
29-
## Network device
30-
class NetworkDevice:
31-
var device: String
32-
var type: String
33-
var state: String
34-
var connection: String
35-
36-
37-
## Returns true if the system has network controls we support
38-
static func supports_network() -> bool:
39-
var code := OS.execute("which", ["nmcli"])
40-
return code == 0
41-
42-
43-
## Returns a list of network devices
44-
#$nmcli --terse --color no device
45-
#enp5s0:ethernet:connected:Wired connection 1
46-
#wlp4s0:wifi:connected:Chonenberg
47-
#lo:loopback:connected (externally):lo
48-
#p2p-dev-wlp4s0:wifi-p2p:disconnected:
49-
static func get_devices() -> Array[NetworkDevice]:
50-
var result: Array[NetworkDevice] = []
51-
var output := _run_nmcli(["device"])
52-
for line in output:
53-
var device := NetworkDevice.new()
54-
device.device = line[0]
55-
device.type = line[1]
56-
device.state = line[2]
57-
device.connection = line[3]
58-
result.append(device)
59-
60-
return result
61-
62-
63-
## Returns a list of available wifi access points
64-
#$ nmcli --terse --color no dev wifi
65-
# :AA\:BB\:CC\:83\:82\:FF:Chronenberg 5GHz:Infra:120:405 Mbit/s:94:▂▄▆█:WPA2
66-
#*:AA\:BB\:CC\:83\:82\:FB:Chonenberg:Infra:11:195 Mbit/s:83:▂▄▆█:WPA2
67-
static func get_access_points() -> Array[WifiAP]:
68-
var result: Array[WifiAP] = []
69-
var output := _run_nmcli(["dev", "wifi"])
70-
for line in output:
71-
var ap := WifiAP.new()
72-
ap.in_use = line[0] == "*"
73-
ap.bssid = line[1]
74-
ap.ssid = line[2]
75-
ap.mode = line[3]
76-
ap.channel = line[4].to_int()
77-
ap.rate = line[5]
78-
ap.strength = line[6].to_int()
79-
ap.security = line[8]
80-
result.append(ap)
81-
82-
return result
83-
84-
85-
## Returns the currently connected access point
86-
static func get_current_access_point() -> WifiAP:
87-
var access_points := get_access_points()
88-
for ap in access_points:
89-
if ap.in_use:
90-
return ap
91-
return null
92-
93-
94-
## Connect to the given wifi access point
95-
static func connect_access_point(ssid: String, password: String = "") -> int:
96-
var args := ["dev", "wifi", "connect", ssid]
97-
if password != "":
98-
args.append_array(["password", password])
99-
var output := []
100-
var code := OS.execute("nmcli", args, output)
101-
if code != OK:
102-
push_warning("Unable to connect to ", ssid, ": ", output[0])
103-
return code
17+
@export var instance: NetworkManagerInstance = load("res://core/systems/network/network_manager.tres") as NetworkManagerInstance
10418

10519

10620
## Returns the texture reflecting the given wifi strength
@@ -114,34 +28,7 @@ static func get_strength_texture(strength: int) -> Texture2D:
11428
return bar_0
11529

11630

117-
# Run nmcli with the given arguments. Returns the parsed output.
118-
static func _run_nmcli(args: PackedStringArray) -> Array[PackedStringArray]:
119-
var output := []
120-
var cmd_args := common_args.duplicate()
121-
cmd_args.append_array(args)
122-
var code := OS.execute("nmcli", cmd_args, output)
123-
if code != OK:
124-
return []
125-
126-
return _parse_nmcli(output[0])
127-
128-
129-
# Parses the terse output of nmcli, which is separated by ':'
130-
#$ nmcli --terse --color no dev wifi
131-
# :AA\:BB\:CC\:83\:82\:FF:Chronenberg 5GHz:Infra:120:405 Mbit/s:94:▂▄▆█:WPA2
132-
#*:AA\:BB\:CC\:83\:82\:FB:Chonenberg:Infra:11:195 Mbit/s:83:▂▄▆█:WPA2
133-
static func _parse_nmcli(output: String) -> Array[PackedStringArray]:
134-
var parsed: Array[PackedStringArray] = []
135-
var lines := output.split("\n")
136-
for line in lines:
137-
var parsed_line := PackedStringArray()
138-
if line == "":
139-
continue
140-
line = line.replace("\\:", "%COLON%")
141-
var columns := line.split(":")
142-
for column in columns:
143-
column = column.replace("%COLON%", ":")
144-
parsed_line.append(column)
145-
parsed.append(parsed_line)
146-
147-
return parsed
31+
func _process(_delta: float) -> void:
32+
if not instance:
33+
return
34+
instance.process()

0 commit comments

Comments
 (0)